Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F96057908
lib_amcstats.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Dec 22, 04:57
Size
17 KB
Mime Type
text/x-php
Expires
Tue, Dec 24, 04:57 (1 d, 18 h)
Engine
blob
Format
Raw Data
Handle
23105985
Attached To
R1066 amc-cape
lib_amcstats.php
View Options
<?php
# some functions for array_maps
function
clean_array
(
$string
)
{
return
preg_replace
(
'/"/'
,
''
,
$string
);
}
function
decimal_conversion
(
$string
)
{
return
preg_replace
(
'/,/'
,
'.'
,
$string
);
}
function
square
(
$n
)
{
return
(
$n
*
$n
);
}
# standard deviation function (if PECL stats not available)
if
(!
function_exists
(
'stats_standard_deviation'
))
{
function
stats_standard_deviation
(
array
$a
,
$sample
=
false
)
{
$n
=
count
(
$a
);
if
(
$n
===
0
)
{
trigger_error
(
"The array has zero elements"
,
E_USER_WARNING
);
return
false
;
}
if
(
$sample
&&
$n
===
1
)
{
trigger_error
(
"The array has only 1 element"
,
E_USER_WARNING
);
return
false
;
}
$mean
=
array_sum
(
$a
)/
$n
;
$carry
=
0.0
;
foreach
(
$a
as
$val
)
{
$d
=
((
double
)
$val
)
-
$mean
;
$carry
+=
$d
*
$d
;
}
if
(
$sample
)
--
$n
;
return
sqrt
(
$carry
/
$n
);
}
}
class
AmcReader
{
protected
$filename
=
null
;
protected
$teacher
=
null
;
protected
$raw_data
=
null
;
protected
$columns
=
null
;
protected
$students
=
null
;
protected
$exam_points
=
null
;
public
function
__construct
(
$filename
,
$teacher
,
$exam_points
,
$only_questions
=
null
,
$inverse_filter
=
false
,
$external
=
null
)
{
if
(!
file_exists
(
$filename
))
throw
new
Exception
(
'File not found: '
.
$filename
);
$this
->
filename
=
$filename
;
$this
->
teacher
=
$teacher
;
$this
->
exam_points
=
$exam_points
;
$raw_data
=
file
(
$this
->
filename
,
FILE_IGNORE_NEW_LINES
);
$this
->
raw_data
=
array
();
foreach
(
$raw_data
as
$line
)
{
$line
=
array_map
(
"clean_array"
,
explode
(
';'
,
$line
));
$line
=
array_map
(
"decimal_conversion"
,
$line
);
$this
->
raw_data
[]
=
$line
;
}
$this
->
parseHeader
();
$this
->
parseStudents
(
$only_questions
,
$inverse_filter
,
$external
);
}
public
function
getStudents
()
{
return
$this
->
students
;
}
protected
function
parseHeader
()
{
foreach
(
$this
->
raw_data
[
0
]
as
$col_id
=>
$value
)
{
// Analyse header from CSV file, based on content
$item
=
array
();
switch
(
$value
)
{
case
"ID"
:
case
"NAME"
:
case
"EMAIL"
:
case
"SECTION"
:
case
"Mark"
:
$item
[
'name'
]
=
$value
;
$item
[
'type'
]
=
"info"
;
break
;
case
"SCIPER"
:
$item
[
'name'
]
=
$value
;
$item
[
'type'
]
=
"unique_id"
;
break
;
default
:
$item
[
'name'
]
=
$value
;
if
(
preg_match
(
'/^TICKED:/'
,
$value
))
{
$item
[
'name'
]
=
preg_replace
(
'/^TICKED:/'
,
''
,
$value
);
$item
[
'type'
]
=
"ticked"
;
}
else
{
$item
[
'type'
]
=
"question"
;
$item
[
'subtype'
]
=
$this
->
guessSubtype
(
$col_id
);
}
}
// Stats will be computed at a later stage
$item
[
'stats'
]
=
null
;
$this
->
columns
[]
=
$item
;
}
}
protected
function
guessSubtype
(
$col_id
)
{
$subtype
=
null
;
$min_points
=
0
;
$max_points
=
0
;
$decimal
=
false
;
foreach
(
$this
->
raw_data
as
$line
)
{
if
(
preg_match
(
'/
\.
/'
,
$line
[
$col_id
]))
$decimal
=
true
;
if
(
$line
[
$col_id
]
>
$max_points
)
$max_points
=
$line
[
$col_id
];
}
// This only works for MATHS exams...
if
(
$decimal
or
$max_points
>
3
)
{
// Only open questions have decimal points
return
'open'
;
}
if
(
$max_points
==
3
)
return
'mc'
;
if
(
$max_points
==
1
)
return
'tf'
;
return
'unknown'
;
}
protected
function
getColIdByName
(
$name
)
{
foreach
(
$this
->
columns
as
$id
=>
$col
)
if
(
$col
[
'name'
]
==
$name
)
return
$id
;
throw
new
Exception
(
'Column not found: '
.
$name
);
}
protected
function
getColIdsByType
(
$type
,
$name
=
null
)
{
$ids
=
array
();
if
(
is_null
(
$name
))
{
foreach
(
$this
->
columns
as
$id
=>
$col
)
if
(
$col
[
'type'
]
==
$type
)
$ids
[]
=
$id
;
}
else
{
foreach
(
$this
->
columns
as
$id
=>
$col
)
if
(
$col
[
'type'
]
==
$type
and
$col
[
'name'
]
==
$name
)
$ids
[]
=
$id
;
}
if
(
count
(
$ids
)
==
0
)
{
if
(
is_null
(
$name
))
throw
new
Exception
(
'Column type not found: '
.
$type
);
throw
new
Exception
(
'Column type not found: '
.
$type
.
'/'
.
$name
);
}
if
(
count
(
$ids
)
==
1
)
return
$ids
[
0
];
return
$ids
;
}
protected
function
getQuestionNameByColId
(
$id
)
{
if
(
array_key_exists
(
$id
,
$this
->
columns
)
and
$this
->
columns
[
$id
][
'type'
]
==
'question'
)
return
$this
->
columns
[
$id
][
'name'
];
throw
new
Exception
(
'Column not found, or is not a question: '
.
$id
);
}
protected
function
getMaximumPointsByColId
(
$id
)
{
$maximum
=
0.0
;
foreach
(
$this
->
raw_data
as
$student
)
if
((
float
)
$student
[
$id
]
>
$maximum
)
$maximum
=
(
float
)
$student
[
$id
];
return
$maximum
;
}
protected
function
parseStudents
(
$only_questions
,
$inverse_filter
,
$external
)
{
foreach
(
$this
->
raw_data
as
$line
=>
$student
)
{
if
(
$line
==
0
)
continue
;
// skip header
$data
=
array
(
'teacher'
=>
$this
->
teacher
);
foreach
(
array
(
'ID'
,
'SCIPER'
,
'NAME'
,
'EMAIL'
,
'SECTION'
)
as
$key
)
{
$data
[
$key
]
=
$student
[
$this
->
getColIdByName
(
$key
)];
}
// Get points
$points
=
array
();
$data
[
'items'
]
=
array
();
foreach
(
$this
->
getColIdsByType
(
'question'
)
as
$col
)
{
$item
=
array
();
$item
[
'name'
]
=
$this
->
getQuestionNameByColId
(
$col
);
// Should we filter this question ?
if
(
is_null
(
$only_questions
)
or
(!
$inverse_filter
and
in_array
(
$item
[
'name'
],
$only_questions
))
or
(
$inverse_filter
and
!
in_array
(
$item
[
'name'
],
$only_questions
))
)
{
// Take this question into account
$item
[
'points'
]
=
(
float
)
$student
[
$col
];
$item
[
'max_points'
]
=
$this
->
getMaximumPointsByColId
(
$col
);
if
(
$item
[
'max_points'
]
==
0
)
{
// Cancelled question ? Count it right for everyone
$item
[
'right'
]
=
1
;
}
else
{
$item
[
'right'
]
=
max
((
float
)(
$item
[
'points'
]/
$item
[
'max_points'
]),
0.0
);
}
$points
[]
=
$item
[
'points'
];
$item
[
'ticked'
]
=
$student
[
$this
->
getColIdsByType
(
'ticked'
,
$item
[
'name'
])];
$item
[
'type'
]
=
$this
->
columns
[
$col
][
'type'
];
$item
[
'subtype'
]
=
$this
->
columns
[
$col
][
'subtype'
];
$data
[
'items'
][]
=
$item
;
}
}
$data
[
'total'
]
=
array_sum
(
$points
);
$data
[
'present'
]
=
(
int
)(
array_sum
(
array_map
(
"square"
,
$points
))>
0
);
$data
[
'exam_points'
]
=
$this
->
exam_points
;
// Compute marks
if
(
$data
[
'present'
])
{
$data
[
'positive_total'
]
=
(
float
)
max
(
$data
[
'total'
],
0.0
);
if
(
is_null
(
$external
))
{
$data
[
'mark6'
]
=
(
float
)
min
(
$data
[
'positive_total'
]/(
$this
->
exam_points
)*
5.0
+
1
,
6.0
);
}
else
{
$output
=
array
();
exec
(
"./"
.
$external
.
" "
.
$data
[
'total'
],
$output
);
$data
[
'mark6'
]
=
(
float
)
trim
(
$output
[
0
]);
}
$data
[
'quarter_mark6'
]
=
(
float
)
round
(
$data
[
'mark6'
]*
4.0
,
0
)/
4.0
;
}
else
{
$data
[
'positive_total'
]
=
'n/a'
;
$data
[
'mark6'
]
=
'abs'
;
$data
[
'quarter_mark6'
]
=
'abs'
;
}
if
(
preg_match
(
'/^FAKE/'
,
$data
[
'SCIPER'
]))
{
if
(
$data
[
'present'
])
$data
[
'type'
]
=
'unregistered'
;
else
$data
[
'type'
]
=
'unused'
;
}
else
$data
[
'type'
]
=
'student'
;
$this
->
students
[]
=
$data
;
}
}
}
// Compare students on total (higher to lower)
function
cmp_total
(
$a
,
$b
)
{
if
(
$a
[
'total'
]
==
$b
[
'total'
])
{
return
0
;
}
return
(
$a
[
'total'
]
<
$b
[
'total'
])
?
1
:
-
1
;
}
class
ExamCalcs
{
protected
$dataset
=
null
;
protected
$tmp_dataset
=
null
;
public
function
__construct
(
$dataset
=
null
)
{
$this
->
dataset
=
array
();
if
(!
is_null
(
$dataset
))
$this
->
dataset
=
$dataset
;
}
public
function
addFile
(
$teacher
,
$teacher_file
,
$max_points
,
$only_questions
=
null
,
$inverse_filter
=
false
,
$external
=
null
)
{
#echo "Adding $teacher ($teacher_file) to the dataset ($max_points points).\n";
$AR
=
new
AmcReader
(
$teacher_file
,
$teacher
,
$max_points
,
$only_questions
,
$inverse_filter
,
$external
);
$this
->
addDataSet
(
$AR
->
getStudents
());
}
public
function
addDataSet
(
$data
)
{
foreach
(
$data
as
$student
)
$this
->
dataset
[]
=
$student
;
}
public
function
filterBySections
(
$sections
,
$update
=
true
)
{
$dataset
=
array
();
foreach
(
$this
->
dataset
as
$student
)
{
if
(
is_array
(
$sections
))
{
if
(
in_array
(
$student
[
'SECTION'
],
$sections
))
$dataset
[]
=
$student
;
}
else
{
if
(
$student
[
'SECTION'
]
==
$sections
)
$dataset
[]
=
$student
;
}
}
if
(
$update
)
$this
->
dataset
=
$dataset
;
return
$dataset
;
}
public
function
filterByTeachers
(
$teachers
,
$update
=
true
)
{
$dataset
=
array
();
foreach
(
$this
->
dataset
as
$student
)
{
if
(
is_array
(
$teachers
))
{
if
(
in_array
(
$student
[
'teacher'
],
$teachers
))
$dataset
[]
=
$student
;
}
else
{
if
(
$student
[
'teacher'
]
==
$teachers
)
$dataset
[]
=
$student
;
}
}
if
(
$update
)
$this
->
dataset
=
$dataset
;
return
$dataset
;
}
public
function
getTeachers
()
{
$teachers
=
array
();
foreach
(
$this
->
dataset
as
$student
)
{
if
(!
in_array
(
$student
[
'teacher'
],
$teachers
))
$teachers
[]
=
$student
[
'teacher'
];
}
return
$teachers
;
}
public
function
getSections
()
{
$sections
=
array
();
foreach
(
$this
->
dataset
as
$student
)
{
$section
=
$student
[
'SECTION'
];
if
(!
in_array
(
$section
,
$sections
)
and
$section
!=
'XXX'
)
$sections
[]
=
$section
;
}
return
$sections
;
}
public
function
printStatsOnCommonItems
()
{
// Sort dataset by points
$dataset
=
$this
->
sortByTotalPoints
(
false
);
if
(
count
(
$dataset
)
<
3
)
throw
new
Exception
(
'Dataset is too small.'
);
// Get items from the first student
$items
=
array
();
foreach
(
$this
->
dataset
[
0
][
'items'
]
as
$item
)
$items
[]
=
$item
[
'name'
];
foreach
(
$dataset
as
$student
)
{
// Get items for current student
$tmp_items
=
array
();
foreach
(
$student
[
'items'
]
as
$item
)
$tmp_items
[]
=
$item
[
'name'
];
// Keep only items in both '$items' AND '$tmp_items'
$items
=
array_intersect
(
$items
,
$tmp_items
);
}
// Now, filter items in the dataset
$filtered_dataset
=
array
();
foreach
(
$dataset
as
$student
)
{
if
(!
$student
[
'present'
])
continue
;
$filtered_items
=
array
();
foreach
(
$student
[
'items'
]
as
$item
)
{
if
(
in_array
(
$item
[
'name'
],
$items
))
$filtered_items
[]
=
$item
;
}
if
(
count
(
$filtered_items
))
{
$student
[
'items'
]
=
$filtered_items
;
$filtered_dataset
[]
=
$student
;
}
}
$dataset
=
$filtered_dataset
;
if
(
count
(
$dataset
)
<
3
)
throw
new
Exception
(
'Dataset is too small.'
);
// Compute limits
$nb_students
=
count
(
$dataset
);
$twenty_seven
=
(
int
)(
$nb_students
*
27.0
/
100
);
$upper_stop
=
$twenty_seven
-
1
;
$lower_start
=
$nb_students
-
$twenty_seven
+
1
;
#echo "$nb_students / $twenty_seven / 0 -> $upper_stop / $lower_start -> $nb_students \n";
$stats
=
array
();
foreach
(
$dataset
as
$i
=>
$student
)
{
foreach
(
$student
[
'items'
]
as
$item
)
{
$name
=
$item
[
'name'
];
if
(!
array_key_exists
(
$name
,
$stats
))
$stats
[
$name
]
=
array
(
'27%'
=>
$twenty_seven
,
'upper'
=>
0
,
'lower'
=>
0
,
'valid'
=>
null
,
'ticked'
=>
null
,
'ticked_count'
=>
0
,
'empty_count'
=>
0
,
'type'
=>
null
,
'subtype'
=>
null
,
'max_points'
=>
null
,
);
$stats
[
$name
][
'max_points'
]
=
$item
[
'max_points'
];
$stats
[
$name
][
'type'
]
=
$item
[
'type'
];
$stats
[
$name
][
'subtype'
]
=
$item
[
'subtype'
];
// Initialise 'ticked' table
if
(
is_null
(
$stats
[
$name
][
'ticked'
]))
{
switch
(
$stats
[
$name
][
'subtype'
])
{
case
'mc'
:
$stats
[
$name
][
'ticked'
]
=
array
(
'A'
=>
0
,
'B'
=>
0
,
'C'
=>
0
,
'D'
=>
0
,
'multiple'
=>
0
);
break
;
case
'tf'
:
$stats
[
$name
][
'ticked'
]
=
array
(
'TRUE'
=>
0
,
'FALSE'
=>
0
,
'multiple'
=>
0
);
break
;
default
:
$stats
[
$name
][
'ticked'
]
=
array
();
break
;
}
}
// Count right answers
if
(
$item
[
'right'
]
>
0
)
{
// Save valid answer
if
(
is_null
(
$stats
[
$name
][
'valid'
]))
{
switch
(
$stats
[
$name
][
'subtype'
])
{
case
'tf'
:
if
(
$item
[
'ticked'
]
==
'A'
)
$stats
[
$name
][
'valid'
]
=
'TRUE'
;
else
$stats
[
$name
][
'valid'
]
=
'FALSE'
;
break
;
case
'mc'
:
$stats
[
$name
][
'valid'
]
=
$item
[
'ticked'
];
break
;
case
'open'
:
$stats
[
$name
][
'valid'
]
=
'n/a'
;
break
;
default
:
$stats
[
$name
][
'valid'
]
=
'n/a'
;
break
;
}
}
// 'upper 27%' and 'lower 27%' counters
switch
(
$stats
[
$name
][
'subtype'
])
{
case
'mc'
:
case
'tf'
:
if
(
$i
<=
$upper_stop
)
$stats
[
$name
][
'upper'
]++;
if
(
$i
>=
$lower_start
)
$stats
[
$name
][
'lower'
]++;
break
;
case
'open'
:
if
(
$i
<=
$upper_stop
)
$stats
[
$name
][
'upper'
]
+=
$item
[
'points'
];
if
(
$i
>=
$lower_start
)
$stats
[
$name
][
'lower'
]
+=
$item
[
'points'
];
break
;
}
}
// Count empty answers
if
(
empty
(
$item
[
'ticked'
]))
{
$stats
[
$name
][
'empty_count'
]++;
}
else
{
// Stats on non-empty answers
$stats
[
$name
][
'ticked_count'
]++;
if
(
strlen
(
$item
[
'ticked'
])
>
1
)
{
$stats
[
$name
][
'ticked'
]
=
$this
->
createAndIncrement
(
$stats
[
$name
][
'ticked'
],
'multiple'
);
}
else
{
switch
(
$item
[
'subtype'
])
{
case
'tf'
:
if
(
$item
[
'ticked'
]
==
'A'
)
$field
=
'TRUE'
;
if
(
$item
[
'ticked'
]
==
'B'
)
$field
=
'FALSE'
;
$stats
[
$name
][
'ticked'
]
=
$this
->
createAndIncrement
(
$stats
[
$name
][
'ticked'
],
$field
);
break
;
case
'mc'
:
$stats
[
$name
][
'ticked'
]
=
$this
->
createAndIncrement
(
$stats
[
$name
][
'ticked'
],
$item
[
'ticked'
]);
break
;
default
:
$stats
[
$name
][
'ticked'
]
=
$this
->
createAndIncrement
(
$stats
[
$name
][
'ticked'
],
$item
[
'ticked'
]);
break
;
}
}
}
}
}
// Compute more stats
$tmp
=
array
();
foreach
(
$stats
as
$name
=>
$stat
)
{
// Discrimination index
// For open questions, change the '27%' value.
if
(
$stat
[
'subtype'
]
==
'open'
)
$stat
[
'27%'
]
=
$stat
[
'27%'
]*
$stat
[
'max_points'
];
$stat
[
'DI'
]
=
(
$stat
[
'upper'
]-
$stat
[
'lower'
])/(
1.0
*
$stat
[
'27%'
]);
// Calculate percentages
$ticked_percentage
=
array
();
foreach
(
$stat
[
'ticked'
]
as
$t
=>
$n
)
{
$ticked_percentage
[
$t
]
=
array
(
'n'
=>
$n
,
'%'
=>
(
float
)(
100.0
*
$n
/
$stat
[
'ticked_count'
]),
'valid'
=>
(
int
)(
$t
==
$stat
[
'valid'
]));
}
$stat
[
'ticked'
]
=
$ticked_percentage
;
$tmp
[
$name
]
=
$stat
;
}
$stats
=
$tmp
;
// Print CSV
$previous_subtype
=
null
;
$header
=
'"question_id","subtype","27 %","upper","lower","DI","count","valid"'
;
foreach
(
$stats
as
$name
=>
$stat
)
{
if
(
$stat
[
'subtype'
]
!=
$previous_subtype
)
{
#if (!is_null($previous_subtype)) echo "\n";
echo
$header
;
if
(
$stat
[
'subtype'
]
!=
'open'
)
{
foreach
(
$stat
[
'ticked'
]
as
$answer
=>
$data
)
echo
",
\"
[$answer] count
\"
"
;
foreach
(
$stat
[
'ticked'
]
as
$answer
=>
$data
)
echo
",
\"
[$answer] %
\"
"
;
}
echo
"
\n
"
;
$previous_subtype
=
$stat
[
'subtype'
];
}
echo
"$name,{$stat['subtype']},{$stat['27%']},{$stat['upper']},{$stat['lower']},{$stat['DI']},{$stat['ticked_count']}"
;
if
(
$stat
[
'subtype'
]
==
'open'
)
{
echo
",
\"
n/a
\"
"
;
}
else
{
foreach
(
$stat
[
'ticked'
]
as
$answer
=>
$data
)
if
(
$data
[
'valid'
]
==
1
)
echo
",
\"
$answer
\"
"
;
foreach
(
$stat
[
'ticked'
]
as
$answer
=>
$data
)
echo
",{$data['n']}"
;
foreach
(
$stat
[
'ticked'
]
as
$answer
=>
$data
)
echo
",{$data['%']}"
;
}
echo
"
\n
"
;
}
}
public
function
sortByTotalPoints
(
$update
=
true
)
{
if
(
$update
)
{
usort
(
$this
->
dataset
,
"cmp_total"
);
return
$this
->
dataset
;
}
else
{
$dataset
=
$this
->
dataset
;
usort
(
$dataset
,
"cmp_total"
);
return
$dataset
;
}
}
public
function
getDataSet
()
{
return
$this
->
dataset
;
}
protected
function
createAndIncrement
(
$table
,
$field
,
$increment
=
1
)
{
if
(!
array_key_exists
(
$field
,
$table
))
{
$table
[
$field
]
=
0
;
}
$table
[
$field
]
+=
$increment
;
return
$table
;
}
public
function
getMarks
()
{
$marks
=
array
();
foreach
(
$this
->
dataset
as
$student
)
{
$tmp
=
array
();
$tmp
[
'teacher'
]
=
$student
[
'teacher'
];
$tmp
[
'ID'
]
=
$student
[
'ID'
];
$tmp
[
'SECTION'
]
=
$student
[
'SECTION'
];
$tmp
[
'exam_points'
]
=
$student
[
'exam_points'
];
$tmp
[
'total'
]
=
$student
[
'total'
];
$tmp
[
'present'
]
=
$student
[
'present'
];
$tmp
[
'SCIPER'
]
=
$student
[
'SCIPER'
];
$tmp
[
'quarter_mark6'
]
=
$student
[
'quarter_mark6'
];
$marks
[]
=
$tmp
;
}
return
$marks
;
}
public
function
getStats
()
{
$stats
=
array
();
# Presence
$stats
[
'presence'
]
=
array
();
$marks
=
array
();
$stats
[
'quarter_mark6'
]
=
array
(
'n'
=>
0
,
'tot'
=>
0
,
'average'
=>
null
,
'stddev'
=>
null
,
'median'
=>
null
);
foreach
(
$this
->
dataset
as
$student
)
{
// Presence
$stats
[
'presence'
]
=
$this
->
createAndIncrement
(
$stats
[
'presence'
],
'total'
);
switch
(
$student
[
'type'
])
{
case
'student'
:
if
(
$student
[
'present'
])
{
$stats
[
'presence'
]
=
$this
->
createAndIncrement
(
$stats
[
'presence'
],
'present'
);
}
else
{
$stats
[
'presence'
]
=
$this
->
createAndIncrement
(
$stats
[
'presence'
],
'absent'
);
}
break
;
case
'unused'
:
$stats
[
'presence'
]
=
$this
->
createAndIncrement
(
$stats
[
'presence'
],
'unsused'
);
break
;
default
:
$stats
[
'presence'
]
=
$this
->
createAndIncrement
(
$stats
[
'presence'
],
'unknown'
);
}
// Average
if
(
$student
[
'present'
])
$marks
[]
=
$student
[
'quarter_mark6'
];
}
$stats
[
'quarter_mark6'
][
'n'
]
=
count
(
$marks
);
if
(
$stats
[
'quarter_mark6'
][
'n'
]
>
0
)
{
$stats
[
'quarter_mark6'
][
'tot'
]
=
array_sum
(
$marks
);
$stats
[
'quarter_mark6'
][
'average'
]
=
$stats
[
'quarter_mark6'
][
'tot'
]/
$stats
[
'quarter_mark6'
][
'n'
];
$stats
[
'quarter_mark6'
][
'stddev'
]
=
stats_standard_deviation
(
$marks
);
if
(
count
(
$marks
)
>=
3
)
{
sort
(
$marks
);
$stats
[
'quarter_mark6'
][
'median'
]
=
$marks
[
round
(
count
(
$marks
)/
2
)];
}
else
{
$stats
[
'quarter_mark6'
][
'median'
]
=
'n/a'
;
}
}
else
{
$stats
[
'quarter_mark6'
][
'tot'
]
=
0
;
$stats
[
'quarter_mark6'
][
'average'
]
=
0
;
$stats
[
'quarter_mark6'
][
'stddev'
]
=
0
;
$stats
[
'quarter_mark6'
][
'median'
]
=
0
;
}
// Distribution (of marks)
$distribution
=
array
();
for
(
$m
=
1.0
;
$m
<=
6.0
;
$m
+=
0.25
)
$distribution
[(
string
)
$m
]
=
0
;
$stats
[
'distribution_total'
]
=
0
;
foreach
(
$marks
as
$mark
)
{
$distribution
[(
string
)
$mark
]++;
$stats
[
'distribution_total'
]++;
}
$stats
[
'distribution'
]
=
$distribution
;
$stats
[
'distribution_percentage'
]
=
array
();
if
(
$stats
[
'quarter_mark6'
][
'n'
])
{
foreach
(
$stats
[
'distribution'
]
as
$mark
=>
$count
)
$stats
[
'distribution_percentage'
][
$mark
]
=
$count
*
100.0
/
$stats
[
'distribution_total'
];
}
else
{
$stats
[
'distribution_percentage'
]
=
$stats
[
'distribution'
];
}
return
(
$stats
);
}
}
?>
Event Timeline
Log In to Comment