Skip to content

Commit

Permalink
Merge branch 'MDL-43369-master' of git://github.com/jamiepratt/moodle
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Hemelryk committed Feb 4, 2014
2 parents ab20c84 + 8e32861 commit aa01949
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 33 deletions.
7 changes: 3 additions & 4 deletions mod/quiz/report/statistics/tests/statistics_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ protected function get_random_guess_score($questiondata) {

/**
* @param $qubaids qubaid_condition is ignored in this test
* @return array with three items
* @return array with two items
* - $lateststeps array of latest step data for the question usages
* - $summarks array of total marks for each usage, indexed by usage id
* - $summarksavg the average of the total marks over all the usages */
*/
protected function get_latest_steps($qubaids) {
$summarks = array();
$fakeusageid = 0;
Expand All @@ -72,8 +72,7 @@ protected function get_latest_steps($qubaids) {
$step->questionusageid = $fakeusageid;
}

$summarksavg = array_sum($summarks) / count($summarks);
return array($this->lateststeps, $summarks, $summarksavg);
return array($this->lateststeps, $summarks);
}

protected function cache_stats($qubaids) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
require_once($CFG->dirroot . '/mod/quiz/report/statistics/report.php');
require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');


/**
* Quiz attempt walk through using data from csv file.
*
Expand All @@ -42,7 +41,7 @@
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quiz_report_statistics_from_steps extends mod_quiz_attempt_walkthrough_from_csv_testcase {
class quiz_report_statistics_from_steps_testcase extends mod_quiz_attempt_walkthrough_from_csv_testcase {

/**
* @var quiz_statistics_report object to do stats calculations.
Expand Down Expand Up @@ -103,9 +102,11 @@ public function test_walkthrough_from_csv($quizsettings, $csvdata) {
$this->assertTimeCurrent($responesstats->get_last_analysed_time($qubaids));
}

// These quiz stats and the question stats found in qstats00.csv were calculated independently in spreadsheet which is
// These quiz stats and the question stats found in qstats00.csv were calculated independently in spreadsheets which are
// available in open document or excel format here :
// https://github.com/jamiepratt/moodle-quiz-tools/tree/master/statsspreadsheet

// These quiz stats and the position stats here are calculated in stats.xls and stats.ods available, see above github URL.
$quizstatsexpected = array(
'median' => 4.5,
'firstattemptsavg' => 4.617333332,
Expand All @@ -128,22 +129,62 @@ public function test_walkthrough_from_csv($quizsettings, $csvdata) {
$slotqstats = $csvdata['qstats']->getRow($rowno);
foreach ($slotqstats as $statname => $slotqstat) {
if ($statname !== 'slot') {
switch ($statname) {
case 'covariance' :
case 'discriminationindex' :
case 'discriminativeefficiency' :
case 'effectiveweight' :
$precision = 1e-5;
break;
default :
$precision = 1e-6;
}
$slot = $slotqstats['slot'];
$delta = abs($slotqstat) * $precision;
$actual = $questionstats[$slot]->{$statname};
$this->assertEquals(floatval($slotqstat), $actual, "$statname for slot $slot", $delta);
$this->assert_stat_equals($questionstats, $subquestionstats, $slotqstats['slot'],
null, null, $statname, (float)$slotqstat);
}
}
}

$itemstats = array('s' => 12,
'effectiveweight' => null,
'discriminationindex' => 35.803933,
'discriminativeefficiency' => 39.39393939,
'sd' => 0.514928651,
'facility' => 0.583333333,
'maxmark' => 1,
'positions' => '1',
'slot' => null,
'subquestion' => true);
foreach ($itemstats as $statname => $expected) {
$this->assert_stat_equals($questionstats, $subquestionstats, 1, null, 'numerical', $statname, $expected);
}
}

/**
* Check that the stat is as expected within a reasonable tolerance.
*
* @param \core_question\statistics\questions\calculated[] $questionstats
* @param \core_question\statistics\questions\calculated_for_subquestion[] $subquestionstats
* @param int $slot
* @param int|null $variant if null then not a variant stat.
* @param string|null $subqname if null then not an item stat.
* @param string $statname
* @param float $expected
*/
protected function assert_stat_equals($questionstats, $subquestionstats, $slot, $variant, $subqname, $statname, $expected) {

if ($variant === null && $subqname === null) {
$actual = $questionstats[$slot]->{$statname};
} else if ($subqname !== null) {
$actual = $subquestionstats[$this->randqids[$slot][$subqname]]->{$statname};
} else {
$actual = $questionstats[$slot]->variantstats[$variant]->{$statname};
}
if (is_bool($expected) || is_string($expected)) {
$this->assertEquals($expected, $actual, "$statname for slot $slot");
} else {
switch ($statname) {
case 'covariance' :
case 'discriminationindex' :
case 'discriminativeefficiency' :
case 'effectiveweight' :
$precision = 1e-5;
break;
default :
$precision = 1e-6;
}
$delta = abs($expected) * $precision;
$this->assertEquals(floatval($expected), $actual, "$statname for slot $slot", $delta);
}
}
}
11 changes: 11 additions & 0 deletions question/classes/statistics/questions/calculated.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class calculated {
*/
public $randomguessscore = null;


// End of fields in db.

protected $fieldsindb = array('questionid', 'slot', 'subquestion', 's', 'effectiveweight', 'negcovar', 'discriminationindex',
Expand All @@ -110,6 +111,11 @@ class calculated {

public $totalothermarks = 0;

/**
* @var float The total of marks achieved for all positions in all attempts where this item was seen.
*/
public $totalsummarks = 0;

public $markvariancesum = 0;

public $othermarkvariancesum = 0;
Expand All @@ -130,6 +136,11 @@ class calculated {

public $othermarkaverage;

/**
* @var float The average for all attempts, of the sum of the marks for all positions in which this item appeared.
*/
public $summarksaverage;

public $markvariance;
public $othermarkvariance;
public $covariance;
Expand Down
21 changes: 9 additions & 12 deletions question/classes/statistics/questions/calculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function __construct($questions) {
public function calculate($qubaids) {
\core_php_time_limit::raise();

list($lateststeps, $summarks, $summarksavg) = $this->get_latest_steps($qubaids);
list($lateststeps, $summarks) = $this->get_latest_steps($qubaids);

if ($lateststeps) {

Expand Down Expand Up @@ -169,10 +169,10 @@ public function calculate($qubaids) {

// Go through the records one more time.
foreach ($lateststeps as $step) {
$this->secondary_steps_walker($step, $this->questionstats[$step->slot], $summarks, $summarksavg);
$this->secondary_steps_walker($step, $this->questionstats[$step->slot], $summarks);

if ($this->questionstats[$step->slot]->subquestions) {
$this->secondary_steps_walker($step, $this->subquestionstats[$step->questionid], $summarks, $summarksavg);
$this->secondary_steps_walker($step, $this->subquestionstats[$step->questionid], $summarks);
}
}

Expand Down Expand Up @@ -268,10 +268,9 @@ public function get_sum_of_mark_variance() {

/**
* @param $qubaids \qubaid_condition
* @return array with three items
* @return array with two items
* - $lateststeps array of latest step data for the question usages
* - $summarks array of total marks for each usage, indexed by usage id
* - $summarksavg the average of the total marks over all the usages
*/
protected function get_latest_steps($qubaids) {
$dm = new \question_engine_data_mapper();
Expand All @@ -292,12 +291,9 @@ protected function get_latest_steps($qubaids) {
}
$summarks[$step->questionusageid] += $step->mark;
}
$summarksavg = array_sum($summarks) / count($summarks);
} else {
$summarksavg = null;
}

return array($lateststeps, $summarks, $summarksavg);
return array($lateststeps, $summarks);
}

/**
Expand Down Expand Up @@ -341,6 +337,8 @@ protected function initial_question_walker($stats) {

$stats->othermarkaverage = $stats->totalothermarks / $stats->s;

$stats->summarksaverage = $stats->totalsummarks / $stats->s;

sort($stats->markarray, SORT_NUMERIC);
sort($stats->othermarksarray, SORT_NUMERIC);
}
Expand All @@ -352,16 +350,15 @@ protected function initial_question_walker($stats) {
* @param object $step the state to add to the statistics.
* @param calculated $stats the question statistics we are accumulating.
* @param array $summarks of the sum of marks for each question usage, indexed by question usage id
* @param float $summarksavg the average sum of marks for all question usages
*/
protected function secondary_steps_walker($step, $stats, $summarks, $summarksavg) {
protected function secondary_steps_walker($step, $stats, $summarks) {
$markdifference = $step->mark - $stats->markaverage;
if ($stats->subquestion) {
$othermarkdifference = $summarks[$step->questionusageid] - $stats->othermarkaverage;
} else {
$othermarkdifference = $summarks[$step->questionusageid] - $step->mark - $stats->othermarkaverage;
}
$overallmarkdifference = $summarks[$step->questionusageid] - $summarksavg;
$overallmarkdifference = $summarks[$step->questionusageid] - $stats->summarksaverage;

$sortedmarkdifference = array_shift($stats->markarray) - $stats->markaverage;
$sortedothermarkdifference = array_shift($stats->othermarksarray) - $stats->othermarkaverage;
Expand Down

0 comments on commit aa01949

Please sign in to comment.