diff --git a/checkin_notes b/checkin_notes index b6bb733a58..5ba78388e9 100644 --- a/checkin_notes +++ b/checkin_notes @@ -10182,3 +10182,22 @@ David 30 Oct 2007 forum_thread.php account_finish_action.php account_finish.php + +David 30 Oct 2007 + - initial checkin for Bolt + + db/ + bolt_constraints.sql + bolt_db.sql + html/ + inc/ + bolt.inc + bolt_db.inc + bolt_ex.inc + bossa_db.inc + ops/ + bolt_setup_sample.php + user/ + bolt.php + bolt_course_sample.php + bolt_sched.php diff --git a/db/bolt_constraints.sql b/db/bolt_constraints.sql new file mode 100644 index 0000000000..56db94c362 --- /dev/null +++ b/db/bolt_constraints.sql @@ -0,0 +1,8 @@ +alter table bolt_course + add unique(name); + +alter table bolt_enrollment + add unique(user_id, course_id); + +alter table bolt_view + add index bv_cs(course_id, start_time); diff --git a/db/bolt_schema.sql b/db/bolt_schema.sql new file mode 100644 index 0000000000..6b4433b43f --- /dev/null +++ b/db/bolt_schema.sql @@ -0,0 +1,26 @@ +create table bolt_course ( + id integer not null auto_increment, + create_time integer not null, + short_name varchar(255) not null, + name varchar(255) not null, + description text not null, + doc_file varchar(255) not null, + primary key (id) +); + +create table bolt_enrollment ( + create_time integer not null, + user_id integer not null, + course_id integer not null, + state text not null +); + +create table bolt_view ( + id integer not null auto_increment, + user_id integer not null, + course_id integer not null, + item_name varchar(255) not null, + start_time integer not null, + end_time integer not null, + primary key (id) +); diff --git a/html/inc/bolt.inc b/html/inc/bolt.inc new file mode 100644 index 0000000000..d120970981 --- /dev/null +++ b/html/inc/bolt.inc @@ -0,0 +1,185 @@ +state = $state; + } +} + +abstract class BoltUnit { + public $name; // logical name. + + abstract function walk($old_stack, &$new_stack, $next, &$item); + // 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 + 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 + // + function at() { + $new_stack = array(); + $this->top->walk($this->stack, $new_stack, false, $item); + $this->stack = $new_stack; + return $item; + } + + // move to the next item (and return it) + // return true if we're off the end + // + function next() { + $item = null; + $new_stack = array(); + $this->top->walk($this->stack, $new_stack, true, $item); + $this->stack = $new_stack; + return $item; + } +} + +class BoltSeq extends BoltUnit { + public $units; + function __construct($n, $u) { + $this->name = $n; + $this->units = $u; + } + + function walk($old_stack, &$new_stack, $next, &$item) { + //echo "call to walk() for $this->name: next: $next\n"; + if ($old_stack) { + //echo "old stack: \n"; + //var_dump($old_stack); + //echo "------------\n"; + $frame = $old_stack[0]; + $state = $frame->state; + $i = $state->i; + $restart = false; + if ($i >= count($this->units)) { + echo "index too large - restarting\n"; + $restart = true; + } + $child = $this->units[$i]; + if ($state->child_name != $child->name) { + echo "bad name - restarting\n"; + $restart = true; + } + if (!$restart) { + if ($next) { + $inc = false; + if ($child->is_item()) { + $inc = true; + } else { + array_shift($old_stack); + $inc = $child->walk($old_stack, $new_stack, true, &$item); + } + if ($inc) { + $i++; + if ($i == count($this->units)) { + return true; + } + } + } + } + } else { + $restart = true; + } + if ($restart) { + $i = 0; + } + $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 { + $child->walk(null, $new_stack, false, $item); + } + } + 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; + } + function walk($old_stack, &$new_stack, $next, &$item) { + 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"; +} + +?> diff --git a/html/inc/bolt_db.inc b/html/inc/bolt_db.inc new file mode 100644 index 0000000000..83b7c3896b --- /dev/null +++ b/html/inc/bolt_db.inc @@ -0,0 +1,86 @@ +'); + $passwd = parse_config($config, ''); + $host = parse_config($config, ''); + $name = parse_config($config, ''); + if ($host == null) { + $host = "localhost"; + } + $instance = new DbConn(); + $retval = $instance->init_conn($user, $passwd, $host, $name); + if (!$retval) return null; + } + return $instance; + } +} + +class BoltCourse { + function insert() { + $db = BoltDb::get(); + $now = time(); + $query = "insert into DBNAME.bolt_course (create_time, short_name, name, description, doc_file) values ($now, '$this->short_name', '$this->name', '$this->description', '$this->doc_file')"; + $result = $db->do_query($query); + if (!$result) return false; + $this->id = $db->insert_id(); + return true; + } + + static function lookup_id($id) { + $db = BoltDb::get(); + return $db->lookup_id($id, 'bolt_course', 'BoltCourse'); + } + + static function enum() { + $db = BoltDb::get(); + return $db->enum('bolt_course', 'BoltCourse'); + } +} + +class BoltEnrollment { + function insert() { + $db = BoltDb::get(); + $now = time(); + $query = "insert into DBNAME.bolt_enrollment (create_time, user_id, course_id) values ($now, $this->user_id, $this->course_id)"; + return $db->do_query($query); + } + function lookup($userid, $courseid) { + $db = BoltDb::get(); + return $db->lookup('bolt_enrollment', 'BoltEnrollment', "user_id=$userid and course_id=$courseid"); + } + function update_aux($clause) { + $db = BoltDb::get(); + $db->update_aux('bolt_enrollment', $clause); + } +} + +class BoltView { + function insert() { + $db = BoltDb::get(); + $now = time(); + $query = "insert into DBNAME.bolt_view (user_id, course_id, item_name, start_time) values ($this->user_id, $this->course_id, '$this->item_name', $now)"; + $result = $db->do_query($query); + if (!$result) return false; + $this->id = $db->insert_id(); + return true; + } + static function lookup_id($id) { + $db = BoltDb::get(); + return $db->lookup_id($id, 'bolt_view', 'BoltView'); + } + function update($clause) { + $db = BoltDb::get(); + $db->update($this, 'bolt_view', $clause); + } +} + +?> diff --git a/html/inc/bolt_ex.inc b/html/inc/bolt_ex.inc new file mode 100644 index 0000000000..357dbf56f3 --- /dev/null +++ b/html/inc/bolt_ex.inc @@ -0,0 +1,8 @@ + $choice"; + } +} +?> diff --git a/html/inc/bossa_db.inc b/html/inc/bossa_db.inc index fc1f15044c..e1ede7bc56 100644 --- a/html/inc/bossa_db.inc +++ b/html/inc/bossa_db.inc @@ -1,17 +1,23 @@ '); + $passwd = parse_config($config, ''); + $host = parse_config($config, ''); + $name = parse_config($config, ''); + if ($host == null) { + $host = "localhost"; + } $instance = new DbConn(); - $retval = $instance->init_conn( - "", "", - "", "" - ); + $retval = $instance->init_conn($user, $passwd, $host, $name); if (!$retval) return null; } return $instance; diff --git a/html/ops/bolt_setup_sample.php b/html/ops/bolt_setup_sample.php new file mode 100644 index 0000000000..08081108b3 --- /dev/null +++ b/html/ops/bolt_setup_sample.php @@ -0,0 +1,17 @@ +short_name = 'test_course'; +$c->name = 'A test course'; +$c->description = 'This course is a demonstration of Bolt'; +$c->doc_file = 'bolt_course_sample.php'; + +if ($c->insert()) { + echo "all done\n"; +} else { + echo "database error\n"; +} + +?> diff --git a/html/user/bolt.php b/html/user/bolt.php new file mode 100644 index 0000000000..d01c7c01c8 --- /dev/null +++ b/html/user/bolt.php @@ -0,0 +1,25 @@ +id, $course->id); + echo "$course->name id&action=start>start + "; + if ($e) { + echo "id>resume + "; + } + echo " +
$course->description + "; +} +page_tail(); + +?> diff --git a/html/user/bolt_course_sample.php b/html/user/bolt_course_sample.php new file mode 100644 index 0000000000..483d12176a --- /dev/null +++ b/html/user/bolt_course_sample.php @@ -0,0 +1,18 @@ + diff --git a/html/user/bolt_sched.php b/html/user/bolt_sched.php new file mode 100644 index 0000000000..cbf4749825 --- /dev/null +++ b/html/user/bolt_sched.php @@ -0,0 +1,79 @@ +doc_file); + +if ($view_id) { + $view = BoltView::lookup_id($view_id); + if ($view && $view->user_id == $user->id && !$view->end_time) { + $now = time(); + $view->update("end_time=$now"); + } +} + +$e = BoltEnrollment::lookup($user->id, $course_id); + +if ($e) { + $iter = new BoltIter($course_doc); + $iter->stack = json_decode($e->state); + if ($action == 'next') { + $item = $iter->next(); + $state = json_encode($iter->stack); + $e->update_aux("state='$state' where user_id=$user->id and course_id=$course_id"); + } else if ($action == 'start') { + $iter->stack = null; + $item = $iter->at(); + $state = json_encode($iter->stack); + $e->update_aux("state='$state' where user_id=$user->id and course_id=$course_id"); + } else { + $item = $iter->at(); + } +} else { + $iter = new BoltIter($course_doc); + $item = $iter->at(); + + $e = new BoltEnrollment($course); + $e->user_id = $user->id; + $e->course_id = $course_id; + $e->state = json_encode($iter->stack); + $e->insert(); +} + +if (!$item) { + page_head("Done with course"); + echo "All done!"; + page_tail(); + exit(); +} + +$view = new BoltView(); +$view->user_id = $user->id; +$view->course_id = $course_id; +$view->item_name = $item->name; +$view->insert(); + +require_once($item->filename); + +echo "

id>Next"; +?>