. // actions: // (none) // if have a snapshot, show start/end // show form to get new snapshot // snap_action // make new snapshot and go to... // map // show a map; // show form to set or change filter or breakdown // // columns: // name // type // breakdown category (if using breakdown) // nviews (as number) // outcome (as color-coded bar graph: green=next, yellow=back, red=none) // time (bar graph of log(t)) // score (bar graph) // // what's shown: // lessons: nviews, outcome, time // exercise: nviews, outcome, time, score // exercise answer: nviews, outcome, time // exercise set: score // // When breakdown is used, each of above has N lines // Total, followed by each breakdown category require_once("../inc/bolt_util_ops.inc"); require_once("../inc/bolt_db.inc"); require_once("../inc/bolt_cat.inc"); require_once("../inc/bolt.inc"); require_once("../inc/bolt_snap.inc"); // the following are to minimize argument passing $snap = null; $course_id = 0; $top_unit = null; $filter = null; $filter_cat = null; $breakdown = null; $breakdown_cat = null; function show_snap_form() { global $course_id; admin_page_head("Data snapshot"); $s = read_map_snapshot($course_id); if ($s) { $end = date_str($s->time); echo " A data snapshot exists for the $s->dur days prior to $end. "; show_button( "bolt_map.php?action=map&course_id=$course_id", "Use this snapshot", "Use this snapshot" ); } else { echo "There is currently no snapshot."; } echo "
Create a new snapshot using data from the last days.
"; admin_page_tail(); } function snap_action() { global $course_id; global $top_unit; $dur = get_int('dur'); $s = write_map_snapshot($course_id, $dur); show_map(); } function spaces($level) { $x = ""; for ($i=0; $i<$level; $i++) { $x .= "    "; } return $x; } // filter arrays of anything that has a user_id field // (view, xset_result, question) // function filter_array($array) { global $snap, $filter, $filter_cat, $breakdown, $breakdown_cat; if (!$filter && !$breakdown) return $array; $x = array(); foreach ($array as $y) { if (!array_key_exists($y->user_id, $snap->users)) continue; $u = $snap->users[$y->user_id]; if ($filter && $filter->categorize($u) != $filter_cat) { continue; } if ($breakdown && $breakdown_cat) { if ($breakdown->categorize($u) != $breakdown_cat) { continue; } } $x[] = $y; } return $x; } function avg_score($array) { $sum = 0; $n = count($array); if ($n ==0) return 0; foreach ($array as $a) { $sum += $a->score; } return $sum/count($array); } function avg_time($views) { $sum = 0; $n = 0; foreach ($views as $v) { if ($v->start_time && $v->end_time) { $sum += $v->end_time - $v->start_time; $n++; } } if ($n ==0) return 0; return $sum/$n; } function outcomes($views) { $x = array(); $x[0] = 0; $x[1] = 0; $x[2] = 0; foreach ($views as $v) { switch ($v->action) { case BOLT_ACTION_NONE: $x[0]++; break; case BOLT_ACTION_NEXT: $x[1]++; break; case BOLT_ACTION_SUBMIT: $x[1]++; break; default: $x[2]++; break; } } return $x; } function get_nquestions($unit, $mode) { global $snap; if (array_key_exists($unit->name, $snap->questions)) { $a = filter_array($snap->questions[$unit->name]); $n = 0; foreach ($a as $q) { if ($q->mode == $mode) $n++; } return $n; } return 0; } function get_views($unit, $mode) { global $snap; $y = array(); if (array_key_exists($unit->name, $snap->views)) { $a = filter_array($snap->views[$unit->name]); foreach ($a as $x) { if ($x->mode == $mode) $y[] = $x; } } return $y; } function get_results($unit) { global $snap; if (array_key_exists($unit->name, $snap->results)) { return filter_array($snap->results[$unit->name]); } return array(); } function get_xset_results($unit) { global $snap; if (array_key_exists($unit->name, $snap->xset_results)) { return filter_array($snap->xset_results[$unit->name]); } return array(); } function class_name($class) { switch ($class) { case "BoltSequence": return "sequence"; case "BoltSelect": return "select"; case "BoltLesson": return "lesson"; case "BoltExercise": return "exercise"; case "BoltExerciseSet": return "exercise set"; case "BoltRandom": return "random"; } } $rownum = 0; function show_unit_row($unit, $class, $level, $is_answer) { global $breakdown, $breakdown_cat; global $rownum, $course_id; $a = $is_answer?" (answer)":""; $j = ($rownum++)%2; echo ""; if ($breakdown && $breakdown_cat) { echo "

