diff --git a/db/bossa_schema.sql b/db/bossa_schema.sql index 8dcbf4200b..afd0abf44a 100644 --- a/db/bossa_schema.sql +++ b/db/bossa_schema.sql @@ -2,11 +2,16 @@ create table bossa_app ( id integer not null auto_increment, create_time integer not null, name varchar(255) not null, - user_friendly_name varchar(255) not null, + description varchar(255) not null, long_jobs tinyint not null, - start_url varchar(255) not null, - deprecated tinyint not null, + display_script varchar(255) not null, + backend_script varchar(255) not null, + hidden tinyint not null, + min_conf_sum double not null, + min_conf_frac double not null, + max_instances integer not null, info text, + -- app-specific info, JSON primary key(id) ); @@ -19,12 +24,10 @@ create table bossa_job ( batch integer not null, time_estimate integer not null, time_limit integer not null, - more_needed tinyint not null, - npending smallint not null, - nsuccess smallint not null, - nsuccess_needed smallint not null, + transition_time double not null, + nneeded integer not null, primary key(id) -); +) engine=InnoDB; create table bossa_job_inst ( id integer not null auto_increment, @@ -34,7 +37,7 @@ create table bossa_job_inst ( finish_time integer not null, info text, primary key(id) -); +) engine=InnoDB; create table bossa_app_user ( app_id integer not null, diff --git a/doc/boinc_news.php b/doc/boinc_news.php index e18b819202..08f7e7c7cb 100644 --- a/doc/boinc_news.php +++ b/doc/boinc_news.php @@ -1,6 +1,11 @@ $project_news = array( +array("Feb 11, 2008", + "Bulgarian BOINC users: + find forums and information in your language at + BOINC Bulgaria." +), array("Feb 7, 2008", "Proteins@Home has resumed operations. diff --git a/doc/links.php b/doc/links.php index afbd13c7e5..713a4a9811 100644 --- a/doc/links.php +++ b/doc/links.php @@ -170,6 +170,9 @@ language("Belgium (Dutch/French/English)", array( site("http://www.boinc.be", "www.boinc.be"), site("http://icewolves.plid.be", "IceWolves"), )); +language("Bulgarian", array( + site("http://www.boinc-bulgaria.net", "BOINC Bulgaria") +)); language("Catalan", array( site("http://www.boinc.cat", "BOINC.cat"), )); diff --git a/html/inc/bossa.inc b/html/inc/bossa.inc index 2093ed4efb..664365c9ee 100644 --- a/html/inc/bossa.inc +++ b/html/inc/bossa.inc @@ -15,6 +15,9 @@ class Bossa { if ($bji->user_id != $user->id) { error_page("Bad user ID"); } + if ($bji->finish_time) { + error_page("You already finished this job"); + } $bj = BossaJob::lookup_id($bji->job_id); if (!$bj) { error_page("No such job"); diff --git a/html/inc/bossa_db.inc b/html/inc/bossa_db.inc index e1ede7bc56..5884d92710 100644 --- a/html/inc/bossa_db.inc +++ b/html/inc/bossa_db.inc @@ -22,18 +22,16 @@ class BossaDb extends DbConn { } return $instance; } + static function escape_string($string) { + $db = self::get(); + return $db->base_escape_string($string); + } } class BossaApp { - function insert() { + function insert($clause) { $db = BossaDb::get(); - if (!isset($this->long_jobs)) $this->long_jobs = 0; - $now = time(); - $query = "insert into DBNAME.bossa_app (create_time, name, user_friendly_name, long_jobs, start_url) values ($now, '$this->name', '$this->user_friendly_name', $this->long_jobs, '$this->start_url')"; - $result = $db->do_query($query); - if (!$result) return false; - $this->id = $db->insert_id(); - return true; + return $db->insert('bossa_app', $clause); } static function lookup_name($name) { @@ -56,7 +54,7 @@ class BossaJob { function insert() { $db = BossaDb::get(); $now = time(); - $query = "insert into DBNAME.bossa_job (create_time, name, app_id, info, batch, time_estimate, time_limit, more_needed, npending, nsuccess, nsuccess_needed) values ($now, '$this->name', $this->app_id, '$this->info', $this->batch, $this->time_estimate, $this->time_limit, 1, 0, 0, $this->nsuccess_needed)"; + $query = "insert into DBNAME.bossa_job (create_time, name, app_id, info, batch, time_estimate, time_limit, nneeded) values ($now, '$this->name', $this->app_id, '$this->info', $this->batch, $this->time_estimate, $this->time_limit, $this->nneeded)"; $result = $db->do_query($query); if (!$result) { echo "$query\n"; @@ -114,8 +112,9 @@ class BossaJobInst { // this query skips jobs for which this user // has already been assigned an instance // + // TODO: put the following in a transaction $db = BossaDb::get(); - $query = "select bossa_job.* from DBNAME.bossa_job left join DBNAME.bossa_job_inst on bossa_job_inst.job_id = bossa_job.id where bossa_job.more_needed<>0 and bossa_job_inst.user_id is null limit 1"; + $query = "select bossa_job.* from DBNAME.bossa_job left join DBNAME.bossa_job_inst on bossa_job_inst.job_id = bossa_job.id where bossa_job.nneeded>0 and bossa_job_inst.user_id is null limit 1"; $result = $db->do_query($query); if (!$result) return null; $job = mysql_fetch_object($result, 'BossaJob'); @@ -130,6 +129,8 @@ class BossaJobInst { echo mysql_error(); return null; } + + $job->update("nneeded=nneeded-1"); return $ji; } diff --git a/html/inc/bossa_example.inc b/html/inc/bossa_example.inc new file mode 100644 index 0000000000..2f22a839b2 --- /dev/null +++ b/html/inc/bossa_example.inc @@ -0,0 +1,40 @@ +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; + } +} + +// handle a completed job with the given consensus set +// +function handle_consensus($bj, $c) { + $res = $c[0]; + if ($res->have_ellipse) { + $res->cx = 0; + $res->cy = 0; + foreach ($c as $r) { + $res->cx += $r->cx; + $res->cy += $r->cy; + } + $res->cx /= count($c); + $res->cy /= count($c); + } + + $info = json_decode[$bj->info); + $info->result = $res; + $i = json_encode($info); + $bj->update("info='$i'"); +} + +?> diff --git a/html/inc/dir_hier.inc b/html/inc/dir_hier.inc new file mode 100644 index 0000000000..f835895e10 --- /dev/null +++ b/html/inc/dir_hier.inc @@ -0,0 +1,26 @@ + diff --git a/html/ops/bossa_ops.php b/html/ops/bossa_ops.php new file mode 100644 index 0000000000..9a976ff6af --- /dev/null +++ b/html/ops/bossa_ops.php @@ -0,0 +1,120 @@ + +
"; + add_app_form(); + echo "
";
+ user_settings();
+ admin_page_tail();
+}
+
+$user = get_logged_in_user();
+
+$submit = get_str('submit', true);
+if ($submit == 'Create app') {
+ $name = BossaDb::escape_string(get_str('app_name'));
+ $description = BossaDb::escape_string(get_str('description'));
+ $display_script = get_str('display_script');
+ $backend_script = get_str('backend_script');
+ $min_conf_sum = get_str('min_conf_sum');
+ $min_conf_frac = get_str('min_conf_frac');
+ $max_instances = get_str('max_instances');
+ $now = time();
+ BossaApp::insert("(create_time, name, description, display_script, backend_script, min_conf_sum, min_conf_frac, max_instances) values ($now, '$name', '$description', '$display_script', '$backend_script', $min_conf_sum, $min_conf_frac, $max_instances)");
+ Header('Location: bossa_ops.php');
+ exit();
+} else if ($submit == 'Update user') {
+ $flags = 0;
+ if (get_str('show_all', true)) $flags |= BOLT_FLAGS_SHOW_ALL;
+ if (get_str('debug', true)) $flags |= BOLT_FLAGS_DEBUG;
+ $user->bossa->update("flags=$flags");
+ $user->bossa->flags = $flags;
+ Header('Location: bossa_ops.php');
+ exit();
+} else {
+ $action = get_str('action', true);
+ if ($action) {
+ $app_id = get_int('app_id');
+ $app = BoltApp::lookup_id($app_id);
+ if (!$app) error_page("no such app");
+ switch ($action) {
+ case 'hide':
+ $app->update("hidden=1");
+ break;
+ case 'unhide':
+ $app->update("hidden=0");
+ break;
+ default:
+ error_page("unknown action $action");
+ }
+ Header('Location: bossa_ops.php');
+ exit();
+ }
+}
+
+show_all();
+
+?>
diff --git a/html/ops/bossa_setup_example.php b/html/ops/bossa_setup_example.php
deleted file mode 100644
index 9f6a49d528..0000000000
--- a/html/ops/bossa_setup_example.php
+++ /dev/null
@@ -1,19 +0,0 @@
-name = 'bossa_test';
-$ba->user_friendly_name = 'Simple pattern recognition';
-$ba->start_url = 'bossa_example.php';
-
-if ($ba->insert($ba)) {
- echo "Added application '$ba->name'\n";
-} else {
- echo "Couldn't add '$ba->name': ", mysql_error(), "\n";
-}
-
-?>
diff --git a/html/ops/bossa_transitioner.php b/html/ops/bossa_transitioner.php
new file mode 100644
index 0000000000..b4116b2dfb
--- /dev/null
+++ b/html/ops/bossa_transitioner.php
@@ -0,0 +1,41 @@
+id == $id) return $app;
+ }
+ return null;
+}
+
+function handle_job($job) {
+ $app = lookup_app($job->app_id);
+ if (!$app) {
+ echo "Missing app: $job->app_id\n";
+ return;
+ }
+ $instances = BossaJobInst::enum("job_id=$job->id");
+}
+
+function do_pass() {
+ $now = time();
+ $jobs = BossaJob::enum("transition_time < $now");
+ foreach ($jobs as $job) {
+ handle_job($job);
+ }
+}
+
+function main() {
+ global $apps;
+ $apps = BossaApp::enum();
+ while (1) {
+ do_pass();
+ }
+}
+
+main();
+?>
diff --git a/html/user/bossa_apps.php b/html/user/bossa_apps.php
new file mode 100644
index 0000000000..dbfdc587bb
--- /dev/null
+++ b/html/user/bossa_apps.php
@@ -0,0 +1,31 @@
+name
$app->description",
+ "id>Get job"
+ );
+}
+
+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();
+}
+
+main();
+
+?>
diff --git a/html/user/bossa_example.php b/html/user/bossa_example.php
index d71a4a6c8c..52a11b2a0a 100644
--- a/html/user/bossa_example.php
+++ b/html/user/bossa_example.php
@@ -3,42 +3,43 @@
require_once("../inc/bossa.inc");
// Bossa example.
-// Show the user an image and ask them whether it's a zero or one.
+// Show the user an image and ask them to click on the ellipse
function show_job($bj, $bji) {
- if ($bji->finish_time) {
- error_page("You already finished this job");
- }
$info = json_decode($bj->info);
- $img_url = "http://boinc.berkeley.edu/images/number_".$info->number.".jpg";
+ print_r($info);
+ $img_url = $info->url;
echo "