- API: fix Win build error

- API: fix Makefile.am
- add LGPL license on some files

svn path=/trunk/boinc/; revision=14629
This commit is contained in:
David Anderson 2008-01-28 22:42:05 +00:00
parent 9c89b45af2
commit f682236bd9
15 changed files with 302 additions and 338 deletions

View File

@ -6,10 +6,12 @@ include $(top_srcdir)/Makefile.incl
AM_CFLAGS += @GLUT_CFLAGS@
AM_LDFLAGS += @GLUT_LIBS@
# stuff linked into both main app and graphics app
api_files= \
boinc_api.C \
graphics2_util.C
# stuff linked into graphics app
graphics2_files = \
gutil.C \
gutil_text.C \
@ -21,8 +23,8 @@ graphics2_files = \
graphics2_unix.C
if OS_DARWIN
api_files += mac_icon.C
graphics2_files += macglutfix.m
graphics2_files += mac_icon.C
graphics2_files += macglutfix.m
endif
EXTRA_DIST = *.h

View File

@ -1,3 +1,24 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// This 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 2.1 of the License, or (at your option) any later version.
//
// This software 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.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// platform-independent part of graphics library
//
#include "util.h"
#include "app_ipc.h"
#include "shmem.h"

View File

@ -1,3 +1,24 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// This 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 2.1 of the License, or (at your option) any later version.
//
// This software 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.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// unix-specific graphics stuff
//
#include "config.h"
#include <stdlib.h>
#include <stdio.h>

View File

@ -1,3 +1,25 @@
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// This 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 2.1 of the License, or (at your option) any later version.
//
// This software 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.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// graphics-related utilities, used both from main applications
// (set create shared mem) and by the graphics app
#ifdef _WIN32
#include "boinc_win.h"
#elif (!defined(__EMX__))

View File

@ -375,18 +375,18 @@ void boinc_graphics_loop(int argc, char** argv) {
extern int main(int, char**);
static HINSTANCE hInstance = NULL;
static HINSTANCE instance = NULL;
// call this with the resource names you compiled the icons with
// (16x16 and 48x48 pixel)
//
void boinc_set_windows_icon(const char*icon16,const char*icon48) {
void boinc_set_windows_icon(const char* icon16, const char* icon48) {
LONG ic;
HWND hWnd=FindWindow("BOINC_app",NULL);
if (ic=(LONG)LoadIcon(hInstance,icon48)) {
if (ic=(LONG)LoadIcon(instance,icon48)) {
SetClassLongPtr(hWnd,GCLP_HICON,ic);
}
if (ic=(LONG)LoadImage(hInstance,icon16, IMAGE_ICON, 16, 16, 0)) {
if (ic=(LONG)LoadImage(instance,icon16, IMAGE_ICON, 16, 16, 0)) {
SetClassLongPtr(hWnd,GCLP_HICONSM,ic);
}
}
@ -396,7 +396,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode
char* argv[100];
int argc;
hInstance = hInst;
instance = hInst;
command_line = GetCommandLine();
argc = parse_command_line(command_line, argv);
main(argc, argv);

View File

@ -17,6 +17,8 @@
// or write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// DEPRECATED - DO NOT USE
#if defined(_WIN32) && !defined(__STDWX_H__) && !defined(_BOINC_WIN_) && !defined(_AFX_STDAFX_H_)
#include "boinc_win.h"
#else

View File

@ -822,3 +822,16 @@ David Jan 28 2008
http_curl.C
log_flags.C,h
scheduler_op.C
David Jan 28 2008
- API: fix Win build error
- API: fix Makefile.am
- add LGPL license on some files
api/
Makefile.am
graphics_api.C
graphics2_win.C
graphics2_unix.C
graphics2_util.C
graphics2.C

View File

@ -76,7 +76,7 @@ create table bolt_result (
);
-- represents the result of a completed exercise set,
-- where "completed" means the student clicked Next on the final answer page.
-- 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
--

View File

@ -1,25 +1,11 @@
<?php
// Bolt course document API
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
// stuff needed in Bolt course documents
// rules about course structures:
//
// - Each unit has a logical name.
// - The members of a set must have distinct logical names
// - Different units may have the same logical name;
// however, such units must be identical.
// 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.
abstract class BoltUnit {
public $name; // logical name.
public $title;
@ -36,47 +22,8 @@ abstract class BoltUnit {
// frac_done: Fraction done (of this unit and any subunits)
}
// An iterator represents a user's position in a course.
// Its state is stored in the database,
// and the course may change underneath it.
// base class for exercise and lesson
//
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 = json_decode($encoded_state, true);
}
function encode_state() {
return json_encode($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);
}
}
class BoltItem extends BoltUnit {
public $filename;
public $query_string;
@ -113,6 +60,106 @@ class BoltExercise extends BoltItem {
}
}
// Base class for control structures (i.e. all units that are not items).
// These have the following properties:
// - a set of units
// - an ordering of this set, defined in the derived class
// (i.e., random, student-specific, or identity)
// - an index (state_rec::index) for where we are in this list
// - an index (state_rec::nshown) for how many units completed so far
// - a number "ntoshow" for how many to show
//
class BoltSet extends BoltUnit {
public $units;
function __construct($name, $units, $ntoshow) {
$this->name = $name;
$this->is_item = false;
$this->units = $units;
$this->ntoshow = $ntoshow;
$this->ordered = false;
}
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($state_rec);
$this->ordered = true;
}
// 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;
$state_rec['nshown'] = 0;
$state_rec['child_name'] = null;
$iter->state[$this->name] = $state_rec;
return true;
} else {
$i = ($i+1)%$n;
}
}
}
} else {
// here if no state record; initialize
//
$i = 0;
$nshown = 0;
$state_rec = null;
$this->order($state_rec);
}
// at this point, $i is index of current child
//
$child = $this->units[$i];
$frac_done = $nshown/$n;
$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;
}
}
function name($n) {
return array('name', $n);
}
@ -185,19 +232,6 @@ function exercise() {
return new BoltExercise($name, $title, $file);
}
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";
}
require_once('../inc/bolt_seq.inc');
require_once('../inc/bolt_rnd.inc');
require_once('../inc/bolt_xset.inc');

View File

@ -1,5 +1,7 @@
<?php
// Bolt exercise API
$bolt_ex_mode = 0;
$bolt_ex_index = 0;
$bolt_ex_state = 0;

View File

@ -1,99 +1,20 @@
<?php
// state for random unit is:
// seed The RNG seed used to shuffle
// i index of current child
// number_shown number of units shown so far (not necessarily the
// same as i on 2nd and later pass through this unit)
// child_name name of current child
class BoltRandom extends BoltUnit {
class BoltRandom extends BoltSet {
public $units;
function __construct($name, $units, $number) {
$this->name = $name;
$this->units = $units;
$this->number = $number;
$this->is_item = false;
$this->shuffled = false;
parent::__construct($name, $units, $number);
}
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'];
$number_shown = $state_rec['number_shown'];
if (!$this->shuffled) {
srand($state_rec['seed']);
shuffle($this->units);
$this->shuffled = true;
}
// 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['i'];
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) {
$my_inc = false;
if ($child->is_item) {
$my_inc = true;
} else {
$my_inc = $child->walk($iter, $incr, $frac_done);
}
if ($my_inc) {
$i = ($i+1)%$n;
$number_shown++;
if ($number_shown >= $this->number) {
$frac_done = 1;
$state_rec['i'] = $i;
$state_rec['number_shown'] = 0;
$state_rec['child_name'] = null;
$iter->state[$this->name] = $state_rec;
return true;
}
}
}
function order(&$state_rec) {
if ($state_rec) {
$seed = $state_rec['seed'];
} else {
$i = 0;
$number_shown = 0;
$state_rec = null;
$seed = ((double)microtime()*1000000);
srand($seed);
shuffle($this->units);
$state_rec['seed'] = $seed;
}
$child = $this->units[$i];
$frac_done = $number_shown/$this->number;
$state_rec['i'] = $i;
$state_rec['number_shown'] = $number_shown;
$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/$number);
}
srand($seed);
shuffle($this->units);
}
}

65
html/inc/bolt_sched.inc Normal file
View File

@ -0,0 +1,65 @@
<?php
// 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 = json_decode($encoded_state, true);
}
function encode_state() {
return json_encode($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,77 +1,11 @@
<?php
class BoltSequence extends BoltUnit {
public $units;
class BoltSequence extends BoltSet {
function __construct($name, $units) {
$this->name = $name;
$this->units = $units;
$this->is_item = false;
parent::__construct($name, $units, count($units));
}
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'];
// 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['i'];
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) {
$my_inc = false;
if ($child->is_item) {
$my_inc = true;
} else {
$my_inc = $child->walk($iter, $incr, $frac_done);
}
if ($my_inc) {
$i++;
if ($i == $n) {
$frac_done = 1;
$state_rec['i'] = 0;
$state_rec['child_name'] = null;
$iter->state[$this->name] = $state_rec;
return true;
}
}
}
} else {
$i = 0;
}
$child = $this->units[$i];
$frac_done = $i/$n;
$state_rec = null;
$state_rec['i'] = $i;
$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);
}
function order() {
}
}

View File

@ -1,128 +1,48 @@
<?php
class BoltExerciseSet extends BoltUnit {
public $units;
class BoltExerciseSet extends BoltRandom {
public $repeats;
public $state_rec;
function __construct($name, $units, $number, $repeats) {
$this->name = $name;
$this->units = $units;
$this->number = $number;
parent::__construct($name, $units, $number);
$this->repeats = $repeats;
$this->is_item = false;
$this->shuffled = false;
}
// the scheduler calls this when an exercise in this set
// has just been graded.
// called when an exercise in this set has just been graded.
// - record the score in our state structure
// - return a structure saying what navigation info to show:
// - review
// - repeat now
// - next
//
function xset_callback($iter, $score, &$is_last, &$nav_info) {
function xset_callback(&$iter, $score, $view_id, &$is_last, &$nav_info) {
echo "XSET_CALLBACK: $score";
$nav_info = null;
$state_rec = $iter->state[$this->name];
$number_shown = $state_rec['number_shown'];
$state_rec['scores'][$number_shown] = $score;
$is_last = ($number_shown == $this->number);
if ($is_last) {
} else {
}
}
$nshown = $state_rec['nshown'];
$state_rec['scores'][$nshown] = $score;
$iter->state[$this->name] = $state_rec;
$is_last = ($nshown == $this->ntoshow);
if (!$is_last) return;
// 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; $i++) {
$total_score += $state_rec['score'][$i];
}
$avg_score = $total_score/$nshown;
// The user clicked "Next" on last answer page,
// so this exercise set is now "completed".
// - create exercise_set_result record
// - optionally create or update bolt_refresh record
//
function completed($score, $view_id) {
$now = time();
$id = BoincXsetResult::insert("(create_time, user_id, course_id, name, score, view_id) values ($now, $user->id, $course->id, '$this->name', $score, $view_id)");
$id = BoincXsetResult::insert("(create_time, user_id, course_id, name, score, view_id) values ($now, $user->id, $course->id, '$this->name', $avg_score, $view_id)");
$due_time = $now + 100000;
BoincRefresh::replace("create_time=$now, user_id=$user->id, course_id=$course->id, name='$this->name', set_result_id=$id, due_time=$due_time");
}
function walk(&$iter, $incr, &$frac_done) {
$iter->xset = $this;
$n = count($this->units);
if (array_key_exists($this->name, $iter->state)) {
$state_rec = $iter->state[$this->name];
$this->state_rec = $state_rec;
$child_name = $state_rec['child_name'];
$number_shown = $state_rec['number_shown'];
if (!$this->shuffled) {
srand($state_rec['seed']);
shuffle($this->units);
$this->shuffled = true;
}
// 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['i'];
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) {
$my_inc = false;
if ($child->is_item) {
$my_inc = true;
} else {
$my_inc = $child->walk($iter, $incr, $frac_done);
}
if ($my_inc) {
$i = ($i+1)%$n;
$number_shown++;
if ($number_shown >= $this->number) {
$frac_done = 1;
$state_rec['i'] = $i;
$state_rec['number_shown'] = 0;
$state_rec['child_name'] = null;
$iter->state[$this->name] = $state_rec;
return true;
}
}
}
} else {
$i = 0;
$number_shown = 0;
$state_rec = null;
$seed = ((double)microtime()*1000000);
srand($seed);
shuffle($this->units);
$state_rec['seed'] = $seed;
}
$child = $this->units[$i];
$frac_done = $number_shown/$this->number;
$state_rec['i'] = $i;
$state_rec['number_shown'] = $number_shown;
$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/$number);
}
return parent::walk($iter, $incr, $frac_done);
}
}

View File

@ -6,6 +6,7 @@
// 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");
@ -261,11 +262,11 @@ case 'next': // "next" button in lesson or exercise answer page
break;
case 'answer': // submit answer in exercise
$view = finalize_view($user, $view_id, BOLT_ACTION_SUBMIT);
if ($user->bolt->debug) {
echo "<pre>State: $view->state</pre>\n";
}
$iter = new BoltIter($course_doc);
$iter->decode_state($view->state);
if ($user->bolt->debug) {
echo "<pre>Initial state:"; print_r($iter->state); echo "</pre>\n";
}
$iter->at();
if ($user->bolt->debug) {
@ -303,6 +304,12 @@ case 'answer': // submit answer in exercise
);
$view->update("result_id=$result_id");
// If this is part of an exercise set, call its callback function
//
if ($iter->xset) {
$iter->xset->xset_callback($iter, $bolt_ex_score, $view->id, $is_last, $nav_info);
}
// show the answer page
srand($view_id);