= Bossa tutorial = == Create a Bossa server == [ServerIntro Install the BOINC software] on a Linux system (or run the [VirtualMachines BOINC server virtual machine] in a VMWare player on any computer). Use [MakeProject make_project] to create a BOINC project named "test": {{{ > cd boinc/tools > make_project --web_only test }}} Edit httpd.conf as directed (you'll need root access to do this). Let's say your server's domain name is "a.b.c". Visit http://a.b.c/test/create_account.php and create an account for yourself. == Example application == We'll create an application in which volunteers view images consisting of random rectangles, possibly with an ellipse superimposed. Their task is to click on the center of the ellipse, or to indicate that there is no ellipse. Here's an example: [[Image(bossa_test.png, nolink)]] (this has an ellipse slightly below/left of center). Visit http://a.b.c/test_ops/bossa_ops.php, and create an application named "example", with display file "bossa_example.php" and backend file "bossa_example_backend.inc". == A script to generate jobs == We'll need a program to generate jobs. This is done with a PHP script: [source:/trunk/html/ops/bossa_test.php html/ops/bossa_test.php]. The first part of this script is code for generating an image; the key functions are '''make_test_case()''', which generates a structure saying if and where there's an ellipse, and '''make_image()''', which generates an image given this info. Next we have {{{ function make_job($app, $batch, $i, $config) { // create the image file; // store it in the download directory hierarchy // $jobname = "job_$batch_$i"; $case = make_test_case(); $filename = "$jobname.png"; $path = dir_hier_path( $filename, $config->download_dir, $config->uldl_dir_fanout ); $url = dir_hier_url( $filename, $config->download_url, $config->uldl_dir_fanout ); imagepng(make_image($case), $path); $case->url = $url; // make a job record in the Bossa database // $job = new BossaJob; $job->app_id = $app->id; $job->batch = $batch; $job->time_estimate = 30; $job->time_limit = 600; $job->name = $jobname; $job->info = json_encode($case); if (!$job->insert()) { echo "BossaJob::insert failed: ", mysql_error(), "\n"; exit(1); } } }}} This creates one job. It does the following: * Choose a name for the job, and a name for the corresponding image file. * Decide where the file will go in the project's download hierarchy. * Create the image file. * Create a job record in the Bossa database. Finally we have: {{{ function make_jobs() { $c = get_config(); $config = null; $config->download_dir = parse_config($c, ""); $config->download_url = parse_config($c, ""); $config->uldl_dir_fanout = parse_config($c, ""); $app = BossaApp::lookup_name("bossa_test"); if (!$app) { echo "Application $appname not found\n"; exit(1); } $batch = time(); for ($i=0; $i<10; $i++) { make_job($app, $batch, $i, $config); } } if ($_GET['make_jobs']) { make_jobs(); } else { header ("Content-type: image/png"); imagepng(make_image(make_test_case())); } }}} '''make_jobs()''' parses the project configuration file, looks up the application in the database, and creates 10 jobs. You can invoke this by visiting '''http://a.b.c/test_ops/bossa_test.php?make_jobs'''. == Displaying jobs == Next we'll need a script that displays a job and handles user input. {{{ function show_job($bj, $bji) { $info = json_decode($bj->info); $img_url = $info.url; echo "
Click on the center of the ellipse. If you don't see one, click here:

id>
"; } function handle_job_completion($bj, $bji) { $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'); } $bji->info = json_encode($response); $bji->completed($bj); Bossa::show_next_job($bj); // show another job immediately } Bossa::script_init($user, $bj, $bji); if (isset($_GET['completion'])) { handle_job_completion($bj, $bji); } else { show_job($bj, $bji); } }}} == What volunteers see == == Handling completed results == Finally, we need to specify how results are handled. This is specified in "html/inc/bossa_example.inc". This defines two functions. The first defines a comparison of two results: {{{ function compare($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; } } }}} The second function specifies what happens when a job has been completed, i.e. a consensus set has been found: {{{ 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'"); } }}}