remove Bossa and Bolt files.

These aren't part of BOINC.  I moved them to new repos.
This commit is contained in:
David Anderson 2023-04-16 12:18:25 -07:00
parent 10769728db
commit 0f4960c6ba
33 changed files with 0 additions and 5255 deletions

View File

@ -1,11 +0,0 @@
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);
alter table bolt_refresh
add unique br_u(user_id, course_id, name);

View File

@ -1,154 +0,0 @@
create table bolt_user (
user_id integer not null,
birth_year integer not null,
sex tinyint not null,
flags integer not null,
attrs text not null,
-- project-defined. Use serialized PHP object
primary key (user_id)
);
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,
hidden tinyint not null,
bossa_app_id integer not null,
-- on completion, go to this Bossa app
primary key (id)
);
create table bolt_enrollment (
create_time integer not null,
user_id integer not null,
course_id integer not null,
last_view_id integer not null,
-- ID of last study phase view
mastery double not null
);
-- Represents a view of an item;
-- created when we show the item,
-- and finalized when the user clicks on something to leave the page
-- A special view is used to represent the end of a course;
-- its mode is BOLT_MODE_FINISHED.
--
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,
-- name of the item
state text not null,
-- course state
mode integer not null,
-- distinguishes exercise show/answer
phase integer not null,
-- distinguishes study/review/refresh
action integer not null,
-- what the user clicked to leave page
start_time integer not null,
end_time integer not null,
prev_view_id integer not null,
-- for exercise answer views;
-- refers to the original exercise view
fraction_done double not null,
result_id integer not null,
-- if this was an exercise show, link to result record
refresh_id integer not null,
-- if unit was flagged for review, link to review record
-- ?? remove?
primary key (id)
);
-- represents the result of a single exercise
--
create table bolt_result (
id integer not null auto_increment,
create_time integer not null,
user_id integer not null,
course_id integer not null,
view_id integer not null,
-- the display of exercise
item_name varchar(255) not null,
score double not null,
response text not null,
-- the query string containing user's responses
primary key(id)
);
-- represents the result of a completed exercise set,
-- where "completed" means the last exercise was scored.
-- In theory this could be reconstructed from the individual exercise results,
-- but this table makes it easier for analytics
--
create table bolt_xset_result (
id integer not null auto_increment,
create_time integer not null,
user_id integer not null,
course_id integer not null,
start_time integer not null,
end_time integer not null,
name varchar(255) not null,
-- logical name of exercise set unit
score double not null,
-- weighted average score
view_id integer not null,
-- the view of the answer page of last exercise in set
primary key(id)
);
-- represents the completion of a select structure
--
create table bolt_select_finished (
id integer not null auto_increment,
user_id integer not null,
course_id integer not null,
end_time integer not null,
name varchar(255) not null,
-- logical name of the select unit
selected_unit varchar(255) not null,
-- name of selected subunit
view_id integer not null,
-- the view of the last item
primary key(id)
);
-- represents a refresh/repeat of an exercise set,
-- either pending (not due yet),
-- due but not started, or in progress.
--
create table bolt_refresh (
id integer not null auto_increment,
create_time integer not null,
user_id integer not null,
course_id integer not null,
name varchar(255) not null,
-- logical name of result set unit
last_view_id integer not null,
-- if refresh is in progress, the last view
xset_result_id integer not null,
-- most recent result for this exercise set
due_time integer not null,
-- when refresh will be due
count integer not null,
-- index into intervals array
primary key (id)
);
create table bolt_question (
id integer not null auto_increment,
create_time integer not null,
user_id integer not null,
course_id integer not null,
name varchar(255) not null,
-- logical name of item where question was asked
mode integer not null,
-- distinguishes exercise show/answer
question text not null,
state integer not null,
-- whether question has been handled
primary key (id)
);

View File

@ -1,10 +0,0 @@
alter table bossa_app
add unique(name),
add unique(short_name);
alter table bossa_job
add index bj_conf_needed(app_id, calibration, priority_0);
alter table bossa_job_inst
add index bji_job(job_id),
add index bji_user(user_id);

View File

@ -1,63 +0,0 @@
create table bossa_app (
id integer not null auto_increment,
create_time integer not null,
name varchar(255) not null,
short_name varchar(255) not null,
description varchar(255) not null,
long_jobs tinyint not null,
hidden tinyint not null,
bolt_course_id integer not null,
time_estimate integer not null,
time_limit integer not null,
calibration_frac double not null,
info text,
-- app-specific info, JSON
primary key(id)
) engine = InnoDB;
create table bossa_job (
id integer not null auto_increment,
create_time integer not null,
app_id integer not null,
batch_id integer not null,
state integer not null,
info text,
calibration tinyint not null,
priority_0 double not null,
-- add more as needed
-- for calibration jobs, init to random and decrement on each view
primary key(id)
) engine=InnoDB;
create table bossa_job_inst (
id integer not null auto_increment,
create_time integer not null,
app_id integer not null,
job_id integer not null,
user_id integer not null,
batch_id integer not null,
finish_time integer not null,
timeout integer not null,
calibration tinyint not null,
info text,
primary key(id)
) engine=InnoDB;
create table bossa_user (
user_id integer not null,
category integer not null,
flags integer not null,
-- debug, show_all
info text,
-- Project-dependent info about users ability and performance.
primary key(user_id)
) engine = InnoDB;
create table bossa_batch (
id integer not null auto_increment,
create_time integer not null,
name varchar(255) not null,
app_id integer not null,
calibration tinyint not null,
primary key(id)
) engine = InnoDB;

View File

@ -1,381 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Bolt course document API
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
abstract class BoltUnit {
public $name;
// Logical name. Changing this makes it a different unit.
// For items, this is the filename with query string;
// for structures, it must be specified with name()
public $title;
// Optional; used when showing course history outline.
public $is_item;
public $attrs; // course-defined
abstract function walk(&$iter, $incr, &$frac_done);
// multi-purpose function for traversing a course.
// Create entry in $iter->state if not there.
// Recurse to first child.
// If first child is an item, set $iter->item
// If incr is set
// 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)
}
// base class for exercise and lesson
//
class BoltItem extends BoltUnit {
public $filename;
public $query_string;
function __construct($filename, $title, $attrs) {
$p = strpos($filename, '?');
if ($p === false) {
$this->filename = $filename;
$this->query_string = null;
} else {
$this->filename = substr($filename, 0, $p);
$this->query_string = substr($filename, $p+1);
}
$this->name = $filename;
$this->title = $title;
$this->is_item = true;
$this->attrs = $attrs;
}
function begin() {
return array(new BoltFrame($this));
}
function walk(&$iter, $incr, &$frac_done) {
echo "SHOULDN'T BE HERE\n";
}
}
class BoltLesson extends BoltItem {
function is_exercise() {
return false;
}
}
class BoltExercise extends BoltItem {
public $callback;
// called as func($student, $score, $query_string) after scoring
public $weight;
public $has_answer_page;
function __construct(
$filename, $title, $attrs, $callback, $weight, $has_answer_page
) {
parent::__construct($filename, $title, $attrs);
$this->callback = $callback;
$this->weight = $weight;
$this->has_answer_page = $has_answer_page;
}
function is_exercise() {
return true;
}
}
// Base class for control structures (all units other than items).
// The state of a control structure has two parts:
// 1) a transient PHP object
// 2) a persistent "state record" (stored in JSON in the DB)
//
// The PHP object has the following properties:
// - a set of units
// - ordered: a flag for whether the set has been ordered yet
// - order($state_rec): a function for ordering this set,
// defined in the derived class
// (i.e., random, student-specific, or identity)
// This orders the set, sets "ordered", and adds info to the state rec
// saying how the ordering was done (e.g. RNG seed)
// - a number "ntoshow" for how many units to show
//
// The state record has the following items:
// - index: index into the unit array
// - nshown: for how many units completed so far
// - child_name: name of current child, or null
//
class BoltSet extends BoltUnit {
public $units;
function __construct($name, $units, $ntoshow, $attrs) {
$this->name = $name;
$this->is_item = false;
$this->units = $units;
$this->ntoshow = $ntoshow;
$this->ordered = false;
$this->attrs = $attrs;
}
// restart this unit - set its state record to an initial state
//
function restart(&$iter) {
$state_rec = $iter->state[$this->name];
if (!$state_rec) $state_rec = $this->init();
$state_rec['nshown'] = 0;
$state_rec['child_name'] = null;
$iter->state[$this->name] = $state_rec;
}
// initialize this unit (once per course)
//
function init(&$iter) {
$state_rec = array();
$state_rec['index'] = 0;
$iter->state[$this->name] = $state_rec;
return $state_rec;
}
function finished(&$iter) {
$this->restart($iter);
}
function walk(&$iter, $incr, &$frac_done) {
$n = count($this->units);
if (array_key_exists($this->name, $iter->state)) {
$state_rec = $iter->state[$this->name];
$child_name = $state_rec['child_name'];
$nshown = $state_rec['nshown'];
if (!$this->ordered) {
$this->order($iter);
}
// look up unit by name
//
$child = null;
for ($i=0; $i<$n; $i++) {
$c = $this->units[$i];
if ($c->name == $child_name) {
$child = $c;
break;
}
}
// if not there, look up by index
//
if (!$child) {
$i = $state_rec['index'];
if ($i >= $n) {
// and if index is too big, use last unit
//
$i = $n-1;
}
$child = $this->units[$i];
}
// at this point, $child is the current unit, and $i is its index
//
if ($incr) {
if ($child->is_item) {
$my_inc = true;
} else {
$my_inc = $child->walk($iter, $incr, $frac_done);
}
if ($my_inc) {
$nshown++;
if ($nshown == $this->ntoshow) {
$frac_done = 1;
$this->finished($iter);
return true;
} else {
$i = ($i+1)%$n;
}
}
}
} else {
// here if no state record; initialize
//
$i = 0;
$nshown = 0;
$this->init($iter);
$this->order($iter);
}
// at this point, $i is index of current child, $nshown is valid,
// and this unit has a record in the state array
//
$child = $this->units[$i];
$frac_done = $nshown/$n;
$state_rec = $iter->state[$this->name];
$state_rec['index'] = $i;
$state_rec['nshown'] = $nshown;
$state_rec['child_name'] = $child->name;
$iter->state[$this->name] = $state_rec;
if ($child->is_item) {
$iter->item = $child;
} else {
$child->walk($iter, false, $f);
$frac_done += $f*(1/$n);
}
return false;
}
// return the name of our child, if we exist in the state
//
function get_child($state) {
if (array_key_exists($this->name, $state)) {
$state_rec = $state[$this->name];
$child_name = $state_rec['child_name'];
foreach($this->units as $c) {
if ($c->name == $child_name) {
return $c;
}
}
}
return null;
}
}
function name($n) {
return array('name', $n);
}
function title($n) {
return array('title', $n);
}
function number($n) {
return array('number', $n);
}
function filename($n) {
return array('filename', $n);
}
function has_answer_page($n) {
return array('has_answer_page', $n);
}
function attrs($n) {
return array('attrs', $n);
}
function callback($n) {
return array('callback', $n);
}
function lesson() {
$filename = "";
$title = "";
$attrs = null;
$args = func_get_args();
foreach ($args as $arg) {
if (is_array($arg)) {
switch ($arg[0]) {
case 'title': $title = $arg[1]; break;
case 'filename': $filename = $arg[1]; break;
case 'attrs': $attrs = $arg[1]; break;
default: echo "Unrecognized lesson parameter: ", $arg[0], "\n"; break;
}
} else {
echo "unprocessed arg of class ".get_class($arg);
}
}
if (!$title) {
$title = $filename;
}
if (!$filename) {
error_page("Missing filename in lesson");
}
return new BoltLesson($filename, $title, $attrs);
}
function exercise() {
$filename = "";
$title = "";
$attrs = null;
$weight = 1;
$has_answer_page = true;
$args = func_get_args();
$callback = null;
foreach ($args as $arg) {
if (is_array($arg)) {
switch ($arg[0]) {
case 'title': $title = $arg[1]; break;
case 'filename': $filename = $arg[1]; break;
case 'attrs': $attrs = $arg[1]; break;
case 'callback': $callback = $arg[1]; break;
case 'weight': $weight = $arg[1]; break;
case 'has_answer_page': $has_answer_page = $arg[1]; break;
default: echo "Unrecognized exercise parameter: ", $arg[0], "\n"; break;
}
}
}
if (!$title) {
$title = $filename;
}
if (!$filename) {
error_page("Missing filename in lesson");
}
return new BoltExercise(
$filename, $title, $attrs, $callback, $weight, $has_answer_page
);
}
function item_attrs() {
global $item;
return $item->attrs;
}
function student_sex() {
global $user;
return $user->bolt->sex;
}
function student_age() {
global $user;
if (!$user->bolt->birth_year) return -1;
$date = getdate();
$this_year = $date["year"];
return $this_year - $user->bolt->birth_year;
}
function student_country() {
global $user;
return $user->country;
}
function student_name() {
global $user;
return $user->name;
}
function student_attrs() {
global $user;
return unserialize($user->bolt->attrs);
}
function set_student_attrs($attrs) {
global $user;
$attrs = serialize($attrs);
$user->bolt->update("attrs='$attrs'");
}
require_once('../inc/bolt_seq.inc');
require_once('../inc/bolt_rnd.inc');
require_once('../inc/bolt_xset.inc');
require_once('../inc/bolt_select.inc');
?>

View File

