Find Average Marks in an Array

Opeyemi AbdulRasheed
Opeyemi AbdulRasheed used Ask the Experts™
on
Hello Experts!

I already got help on how to calculate Total and Average per Student. Now, I want to find Average Marks per SUBJECT as in the following :

SN       Name                     Eng           Maths         No_of_Subjects    Total      Avg
1          Stu1                        40             45                2                             85          42.5
2          Stu2                        50             55                2                             105        52.5
            Subject Avg.          45              50    

This is the code I'm currently using:
class Student
{
  public $ID;
  public $Name;
  public $Subjects = array();

  // Functions to get Total and Average marks per student
  public function getTotalMarks()
  {
    $total = 0;
    foreach($this->Subjects as $subject => $marks)
    {
      $total += $marks;
    }
    return $total;
  } 

  public function getAverageMarks()
  {
    if(!count($this->Subjects)) { return 0; }
    return round($this->getTotalMarks() / count($this->Subjects), 1);
  } 
}

class ClassName
{
  public $ID;
  public $Name;
  public $Students = array();
  public $SubjectList = array();
}

Open in new window


Thank you so much
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Commented:
I'm guessing you want the averages per each class, so you would adjust the definition of the ClassName. It would looks something like this:

class ClassName
{
  public $ID;
  public $Name;
  public $Students = array();
  public $SubjectList = array();

  public function getSubjectAverages()
  {
    $results = array();
    foreach($this->SubjectList as $subjectName)
    {
      $results[$subjectName] = $this->getSubjectAverage($subjectName);
    }
    return $results;
  }

  // Get the average marks of all students for one subject
  public function getSubjectAverage($subjectName)
  {
      $subjectTotalMarks = 0;
      $subjectStudentsWithMarks = 0;

      foreach$(this->Students as $student)
      {
        if(isset($student->Subjects[$subjectName]))
        {
          $subjectStudentsWithMarks++;
          $subjectTotalMarks += $student->Subjects[$subjectName];
        }
      }

      if($subjectStudentsWithMarks == 0) { return 0; }
      return $subjectTotalMarks / $subjectStudentsWithMarks;
  }
}

Open in new window


And you would call $classObjectHere->getSubjectAverages() to get an array that looked like:

[Eng] = 45
[Maths] = 50
Please help me out. Which one is $classObject?

I tried it like this but nothing happend:

foreach($Class->SubjectList as $subject)
    {
      $pdf->Cell(10, 5, $subjectName->getSubjectAverage(), 1, 0, 'C');
    }

Open in new window

Commented:
$Class->getSubjectAverage($subjectName)
Starting with Angular 5

Learn the essential features and functions of the popular JavaScript framework for building mobile, desktop and web applications.

Getting zeroes. getting_zeroes.pngPlease see attached.

Commented:
I noticed I have a typo in my code:
foreach$(this->Students as $student)

should be:
foreach($this->Students as $student)

If you didn't fix that already, that could be the issue. If you DID fix it, then try logging the two variables out somewhere:

      ...
      file_put_contents("/path/to/a/log.file", "{$subjectTotalMarks} / {$subjectStudentsWithMarks}");
      if($subjectStudentsWithMarks == 0) { return 0; }
      return $subjectTotalMarks / $subjectStudentsWithMarks;

...and then check that log file to see which value is 0.
I already fixed that. The log file shows that both variables are 0

0 / 0

Commented:
Can you show the actual code you're using for that function?
Everything:
<?php

require('../assets/library/fpdf.php');
require('../includes/connection.php');
error_reporting(0);
// ================== CLASS DEFINITIONS ==================
class Student
{
  public $ID;
  public $Name;
  public $Subjects = array();

  // Functions to get Total and Average marks per student
  public function getTotalMarks()
  {
    $total = 0;
    foreach($this->Subjects as $subject => $marks)
    {
      $total += $marks;
    }
    return $total;
  } 

  public function getAverageMarks()
  {
    if(!count($this->Subjects)) { return 0; }
    return round($this->getTotalMarks() / count($this->Subjects), 1);
  } 
}

class ClassName
{
  public $ID;
  public $Name;
  public $Students = array();
  public $SubjectList = array();

  public function getSubjectAverages()
  {
    $results = array();
    foreach($this->SubjectList as $subjectName)
    {
      $results[$subjectName] = $this->getSubjectAverage($subjectName);
    }
    return $results;
  }

  // Get the average marks of all students for one subject
  public function getSubjectAverage($subjectName)
  {
      $subjectTotalMarks = 0;
      $subjectStudentsWithMarks = 0;

      foreach($this->Students as $student)
      {
        if(isset($student->Subjects[$subjectName]))
        {
          $subjectStudentsWithMarks++;
          $subjectTotalMarks += $student->Subjects[$subjectName];
        }
      }
      file_put_contents("../assets/log.file", "{$subjectTotalMarks} / {$subjectStudentsWithMarks}");
      if($subjectStudentsWithMarks == 0) { return 0; }
      return $subjectTotalMarks / $subjectStudentsWithMarks;
  }
}

$session = $_POST['session'];
$term = $_POST['term'];
$class_name = $_POST['class_name'];

// ================== QUERY AND ORGANIZE DATA INTO CLASS OBJECTS ==================
// Our top-level data array
$classes = array();