"; } else { $c = class_name($class); echo " ".spaces($level)."$unit->name $c $a "; } if ($breakdown) { if ($breakdown_cat) { echo "$breakdown_cat\n"; } else { echo "Total\n"; } } switch ($class) { case "BoltLesson": $mode = BOLT_MODE_LESSON; $views = get_views($unit, $mode); $n = count($views); $out = outcomes($views); $t = avg_time($views); echo "$n"; $n = get_nquestions($unit, $mode); if ($n) { echo "name&mode=$mode".filter_url().">$n\n"; } else { echo "0\n"; } echo outcome_graph($out, 200); echo empty_cell(); echo time_graph($t, 200); break; case "BoltExercise": $mode = $is_answer?BOLT_MODE_ANSWER:BOLT_MODE_SHOW; $views = get_views($unit, $mode); $n = count($views); $out = outcomes($views); $t = avg_time($views); echo "$n"; $n = get_nquestions($unit, $mode); if ($n) { echo "name&mode=$mode>$n\n"; } else { echo "0\n"; } echo outcome_graph($out, 200); if ($is_answer) { echo empty_cell(); } else { $results = get_results($unit); $score = avg_score($results); echo score_graph($score, 200); } echo time_graph($t, 200); break; case "BoltExerciseSet": $xr = get_xset_results($unit); $n = count($xr); echo "$n"; echo empty_cell(); echo empty_cell(); $score = avg_score($xr); echo score_graph($score, 200); echo empty_cell(); break; default: echo empty_cell(); echo empty_cell(); echo empty_cell(); echo empty_cell(); echo empty_cell(); } echo "\n"; } function breakdown_class($class) { switch ($class) { case "BoltLesson": case "BoltExercise": case "BoltExerciseSet": return true; } return false; } function show_unit($unit, $level) { global $snap, $filter, $filter_cat, $breakdown, $breakdown_cat; $class = get_class($unit); $breakdown_cat = null; show_unit_row($unit, $class, $level, false); if ($breakdown && breakdown_class($class)) { foreach ($breakdown->categories() as $c) { $breakdown_cat = $c; show_unit_row($unit, $class, $level, false); } } // if exercise, show answer page views // if ($class == "BoltExercise") { $breakdown_cat = null; show_unit_row($unit, $class, $level, true); if ($breakdown) { foreach ($breakdown->categories() as $c) { $breakdown_cat = $c; show_unit_row($unit, $class, $level, true); } } } } function show_unit_recurse($unit, $level) { show_unit($unit, $level); if ($unit->is_item) return; foreach ($unit->units as $u) { show_unit_recurse($u, $level+1); } } function show_map() { global $snap, $course_id, $top_unit, $filter, $filter_cat, $breakdown; global $course; get_filters_from_form(); admin_page_head("Course map for '$course->name'"); bolt_style(); $snap = read_map_snapshot($course_id); start_table(); echo " Name Type "; if ($breakdown) { echo "Group"; } echo " Views Questions Outcome
Next Back None Score Time "; show_unit_recurse($top_unit, 0); echo "
"; filter_form($filter?$filter->name():"", $filter_cat); echo ""; breakdown_form($breakdown?$breakdown->name():""); echo "

"; admin_page_tail(); } function show_questions() { global $course_id; $name = get_str('name'); $mode = get_int('mode'); get_filters_from_form(); $snap = read_map_snapshot($course_id); $qs = $snap->questions[$name]; admin_page_head("Questions about $name"); start_table(); echo " When Who Question "; foreach ($qs as $q) { if ($q->mode != $mode) continue; $user = $snap->users[$q->user_id]; echo " ".time_str($q->create_time)." $user->name $q->question "; } end_table(); admin_page_tail(); } $course_id = get_int('course_id'); $course = BoltCourse::lookup_id($course_id); if (!$course) error_page("no course"); $top_unit = require_once($course->doc_file()); $action = get_str('action', true); switch ($action) { case "": show_snap_form(); break; case "snap_action": snap_action(); break; case "map": show_map(); break; case "questions": show_questions(); break; default: error_page("Unknown action $action"); } ?>