@ -1,168 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// represents a categorization of students
//
abstract class Categorization {
abstract function name();
// returns descriptive name
abstract function categories();
// returns list of categories
abstract function categorize($user);
// returns a student's category
}
class CatSex extends Categorization {
function name() {
return "Sex";
}
function categories() {
return array ("Male", "Female", "Unknown");
}
function categorize($user) {
switch ($user->bolt->sex) {
case 1: return "Male";
case 2: return "Female";
default: return "Unknown";
}
}
}
$x = localtime(time(), true);
$this_year = 1900 + $x['tm_year'];
class CatAge20 extends Categorization {
function name() {
return "Age (20-year groups)";
}
function categories() {
return array("0-19", "20-39", "40-59", "60-79", "80+", "Unknown");
}
function categorize($user) {
if (!$user->bolt->birth_year) return "Unknown";
global $this_year;
$n = $this_year - $user->bolt->birth_year;
if ($n < 20) return "0-19";
if ($n < 40) return "20-39";
if ($n < 60) return "40-59";
if ($n < 80) return "60-79";
return "80+";
}
}
$categorizations = array(new CatSex(), new CatAge20());
function lookup_categorization($name) {
global $categorizations;
foreach ($categorizations as $c) {
if ($c->name() == $name) return $c;
}
return null;
}
function filter_form($sel_name, $sel_cat) {
global $categorizations;
$checked = (!$sel_name || $sel_name == "none")?"checked":"";
echo "
Filter by:
<ul>
<li><input type=radio name=filter value=none $checked> None
";
foreach ($categorizations as $c) {
$name = $c->name();
$cats = $c->categories();
echo "
<li> $name
<ul>
";
foreach ($cats as $x) {
$checked = ($sel_name == $name && $sel_cat == $x) ? "checked":"";
echo "
<li> <input type=radio name=filter value=\"$name:$x\" $checked> $x
";
}
echo "</ul>";
}
echo "</ul>";
}
function breakdown_form($sel_name) {
global $categorizations;
$checked = (!$sel_name || $sel_name == "none")?"checked":"";
echo "
Break down by:
<ul>
<li><input type=radio name=breakdown value=none $checked> None
";
foreach ($categorizations as $c) {
$name = $c->name();
$checked = ($sel_name == $name)?"checked":"";
echo "
<li> <input type=radio name=breakdown value=\"$name\" $checked> $name
";
}
echo "</ul>";
}
// return filter and breakdown info for URLs
//
function filter_url() {
global $filter, $filter_cat, $breakdown, $breakdown_cat;
$x = "";
if ($filter && $filter_cat) {
$x .= "&filter=".$filter->name.":$filter_cat";
}
if ($breakdown && $breakdown_cat) {
$x .= "&breakdown=".$breakdown->name.":$breakdown_cat";
}
return $x;
}
// get filter and breakdown from form vars
//
function get_filters_from_form() {
global $breakdown, $breakdown_cat, $filter, $filter_cat;
$breakdown_cat = null;
$breakdown_info = get_str('breakdown', true);
if ($breakdown_info && $breakdown_info != 'none') {
$arr = explode(":", $breakdown_info);
$breakdown_name = $arr[0];
if (count($arr) == 2) {
$breakdown_cat = $arr[1];
}
$breakdown = lookup_categorization($breakdown_name);
if (!$breakdown) error_page("unknown breakdown $breakdown_name");
} else {
$breakdown = null;
}
$filter_info = get_str('filter', true);
if ($filter_info && $filter_info != "none") {
$arr = explode(":", $filter_info);
$filter_name = $arr[0];
$filter_cat = $arr[1];
$filter = lookup_categorization($filter_name);
if (!$filter) error_page("unknown filter $filter_name");
} else {
$filter_cat = "";
$filter = null;
}
}
?>

View File

@ -1,325 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/db_conn.inc");
require_once("../inc/util.inc");
define('BOLT_PHASE_STUDY', 1);
// sequential progress through course
define('BOLT_PHASE_REVIEW', 2);
// review and repeat of an exercise set
define('BOLT_PHASE_REFRESH', 3);
// timed repeat of exercise set, and possibly review and repeat
define('BOLT_MODE_LESSON', 1);
define('BOLT_MODE_SHOW', 2);
define('BOLT_MODE_SCORE', 3);
define('BOLT_MODE_ANSWER', 4);
define('BOLT_MODE_FINISHED', 5);
define('BOLT_ACTION_NONE', 0);
define('BOLT_ACTION_NEXT', 1);
define('BOLT_ACTION_PREV', 2);
define('BOLT_ACTION_SUBMIT', 3);
define('BOLT_ACTION_QUESTION', 4);
define('BOLT_ACTION_COURSE_HOME', 5);
define('BOLT_ACTION_REVIEW', 6);
define('BOLT_ACTION_REPEAT', 7);
define('BOLT_COURSE_NOT_STARTED', 1);
define('BOLT_COURSE_STARTED', 2);
define('BOLT_COURSE_FINISHED', 3);
// bits in bolt_user.flags
define('BOLT_FLAGS_DEBUG', 1); // print debugging info in output pages
define('BOLT_FLAGS_SHOW_ALL', 2); // show hidden courses
class BoltDb extends DbConn {
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();
$name = parse_config($config, '<bolt_db_name>');
if (!$name) {
$name = parse_config($config, '<db_name>');
$user = parse_config($config, '<db_user>');
$passwd = parse_config($config, '<db_passwd>');
$host = parse_config($config, '<db_host>');
} else {
$user = parse_config($config, '<bolt_db_user>');
$passwd = parse_config($config, '<bolt_db_passwd>');
$host = parse_config($config, '<bolt_db_host>');
}
if ($host == null) {
$host = "localhost";
}
$instance = new DbConn();
$retval = $instance->init_conn($user, $passwd, $host, $name, true);
if (!$retval) $instance = null;
}
if (!$instance) {
error_page("no DB conn");
}
return $instance;
}
static function escape_string($string) {
$db = self::get();
return $db->base_escape_string($string);
}
}
class BoltUser {
static $cache;
static function lookup_userid($id) {
$db = BoltDb::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();
$ret = $db->insert('bolt_course', $clause);
if (!$ret) return $ret;
return $db->insert_id();
}
static function lookup_id($id) {
$db = BoltDb::get();
return $db->lookup_id($id, 'bolt_course', 'BoltCourse');
}
static function lookup_name($name) {
$db = BoltDb::get();
$name = BoincDb::escape_string($name);
return $db->lookup('bolt_course', 'BoltCourse', "short_name='$name'");
}
static function enum() {
$db = BoltDb::get();
return $db->enum('bolt_course', 'BoltCourse');
}
function update($clause) {
$db = BoltDb::get();
return $db->update($this, 'bolt_course', $clause);
}
function doc_file() {
$sn = $this->short_name;
return "../inc/$sn.inc";
}
}
class BoltEnrollment {
static function insert($clause) {
$db = BoltDb::get();
return $db->insert('bolt_enrollment', $clause);
}
static function lookup($user_id, $course_id) {
$db = BoltDb::get();
return $db->lookup('bolt_enrollment', 'BoltEnrollment', "user_id=$user_id and course_id=$course_id");
}
function update($clause) {
$db = BoltDb::get();
$db->update_aux('bolt_enrollment', "$clause where user_id=$this->user_id and course_id=$this->course_id");
}
static function delete($user_id, $course_id) {
$db = BoltDb::get();
$db->delete_aux('bolt_enrollment', "user_id=$user_id and course_id=$course_id");
}
static function delete_aux($clause) {
$db = BoltDb::get();
$db->delete_aux('bolt_enrollment', $clause);
}
}
class BoltView {
static function insert($clause) {
$db = BoltDb::get();
$ret = $db->insert('bolt_view', $clause);
if (!$ret) return null;
return $db->insert_id();
}
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);
}
static function enum($clause) {
$db = BoltDb::get();
return $db->enum('bolt_view', 'BoltView', $clause);
}
static function delete_aux($clause) {
$db = BoltDb::get();
$db->delete_aux('bolt_view', $clause);
}
}
class BoltResult {
static function insert($clause) {
$db = BoltDb::get();
$ret = $db->insert('bolt_result', $clause);
if (!$ret) return null;
return $db->insert_id();
}
static function lookup_id($id) {
$db = BoltDb::get();
return $db->lookup_id($id, 'bolt_result', 'BoltResult');
}
static function enum($clause) {
$db = BoltDb::get();
return $db->enum('bolt_result', 'BoltResult', $clause);
}
static function delete_aux($clause) {
$db = BoltDb::get();
$db->delete_aux('bolt_result', $clause);
}
}
class BoltXsetResult {
static function lookup_id($id) {
$db = BoltDb::get();
return $db->lookup_id($id, 'bolt_xset_result', 'BoltXsetResult');
}
static function insert($clause) {
$db = BoltDb::get();
$ret = $db->insert('bolt_xset_result', $clause);
if (!$ret) return null;
return $db->insert_id();
}
static function enum($clause) {
$db = BoltDb::get();
return $db->enum('bolt_xset_result', 'BoltXsetResult', $clause);
}
static function delete_aux($clause) {
$db = BoltDb::get();
$db->delete_aux('bolt_xset_result', $clause);
}
}
class BoltRefreshRec {
static function lookup_id($id) {
$db = BoltDb::get();
return $db->lookup_id($id, 'bolt_refresh', 'BoltRefreshRec');
}
function lookup($clause) {
$db = BoltDb::get();
return $db->lookup('bolt_refresh', 'BoltRefreshRec', $clause);
}
static function replace($clause) {
$db = BoltDb::get();
return $db->replace('bolt_refresh', $clause);
}
static function insert($clause) {
$db = BoltDb::get();
$ret = $db->insert('bolt_refresh', $clause);
if (!$ret) return null;
return $db->insert_id();
}
static function enum($clause) {
$db = BoltDb::get();
return $db->enum('bolt_refresh', 'BoltRefreshRec', $clause);
}
function update($clause) {
$db = BoltDb::get();
$db->update($this, 'bolt_refresh', $clause);
}
static function delete_aux($clause) {
$db = BoltDb::get();
$db->delete_aux('bolt_refresh', $clause);
}
}
class BoltSelectFinished {
static function insert($clause) {
$db = BoltDb::get();
return $db->insert('bolt_select_finished', $clause);
}
static function enum($clause) {
$db = BoltDb::get();
return $db->enum('bolt_select_finished', 'BoltSelectFinished', $clause);
}
static function delete_aux($clause) {
$db = BoltDb::get();
$db->delete_aux('bolt_select_finished', $clause);
}
}
class BoltQuestion {
static function insert($clause) {
$db = BoltDb::get();
return $db->insert('bolt_question', $clause);
}
static function enum($clause) {
$db = BoltDb::get();
return $db->enum('bolt_question', 'BoltQuestion', $clause);
}
static function delete_aux($clause) {
$db = BoltDb::get();
$db->delete_aux('bolt_question', $clause);
}
}
// TODO: move this somewhere else, and think about whether it's correct
//
function bolt_course_status($course_id, $user_id) {
$e = BoltEnrollment::lookup($user_id, $course_id);
if (!$e) return BOLT_COURSE_NOT_STARTED;
$view = BoltView::lookup_id($e->last_view_id);
if ($view->fraction_done == 1) return BOLT_COURSE_FINISHED;
return BOLT_COURSE_STARTED;
}
?>

View File

@ -1,347 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Bolt exercise API
// The following is a global var accessed by exercise functions.
//
$bolt_ex = null;
$bolt_ex->mode = 0; // input: SHOW/SCORE/ANSWER
$bolt_ex->index = 0; // input: sequence of this exercise in file
$bolt_ex->score = 0; // input/output: cumulative score (if mode = SCORE)
$bolt_ex->weight = 0; // input/output: cumulative weight
$bolt_ex->query_string = ""; // user's response (if SCORE or ANSWER)
function weight($w) {
return array('weight', $w);
}
function exclusive_choice() {
global $bolt_ex;
$weight = 1;
$choices = array();
$args = func_get_args();
foreach ($args as $arg) {
if (is_string($arg)) {
$choices[] = $arg;
} else if (is_array($arg)) {
switch ($arg[0]) {
case 'weight': $weight = $arg[1]; break;
default: echo "bad arg to exclusive_choice()";
}
} else {
echo "bad arg to exclusive_choice()";
}
}
parse_str($bolt_ex->query_string);
switch ($bolt_ex->mode) {
case BOLT_MODE_SHOW:
shuffle($choices);
$i = 0;
start_table();
foreach ($choices as $choice) {
row2($choice, "<input name=q_$bolt_ex->index type=radio value=$i>");
$i++;
}
end_table();
break;
case BOLT_MODE_SCORE:
$right_ans = $choices[0];
shuffle($choices);
$key = "q_$bolt_ex->index";
if (isset($$key)) {
$response = $$key;
if ($choices[$response] == $right_ans) {
$bolt_ex->score += 1;
}
}
$bolt_ex->weight += $weight;
break;
case BOLT_MODE_ANSWER:
$right_ans = $choices[0];
shuffle($choices);
$key = "q_$bolt_ex->index";
if (isset($$key)) {
$response = $$key;
} else {
$response = -1;
}
$i = 0;
start_table();
foreach ($choices as $choice) {
$x = "<td><br></td>";
if ($response == $i) {
if ($choice == $right_ans) {
$x = "<td bgcolor=#88ff88>Right</a>";
} else {
$x = "<td bgcolor=#ff8888>You chose this answer</a>";
}
} else {
if ($choice == $right_ans) {
$x = "<td>Right answer</td>";
}
}
echo "<tr><td width=50% class=fieldname>$choice $x </tr>";
$i++;
}
end_table();
break;
}
$bolt_ex->index++;
}
function inclusive_choice() {
global $bolt_ex;
$weight = 1;
$choices = array();
$args = func_get_args();
foreach ($args as $arg) {
if (is_array($arg)) {
$choices[] = $arg;
} else if (is_object($arg)) {
if (get_class($arg) == 'BoltWeight') {
$weight = $arg->weight;
} else {
echo "bad arg to inclusive_choice()";
}
} else {
echo "bad arg to inclusive_choice()";
}
}
parse_str($bolt_ex->query_string);
switch ($bolt_ex->mode) {
case BOLT_MODE_SHOW:
shuffle($choices);
$i = 0;
start_table();
foreach ($choices as $choice) {
$c = $choice[0];
row2("<input name=q_".$bolt_ex->index."_$i type=checkbox>", $c);
$i++;
}
end_table();
break;
case BOLT_MODE_SCORE:
$i = 0;
$n = count($choices);
$score = 0;
shuffle($choices);
foreach ($choices as $choice) {
$key = "q_".$bolt_ex->index."_$i";
$response = isset($$key);
$r = $choice[1];
$correct = ($r && $response) || (!$r && !$response);
if ($correct) $score += 1./$n;
$i++;
}
$bolt_ex->score += $score;
$bolt_ex->weight += $weight;
break;
case BOLT_MODE_ANSWER:
$i = 0;
$n = count($choices);
shuffle($choices);
start_table();
table_header("Choice", "Correct?", "Your answer");
foreach ($choices as $choice) {
$c = $choice[0];
$key = "q_".$bolt_ex->index."_$i";
$response = isset($$key);
$r = $choice[1];
$correct = ($r && $response) || (!$r && !$response);
$color = $correct?"#88ff88":"#ff8888";
table_row($c, $r?"yes":"no",
array($response?"yes":"no", "bgcolor=$color")
);
$i++;
}
end_table();
break;
}
$bolt_ex->index++;
}
function image_rect($img, $rect) {
global $bolt_ex;
parse_str($bolt_ex->query_string);
switch ($bolt_ex->mode) {
case BOLT_MODE_SHOW:
echo "<input type=image name=pic_$bolt_ex->index src=$img>
";
break;
case BOLT_MODE_SCORE:
$x = get_int("pic_".$bolt_ex->index."_x");
$y = get_int("pic_".$bolt_ex->index."_y");
$right = true;
if ($x < $rect[0]) $right = false;
if ($x > $rect[1]) $right = false;
if ($y < $rect[2]) $right = false;
if ($y > $rect[3]) $right = false;
if ($right) {
$bolt_ex->score += 1;
}
$bolt_ex->weight += $weight;
break;
case BOLT_MODE_ANSWER:
$x = get_int("pic_".$bolt_ex->index."_x");
$y = get_int("pic_".$bolt_ex->index."_y");
$right = true;
if ($x < $rect[0]) $right = false;
if ($x > $rect[1]) $right = false;
if ($y < $rect[2]) $right = false;
if ($y > $rect[3]) $right = false;
$cx = $rect[0];
$cy = $rect[2];
$sizex = $rect[1]-$rect[0];
$sizey = $rect[3]-$rect[2];
$ax = $x-4;
$ay = $y-4;
$color = $right?"green":"red";
if ($right) {
echo "The point you selected (shown in green) is correct.";
} else {
echo "The point you selected (shown in red) is not correct.";
}
echo "
<div style=\"position:relative; \">
<span style=\"width:".$sizex."px;height:".$sizey."px;position:absolute;top:".$cy.";left:".$cx.";color:white;border-style:solid;border-width:3px\"><br></span>
<span style=\"width:8;height:8;position:absolute;top:".$ay.";left:".$ax.";color:$color;border-style:solid;border-width:4px\"><br></span>
<img src=$img align=left>
</div>
<br clear=all>
";
break;
}
$bolt_ex->index++;
}
class BoltFitbField {
public $textarea, $nrows, $ncols;
function __construct($textarea, $nrows, $ncols) {
$this->textarea = $textarea;
$this->nrows = $nrows;
$this->ncols = $ncols;
}
}
function field($n) {
return new BoltFitbField(false, 1, $n);
}
function box($nr, $nc) {
return new BoltFitbField(true, $nr, $nc);
}
class BoltFitbAnswer {
public $type; // 0=constant, 1=regexp, 2=func
public $ans;
function __construct($type, $ans) {
$this->type = $type;
$this->ans = $ans;
}
}
function answer($ans) {
return new BoltFitbAnswer(0, $ans);
}
function answer_regexp($ans) {
return new BoltFitbAnswer(1, $ans);
}
function answer_func($ans) {
return new BoltFitbAnswer(2, $ans);
}
function fitb() {
global $bolt_ex;
$args = func_get_args();
$field = new BoltFitbField(false, 1, 20);
$answer = null;
foreach ($args as $arg) {
if (is_array($arg)) {
$choices[] = $arg;
} else if (is_object($arg)) {
if (get_class($arg) == 'BoltFitbField') {
$field = $arg;
} else if (get_class($arg) == 'BoltFitbAns') {
$answer = $arg;
} else {
echo "bad arg to fitb()";
}
} else {
echo "bad arg to fitb()";
}
}
switch ($bolt_ex->mode) {
case BOLT_MODE_SHOW:
if ($field->textarea) {
echo "<textarea name=q_".$bolt_ex->index." nrows=$field->nrows ncols=$field->ncols>
</textarea>
";
} else {
echo "<input name=q_".$bolt_ex->index." length=$field->ncols>";
}
break;
case BOLT_MODE_SCORE:
if (!$answer) break;
$bolt_ex->score = 0;
$key = "q_".$bolt_ex->index;
if (isset($$key)) {
$response = $$key;
} else {
$response = "";
}
switch ($answer->type) {
case 0:
if ($response == $answer->ans) {
$bolt_ex->score = 1;
}
break;
case 1:
if (preg_match('/'.$answer->ans.'/', $response)) {
$bolt_ex->score = 1;
}
break;
case 2:
$bolt_ex->score = call_user_func($answer->ans, $response);
break;
}
break;
case BOLT_MODE_ANSWER:
$key = "q_".$bolt_ex->index;
if (isset($$key)) {
$response = $$key;
} else {
$response = "";
}
break;
}
$bolt_ex->index++;
}
?>

View File

@ -1,75 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
class BoltRandom extends BoltSet {
public $units;
function __construct($name, $units, $number, $attrs) {
parent::__construct($name, $units, $number, $attrs);
}
function order(&$iter) {
$state_rec = $iter->state[$this->name];
if ($state_rec) {
if (array_key_exists('seed', $state_rec)) {
$seed = $state_rec['seed'];
} else {
$seed = ((double)microtime()*1000000);
$state_rec['seed'] = $seed;
$iter->state[$this->name] = $state_rec;
}
} else {
$state_rec = $this->init();
$seed = ((double)microtime()*1000000);
$state_rec['seed'] = $seed;
$iter->state[$this->name] = $state_rec;
}
srand($seed);
shuffle($this->units);
$this->ordered = true;
}
}
function random() {
$args = func_get_args();
$units = array();
$name = "";
$number = 0;
$attrs = null;
foreach ($args as $arg) {
if (is_array($arg)) {
switch ($arg[0]) {
case 'name': $name = $arg[1]; break;
case 'title': $title = $arg[1]; break;
case 'number': $number = $arg[1]; break;
case 'attrs': $attrs = $arg[1]; break;
default: echo "Unrecognized array arg: ", $arg[0], "\n"; break;
}
} else if (is_object($arg)) {
if (is_subclass_of($arg, "BoltUnit")) {
$units[] = $arg;
} else {
echo "Unrecognized arg: ";
print_r($arg);
}
}
}
if ($number == 0) $number = count($units);
return new BoltRandom($name, $units, $number, $attrs);
}
?>

View File

@ -1,81 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// An iterator represents a user's position in a course.
// Its state is stored in the database,
// and the course may change underneath it.
//
// A state in a course is described by an associative array
// mapping logical names to state structures.
// Typically this includes the logical name of the current child
// and info such as a sequence index.
// This is kind of like a "call stack",
// except that it can contain units not currently active.
//
class BoltIter {
public $top; // topmost unit
public $state;
public $xset; // exercise set, if any
// the following are temps
public $item; // current item
public $frac_done; // fraction done
function __construct($top) {
$this->top = $top;
$this->state = array();
}
function decode_state($encoded_state) {
$this->state = unserialize($encoded_state);
}
function encode_state() {
return serialize($this->state);
}
// get current item and fraction done
//
function at() {
$this->xset = null;
$this->top->walk($this, false, $this->frac_done);
}
// move to the next item, and return it in $this->item
// (null if course finished)
//
function next() {
$this->top->walk($this, true, $this->frac_done);
}
}
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";
}
?>

View File

@ -1,88 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
function select_cmp($a, $b) {
if ($a->value == $b->value) return 0;
return ($a->value < $b->value)?1:-1;
}
class BoltSelect extends BoltSet {
public $valuator;
function __construct($name, $units, $valuator, $attrs) {
$this->valuator = $valuator;
parent::__construct($name, $units, 1, $attrs);
}
function order() {
global $student;
foreach ($this->units as $u) {
$func = $this->valuator;
$u->value = $func($student, $u);
}
usort($this->units, 'select_cmp');
$this->ordered = true;
}
function finished($iter) {
global $user;
global $course;
global $view;
$state_rec = $iter->state[$this->name];
$child_name = $state_rec['child_name'];
$now = time();
BoltSelectFinished::insert("(user_id, course_id, end_time, name, selected_unit, view_id) values ($user->id, $course->id, $now, '$this->name', '$child_name', $view->id)");
parent::finished($iter);
}
}
function valuator($n) {
return array('valuator', $n);
}
function select() {
$args = func_get_args();
$units = array();
$name = "";
$attrs = null;
foreach ($args as $arg) {
if (is_array($arg)) {
switch ($arg[0]) {
case 'name': $name = $arg[1]; break;
case 'title': $title = $arg[1]; break;
case 'valuator': $valuator = $arg[1]; break;
case 'attrs': $attrs = $arg[1]; break;
default: echo "Unrecognized array arg: ", $arg[0], "\n"; break;
}
} else if (is_object($arg)) {
if (is_subclass_of($arg, "BoltUnit")) {
$units[] = $arg;
} else {
echo "Unrecognized arg: ";
print_r($arg);
}
}
}
if (!$valuator) {
error_page("missing valuator");
}
return new BoltSelect($name, $units, $valuator, $attrs);
}
?>

View File

@ -1,63 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
class BoltSequence extends BoltSet {
function __construct($name, $units, $attrs) {
parent::__construct($name, $units, count($units), $attrs);
}
function order() {
$this->ordered = true;
}
function restart(&$iter) {
$state_rec = $iter->state[$this->name];
if (!$state_rec) $state_rec = $this->init();
$state_rec['nshown'] = 0;
$state_rec['index'] = 0;
$state_rec['child_name'] = null;
$iter->state[$this->name] = $state_rec;
}
}
function sequence() {
$args = func_get_args();
$units = array();
$name = "";
$attrs = null;
foreach ($args as $arg) {
if (is_array($arg)) {
switch ($arg[0]) {
case 'name': $name = $arg[1]; break;
case 'title': $title = $arg[1]; break;
case 'attrs': $attrs = $arg[1]; break;
default: echo "Unrecognized array arg: ", $arg[0], "\n"; break;
}
} else if (is_object($arg)) {
if (is_subclass_of($arg, "BoltUnit")) {
$units[] = $arg;
} else {
echo "Unrecognized arg: ";
print_r($arg);
}
}
}
return new BoltSequence($name, $units, $attrs);
}
?>

View File

@ -1,229 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
////// stuff related to snapshots
//
// There are 2 kinds of snapshots: "compare" and "map".
//
// A "compare snapshot" is a condensed representation of the results
// for a particular select/xset pair.
// Namely, it's an array whose elements contain
// bolt_user: the user
// xset_result: the user's first completion of the xset
// select_finished: the user's last completion of the select before this
//
// A "map snapshot" is:
// - an assoc array "views" mapping unit name to a list of views
// - an assoc array "results" mapping unit name to a list of results
// - an assoc array "xset_results" mapping unit name to a list of xset results
// - an assoc array "questions" mapping unit name to a list of questions
// - an assoc array "users" mapping user ID to user record
//
function compare_snapshot_filename($course_id, $select_name, $xset_name) {
@mkdir("../bolt_snap");
$x = urlencode($course_id."_".$select_name."_".$xset_name);
return "../bolt_snap/compare_snapshot_$x";
}
function write_compare_snapshot($course_id, $select_name, $xset_name, $dur) {
$now = time();
$start = $now - $dur*86400;
$xrs = BoltXsetResult::enum(
"course_id=$course_id and name='$xset_name' and create_time >= $start"
);
$sfs = BoltSelectFinished::enum(
"course_id=$course_id and name='$select_name' and end_time >= $start"
);
// make an array $a, keyed by user ID, of earliest xset result
//
$a = array();
foreach ($xrs as $xr) {
$uid = $xr->user_id;
if (!array_key_exists($uid, $a) || $xr->create_time < $a[$uid]->xr->create_time) {
$x = null;
$x->xr = $xr;
$a[$uid] = $x;
}
}
// now scan select finishes, and for each user find last one before xset
//
foreach ($sfs as $sf) {
$uid = $sf->user_id;
if (!array_key_exists($uid, $a)) {
echo "no xset result";
continue;
}
$x = $a[$uid];
$xr = $x->xr;
if ($sf->end_time > $xr->create_time) {
//echo "select finish is too late";
continue;
}
if (!isset($x->sf) || $sf->end_time > $x->sf->end_time) {
$x->sf = $sf;
$a[$uid] = $x;
}
}
// cull array elements for which we didn't find a select finish.
// Look up user records for other elements.
//
foreach ($a as $uid=>$x) {
if (!isset($x->sf)) {
unset($a[$uid]);
} else {
$user = BoincUser::lookup_id($uid);
BoltUser::lookup($user);
$x->user = $user;
$a[$uid] = $x;
}
}
$filename = compare_snapshot_filename($course_id, $select_name, $xset_name);
$f = fopen($filename, "w");
$s = null;
$s->recs = $a;
$s->dur = $dur;
$s->time = $now;
fwrite($f, serialize($s));
fclose($f);
return $s;
}
function read_compare_snapshot($course_id, $select_name, $xset_name) {
$filename = compare_snapshot_filename($course_id, $select_name, $xset_name);
$f = @fopen($filename, "r");
if (!$f) return null;
$x = fread($f, filesize($filename));
fclose($f);
return unserialize($x);
}
function map_snapshot_filename($course_id) {
return "../bolt_snap/map_snapshot_".$course_id;
}
function write_map_snapshot($course_id, $dur) {
$now = time();
$start = $now - $dur*86400;
$views = array();
$results = array();
$xset_results = array();
$users = array();
$questions = array();
$vs = BoltView::enum("course_id=$course_id and start_time>$start");
foreach ($vs as $v) {
if (array_key_exists($v->item_name, $views)) {
$x = $views[$v->item_name];
$x[] = $v;
$views[$v->item_name] = $x;
} else {
$views[$v->item_name] = array($v);
}
if (!array_key_exists($v->user_id, $users)) {
$user = BoincUser::lookup_id($v->user_id);
BoltUser::lookup($user);
$users[$v->user_id] = $user;
}
}
$rs = BoltResult::enum("course_id=$course_id and create_time>$start");
foreach ($rs as $r) {
if (array_key_exists($r->item_name, $results)) {
$x = $results[$r->item_name];
$x[] = $r;
$results[$r->item_name] = $x;
} else {
$results[$r->item_name] = array($r);
}
if (!array_key_exists($r->user_id, $users)) {
$user = BoincUser::lookup_id($r->user_id);
BoltUser::lookup($user);
$users[$r->user_id] = $user;
}
}
$xrs = BoltXsetResult::enum("course_id=$course_id and create_time>$start");
foreach ($xrs as $xr) {
if (array_key_exists($xr->name, $xset_results)) {
$x = $xset_results[$xr->name];
$x[] = $xr;
$xset_results[$xr->name] = $x;
} else {
$xset_results[$xr->name] = array($xr);
}
if (!array_key_exists($xr->user_id, $users)) {
$user = BoincUser::lookup_id($xr->user_id);
BoltUser::lookup($user);
$users[$xr->user_id] = $user;
}
}
$qs = BoltQuestion::enum("course_id=$course_id and create_time>$start");
foreach ($qs as $q) {
if (array_key_exists($q->name, $questions)) {
$x = $questions[$q->name];
$x[] = $q;
$questions[$q->name] = $x;
} else {
$questions[$q->name] = array($q);
}
if (!array_key_exists($q->user_id, $users)) {
$user = BoincUser::lookup_id($q->user_id);
BoltUser::lookup($user);
$users[$q->user_id] = $user;
}
}
$y = null;
$y->views = $views;
$y->results = $results;
$y->xset_results = $xset_results;
$y->users = $users;
$y->questions = $questions;
$y->dur = $dur;
$y->time = $now;
$filename = map_snapshot_filename($course_id);
$f = fopen($filename, "w");
fwrite($f, serialize($y));
fclose($f);
return $y;
}
function read_map_snapshot($course_id) {
$filename = map_snapshot_filename($course_id);
$f = @fopen($filename, "r");
if (!$f) return null;
$x = fread($f, filesize($filename));
fclose($f);
return unserialize($x);
}
?>

View File

@ -1,110 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Utililty functions for student pages
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("About you");
echo "
You may optionally tell us some facts about yourself.
This information will help us improve this course,
and will be kept private.
<p>
<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 class=\"btn btn-default\" type=submit value=OK>");
end_table();
echo "</form>\n";
page_tail();
}
//////////// show refresh schedule //////////////
function show_refresh($r) {
echo "<tr>
<td>$r->name</td>
<td>".time_str($r->due_time)."</td>
<td>
";
if ($r->last_view_id) {
echo "
<a href=bolt_sched.php?course_id=$r->course_id&refresh_id=$r->id&action=start>Restart</a>
| <a href=bolt_sched.php?course_id=$r->course_id&refresh_id=$r->id&action=resume>Resume</a>
";
} else {
echo "
<a href=bolt_sched.php?course_id=$r->course_id&refresh_id=$r->id&action=start>Start</a>
";
}
echo "
</td>
</tr>
";
}
function show_refreshes() {
global $user;
global $course;
$refreshes = BoltRefreshRec::enum("user_id=$user->id and course_id=$course->id");
if (!count($refreshes)) return;
start_table();
echo "<tr><th colspan=3>Refresh schedule</th></tr>\n";
foreach ($refreshes as $r) {
show_refresh($r);
}
end_table();
}
?>

View File

@ -1,230 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Utility functions for admin pages
require_once("../inc/util_ops.inc");
// get names of units of a given type
function units_of_type($unit, $type) {
$names = array();
if (get_class($unit) == $type) {
$names[] = $unit->name;
}
if (is_subclass_of($unit, "BoltSet")) {
foreach ($unit->units as $u) {
$n = units_of_type($u, $type);
$names = array_merge($names, $n);
}
}
return array_unique($names);
}
// show a menu of select units
//
function choose_select($top_unit) {
echo "<select name=select_name>
<option selected> ---
";
$names = units_of_type($top_unit, "BoltSelect");
foreach ($names as $n) {
echo "<option> $n";
}
echo "</select>";
}
// show a menu of exercise sets
//
function choose_xset($top_unit) {
echo "<select name=xset_name>
<option selected> ---
";
$names = units_of_type($top_unit, "BoltExerciseSet");
foreach ($names as $n) {
echo "<option> $n";
}
echo "</select>";
}
// Find a unit of given name
//
function lookup_unit($top_unit, $name) {
if ($top_unit->name == $name) return $top_unit;
if (is_subclass_of($top_unit, "BoltSet")) {
foreach ($top_unit->units as $child) {
$u = lookup_unit($child, $name);
if ($u) return $u;
}
}
return null;
}
////// Statistics
// compute the mean and stdev of an array
//
function mean_stdev($array, &$mean, &$stdev) {
$n = 0;
$m = 0;
$m2 = 0;
foreach ($array as $x) {
$n++;
$delta = $x - $m;
$m += $delta/$n;
$m2 += $delta*($x-$m);
}
$mean = $m;
$stdev = sqrt($m2/($n-1));
}
// approximate the 90% confidence interval for the mean of an array
//
function conf_int_90($array, &$lo, &$hi) {
$n = count($array);
mean_stdev($array, $mean, $stdev);
// I'm too lazy to compute the t distribution
$t_90 = 1.7;
$d = $t_90 * $stdev / sqrt($n);
$lo = $mean - $d;
$hi = $mean + $d;
}
function test_stats() {
$a = array(1,1,1,1,0,1,1,1,3, 1, 1, 1, 1);
mean_stdev($a, $mean, $stdev);
echo "mean: $mean stdev: $stdev\n";
conf_int_90($a, $lo, $hi);
echo "lo $lo hi $hi\n";
}
//////////// graph drawing
function compare_bar($title, $n, $width, $lo, $hi) {
$x1 = $width*$lo;
$x2 = $width*($hi-$lo);
$a1 = number_format($lo*100);
$a2 = number_format($hi*100);
return "
<tr>
<td>$title<br><p class=\"text-muted\">($n students)</p></td>
<td>
<table class=bolt_bar width=$width><tr class=bolt_bar>
<td class=bolt_bar1 width=$x1 bgcolor=lightgray align=right>$a1</td>
<td class=bolt_bar2 width=$x2 bgcolor=black></td>
<td class=bolt_bar1 bgcolor=lightgray>$a2</td>
</tr></table>
</td>
</tr>
";
}
function compare_bar_insuff($title, $width) {
return "
<tr>
<td>$title</td>
<td>
<table class=bolt_bar width=$width><tr class=bolt_bar>
<td class=bolt_bar1 bgcolor=lightgray>Insufficient data</td>
</tr></table>
</td>
</tr>
";
}
function outcome_graph($x, $width) {
$n = $x[0]+$x[1]+$x[2];
if (!$n) return empty_cell();
$x0 = $width*$x[1]/$n;
$x1 = $width*$x[0]/$n;
$x2 = $width*$x[2]/$n;
if ($x[1]/$n>0.05) {
$t0 = number_format(100*$x[1]/$n)."%";
} else {
$t0 = "";
}
$s = "<td>
<table class=bolt_bar><tr>
";
if ($x0) {
$s .= "<td class=bolt_bar height=10 width=$x0 bgcolor=#88ff88><p class=\"text-muted\">$t0</p></td>
";
}
if ($x1) {
$s .= "<td class=bolt_bar height=10 width=$x1 bgcolor=#ff8888><br></td>
";
}
if ($x2) {
$s .= "<td class=bolt_bar height=10 width=$x2 bgcolor=#ffff88><br></td>
";
}
$s .= "</tr></table>
</td>
";
return $s;
}
function time_graph($t, $w) {
if ($t == 0) return "<td>---</td>";
$x = (log10($t)+2)*$w/4;
$t = number_format($t, 1);
return "<td>
<table class=bolt_bar><tr>
<td class=bolt_bar height=10 width=$x bgcolor=#ffffcc><p class=\"text-muted\">$t sec</p></td>
</tr></table>
</td>";
}
function score_graph($t, $w) {
if ($t == 0) return "<td>---</td>";
$x = $t*$w;
$y = (1-$t)*$w;
$t = number_format($t*100);
$s = "<td>
<table class=bolt_bar><tr>
";
if ($x) {
$s .= "<td class=bolt_bar height=10 width=$x bgcolor=#ffffcc><p class=\"text-muted\">$t%</p></td>
";
}
if ($y) {
$s .= "<td class=bolt_bar width=$y bgcolor=gray></td>
";
}
$s .= "</tr></table></td>
";
return $s;
}
function empty_cell() {
return "<td><br></td>";
}
function empty_row() {
return "<tr><td><br></td></tr>";
}
function bolt_style() {
echo "
<link rel=\"stylesheet\" type=\"text/css\" href=\"".URL_BASE."bolt.css\">
";
}
?>

View File

@ -1,209 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
class BoltExerciseSet extends BoltRandom {
public $repeats;
public $refresh;
public $weight;
public $callback;
function __construct(
$name, $units, $number, $repeats, $refresh, $attrs, $callback, $weight
) {
parent::__construct($name, $units, $number, $attrs);
$this->repeats = $repeats;
$this->refresh = $refresh;
$this->callback = $callback;
$this->weight = $weight;
}
// called when an exercise in this set has just been graded.
// - record the score in our state structure
// - return true if this was last exercise in the set
// - if so, also return a structure saying what navigation info to show:
// - review
// - repeat now
// - next
//
function xset_record_score(
&$iter, $score, $view_id, &$avg_score, &$repeat
) {
global $course;
global $user;
$nav_info = null;
$state_rec = $iter->state[$this->name];
$nshown = $state_rec['nshown'];
$state_rec['scores'][$nshown] = $score;
$iter->state[$this->name] = $state_rec;
$is_last = ($nshown+1 == $this->ntoshow);
if (!$is_last) {
return false;
}
// this exercise set is now "completed".
// - create exercise_set_result record
// - optionally create or update bolt_refresh record
//
$total_score = 0;
for ($i=0; $i<$nshown+1; $i++) {
$total_score += $state_rec['scores'][$i];
}
$avg_score = $total_score/($nshown+1);
$repeat = null;
$least = 2;
foreach ($this->repeats as $r) {
if ($avg_score < $r->score && $r->score<$least) {
$repeat = $r;
$least = $r->score;
}
}
return true;
}
function walk(&$iter, $incr, &$frac_done) {
$iter->xset = $this;
// see if we're doing a review
//
if (array_key_exists($this->name, $iter->state)) {
$state_rec = $iter->state[$this->name];
$child_name = $state_rec['child_name'];
foreach ($this->repeats as $r) {
if ($r->unit && ($r->unit->name == $child_name)) {
// we're doing a review
//
$child = $r->unit;
if ($incr) {
if ($child->is_item) {
$my_inc = true;
} else {
$my_inc = $child->walk($iter, $incr, $frac_done);
}
if ($my_inc) {
// we're done with review. do exercises again
//
$state_rec['child_name'] = null;
$state_rec['nshown'] = 0;
$iter->state[$this->name] = $state_rec;
}
} else {
if ($child->is_item) {
$iter->item = $child;
} else {
$child->walk($iter, false, $f);
}
}
return false;
}
}
}
return parent::walk($iter, $incr, $frac_done);
}
function start_review(&$iter, $unit_name) {
foreach ($this->repeats as $r) {
if ($r->unit->name == $unit_name) {
$state_rec = $iter->state[$this->name];
$state_rec['child_name'] = $unit_name;
$iter->state[$this->name] = $state_rec;
if (!$r->unit->is_item) {
$r->unit->restart($iter);
}
return true;
}
}
return false;
}
}
class BoltRefresh{
public $intervals;
function __construct($i) {
$this->intervals = $i;
}
}
class BoltRepeat {
public $score;
public $unit;
public $flags;
function __construct($s, $u, $f) {
$this->score = $s;
$this->unit = $u;
$this->flags = $f;
}
}
define('REVIEW', 1);
define('REPEAT', 2);
define('NEXT', 4);
function repeat($s, $u, $f) {
return new BoltRepeat($s, $u, $f);
}
function refresh($a) {
return new BoltRefresh($a);
}
function exercise_set() {
$args = func_get_args();
$units = array();
$repeats = array();
$refresh = null;
$callback = null;
$name = "";
$number = 0;
$attrs = null;
$weight = 1;
foreach ($args as $arg) {
if (is_array($arg)) {
switch ($arg[0]) {
case 'name': $name = $arg[1]; break;
case 'title': $title = $arg[1]; break;
case 'number': $number = $arg[1]; break;
case 'attrs': $attrs = $arg[1]; break;
case 'callback': $callback = $arg[1]; break;
case 'weight': $weight = $arg[1]; break;
default: echo "Unrecognized array arg: ", $arg[0], "\n"; break;
}
} else if (is_object($arg)) {
if (get_class($arg) == "BoltExercise") {
$units[] = $arg;
} else if (get_class($arg) == "BoltRepeat") {
$repeats[] = $arg;
} else if (get_class($arg) == "BoltRefresh") {
$refresh= $arg;
} else {
echo "Can't include object of type ".get_class($arg)." within an exercise set.";
}
} else {
echo "Unexpected arg to exercise_set(): "; print_r($arg);
}
}
if ($number == 0) $number = count($units);
return new BoltExerciseSet(
$name, $units, $number, $repeats, $refresh, $attrs, $callback, $weight
);
}
?>

View File

@ -1,63 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/util.inc");
require_once("../inc/bossa_db.inc");
function bossa_job_create(
$app_id, $batch_id, $info, $calibration
) {
$job = new BossaJob;
$info = serialize($info);
if ($calibration) {
$priority = drand();
$c = 1;
} else {
$priority = 1;
$c = 0;
}
$now = time();
$int_max = 2147483647;
$clause = "(create_time, app_id, batch_id, state, info, calibration, priority_0) values ($now, $app_id, $batch_id, 1, '$info', $c, $priority)";
return $job->insert($clause);
}
function bossa_batch_create($appid, $name, $calibration) {
$now = time();
$c = $calibration?"1":"0";
return BossaBatch::insert("(create_time, app_id, name, calibration) values ($now, $appid, '$name', $c)");
}
function bossa_app_lookup($name) {
$name = BoincDb::escape_string($name);
$app = BossaApp::lookup("short_name='$name'");
if (!$app) return 0;
return $app->id;
}
function bossa_lookup_job($instid, &$job, &$inst, &$user) {
$inst = BossaJobInst::lookup_id($instid);
if (!$inst) return false;
$job = BossaJob::lookup_id($inst->job_id);
$user = BoincUser::lookup_id($inst->user_id);
BossaUser::lookup($user);
return true;
}
?>

View File

@ -1,291 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/db_conn.inc");
require_once("../inc/util_basic.inc");
class BossaDb extends DbConn {
public static $instance;
static function get() {
if (!isset($instance)) {
$config = get_config();
$name = parse_config($config, '<bossa_db_name>');
if (!$name) {
$name = parse_config($config, '<db_name>');
$user = parse_config($config, '<db_user>');
$passwd = parse_config($config, '<db_passwd>');
$host = parse_config($config, '<db_host>');
} else {
$user = parse_config($config, '<bossa_db_user>');
$passwd = parse_config($config, '<bossa_db_passwd>');
$host = parse_config($config, '<bossa_db_host>');
}
if ($host == null) {
$host = "localhost";
}
$instance = new DbConn();
$retval = $instance->init_conn($user, $passwd, $host, $name, true);
if (!$retval) return null;
}
return $instance;
}
static function escape_string($string) {
$db = self::get();
return $db->base_escape_string($string);
}
static function start_transaction() {
//echo "start transaction\n";
return;
$db = BossaDb::get();
$db->do_query("start transaction");
}
static function commit() {
//echo "commit\n";
return;
$db = BossaDb::get();
$db->do_query("commit");
}
}
// use this as a local to ensure that transaction is committed
// regardless of exceptions
//
class BossaTransaction {
function __construct() {
BossaDb::start_transaction();
}
function __destruct() {
BossaDb::commit();
}
}
class BossaUser {
static $cache;
static function lookup_userid($id) {
$db = BossaDb::get();
return $db->lookup('bossa_user', 'BossaUser', "user_id=$id");
}
static function insert($clause) {
$db = BossaDb::get();
return $db->insert('bossa_user', $clause);
}
static function lookup(&$user) {
if (!$user) return;
if (isset($user->bossa)) return;
if (isset(self::$cache[$user->id])) {
$bossa = self::$cache[$user->id];
} else {
$bossa = self::lookup_userid($user->id);
if (!$bossa) {
self::insert("(user_id) values ($user->id)");
$bossa = self::lookup_userid($user->id);
}
self::$cache[$user->id] = $bossa;
}
$user->bossa = $bossa;
}
function update($clause) {
$db = BossaDb::get();
$clause = "$clause where user_id=$this->user_id";
return $db->update_aux('bossa_user', $clause);
}
// app-callable:
//
function get_opaque_data() {
return unserialize($this->info);
}
function set_opaque_data($info) {
$info = serialize($info);
$this->update("info='$info'");
}
}
class BossaApp {
static function insert($clause) {
$db = BossaDb::get();
return $db->insert('bossa_app', $clause);
}
static function lookup($clause) {
$db = BossaDb::get();
return $db->lookup('bossa_app', 'BossaApp', $clause);
}
static function lookup_id($id) {
$db = BossaDb::get();
return $db->lookup_id($id, 'bossa_app', 'BossaApp');
}
static function enum() {
$db = BossaDb::get();
return $db->enum('bossa_app', 'BossaApp');
}
function update($clause) {
$db = BossaDb::get();
return $db->update($this, 'bossa_app', $clause);
}
}
// values for bossa_job.state
//
define("BOSSA_JOB_EMBARGOED", 0);
define("BOSSA_JOB_IN_PROGRESS", 1);
define("BOSSA_JOB_DONE", 2);
define("BOSSA_JOB_INCONCLUSIVE", 3);
class BossaJob {
static function insert($clause) {
$db = BossaDb::get();
$ret = $db->insert('bossa_job', $clause);
if (!$ret) return 0;
return $db->insert_id();
}
function update($clause) {
$db = BossaDb::get();
return $db->update($this, 'bossa_job', $clause);
}
static function lookup_id($id) {
$db = BossaDb::get();
return $db->lookup_id($id, 'bossa_job', 'BossaJob');
}
static function enum($clause) {
$db = BossaDb::get();
return $db->enum('bossa_job', 'BossaJob', $clause);
}
static function count($clause) {
$db = BossaDb::get();
return $db->count('bossa_job', $clause);
}
// app-callable:
//
function get_opaque_data() {
return unserialize($this->info);
}
function set_priority($x) {
return $this->update("priority_0=$x");
}
function get_instances() {
return BossaJobInst::enum("job_id = $this->id");
}
function get_finished_instances() {
return BossaJobInst::enum("job_id = $this->id and finish_time>0");
}
function set_state($s) {
$this->update("state=$s");
}
}
class BossaJobInst {
function insert($clause) {
$db = BossaDb::get();
$ret = $db->insert('bossa_job_inst', $clause);
if (!$ret) return 0;
return $db->insert_id();
}
static function lookup_id($id) {
$db = BossaDb::get();
return $db->lookup_id($id, 'bossa_job_inst', 'BossaJobInst');
}
static function enum($clause) {
$db = BossaDb::get();
return $db->enum('bossa_job_inst', 'BossaJobInst', $clause);
}
function update($clause) {
$db = BossaDb::get();
return $db->update($this, 'bossa_job_inst', $clause);
}
// Assign a job from the given app to the given user.
// Returns the job instance or NULL.
//
static function assign($app, $user) {
$db = BossaDb::get();
// first look for unfinished jobs previously assigned to this user
//
$job = $db->lookup("bossa_job_inst", "BossaJobInst",
"app_id=$app->id and user_id=$user->id and finish_time=0 limit 1"
);
if ($job) return $job;
if ($app->calibration_frac && drand() < $app->calibration_frac) {
$job = $db->lookup("bossa_job", "BossaJob", "app_id=$app->id and (select count(*) from ".$db->db_name.".bossa_job_inst where job_id=bossa_job.id and user_id=$user->id) = 0 and state=1 and calibration=1 order by priority_0 desc limit 1");
if (!$job) return null;
$job->update("priority_0=priority_0-1");
} else {
if (isset($user->bossa->category)) {
$prio = "priority_".$user->bossa->category;
} else {
$prio = "priority_0";
}
// skips jobs for which this user
// has already been assigned an instance
//
$job = $db->lookup("bossa_job", "BossaJob", "app_id=$app->id and (select count(*) from ".$db->db_name.".bossa_job_inst where job_id=bossa_job.id and user_id=$user->id) = 0 and state=1 and calibration=0 order by $prio desc limit 1");
if (!$job) return null;
}
$now = time();
$clause = "(create_time, app_id, job_id, user_id, batch_id, calibration) values ($now, $app->id, $job->id, $user->id, $job->batch_id, $job->calibration)";
$id = BossaJobInst::insert($clause);
return BossaJobInst::lookup_id($id);
}
function delete_aux($clause) {
$db = BossaDb::get();
return $db->delete_aux('bossa_job_inst', $clause);
}
// app-callable functions
//
function set_opaque_data($info) {
$info = serialize($info);
return $this->update("info='$info'");
}
function get_opaque_data() {
return unserialize($this->info);
}
function get_user() {
$user = BoincUser::lookup_id($this->user_id);
BossaUser::lookup($user);
return $user;
}
}
class BossaBatch {
function insert($clause) {
$db = BossaDb::get();
$ret = $db->insert('bossa_batch', $clause);
if (!$ret) return 0;
return $db->insert_id();
}
static function enum($clause) {
$db = BossaDb::get();
return $db->enum('bossa_batch', 'BossaBatch', $clause);
}
static function lookup_id($id) {
$db = BossaDb::get();
return $db->lookup_id($id, 'bossa_batch', 'BossaBatch');
}
}
?>

View File

@ -1,80 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/bossa.inc");
// Bossa example #1.
// Show the user an image and ask them to click on the ellipse
// This version does no replication.
function job_show($job, $inst, $user) {
$info = $job->get_opaque_data($job);
$path = $info->path;
page_head("Find the Ellipse");
echo "
<form method=get action=bossa_job_finished.php>
Click on the center of the ellipse.
If you don't see one, click here:
<input class=\"btn btn-default\" type=submit name=submit value=None>
<br><br>
<input type=hidden name=bji value=$inst->id>
<input type=image name=pic src=$path>
</form>
";
page_tail();
}
function job_issued($job, $inst, $user) {
$job->set_priority(0);
}
function job_finished($job, $inst) {
$response = new stdClass;
if (get_str('submit', true)) {
$response->have_ellipse = 0;
} else {
$response->have_ellipse = 1;
$response->cx = get_int('pic_x');
$response->cy = get_int('pic_y');
}
$inst->set_opaque_data($response);
$job->set_state(BOSSA_JOB_DONE);
}
function job_timed_out($job, $inst, $user) {
$job->set_priority(1);
}
function job_summary($job) {
$info = $job->get_opaque_data();
return "<a href=".URL_BASE."$info->path>View image</a>";
}
function instance_summary($info) {
if ($info->have_ellipse) {
return "($info->cx, $info->cy)";
} else {
return "no ellipse";
}
}
function user_summary($user) {
return "";
}
?>

View File

@ -1,135 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/bossa.inc");
// Bossa example #2.
// Show the user an image and ask them to click on the ellipse
// This version does replication;
// a job is considered done if either
// - 2 instances are positive and match within +- 20 pixels
// - 2 instances are negative
// - there are 10 finished instances
// (in which case the job is marked as inconclusive)
function job_show($job, $inst, $user) {
$info = $job->get_opaque_data($job);
$path = $info->path;
echo "
<h2>Find the Ellipse!</h2>
<form method=get action=bossa_job_finished.php>
Click on the center of the ellipse.
If you don't see one, click here:
<input class=\"btn btn-default\" type=submit name=submit value=None>
<br><br>
<input type=hidden name=bji value=$inst->id>
<input type=image name=pic src=$path>
</form>
";
}
function job_issued($job, $inst, $user) {
$insts = $job->get_instances();
if (count($insts) == 1) {
$job->set_priority(2);
} else {
$job->set_priority(0);
}
}
function job_finished($job, $inst) {
// record the user's response
//
$response = null;
if (get_str('submit', true)) {
$response->have_ellipse = 0;
} else {
$response->have_ellipse = 1;
$response->cx = get_int('pic_x');
$response->cy = get_int('pic_y');
}
$inst->set_opaque_data($response);
// see whether we have a consensus
//
$insts = $job->get_finished_instances();
$n = count($insts);
$results = null;
foreach ($insts as $inst) {
$results[] = $inst->get_opaque_data();
}
for ($i=0; $i<$n-1; $i++) {
$r1 = $results[$i];
for ($j=$i+1; $j<$n; $j++) {
$r2 = $results[$j];
if (compatible($r1, $r2)) {
$job->set_state(BOSSA_JOB_DONE);
return;
}
}
}
// no consensus - see whether we've reached replication limit
//
if ($n >= 10) {
$job->set_state(BOSSA_JOB_INCONCLUSIVE);
return;
}
// still looking for consensus - get another instance
//
$job->set_priority(2);
}
// two results are compatible if neither found an ellipse,
// or they both did and centers are within 20 pixels
//
function compatible($r1, $r2) {
if ($r1->have_ellipse) {
if ($r2->have_ellipse) {
$dx = ($r1->cx - $r2->cx);
$dy = ($r1->cy - $r2->cy);
$dsq = $dx*$dx + $dy*$dy;
return ($dsq < 400);
} else return false;
} else {
return !$r2->have_ellipse;
}
}
function job_timed_out($job, $inst, $user) {
$job->set_priority(2);
}
function job_summary($job) {
$info = $job->get_opaque_data();
return "<a href=".URL_BASE."$info->path>View image</a>";
}
function instance_summary($info) {
if ($info->have_ellipse) {
return "ellipse ($info->cx, $info->cy)";
} else {
return "no ellipse";
}
}
function user_summary($user) {
return "";
}

View File

@ -1,224 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Bossa example #3 - calibration jobs.
// We maintain the following for each user:
// nneg # of negative calibration jobs shown
// nneg_err # of errors
// npos
// npos_err
//
// from these we derive
// neg_err_rate
// pos_err_rate
//
// a job is considered done if either
// - N instances are positive and match within +- 20 pixels,
// and prod(pos_err_rate)<PROB_LIMIT
// - N instances are negative
// and prod(neg_err_rate)<PROB_LIMIT
// - there are 10 finished instances
// (in which case the job is marked as inconclusive)
require_once("../inc/bossa.inc");
define("PROB_LIMIT", 1e-3);
function job_show($job, $inst, $user) {
$info = $job->get_opaque_data();
$path = $info->path;
page_head("Find the Ellipse");
echo "
<form method=get action=bossa_job_finished.php>
Click on the center of the ellipse.
If you don't see one, click here:
<input type=submit name=submit value=None>
<br><br>
<input type=hidden name=bji value=$inst->id>
<input type=image name=pic src=$path>
</form>
";
page_tail();
}
function job_issued($job, $inst, $user) {
$insts = $job->get_instances();
if (count($insts) > 1) {
$job->set_priority(0);
}
}
function job_finished($job, $inst, $user) {
$response = null;
if (get_str('submit', true)) {
$response->have_ellipse = 0;
} else {
$response->have_ellipse = 1;
$response->cx = get_int('pic_x');
$response->cy = get_int('pic_y');
}
$inst->set_opaque_data($response);
// if this is a calibration job, update user's opaque data
//
if ($job->calibration) {
$b = $user->bossa;
$info = $job->get_opaque_data();
$answer = $info->answer;
$u = $b->get_opaque_data();
if (!$u) {
$u->npos = 0;
$u->npos_err = 0;
$u->nneg = 0;
$u->nneg_err = 0;
}
if (compatible($response, $answer)) {
if ($answer->have_ellipse) {
$u->npos++;
} else {
$u->nneg++;
}
} else {
if ($answer->have_ellipse) {
$u->npos++;
$u->npos_err++;
} else {
$u->nneg++;
$u->nneg_err++;
}
}
$b->set_opaque_data($u);
return;
}
// now see if job is done
//
$insts = $job->get_finished_instances();
$n = count($insts);
$results = null;
$users = null;
foreach ($insts as $inst) {
$results[] = $inst->get_opaque_data();
$u = $inst->get_user();
$users[] = $u->bossa->get_opaque_data();
}
// see if there's a negative consensus
//
$prob = 1;
for ($i=0; $i<$n; $i++) {
$r = $results[$i];
if ($r1->have_ellipse) continue;
$u = $users[$i];
$prob *= $u->neg_err_rate;
}
if ($prob < PROB_LIMIT) {
$job->set_state(BOSSA_JOB_DONE);
return;
}
// see if there's a positive consensus
//
for ($i=0; $i<$n; $i++) {
$r1 = $results[$i];
$u = $users[$i];
$prob = $u->pos_error_rate;
for ($j=0; $j<$n; $j++) {
if ($j == $i) continue;
$r2 = $results[$j];
if (compatible($r1, $r2)) {
$u2 = $users[$j];
$prob *= $u2->pos_err_rate;
}
}
if ($prob < PROB_LIMIT) {
$job->set_state(BOSSA_JOB_DONE);
return;
}
}
// see if there are too many instances without a consensus
//
if ($n >= 10) {
$job->set_state(BOSSA_JOB_INCONCLUSIVE);
return;
}
// still looking for consensus - get another instance
//
$job->set_priority(2);
}
// two results are compatible if neither found an ellipse,
// or they both did and centers are within 20 pixels
//
function compatible($r1, $r2) {
if ($r1->have_ellipse) {
if ($r2->have_ellipse) {
$dx = ($r1->cx - $r2->cx);
$dy = ($r1->cy - $r2->cy);
$dsq = $dx*$dx + $dy*$dy;
return ($dsq < 400);
} else return false;
} else {
return !$r2->have_ellipse;
}
}
function job_timed_out($job, $inst, $user) {
$job->set_priority(1);
}
function job_summary($job) {
$info = $job->get_opaque_data();
return "<a href=".URL_BASE."$info->path>(view image)</a>";
}
function instance_summary($info) {
if ($info->have_ellipse) {
return "ellipse ($info->cx, $info->cy)";
} else {
return "no ellipse";
}
}
function user_summary($user) {
$b = $user->bossa;
$info = $b->get_opaque_data();
if ($info) {
if ($info->npos) {
$pos_err = $info->npos_err/$info->npos;
} else {
$pos_err = "---";
}
if ($info->nneg) {
$neg_err = $info->nneg_err/$info->nneg;
} else {
$neg_err = "---";
}
return "error rate: positive $pos_err ($info->npos_err/$info->npos),
negative $neg_err ($info->nneg_err/$info->nneg)
";
} else {
return "No data";
}
}
?>

View File

@ -1,189 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/bossa.inc");
function job_show($job, $inst, $user) {
$output = $inst->get_opaque_data();
$features = $output->features;
$input = $job->get_opaque_data();
$path = $input->path;
show_style();
echo "
<script>
function image_clicked() {
if (document.forms.main.type.value == 'none') {
alert('Please select a feature type');
return false;
} else {
return true;
}
return false;
}
</script>
<form name=main onsubmit=\"javascript: return image_clicked()\" action=bossa_example4.php>
<div style=\"position:relative; top:60; \">
<input type=hidden name=action value=add>
<input type=hidden name=bji value=\"$inst->id\">
<input type=image name=pic src=$path>
";
$size = 100;
$size2 = 50;
$i = 0;
foreach ($features as $f) {
$cx = $f->x - $size2;
$cy = $f->y - $size2;
echo "
<span style=\"width:".$size."px;height:".$size."px;position:absolute;top:".$cy.";left:".$cx.";color:white;border-style:solid;border-width:1px\">
";
$c = $f->comment?"($f->comment)":"";
echo "
<span class=link>
<a href=\"javascript: void(0)\">
<img border=0 align = left src=example4_images/info_icon.png>
<span>
$f->type $c
</span>
</a>
</span>
";
echo "
<a href=bossa_example4.php?bji=$inst->id&action=delete&index=$i><img border=0 align=right src=example4_images/close_button.jpg></a>
</span>
";
$i++;
}
echo "
</div>
";
control_bar($features, $inst);
echo "
</form>
";
}
function job_issued($job, $inst, $user) {
$job->set_priority(0);
}
function job_finished($job, $inst) {
}
function job_timed_out($job, $inst, $user) {
$job->set_priority(1);
}
function job_summary($job) {
$info = $job->get_opaque_data();
return "<a href=".URL_BASE."$info->path>View image</a>";
}
function instance_summary($opaque_data) {
$features = $opaque_data->features;
$x = "";
foreach ($features as $f) {
$c = $f->comment?"($f->comment)":"";
$x .= "$f->type $c <br>";
}
return $x;
}
function user_summary($user) {
return "";
}
function show_style() {
echo "
<style type=\"text/css\">
body {
font: 15px \"Trebuchet MS\", sans-serif;
}
span.link {
position: relative;
}
span.link a span {
display: none;
}
span.link a:hover {
font-size: 99%;
font-color: #000000;
}
span.link a:hover span {
display: block;
position: absolute;
margin-top: 10px;
margin-left: -10px;
width: 175px; padding: 5px;
z-index: 100;
color: #000000;
background: #ffffcc;
font: 12px \"Arial\", sans-serif;
text-align: left;
text-decoration: none;
}
</style>
";
}
function select_type() {
echo "
<select name=type>
<option value=none> select feature type
<option> Tooth
<option> Skull
<option> Other
</select>
";
}
function control_bar($features, $inst) {
if (count($features)) {
$str1 = "any more";
$str2 = "another";
} else {
$str1 = "any";
$str2 = "a";
}
echo "
<div style=\"position:absolute; top:0px; left:0px; padding-top: 10px; padding-left: 20px; width:100%; background-color:white\">
<input type=hidden name=bji value=\"$inst->id\">
If you see $str2 feature:
";
select_type();
echo "
<script>
function clear_comment() {
document.forms.main.comment.value = '';
}
</script>
<input name=comment onfocus=\"javascript: clear_comment()\" size=30 value=\"enter comment (optional)\">
and click on its center.
<br>
If you don't see $str1 features, click
<a href=bossa_job_finished.php?bji=$inst->id>DONE</a>
</div>
";
}
?>

View File

@ -1,38 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
function show_next_job($app, $user) {
$inst = BossaJobInst::assign($app, $user);
if ($inst) {
$job = BossaJob::lookup_id($inst->job_id);
$file = "../inc/$app->short_name.inc";
require_once($file);
job_issued($job, $inst, $user);
job_show($job, $inst, $user);
} else {
page_head("No jobs available");
echo "
Sorry, no jobs are available right now.
<p>
Please try again later.
";
page_tail();
}
}
?>

View File

@ -1,414 +0,0 @@
/* General */
a, a:link, a:visited, a:active {
color: #0069A1;
text-decoration: none;
}
a:hover { text-decoration: underline; }
body {
background-image: url("img/gray_gradient.png");
background-repeat: repeat-x;
background-color: white;
font-family: Verdana, Arial, Sans Serif;
font-size: 13px;
margin: 5px 10px;
color: black;
}
h1, h2 {
font-size: x-large;
font-weight: normal;
}
h1 {
color: #203C66;
margin: 10px;
}
h3, h4 { font-weight: bold; }
hr {
size: 0px;
border-top: 2px solid #e8e8e8;
margin: 8px 2px;
}
.table {
padding: 4px;
margin: 2px;
}
.table-bordered {
border: 2px solid #e8e8e8;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}
th {
background-color: #c0c0c0;
font-weight: bold;
vertical-align: top;
}
td {
vertical-align: top;
padding: 4px;
}
td.bordered {
border: 1px solid gray;
}
td.indent { border-left: 4px solid white; }
th, td.heading {
font-weight: bold;
margin: 4px 0px;
padding: 8px;
background-color: #d8d8d8;
}
td.fieldname {
background-color: #eeeeee;
text-align: right;
padding-right: 10px;
margin: 2px 0px;
}
td.fieldvalue {
margin: 2px 0px;
vertical-align: middle;
}
td.fieldname_error {
background-color: #ff8888;
text-align: right;
}
td.fieldvalue_error {
background-color: #ff8888;
font-weight: bold;
}
td.navbar {
border: 0px;
text-align: center;
vertical-align: middle;
}
td.friend {
background-color: #e8e8e8;
text-align: center;
vertical-align: middle;
}
.row0 {
background-color: #d9d9d9;
text-align: left;
}
.row1 {
background-color: #eeeeee;
text-align: left;
}
.highlighted_row0 {
background-color: #b9d9f9;
text-align: left;
}
.highlighted_row1 {
background-color: #ceeefe;
text-align: left;
}
.row_hd0 { background-color: #cffacf; }
.row_hd1 { background-color: #defade; }
tr.message { background-color: #e0e0e0; }
input[type="text"], select, textarea, .btn {
border: 1px solid #d8d8d8;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
padding: 2px 4px;
font-size: 12px;
}
input[type="button"], input[type="submit"], input.btn {
margin: 2px 0px;
background: #d4d0c8;
margin-right: 0.6em;
color: #203C66;
border: 1px solid #a8a8a8;
font-size: 12px;
font-weight: normal;
}
/* IE6 doesn't understand [type=XXXX] so we factor this out into its own */
.btn {
margin: 2px 0px;
background: #d4d0c8;
margin-right: 0.6em;
white-space: nowrap;
color: #203C66;
border: 1px solid #a8a8a8;
font-size: 0.9em;
font-weight: normal;
line-height: 2em;
}
.btn:hover {
background: #edece8;
text-decoration:none;
}
input[type="button"]:hover, input[type="submit"]:hover, input.btn:hover, .forum_toplinks a:hover {
background: #edece8;
}
.actionlist {
display: inline;
list-style: none;
margin: 0;
padding: 0;
}
.actionlist li {
display: inline;
}
img { border: 0px; }
img.userimg { border: 0px; }
/* Main Page */
#news {
background-color: #dff0ff;
border: 2px solid #add8e6;
padding: 10px;
margin: 4px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
#news h2, #uotd h2, #mainnav h2 {
margin-top: 0px;
font-size: 1.2em;
font-weight: bold;
}
#news h3 {
color: #666666;
font-size: 1em;
margin-bottom: 2px;
}
#news p {
margin-top: 0px;
}
#uotd {
background-color: #d3d3d3;
border: 2px solid #eeeeee;
padding: 10px;
margin: 4px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
/* Forum */
td.category , tr.subtitle{
background-color: #dddddd;
border: 0px;
font-weight: bold;
margin: 6px 0px;
}
th {
font-weight: bold;
margin: 4px 2px;
padding: 4px;
}
td.postheader {
background-color: #eeeeee;
height: 24px;
margin-left: 4px;
padding-left: 8px;
-moz-border-radius: 0px 0px 10px 10px;
-webkit-border-radius: 0px 0px 10px 10px;
}
td.postbody {
font-size: 9pt;
margin-left: 4px;
background: transparent url('img/75pct_white.png');
}
td.postfooter {
background-color: #eeeeee;
height: 26px;
margin-left: 4px;
padding-left: 8px;
-moz-border-radius: 10px 10px 0px 0px;
-webkit-border-radius: 10px 10px 0px 0px;
}
tr.helpdeskseparator { height: 10pt; }
tr.postseparator {
background-color: #c8c8c8;
border: 1px solid #aaaaaa;
margin: 4px 0px;
}
td.threadline { text-align: left; }
td.numbers {
text-align: center;
}
td.numbers {
text-align: left;
}
td.lastpost {
}
.title {
font-size: 14px;
font-weight: bold;
}
.text-info, .description {
font-size: 80%;
font-weight: normal;
}
.authorcol {
width: 136px;
overflow: hidden;
}
div.authorcol {
border: 1px solid #c8c8c8;
background-color: white;
padding: 8px 5px;
width: 120px;
margin-left: 2px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
.authorinfo img {
border: 1px solid #a8a8a8;
margin: 3px 9px;
}
.authorcol input { margin: 4px 10px; }
blockquote.postbody {
border-left: 2px solid #0089e1;
background-color: #f5fffa;
padding: 2px 6px;
margin: 0px 6px 0px 10px;
font-style: italic;
}
#thread {
width: 100%;
table-layout: fixed;
overflow: visible;
}
.forum_toplinks td {
vertical-align: middle;
}
span.page_title {
font-size: 24px;
margin: 20px;
}
p.text-muted, span.note {
font-weight: normal;
font-size: 0.9em;
font-style: italic;
}
span.news_date {
color: #646464;
font-size: 0.9em;
}
span.news_title {
font-weight: bold;
}
span.inboxunread {
font-weight: bold;
}
span.highlight {
background-color: #ffffcc;
}
.nobr{
white-space: nowrap;
}
.code {
font-family: "Courier New", courier, monospace;
display: block;
margin-left: 5em;
border-left: 3px solid #ccaaaa;
padding-left: 1em;
white-space: nowrap;
overflow: auto;
}
small {
font-size: 0.8em;
}
p.text-danger, .error {
color: #ff0000;
font-weight: bold;
font-size: 1.1em;
}
.notice {
color: #009900;
font-weight: bold;
font-size: 1.1em;
}
#preview {
border: 2px solid #cccccc;
background-color: #eeeeee;
margin: 1em;
padding: 0.2em;
}
#preview .header {
font-weight: bold;
font-size: 1.3em;
border-bottom: 1px solid #cccccc;
}
/* Server Status Page */
td.running { background-color: #9aff4f; }
td.notrunning { background-color: #feff6f; }
td.disabled { background-color: #ff4f4f; }
/* IE hack */
* html body .code {
white-space: normal;
}

View File

@ -1,71 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/bolt_db.inc");
require_once("../inc/util.inc");
require_once("../inc/bolt_util.inc");
page_head("Courses");
$user = get_logged_in_user(false);
if ($user) {
BoltUser::lookup($user);
}
$courses = BoltCourse::enum();
start_table();
table_header(
"Course", "Status"
);
foreach ($courses as $course) {
if ($course->hidden && !($user->bolt->flags&BOLT_FLAG_SHOW_ALL)) {
continue;
}
$e = $user?BoltEnrollment::lookup($user->id, $course->id):null;
if ($e) {
$start = date_str($e->create_time);
$view = BoltView::lookup_id($e->last_view_id);
$ago = time_diff(time() - $view->start_time);
$pct = number_format($view->fraction_done*100, 0);
$status = "Started $start
<br>Last visit: $ago ago
<br>$pct% done
";
if ($view->fraction_done < 1) {
$status .= "<br><a href=bolt_sched.php?course_id=$course->id&action=resume>Resume</a>
";
}
$status .= "<br><a href=bolt_sched.php?course_id=$course->id&action=start>Restart</a>
| <a href=bolt_course.php?course_id=$course->id>History</a>
";
} else {
$status = "
<a href=bolt_sched.php?course_id=$course->id&action=start>Start</a>
";
}
row2_init("<b>$course->name</b>
<br><p class=\"text-muted\">$course->description</p>",
$status
);
show_refreshes();
echo "</td></tr>\n";
}
end_table();
page_tail();
?>

View File

@ -1,63 +0,0 @@
table.bolt_bar {
margin: 0px;
padding: 0px;
border: 0px;
//border-collapse: collapse;
border-spacing: 0px;
}
td.bolt_bar {
border: 1px solid #aaaaaa;
padding: 0px;
margin: 0px;
}
span.green {
padding: 2px;
background-color: #88ff88;
font-size: 0.9em;
font-style: italic;
}
span.yellow {
padding: 2px;
background-color: #ffff88;
font-size: 0.9em;
font-style: italic;
}
span.red {
padding: 2px;
background-color: #ff8888;
font-size: 0.9em;
font-style: italic;
}
td.bolt_bar1 {
padding: 0;
margin: 0px 0px;
font-size: 0.9em;
background-color: #dddddd;
}
td.bolt_bar2 {
padding: 0;
margin: 0px 0px;
font-size: 0.9em;
background-color: #44bb44;
}
tr.bolt_head1 {
background-color: #ccccff;
font-weight: bold;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}
tr.bolt_head2 {
background-color: #cccccc;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}
span.bolt_small {
}

View File

@ -1,116 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/util.inc");
$user = get_logged_in_user();
function phase_name($phase) {
switch ($phase) {
case BOLT_PHASE_STUDY: return "study";
case BOLT_PHASE_REVIEW: return "review";
case BOLT_PHASE_REFRESH: return "refresh";
default: return "unknown phase: $phase";
}
}
function mode_name($mode) {
switch ($mode) {
case BOLT_MODE_LESSON: return "lesson";
case BOLT_MODE_SHOW: return "exercise";
case BOLT_MODE_ANSWER: return "answer page";
case BOLT_MODE_FINISHED: return "course completed";
default: return "unknown mode: $mode";
}
}
function action_name($action) {
switch ($action) {
case BOLT_ACTION_NONE: return "None";
case BOLT_ACTION_NEXT: return "Next";
case BOLT_ACTION_PREV: return "Previous";
case BOLT_ACTION_SUBMIT: return "Submit";
case BOLT_ACTION_QUESTION: return "Question";
case BOLT_ACTION_COURSE_HOME: return "Course home";
default: return "unknown: $action";
}
}
function show_view($view) {
if ($view->end_time) {
$d = $view->end_time - $view->start_time;
$dur = "$d seconds";
} else {
$dur = "---";
}
if ($view->result_id) {
$result = BoltResult::lookup_id($view->result_id);
$qs = str_replace("action=answer", "action=answer_page", $result->response);
$score = number_format($result->score*100);
$x = "<br>Score: $score%
<br><a href=bolt_sched.php?$qs>Answer page</a>";
}
echo "<tr>
<td valign=top>$view->id</td>
<td valign=top>".time_str($view->start_time)."</td>
<td valign=top>$dur</td>
<td valign=top>$view->item_name</td>
<td valign=top>".mode_name($view->mode)." $x</td>
";
//<td valign=top>".phase_name($view->phase)."</td>
echo "
<td valign=top>".action_name($view->action)."</td>
</tr>
";
}
function show_views() {
global $user;
global $course;
$views = BoltView::enum("user_id=$user->id and course_id=$course->id order by id");
start_table();
table_header("ID", "Time", "Duration", "Item", "Mode",
// "Phase",
"Action");
foreach ($views as $view) {
show_view($view);
}
end_table();
}
require_once("../inc/bolt_db.inc");
require_once("../inc/bolt_util.inc");
$course_id = get_int('course_id');
$course = BoltCourse::lookup_id($course_id);
if (!$course) error_page("No such course");
page_head("Your history in $course->name");
show_views();
show_refreshes();
echo "
<a href=bolt_sched.php?course_id=$course_id&action=resume>Resume course</a>
<p>
";
page_tail();
?>

View File

@ -1,136 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/bolt.inc");
function part2() {
return sequence(
name('inner seq'),
lesson(
name('lesson 3'),
filename('bolt_sample_lesson.php?n=3')
)
);
}
function basic_review() {
return sequence(
lesson(
name('lesson 1'),
filename('bolt_sample_lesson.php?n=1')
),
lesson(
name('lesson 2'),
filename('bolt_sample_lesson.php?n=2')
)
);
}
function int_review() {
return lesson(
name('lesson 2'),
filename('bolt_sample_lesson.php?n=2')
);
}
function my_rand($student, $unit) {
return rand();
}
function sample_select() {
return select(
name('sample select'),
valuator('my_rand'),
lesson(
name('lesson 1'),
filename('bolt_sample_lesson.php?n=1')
),
lesson(
name('lesson 2'),
filename('bolt_sample_lesson.php?n=2')
),
lesson(
name('lesson 3'),
filename('bolt_sample_lesson.php?n=3')
)
);
}
function sample_random() {
return random(
name('first lessons'),
number(2),
lesson(
name('lesson 1'),
filename('bolt_sample_lesson.php?n=1')
),
lesson(
name('lesson 2'),
filename('bolt_sample_lesson.php?n=2')
),
lesson(
name('lesson 3'),
filename('bolt_sample_lesson.php?n=3')
)
);
}
function xset_with_review() {
return exercise_set(
name('exercise set 1'),
number(2),
exercise(
name('exercise 1'),
filename('bolt_sample_exercise.php?n=1')
),
exercise(
name('exercise 2'),
filename('bolt_sample_exercise.php?n=2')
),
exercise(
name('exercise 3'),
filename('bolt_sample_exercise.php?n=3')
),
repeat(.3, basic_review(), REVIEW),
repeat(.7, int_review(), REVIEW|REPEAT),
repeat(1, null, REPEAT|NEXT),
refresh(array(7, 14, 28))
);
}
function sample_xset() {
return exercise_set(
name('sample exercise set'),
number(1),
exercise(
name('exercise 1'),
filename('bolt_sample_exercise.php?n=1')
)
);
}
return sequence(
name('course'),
// sample_random(),
// xset_with_review(),
sample_select(),
sample_xset(),
part2()
);
?>

View File

@ -1,661 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
// Bolt scheduler.
// GET args:
// course_id: course ID
// action: see commands below
require_once("../inc/bolt.inc");
require_once("../inc/bolt_sched.inc");
require_once("../inc/bolt_db.inc");
require_once("../inc/bolt_ex.inc");
require_once("../inc/bolt_util.inc");
require_once("../inc/util.inc");
function debug_show_state($state, $tag) {
global $user;
global $refresh;
if ($user->bolt->flags&BOLT_FLAGS_DEBUG) {
echo "$tag state: <pre>"; print_r($state); echo "</pre>\n";
if ($refresh) {
echo "<p>Refresh ID: $refresh->id<p>";
}
echo "<hr>\n";
}
}
function debug_show_item($item) {
global $user;
if ($user->bolt->flags&BOLT_FLAGS_DEBUG) {
echo "Item:<pre>"; print_r($item); echo "</pre>\n";
echo "<hr>\n";
}
}
function update_info() {
global $user;
$sex = get_int('sex');
$birth_year = get_int('birth_year');
$user->bolt->update("sex=$sex, birth_year=$birth_year");
}
// The user clicked something on a page.
// Look up the view record (the ID is in the URL) and update it
// with the action and the time.
// Return the record.
//
function finalize_view($view_id, $action) {
global $user;
if (!$view_id) return null;
$view = BoltView::lookup_id($view_id);
if (!$view) {
error_page("no view");
}
if ($view->user_id != $user->id) {
error_page("wrong user");
}
if (!$view->end_time) {
$now = time();
$view->update("end_time=$now, action=$action");
}
return $view;
}
function default_mode($item) {
return $item->is_exercise()?BOLT_MODE_SHOW:BOLT_MODE_LESSON;
}
// A page is being shown to the user; make a record of it
//
function create_view($iter, $mode, $prev_view_id) {
global $user;
global $course;
$now = time();
$item = $iter->item;
if (!$item) {
$item = null;
$item->name = '--end--';
}
$state = $iter->encode_state();
debug_show_state($iter->state, "Ending");
return BoltView::insert("(user_id, course_id, item_name, start_time, mode, state, fraction_done, prev_view_id) values ($user->id, $course->id, '$item->name', $now, $mode, '$state', $iter->frac_done, $prev_view_id)");
}
function page_header() {
global $course;
echo "<html><head>
<title>$course->name</title>
<link rel=stylesheet type=text/css href=bolt.css>
</head><body>
";
if (function_exists('bolt_header')) bolt_header();
}
function page_footer() {
if (function_exists('bolt_footer')) bolt_footer();
echo "</body></html>";
}
// show a page saying the course has been completed
//
function show_finished_page($view_id, $prev_view_id) {
global $course;
global $url_args;
page_header("Course completed");
if ($course->bossa_app_id) {
require_once("../inc/bossa_db.inc");
$app = BossaApp::lookup_id($course->bossa_app_id);
echo "
Congratulations - you have completed the training for $course->name.
<p>
You may now
<a href=bossa_get_job.php?bossa_app_id=$course->bossa_app_id>do work</a>.
";
} else {
echo "Congratulations - you have completed this course.";
$links[] = "<a href=bolt_sched.php?$url_args&action=prev&view_id=$view_id><img src=img/prev.gif></a>";
$up_link = "<a href=bolt_sched.php?$url_args&action=course_home&view_id=$view_id>Course home page</a>";
show_nav($links, $up_link, $view_id);
}
page_footer();
}
function show_refresh_finished() {
page_header("Refresh completed");
echo "<a href=bolt.php>Return to courses</a>";
page_footer();
}
function show_nav($links, $up_link, $view_id) {
global $course;
echo "<p><center>
<table width=60%><tr>
";
foreach ($links as $link) {
echo "<td align=center>$link</td>\n";
}
echo "</tr></table> </center>
<hr>
<br>
<form action=bolt_sched.php>
<input type=hidden name=course_id value=$course->id>
<input type=hidden name=action value=question>
<input type=hidden name=view_id value=$view_id>
<textarea name=question cols=60 onfocus=\"this.value=''\">Enter question or comment here</textarea>
<br>
<input class=\"btn btn-default\" type=submit value=Submit>
</form>
<p>
$up_link
";
}
// show an item (lesson, exercise, answer page)
//
function show_item($iter, $view_id, $prev_view_id, $mode, $repeat=null) {
global $user;
global $course;
global $bolt_ex;
global $refresh;
global $url_args;
$item = $iter->item;
page_header();
$bolt_query_string = $item->query_string;
$links = array();
if ($prev_view_id) {
$links[] = "<a href=bolt_sched.php?$url_args&action=prev&view_id=$view_id><img src=img/prev.gif></a>";
}
$next = "<a href=bolt_sched.php?$url_args&action=next&view_id=$view_id><img src=img/next.gif border=0></a>";
if ($item->is_exercise()) {
$bolt_ex->mode = $mode;
$bolt_ex->index = 0;
switch ($mode) {
case BOLT_MODE_SHOW:
echo "
<form action=bolt_sched.php>
<input type=hidden name=view_id value=$view_id>
<input type=hidden name=course_id value=$course->id>
<input type=hidden name=action value=answer>
";
if ($refresh) {
echo "
<input type=hidden name=refresh_id value=$refresh->id>
";
}
srand($view_id);
require($item->filename);
if (function_exists('bolt_divide')) bolt_divide();
$next = "<input type=image src=img/next.gif value=OK></form>";
break;
case BOLT_MODE_ANSWER:
require($item->filename);
if (function_exists('bolt_divide')) bolt_divide();
$score_pct = number_format($bolt_ex->score*100);
echo "Score: $score_pct%";
break;
}
} else {
require_once($item->filename);
if (function_exists('bolt_divide')) bolt_divide();
}
if ($repeat) {
$avg = number_format($repeat->avg_score*100, 0);
echo "<p>Score on this exercise set: $avg%";
if ($repeat->flags & REVIEW) {
//echo "<pre>";
//print_r($repeat);
//echo "</pre>";
$name = urlencode($repeat->unit->name);
$r = "<a href=bolt_sched.php?$url_args&action=review&view_id=$view_id&unit_name=$name>Review, then repeat exercises</a>";
$links[] = $r;
}
if ($repeat->flags & REPEAT) {
$r = "<a href=bolt_sched.php?$url_args&action=repeat&view_id=$view_id>Repeat exercises</a>";
$links[] = $r;
}
if ($repeat->flags & NEXT) {
$links[] = $next;
}
} else {
$links[] = $next;
}
$up_link = "<a href=bolt_sched.php?$url_args&action=course_home&view_id=$view_id>Course home page</a>";
show_nav($links, $up_link, $view_id);
page_footer();
if ($refresh) {
$refresh->update("last_view_id=$view_id");
} else {
$e = new BoltEnrollment();
$e->user_id = $user->id;
$e->course_id = $course->id;
$e->update("last_view_id=$view_id");
}
}
// Show the student the results of an old exercise; no navigation items
//
function show_answer_page($iter, $score) {
global $bolt_ex;
$bolt_ex->mode = BOLT_MODE_ANSWER;
$bolt_ex->index = 0;
$item = $iter->item;
page_header();
$bolt_query_string = $item->query_string;
require_once($item->filename);
if (function_exists('bolt_divide')) bolt_divide();
$score_pct = number_format($score*100);
echo "Score: $score_pct%";
page_footer();
}
function start_course() {
global $user;
global $course;
global $course_doc;
BoltEnrollment::delete($user->id, $course->id);
$iter = new BoltIter($course_doc);
$iter->at();
$now = time();
$mode = default_mode($iter->item);
$view_id = create_view($iter, $mode, 0);
BoltEnrollment::insert("(create_time, user_id, course_id, last_view_id) values ($now, $user->id, $course->id, $view_id)");
show_item($iter, $view_id, 0, $mode);
}
function start_refresh() {
global $course_doc;
global $refresh;
$xset_result = BoltXsetResult::lookup_id($refresh->xset_result_id);
if (!$xset_result) error_page("Exercise set result not found");
$view = BoltView::lookup_id($xset_result->view_id);
if (!$view) error_page("view not found");
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
$iter->at();
$xset = $iter->xset;
if (!$xset || $xset->name != $xset_result->name) {
error_page("missing exercise set");
}
$xset->restart($iter);
$iter->at();
$mode = default_mode($iter->item);
$view_id = create_view($iter, $mode, 0);
show_item($iter, $view_id, 0, $mode);
}
function show_next($iter, $view) {
global $refresh, $user, $course;
$iter->next();
if ($refresh) {
$iter->at();
if (!$iter->xset) {
// if we're doing a refresh and are no longer in an xset,
// we must have finished the refresh
//
show_refresh_finished();
$refresh->update('count=count+1');
return;
}
}
if ($iter->item) {
$state = $iter->encode_state();
$mode = default_mode($iter->item);
$view_id = create_view($iter, $mode, $view->id);
show_item($iter, $view_id, $view->id, $mode);
} else {
// course finished
$iter->frac_done = 1;
$fin_view_id = create_view($iter, BOLT_MODE_FINISHED, $view->id);
$e = new BoltEnrollment();
$e->user_id = $user->id;
$e->course_id = $course->id;
$e->update("last_view_id=$fin_view_id");
show_finished_page($fin_view_id, $view->id);
}
}
$user = get_logged_in_user();
BoltUser::lookup($user);
$course_id = get_int('course_id');
$refresh_id = get_int('refresh_id', true);
$refresh = null;
$url_args = "course_id=$course_id";
if ($refresh_id) {
$refresh = BoltRefreshRec::lookup_id($refresh_id);
if (!$refresh) error_page("No such refresh");
if ($refresh->user_id != $user->id) error_page("Wrong user");
if ($refresh->course_id != $course_id) error_page("Wrong course");
$url_args .= "&refresh_id=$refresh_id";
}
$course = BoltCourse::lookup_id($course_id);
if (!$course) {
error_page("no such course");
}
$view_id = get_int('view_id', true);
$action = sanitize_tags(get_str('action', true));
$course_doc = require_once($course->doc_file());
switch ($action) {
case 'start':
if (info_incomplete($user)) {
request_info($user, $course);
exit();
}
if ($refresh) {
start_refresh();
exit();
}
$e = BoltEnrollment::lookup($user->id, $course_id);
if ($e) {
page_header();
echo "You are already enrolled in $course->name.
<p>
Are you sure you want to start over from the beginning?
<p>
";
show_button(
"bolt_sched.php?action=start_confirm&$url_args",
"Yes",
"Start this course from the beginning"
);
show_button(
"bolt_sched.php?action=resume&$url_args",
"Resume",
"Resume course from current position"
);
page_footer();
exit();
}
// fall through
case 'start_confirm':
start_course();
break;
case 'update_info':
update_info();
start_course();
break;
case 'prev':
$view = finalize_view($view_id, BOLT_ACTION_PREV);
debug_show_state(unserialize($view->state), "Initial");
if ($view->prev_view_id) {
$view = BoltView::lookup_id($view->prev_view_id);
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
$iter->at();
$mode = $view->mode;
if ($mode == BOLT_MODE_ANSWER) {
$v2 = BoltView::lookup_id($view->prev_view_id);
$result = BoltResult::lookup_id($v2->result_id);
srand($v2->id);
$bolt_ex->score = $result->score;
$bolt_ex->query_string = $result->response;
}
$view_id = create_view($iter, $mode, $view->prev_view_id);
show_item($iter, $view_id, $view->prev_view_id, $mode);
} else {
error_page("At start of course");
}
break;
case 'next': // "next" button in lesson or exercise answer page
$view = finalize_view($view_id, BOLT_ACTION_NEXT);
debug_show_state(unserialize($view->state), "Initial");
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
show_next($iter, $view);
break;
case 'answer': // submit answer in exercise
$view = finalize_view($view_id, BOLT_ACTION_SUBMIT);
debug_show_state(unserialize($view->state), "Initial");
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
$iter->at();
debug_show_item($iter->item);
$item = $iter->item;
if (!$item->is_exercise()) {
print_r($item);
error_page("expected an exercise");
}
if ($view->item_name != $item->name) {
error_page("unexpected name");
}
// compute the score
$bolt_ex->query_string = $_SERVER['QUERY_STRING'];
$bolt_ex->mode = BOLT_MODE_SCORE;
$bolt_ex->index = 0;
$bolt_ex->score = 0;
$bolt_query_string = $item->query_string;
srand($view_id);
ob_start(); // buffer output to avoid showing exercise text
require($item->filename);
ob_end_clean();
$bolt_ex->score /= $bolt_ex->index;
if ($item->callback) {
call_user_func(
$item->callback, $bolt_ex->score, $bolt_ex->query_string
);
}
// make a record of the result
$qs = BoltDb::escape_string($_SERVER['QUERY_STRING']);
$now = time();
$result_id = BoltResult::insert(
"(create_time, user_id, course_id, view_id, item_name, score, response)
values ($now, $user->id, $course->id, $view->id, '$view->item_name', $bolt_ex->score, '$qs')"
);
$view->update("result_id=$result_id");
// If this is part of an exercise set, call its callback function
//
$repeat = null;
$xset = $iter->xset;
if ($xset) {
$is_last = $xset->xset_record_score(
$iter, $bolt_ex->score, $view->id, $avg_score, $repeat
);
if ($repeat) $repeat->avg_score = $avg_score;
if ($is_last) {
// if the exercise set if finished, make or update DB records
//
if ($xset->callback) {
call_user_func($xset->callback, $avg_score);
}
$now = time();
$id = BoltXsetResult::insert("(create_time, user_id, course_id, name, score, view_id) values ($now, $user->id, $course->id, '$xset->name', $avg_score, $view_id)");
$refresh_intervals = $xset->refresh;
if ($refresh_intervals) {
$refresh_rec = BoltRefreshRec::lookup(
"user_id=$user->id and course_id=$course->id and name='$xset->name'"
);
if ($refresh_rec) {
$count = $refresh_rec->count;
$n = count($refresh_intervals->intervals);
if ($count >= $n) {
$count = $n - 1;
}
$due_time = time() + $refresh_intervals->intervals[$count]*86400;
$refresh_rec->update("create_time=$now, xset_result_id=$id, due_time=$due_time");
} else {
$due_time = time() + $refresh_intervals->intervals[0]*86400;
BoltRefreshRec::insert(
"(user_id, course_id, name, create_time, xset_result_id, due_time, count) values ($user->id, $course->id, '$xset->name', $now, $id, $due_time, 0)"
);
}
}
}
}
// show the answer page
if ($item->has_answer_page) {
srand($view_id);
$view_id = create_view($iter, BOLT_MODE_ANSWER, $view->id);
show_item($iter, $view_id, $view->id, BOLT_MODE_ANSWER, $repeat);
} else {
show_next($iter, $view);
}
break;
case 'answer_page':
$view = BoltView::lookup_id($view_id);
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
$iter->at();
if ($iter->item->name != $view->item_name) {
error_page("Exercise no longer exists in course");
}
$result = BoltResult::lookup_id($view->result_id);
srand($view_id);
$bolt_ex->query_string = $result->response;
show_answer_page($iter, $result->score);
break;
case 'course_home':
$view = finalize_view($view_id, BOLT_ACTION_COURSE_HOME);
Header("Location: bolt.php");
break;
case 'review':
// user chose to do review then repeat an exercise set
//
$view = finalize_view($view_id, BOLT_ACTION_REVIEW);
debug_show_state(unserialize($view->state), "Initial");
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
$iter->at();
if (!$iter->xset) {
echo "NO XSET"; exit;
}
$xset = $iter->xset;
$unit_name = sanitize_tags(get_str('unit_name'));
$found = $xset->start_review($iter, $unit_name);
if (!$found) {
echo "REVIEW UNIT MISSING"; exit;
}
$iter->at();
$mode = default_mode($iter->item);
$view_id = create_view($iter, $mode, $view->id);
show_item($iter, $view_id, $view->id, $mode);
break;
case 'repeat':
// user chose to repeat an exercise set
//
$view = finalize_view($view_id, BOLT_ACTION_REPEAT);
debug_show_state(unserialize($view->state), "Initial");
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
$iter->at();
if (!$iter->xset) {
echo "NO XSET"; exit;
}
$xset = $iter->xset;
$xset->restart($iter);
$iter->at();
$mode = default_mode($iter->item);
$view_id = create_view($iter, $mode, $view->id);
show_item($iter, $view_id, $view->id, $mode);
break;
case 'resume':
// user chose to resume a course or refresh
//
if ($refresh) {
if ($refresh->last_view_id) {
$view = BoltView::lookup_id($refresh->last_view_id);
} else {
start_refresh();
exit();
}
} else {
$view = null;
$e = BoltEnrollment::lookup($user->id, $course_id);
if ($e) {
$view = BoltView::lookup_id($e->last_view_id);
}
if (!$view) {
start_course();
break;
}
}
if ($view->mode == BOLT_MODE_FINISHED) {
show_finished_page($view->id, $view->prev_view_id);
break;
}
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
$iter->at();
$mode = $view->mode;
if ($view->item_name == $iter->item->name && ($mode == BOLT_MODE_ANSWER)) {
// if we're returning to an answer page,
// we need to look up the user's responses and the score.
//
$view_orig = BoltView::lookup_id($view->prev_view_id);
$result = BoltResult::lookup_id($view_orig->result_id);
srand($view_orig->id);
$bolt_ex->query_string = $result->response;
$bolt_ex->score = $result->score;
$bolt_ex->index = 0;
$view_id = create_view($iter, $mode, $view_orig->id);
show_item($iter, $view_id, $view_orig->id, $mode);
} else {
$view_id = create_view($iter, $mode, $view->id);
show_item($iter, $view_id, $view->id, $mode);
}
break;
case 'question':
$view = finalize_view($view_id, BOLT_ACTION_QUESTION);
debug_show_state(unserialize($view->state), "Initial");
$now = time();
$question = BoltDb::escape_string(get_str('question'));
BoltQuestion::insert("(create_time, user_id, course_id, name, mode, question, state) values ($now, $user->id, $course->id, '$view->item_name', $view->mode, '$question', 0)");
page_header();
echo "
Thanks; we have recorded your question.
Questions help us improve this course.
We aren't able to individually respond to all questions.
Responses are delivered as private messages.
<p>
<a href=bolt_sched.php?$url_args&action=resume>Resume course</a>
";
page_footer();
break;
default:
error_page("unknown action: $action");
}
?>

View File

@ -1,69 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/util.inc");
require_once("../inc/bossa_db.inc");
require_once("../inc/bolt_db.inc");
function show_app($app) {
global $user;
if ($app->bolt_course_id) {
if ($user) {
switch (bolt_course_status($app->bolt_course_id, $user->id)) {
case BOLT_COURSE_NOT_STARTED:
$x = "<a href=bolt_sched.php?action=start&course_id=$app->bolt_course_id>Take training course</a>";
break;
case BOLT_COURSE_STARTED:
$x = "<a href=bolt_sched.php?action=resume&course_id=$app->bolt_course_id>Finish training course</a>";
break;
case BOLT_COURSE_FINISHED:
$x = "<a href=bossa_get_job.php?bossa_app_id=$app->id>Get job</a>";
break;
}
} else {
$x = "<a href=bolt_sched.php?action=start&course_id=$app->bolt_course_id>Take training course</a>";
}
} else {
$x = "<a href=bossa_get_job.php?bossa_app_id=$app->id>Get job</a>";
}
$est = number_format($app->time_estimate/60., 2);
$limit = number_format($app->time_limit/60., 2);
row2("$app->name<br><p class=\"text-muted\">$app->description<br>Time: $est min. average, $limit min limit</p>", $x);
}
function show_apps() {
$apps = BossaApp::enum();
foreach ($apps as $app) {
if ($app->hidden) continue;
show_app($app);
}
}
function main() {
page_head("Bossa apps");
start_table();
show_apps();
end_table();
page_tail();
}
$user = get_logged_in_user();
main();
?>

View File

@ -1,69 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/util.inc");
require_once("../inc/bossa.inc");
require_once("../inc/bossa_example4.inc");
function handle_add($job, $inst) {
$f = null;
$f->x = get_int('pic_x');
$f->y = get_int('pic_y');
$f->type = sanitize_tags(get_str('type'));
$c = sanitize_tags(get_str('comment', true));
if (strstr($c, "(optional)")) $c = "";
$f->comment = $c;
$output = $inst->get_opaque_data();
$output->features[] = $f;
$inst->set_opaque_data($output);
header("location: bossa_example4.php?bji=$inst->id");
}
function handle_delete($job, $inst, $index) {
$output = $inst->get_opaque_data();
$features = $output->features;
array_splice($features, $index, 1);
$output->features = $features;
$inst->set_opaque_data($output);
header("location: bossa_example4.php?bji=$inst->id");
}
$bji = get_int("bji");
if (!bossa_lookup_job($bji, $job, $inst, $u)) {
error_page("No such instance");
}
$user = get_logged_in_user();
if ($u->id != $user->id) {
error_page("Not your job");
}
$action = get_str("action", true);
switch ($action) {
case "add":
handle_add($job, $inst);
break;
case "delete":
$index = get_int("index");
handle_delete($job, $inst, $index);
break;
default:
job_show($job, $inst, $user);
break;
}
?>

View File

@ -1,38 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/util.inc");
require_once("../inc/bossa_db.inc");
require_once("../inc/bossa_impl.inc");
$user = get_logged_in_user();
BossaUser::lookup($user);
$bossa_app_id = get_int('bossa_app_id');
$app = BossaApp::lookup_id($bossa_app_id);
if (!$app) {
error_page("no such app: $bossa_app_id");
}
{
$trans = new BossaTransaction();
show_next_job($app, $user);
}
?>

View File

@ -1,54 +0,0 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
require_once("../inc/util.inc");
require_once("../inc/bossa_db.inc");
require_once("../inc/bossa_impl.inc");
$user = get_logged_in_user();
$inst = BossaJobInst::lookup_id(get_int('bji'));
if (!$inst) {
error_page("No such job instance");
}
if ($inst->user_id != $user->id) {
error_page("Bad user ID");
}
if ($inst->finish_time) {
error_page("You already finished this job");
}
$job = BossaJob::lookup_id($inst->job_id);
if (!$job) {
error_page("No such job");
}
$app = BossaApp::lookup_id($job->app_id);
$file = "../inc/$app->short_name.inc";
require_once($file);
{
$trans = new BossaTransaction();
$now = time();
$inst->update("finish_time=$now, timeout=0");
BossaUser::lookup($user);
job_finished($job, $inst, $user);
show_next_job($app, $user);
}
?>