mirror of https://github.com/BOINC/boinc.git
svn path=/trunk/boinc/; revision=14319
This commit is contained in:
parent
2b3dec7557
commit
68ec6e6ce6
|
@ -11781,3 +11781,18 @@ Rom 28 Nov 2007
|
|||
win_build/installerv2/redist/Windows/x64/
|
||||
boinccas.dll
|
||||
boinccas95.dll
|
||||
|
||||
David 288 2007
|
||||
- Bolt development
|
||||
|
||||
db/
|
||||
bolt_schema.sql
|
||||
html/
|
||||
inc/
|
||||
bolt.inc
|
||||
bolt_db.inc
|
||||
ops/
|
||||
bolt_setup_sample.php
|
||||
user/
|
||||
bolt.php
|
||||
bolt_sched.php
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
create table bolt_user (
|
||||
user_id integer not null,
|
||||
birth_year integer not null,
|
||||
sex smallint not null,
|
||||
attrs text not null,
|
||||
primary key (user_id)
|
||||
);
|
||||
|
||||
create table bolt_course (
|
||||
id integer not null auto_increment,
|
||||
create_time integer not null,
|
||||
|
@ -12,6 +20,9 @@ create table bolt_enrollment (
|
|||
create_time integer not null,
|
||||
user_id integer not null,
|
||||
course_id integer not null,
|
||||
last_view integer not null,
|
||||
fraction_done double not null,
|
||||
mastery double not null,
|
||||
state text not null
|
||||
);
|
||||
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
$project_news = array(
|
||||
|
||||
array("November 28, 2007",
|
||||
"Live in Washington DC? Get together with other BOINC users via
|
||||
<a href=http://opensource.meetup.com/84/?gj=sj2>Meetup</a>
|
||||
(or <a href=http://opensource.meetup.com/>create a Meetup
|
||||
in your own city</a>)."
|
||||
),
|
||||
array("November 16, 2007",
|
||||
"<a href=http://boinc.gorlaeus.net/>Leiden Classical</a> allows students (and the public)
|
||||
to submit particle-system simulation jobs,
|
||||
|
|
|
@ -26,7 +26,9 @@ class BoltFrame {
|
|||
abstract class BoltUnit {
|
||||
public $name; // logical name.
|
||||
|
||||
abstract function walk($old_stack, &$new_stack, $next, &$item);
|
||||
abstract function walk(
|
||||
$old_stack, &$new_stack, $next, &$item, &$frac_done
|
||||
);
|
||||
// multi-purpose function for traversing a course.
|
||||
// if $old_stack is null
|
||||
// set up initial state for this unit.
|
||||
|
@ -40,6 +42,7 @@ abstract class BoltUnit {
|
|||
// 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
|
||||
// frac_done: Fraction done (of this unit and any subunits)
|
||||
abstract function is_item();
|
||||
}
|
||||
|
||||
|
@ -59,9 +62,9 @@ class BoltIter {
|
|||
|
||||
// get current item
|
||||
//
|
||||
function at() {
|
||||
function at(&$frac_done) {
|
||||
$new_stack = array();
|
||||
$this->top->walk($this->stack, $new_stack, false, $item);
|
||||
$this->top->walk($this->stack, $new_stack, false, $item, $frac_done);
|
||||
$this->stack = $new_stack;
|
||||
return $item;
|
||||
}
|
||||
|
@ -69,10 +72,10 @@ class BoltIter {
|
|||
// move to the next item (and return it)
|
||||
// return true if we're off the end
|
||||
//
|
||||
function next() {
|
||||
function next(&$frac_done) {
|
||||
$item = null;
|
||||
$new_stack = array();
|
||||
$this->top->walk($this->stack, $new_stack, true, $item);
|
||||
$this->top->walk($this->stack, $new_stack, true, $item, $frac_done);
|
||||
$this->stack = $new_stack;
|
||||
return $item;
|
||||
}
|
||||
|
@ -85,8 +88,9 @@ class BoltSeq extends BoltUnit {
|
|||
$this->units = $u;
|
||||
}
|
||||
|
||||
function walk($old_stack, &$new_stack, $next, &$item) {
|
||||
function walk($old_stack, &$new_stack, $next, &$item, &$frac_done) {
|
||||
//echo "call to walk() for $this->name: next: $next\n";
|
||||
$n = count($this->units);
|
||||
if ($old_stack) {
|
||||
//echo "old stack: \n";
|
||||
//var_dump($old_stack);
|
||||
|
@ -94,39 +98,52 @@ class BoltSeq extends BoltUnit {
|
|||
$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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
$child = $this->units[$i];
|
||||
if ($state->child_name != $child->name) {
|
||||
echo "bad name - restarting\n";
|
||||
$restart = true;
|
||||
// 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];
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$restart = true;
|
||||
}
|
||||
if ($restart) {
|
||||
$i = 0;
|
||||
}
|
||||
$frac_done = $i/$n;
|
||||
$child = $this->units[$i];
|
||||
$state->i = $i;
|
||||
$state->child_name = $child->name;
|
||||
|
@ -135,7 +152,8 @@ class BoltSeq extends BoltUnit {
|
|||
if ($child->is_item()) {
|
||||
$item = $child;
|
||||
} else {
|
||||
$child->walk(null, $new_stack, false, $item);
|
||||
$child->walk(null, $new_stack, false, $item, $f);
|
||||
$frac_done += $f*(1/$n);
|
||||
}
|
||||
}
|
||||
function is_item() {
|
||||
|
@ -158,7 +176,7 @@ class BoltItem extends BoltUnit {
|
|||
function is_item() {
|
||||
return true;
|
||||
}
|
||||
function walk($old_stack, &$new_stack, $next, &$item) {
|
||||
function walk($old_stack, &$new_stack, $next, &$item, &$frac_done) {
|
||||
echo "SHOULDN'T BE HERE\n";
|
||||
}
|
||||
}
|
||||
|
@ -182,4 +200,50 @@ function enum_course($course) {
|
|||
echo "course over\n";
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -4,9 +4,22 @@ require_once("../inc/db_conn.inc");
|
|||
require_once("../inc/util.inc");
|
||||
|
||||
class BoltDb extends DbConn {
|
||||
public static $instance;
|
||||
static $instance;
|
||||
|
||||
static function get() {
|
||||
if (web_stopped()) {
|
||||
if ($generating_xml) {
|
||||
xml_error(-183);
|
||||
} else {
|
||||
page_head("Page not available");
|
||||
echo "This page requires database access.
|
||||
Our database server is temporarily shut down for maintenance.
|
||||
Please try again later.
|
||||
";
|
||||
page_tail();
|
||||
}
|
||||
exit();
|
||||
}
|
||||
if (!isset($instance)) {
|
||||
$config = get_config();
|
||||
$user = parse_config($config, '<bolt_db_user>');
|
||||
|
@ -24,22 +37,47 @@ class BoltDb extends DbConn {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
class BoltUser {
|
||||
static $cache;
|
||||
static function lookup_userid($id) {
|
||||
$db = BoincDb::get();
|
||||
return $db->lookup('bolt_user', 'BoltUser', "user_id=$id");
|
||||
}
|
||||
static function insert($clause) {
|
||||
$db = BoltDb::get();
|
||||
return $db->insert('bolt_user', $clause);
|
||||
}
|
||||
static function lookup(&$user) {
|
||||
if (!$user) return;
|
||||
if (isset($user->bolt)) return;
|
||||
if (isset(self::$cache[$user->id])) {
|
||||
$bolt = self::$cache[$user->id];
|
||||
} else {
|
||||
$bolt = self::lookup_userid($user->id);
|
||||
if (!$bolt) {
|
||||
self::insert("(user_id) values ($user->id)");
|
||||
$bolt = self::lookup_userid($user->id);
|
||||
}
|
||||
self::$cache[$user->id] = $bolt;
|
||||
}
|
||||
$user->bolt = $bolt;
|
||||
}
|
||||
function update($clause) {
|
||||
$db = BoltDb::get();
|
||||
$clause = "$clause where user_id=$this->user_id";
|
||||
return $db->update_aux('bolt_user', $clause);
|
||||
}
|
||||
}
|
||||
|
||||
class BoltCourse {
|
||||
static function insert($clause) {
|
||||
$db = BoltDb::get();
|
||||
return $db->insert('bolt_course', $clause);
|
||||
}
|
||||
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');
|
||||
|
@ -47,31 +85,26 @@ class BoltCourse {
|
|||
}
|
||||
|
||||
class BoltEnrollment {
|
||||
function insert() {
|
||||
function insert($clause) {
|
||||
$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);
|
||||
return $db->insert('bolt_enrollment', $clause);
|
||||
}
|
||||
function lookup($userid, $courseid) {
|
||||
function lookup($user_id, $course_id) {
|
||||
$db = BoltDb::get();
|
||||
return $db->lookup('bolt_enrollment', 'BoltEnrollment', "user_id=$userid and course_id=$courseid");
|
||||
return $db->lookup('bolt_enrollment', 'BoltEnrollment', "user_id=$user_id and course_id=$course_id");
|
||||
}
|
||||
function update_aux($clause) {
|
||||
function update($clause) {
|
||||
$db = BoltDb::get();
|
||||
$db->update_aux('bolt_enrollment', $clause);
|
||||
$db->update_aux('bolt_enrollment', "$clause where user_id=$this->user_id and course_id=$this->course_id");
|
||||
}
|
||||
}
|
||||
|
||||
class BoltView {
|
||||
function insert() {
|
||||
static function insert($clause) {
|
||||
$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;
|
||||
$ret = $db->insert('bolt_view', $clause);
|
||||
if (!$ret) return null;
|
||||
return $db->insert_id();
|
||||
}
|
||||
static function lookup_id($id) {
|
||||
$db = BoltDb::get();
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
require_once("../inc/bolt_db.inc");
|
||||
|
||||
$c = new BoltCourse();
|
||||
$c->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';
|
||||
$short_name = 'test_course';
|
||||
$name = 'Test course';
|
||||
$description = 'This course is a demonstration of Bolt';
|
||||
$doc_file = 'bolt_course_sample.php';
|
||||
$now = time();
|
||||
|
||||
if ($c->insert()) {
|
||||
if (BoltCourse::insert("(create_time, short_name, name, description, doc_file) values ($now, '$short_name', '$name', '$description', '$doc_file')")) {
|
||||
echo "all done\n";
|
||||
} else {
|
||||
echo "database error\n";
|
||||
|
|
|
@ -8,18 +8,27 @@ page_head("Courses");
|
|||
$user = get_logged_in_user(true);
|
||||
|
||||
$courses = BoltCourse::enum();
|
||||
start_table();
|
||||
table_header(
|
||||
"Course<br><span class=note>Click to start, resume, or review</span>
|
||||
", "Status"
|
||||
);
|
||||
foreach ($courses as $course) {
|
||||
$e = BoltEnrollment::lookup($user->id, $course->id);
|
||||
echo "$course->name <a href=bolt_sched.php?course_id=$course->id&action=start>start</a>
|
||||
";
|
||||
$e = $user?BoltEnrollment::lookup($user->id, $course->id):null;
|
||||
$start = date_str($e->create_time);
|
||||
$ago = time_diff(time() - $e->last_view);
|
||||
if ($e) {
|
||||
echo "<a href=bolt_sched.php?course_id=$course->id>resume</a>
|
||||
";
|
||||
$pct = number_format($e->fraction_done*100, 0);
|
||||
$status = "Started $start; last visit $ago ago; $pct% done";
|
||||
} else {
|
||||
$status = "Not started";
|
||||
}
|
||||
echo "
|
||||
<dd>$course->description
|
||||
";
|
||||
row2("<a href=bolt_sched.php?course_id=$course->id&action=start>$course->name</a>
|
||||
<br><span class=note>$course->description</span>",
|
||||
$status
|
||||
);
|
||||
}
|
||||
end_table();
|
||||
page_tail();
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
// Bolt scheduler. POST args:
|
||||
// Bolt scheduler. GET args:
|
||||
// course_id: course ID
|
||||
// action:
|
||||
// 'show' or none: show current (or first) item
|
||||
// 'start' or none: show current (or first) item,
|
||||
// and prompt for user info if any missing
|
||||
// 'next': go to next lesson
|
||||
// answers:
|
||||
// JSON represenation of exercise answers
|
||||
|
@ -13,6 +14,7 @@ require_once("../inc/bolt_db.inc");
|
|||
require_once("../inc/util.inc");
|
||||
|
||||
$user = get_logged_in_user();
|
||||
BoltUser::lookup($user);
|
||||
$course_id = get_int('course_id');
|
||||
$view_id = get_int('view_id', true);
|
||||
$action = get_str('action', true);
|
||||
|
@ -22,6 +24,18 @@ if (!$course) {
|
|||
error_page("no such course");
|
||||
}
|
||||
|
||||
if ($action == 'update_info') {
|
||||
$sex = get_int('sex');
|
||||
$birth_year = get_int('birth_year');
|
||||
$user->bolt->update("sex=$sex, birth_year=$birth_year");
|
||||
$action = "";
|
||||
}
|
||||
|
||||
if ($action == 'start' && info_incomplete($user)) {
|
||||
request_info($user, $course);
|
||||
exit();
|
||||
}
|
||||
|
||||
$course_doc = require_once($course->doc_file);
|
||||
|
||||
if ($view_id) {
|
||||
|
@ -32,20 +46,20 @@ if ($view_id) {
|
|||
}
|
||||
}
|
||||
|
||||
$frac_done = 0;
|
||||
$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();
|
||||
$item = $iter->next($frac_done);
|
||||
$state = json_encode($iter->stack);
|
||||
$e->update_aux("state='$state' where user_id=$user->id and course_id=$course_id");
|
||||
$e->update("state='$state'");
|
||||
} else if ($action == 'start') {
|
||||
$iter->stack = null;
|
||||
$item = $iter->at();
|
||||
$item = $iter->at($frac_done);
|
||||
$state = json_encode($iter->stack);
|
||||
$e->update_aux("state='$state' where user_id=$user->id and course_id=$course_id");
|
||||
$e->update("state='$state'");
|
||||
} else {
|
||||
$item = $iter->at();
|
||||
}
|
||||
|
@ -53,11 +67,10 @@ if ($e) {
|
|||
$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();
|
||||
$now = time();
|
||||
$state = json_encode($iter->stack);
|
||||
BoltEnrollment::insert("(create_time, user_id, course_id, state) values ($now, $user->id, $course_id, '$state')");
|
||||
$e = BoltEnrollment::lookup($user->id, $course_id);
|
||||
}
|
||||
|
||||
if (!$item) {
|
||||
|
@ -67,13 +80,13 @@ if (!$item) {
|
|||
exit();
|
||||
}
|
||||
|
||||
$view = new BoltView();
|
||||
$view->user_id = $user->id;
|
||||
$view->course_id = $course_id;
|
||||
$view->item_name = $item->name;
|
||||
$view->insert();
|
||||
$now = time();
|
||||
$e->update("last_view=$now, fraction_done=$frac_done");
|
||||
$view_id = BoltView::insert("(user_id, course_id, item_name, start_time) values ($user->id, $course_id, '$item->name', $now)");
|
||||
|
||||
require_once($item->filename);
|
||||
|
||||
echo "<p><a href=bolt_sched.php?course_id=$course_id&action=next&view_id=$view->id>Next</a>";
|
||||
echo "<p><a href=bolt_sched.php?course_id=$course_id&action=next&view_id=$view_id>Next</a>";
|
||||
|
||||
echo "<p>Fraction done: $frac_done";
|
||||
?>
|
||||
|
|
Loading…
Reference in New Issue