// Query the data and organize it into objects
$rs = $conn->query("SELECT Student_ID, Student_Name, Class_Name, Subject_Code, Total FROM view_subjects_enrollment WHERE Session = '$session' AND Term = '$term' AND Class_Name = '$class_name' ORDER BY Subject_Code");
while($row = $rs->fetch_assoc())
{
  $id      = $row["Student_ID"];
  $name    = $row["Student_Name"];
  $class   = $row["Class_Name"];
  $subject = $row["Subject_Code"];
  $marks   = $row["Total"];

  // Initialize new Class
  if(!isset($classes[$class]))
  {
    $classes[$class] = new ClassName();
    $classes[$class]->Name = $class;    
  }

  // Record the subject for the class
  $classes[$class]->SubjectList[$subject] = $subject;

  // Initialize student
  if(!isset($classes[$class]->Students[$name]))
  {
    $classes[$class]->Students[$name] = new Student();
    $classes[$class]->Students[$name]->ID = $id;
    $classes[$class]->Students[$name]->Name = $name;
  }

  // Add subject marks
  $classes[$class]->Students[$name]->Subjects[$subject] = $marks;
}

class PDF extends FPDF
{
// Page header
function Header() {

  include ('../includes/connection.php');

  $term = $_POST['term'];
  $session = $_POST['session'];
  
    // Logo
    $this->Image('../assets/img/logo.png',10,5,20);
       
    // Title
    $sql = "SELECT * FROM tbl_school WHERE Status = 1";
    $result = $conn->query($sql);

    while($row = $result->fetch_assoc()) {
    $this->SetFont('Arial','B',14);
    $this->Cell(277, 5, $row['Sch_Name'], 0, 1, 'C');
    $this->SetFont('Arial','',10);
    $this->Cell(277, 5, $row['Sch_Address'], 0, 1, 'C');
  }
    $this->SetFont('Arial','B',12);
    $this->Cell(277, 10, 'BROAD SHEET', 0, 1, 'C');
    
}

// Page footer
function Footer()
{
    $currentDate = date("d-m-Y");
    // Position at 1.5 cm from bottom
    $this->SetY(-15);
    $this->SetFont('Arial','B',8);
    $this->Cell(92,5,'Powered by : HardSoft Tech.', 'T', 0, 'L');
    // Page number
    $this->Cell(92,5,'Page '.$this->PageNo().'/{nb}', 'T', 0, 'C');
    $this->Cell(92,5,'Printed @ '.$currentDate, 'T', 1, 'R');
}
}

// Instanciation of inherited class
$pdf = new PDF('L', 'mm', 'A4');
$pdf->AliasNbPages();
$pdf->AddPage();

$pdf->SetFont('Arial','B',9);
$pdf->Cell(92, 5, 'CLASS: '.$class_name, 'B', 0, 'C');
$pdf->Cell(92, 5, 'TERM: '.$term, 'B', 0, 'C');
$pdf->Cell(92, 5, 'SESSION: '.$session, 'B', 1, 'C');

// ================== BUILD OUTPUT TABLE ==================

$pdf->SetFont('Arial','B',8); 
// Now loop through our data
$cnt = 1;
foreach($classes as $Class)
{
  // Build table - column headers
  $pdf->Cell(10, 5, 'SN', 1, 0, 'C');
  $pdf->Cell(20, 5, 'ADM. NO', 1, 0, 'C');
  $pdf->Cell(60, 5, 'NAME', 1, 0, 'C');
  foreach($Class->SubjectList as $subject)
  {
      $pdf->Cell(10, 5, $subject, 1, 0, 'C');
  }

  $pdf->SetFont('Arial','B',6);
  $pdf->Cell(15, 5, 'NO OF SUB.', 1, 0, 'C');

  $pdf->SetFont('Arial','B',8);
  $pdf->Cell(15, 5, 'TOTAL', 1, 0, 'C');
  $pdf->Cell(15, 5, 'AVG', 1, 1, 'C');

  $pdf->SetFont('Arial','',8);
  // Loop through students and populate the table
  foreach($Class->Students as $Student)
  {
    $pdf->Cell(10, 5, $cnt++, 1, 0, 'C');
    $pdf->Cell(20, 5, $Student->ID, 1, 0, 'L');
    $pdf->Cell(60, 5, $Student->Name, 1, 0, 'L');

    foreach($Class->SubjectList as $subject)
    {
        // Display the marks if the student has them for that subject, otherwise display a blank string
    $pdf->Cell(10, 5, (isset($Student->Subjects[$subject]) ? $Student->Subjects[$subject] : ""), 1, 0, 'C');

    }

    $pdf->Cell(15, 5, count($Student->Subjects), 1, 0, 'C');
    $pdf->Cell(15, 5, $Student->getTotalMarks(), 1, 0, 'C');
    $pdf->Cell(15, 5, $Student->getAverageMarks(), 1, 1, 'C');

  }
  $pdf->Cell(10, 5, '', 1, 0, 'C');
  $pdf->Cell(20, 5, '', 1, 0, 'C');
  $pdf->Cell(60, 5, 'Subject Average', 1, 0, 'C');

  foreach($Class->SubjectList as $subject)
    {
      $pdf->Cell(10, 5, $Class->getSubjectAverage($subjectName), 1, 0, 'C');
    }
  $pdf->Cell(15, 5, '', 1, 0, 'C');
  $pdf->Cell(15, 5, '', 1, 0, 'C');
  $pdf->Cell(15, 5, '', 1, 0, 'C');

}

$pdf->Output('I', $class_name.'_BroadSheet.pdf', false);
?>

Open in new window

Commented:
Ah.

    foreach($Class->SubjectList as $subject)
    {
      $pdf->Cell(10, 5, $Class->getSubjectAverage($subjectName), 1, 0, 'C');
    }

Those variables have to match.
You're such an excellent dev. Million thanks. It's working

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial