2007-10-30 22:31:13 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
error_reporting(E_ALL);
|
|
|
|
ini_set('display_startup_errors', true);
|
|
|
|
|
|
|
|
// rules about course structures:
|
|
|
|
//
|
|
|
|
// - Each unit has a logical name.
|
|
|
|
// - The members of a set must have distinct logical names
|
|
|
|
// - Different units may have the same logical name;
|
|
|
|
// however, such units should be identical.
|
|
|
|
|
|
|
|
class BoltFrame {
|
|
|
|
public $state;
|
|
|
|
// a data structure that's specific to the unit type,
|
|
|
|
// e.g. a loop counter
|
|
|
|
// Typically this includes the logical name of the current child.
|
|
|
|
// Normally this is implied by the state;
|
|
|
|
// however, it may differ if the course structure has changed.
|
|
|
|
// In general the unit should restart in this case
|
|
|
|
function __construct($state=null) {
|
|
|
|
$this->state = $state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class BoltUnit {
|
|
|
|
public $name; // logical name.
|
|
|
|
|
2007-11-29 02:56:10 +00:00
|
|
|
abstract function walk(
|
|
|
|
$old_stack, &$new_stack, $next, &$item, &$frac_done
|
|
|
|
);
|
2007-10-30 22:31:13 +00:00
|
|
|
// multi-purpose function for traversing a course.
|
|
|
|
// if $old_stack is null
|
|
|
|
// set up initial state for this unit.
|
|
|
|
// append frames to $new_stack for this unit and descendants
|
|
|
|
// $next is ignored
|
|
|
|
// $item is the initial item
|
|
|
|
// return is ignored
|
|
|
|
// else
|
|
|
|
// The first frame of $old_stack is for this unit.
|
|
|
|
// Check for name mismatch (if changed course).
|
|
|
|
// Append frames to $new_stack for this unit and descendants
|
|
|
|
// if $next, the bottom-level non-item unit should increment.
|
|
|
|
// return value: true if the caller should increment
|
2007-11-29 02:56:10 +00:00
|
|
|
// frac_done: Fraction done (of this unit and any subunits)
|
2007-10-30 22:31:13 +00:00
|
|
|
abstract function is_item();
|
|
|
|
}
|
|
|
|
|
|
|
|
// An iterator represents a user's position in a course.
|
|
|
|
// It is stored in the database, and the course may change underneath it.
|
|
|
|
//
|
|
|
|
class BoltIter {
|
|
|
|
public $stack; // array of BoltFrame
|
|
|
|
public $top;
|
|
|
|
|
|
|
|
// point to the start of a course; set up stack.
|
|
|
|
//
|
|
|
|
function __construct($top) {
|
|
|
|
$this->top = $top;
|
|
|
|
$this->stack = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get current item
|
|
|
|
//
|
2007-11-29 02:56:10 +00:00
|
|
|
function at(&$frac_done) {
|
2007-10-30 22:31:13 +00:00
|
|
|
$new_stack = array();
|
2007-11-29 02:56:10 +00:00
|
|
|
$this->top->walk($this->stack, $new_stack, false, $item, $frac_done);
|
2007-10-30 22:31:13 +00:00
|
|
|
$this->stack = $new_stack;
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
|
|
|
// move to the next item (and return it)
|
|
|
|
// return true if we're off the end
|
|
|
|
//
|
2007-11-29 02:56:10 +00:00
|
|
|
function next(&$frac_done) {
|
2007-10-30 22:31:13 +00:00
|
|
|
$item = null;
|
|
|
|
$new_stack = array();
|
2007-11-29 02:56:10 +00:00
|
|
|
$this->top->walk($this->stack, $new_stack, true, $item, $frac_done);
|
2007-10-30 22:31:13 +00:00
|
|
|
$this->stack = $new_stack;
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class BoltSeq extends BoltUnit {
|
|
|
|
public $units;
|
|
|
|
function __construct($n, $u) {
|
|
|
|
$this->name = $n;
|
|
|
|
$this->units = $u;
|
|
|
|
}
|
|
|
|
|
2007-11-29 02:56:10 +00:00
|
|
|
function walk($old_stack, &$new_stack, $next, &$item, &$frac_done) {
|
2007-10-30 22:31:13 +00:00
|
|
|
//echo "call to walk() for $this->name: next: $next\n";
|
2007-11-29 02:56:10 +00:00
|
|
|
$n = count($this->units);
|
2007-10-30 22:31:13 +00:00
|
|
|
if ($old_stack) {
|
|
|
|
//echo "old stack: \n";
|
|
|
|
//var_dump($old_stack);
|
|
|
|
//echo "------------\n";
|
|
|
|
$frame = $old_stack[0];
|
|
|
|
$state = $frame->state;
|
|
|
|
$i = $state->i;
|
2007-11-29 02:56:10 +00:00
|
|
|
|
|
|
|
// first, look up unit by name
|
|
|
|
//
|
|
|
|
$child = null;
|
|
|
|
for ($j=0; $j<$n; $j++) {
|
|
|
|
$c = $this->units[$j];
|
|
|
|
if ($c->name == $state->child_name) {
|
|
|
|
$child = $c;
|
|
|
|
break;
|
|
|
|
}
|
2007-10-30 22:31:13 +00:00
|
|
|
}
|
2007-11-29 02:56:10 +00:00
|
|
|
// if not there, look up by index
|
|
|
|
//
|
|
|
|
if (!$child) {
|
|
|
|
if ($i >= $n) {
|
|
|
|
// and if index is too big, use last unit
|
|
|
|
//
|
|
|
|
$i = $n-1;
|
|
|
|
}
|
|
|
|
$child = $this->units[$i];
|
2007-10-30 22:31:13 +00:00
|
|
|
}
|
2007-11-29 02:56:10 +00:00
|
|
|
|
|
|
|
// at this point, $child is the right unit
|
|
|
|
//
|
|
|
|
if ($next) {
|
|
|
|
$inc = false;
|
|
|
|
if ($child->is_item()) {
|
|
|
|
$inc = true;
|
|
|
|
} else {
|
|
|
|
array_shift($old_stack);
|
|
|
|
$inc = $child->walk(
|
|
|
|
$old_stack, $new_stack, true, $item, $frac_done
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if ($inc) {
|
|
|
|
$i++;
|
|
|
|
if ($i == $n) {
|
|
|
|
$frac_done = 1;
|
|
|
|
return true;
|
2007-10-30 22:31:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$i = 0;
|
|
|
|
}
|
2007-11-29 02:56:10 +00:00
|
|
|
$frac_done = $i/$n;
|
2007-10-30 22:31:13 +00:00
|
|
|
$child = $this->units[$i];
|
|
|
|
$state->i = $i;
|
|
|
|
$state->child_name = $child->name;
|
|
|
|
$frame = new BoltFrame($state);
|
|
|
|
$new_stack[] = $frame;
|
|
|
|
if ($child->is_item()) {
|
|
|
|
$item = $child;
|
|
|
|
} else {
|
2007-11-29 02:56:10 +00:00
|
|
|
$child->walk(null, $new_stack, false, $item, $f);
|
|
|
|
$frac_done += $f*(1/$n);
|
2007-10-30 22:31:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
function is_item() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class BoltItem extends BoltUnit {
|
|
|
|
public $filename;
|
|
|
|
function __construct($name, $filename) {
|
|
|
|
$this->filename = $filename;
|
|
|
|
$this->name = $name;
|
|
|
|
}
|
|
|
|
function begin() {
|
|
|
|
return array(new BoltFrame($this));
|
|
|
|
}
|
|
|
|
function unit_list() {
|
|
|
|
return array(&$this);
|
|
|
|
}
|
|
|
|
function is_item() {
|
|
|
|
return true;
|
|
|
|
}
|
2007-11-29 02:56:10 +00:00
|
|
|
function walk($old_stack, &$new_stack, $next, &$item, &$frac_done) {
|
2007-10-30 22:31:13 +00:00
|
|
|
echo "SHOULDN'T BE HERE\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class BoltLesson extends BoltItem {
|
|
|
|
}
|
|
|
|
|
|
|
|
class BoltExercise extends BoltItem {
|
|
|
|
}
|
|
|
|
|
|
|
|
function enum_course($course) {
|
|
|
|
$iter = new BoltIter($course);
|
|
|
|
while (1) {
|
|
|
|
$x = $iter->at();
|
|
|
|
if (!$x) break;
|
|
|
|
echo "at: $x->url\n";
|
|
|
|
$x = $iter->next();
|
|
|
|
if (!$x) break;
|
|
|
|
echo "next: $x->filename\n";
|
|
|
|
}
|
|
|
|
echo "course over\n";
|
|
|
|
}
|
|
|
|
|
2007-11-29 02:56:10 +00:00
|
|
|
function info_incomplete($user) {
|
|
|
|
if (!$user->bolt->birth_year) return true;
|
|
|
|
if (!$user->bolt->sex) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function birth_year_select($user) {
|
|
|
|
$this_year = date("Y");
|
|
|
|
$x = "<select name=birth_year>\n";
|
|
|
|
for ($i=$this_year-100; $i<$this_year; $i++) {
|
|
|
|
$s = ($i == $user->bolt->birth_year)?"selected":"";
|
|
|
|
$x .= "<option value=$i $s>$i</option>\n";
|
|
|
|
}
|
|
|
|
$s = (!$user->bolt->birth_year)?"selected":"";
|
|
|
|
$x .= "<option value=$0 $s>Unspecified</option>\n";
|
|
|
|
$x .= "</select>\n";
|
|
|
|
return $x;
|
|
|
|
}
|
|
|
|
|
|
|
|
function sex_select($user) {
|
|
|
|
$x = "<select name=sex>\n";
|
|
|
|
$s = ($user->bolt->sex == 0)?"selected":"";
|
|
|
|
$x .= "<option value=0 $s>Unspecified</option>\n";
|
|
|
|
$s = ($user->bolt->sex == 1)?"selected":"";
|
|
|
|
$x .= "<option value=1 $s>Male</option>\n";
|
|
|
|
$s = ($user->bolt->sex == 2)?"selected":"";
|
|
|
|
$x .= "<option value=2 $s>Female</option>\n";
|
|
|
|
$x .= "</select>\n";
|
|
|
|
return $x;
|
|
|
|
}
|
|
|
|
|
|
|
|
function request_info($user, $course) {
|
|
|
|
page_head("Student info");
|
|
|
|
echo "<form action=bolt_sched.php>
|
|
|
|
<input type=hidden name=action value=update_info>
|
|
|
|
<input type=hidden name=course_id value=$course->id>
|
|
|
|
";
|
|
|
|
start_table();
|
|
|
|
row2("Birth year", birth_year_select($user));
|
|
|
|
row2("Sex", sex_select($user));
|
|
|
|
row2("", "<input type=submit value=OK>");
|
|
|
|
end_table();
|
|
|
|
echo "</form>\n";
|
|
|
|
page_tail();
|
|
|
|
}
|
|
|
|
|
2007-10-30 22:31:13 +00:00
|
|
|
?>
|