= Bossa tutorial = == Create a Bossa server == [ServerIntro Install the BOINC software] on a Linux system (or run the [VmServer BOINC virtual server] 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 }}} Read '''~/projects/test/test.readme''' and do what it says. 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. * Visit http://a.b.c/test_ops/bossa_admin.php. Follow the instructions to create the Bossa database. == Example application == We'll create an application in which volunteers view images, looking for ellipses on a noisy background. 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 with short name "bossa_example". The application is define by three scripts in ~/projects/test/html/: * '''ops/bossa_example_make_files.php''': this creates image files. * '''ops/bossa_example_make_jobs.php''': this creates jobs. * '''inc/bossa_example.inc''': display jobs and handle completed jobs. We'll go through these scripts and explain how they work. To develop your own Bossa applications you'll need to write corresponding scripts. == Creating jobs == To create some jobs, first we'll create some image files using the script [source:/trunk/boinc/html/ops/bossa_example_make_files.php html/ops/bossa_example_make_files.php]. {{{ cd ~/projects/test/html/ops mkdir ../user/example php bossa_example_make_files.php --nfiles 10 --dir example }}} This creates (in the '''examples/''' directory) 10 image files '''0.png''' to '''9.png''', and corresponding "answer" files '''0.ans''' to '''9.ans'''. Roughly half the images will have ellipses (you can specify this probability with '''--ellipse_frac x'''). Now, create jobs using [source:/trunk/boinc/html/ops/bossa_example_make_jobs.php html/ops/bossa_example_make_jobs.php]. {{{ php bossa_example_make_jobs --app_name bossa_example --dir example }}} This makes 10 jobs (one for each image in the directory) and collects them into a "batch". == Displaying jobs == Next we'll explain the script that displays a job to a volunteer and handles their response: [source:/trunk/boinc/html/user/bossa_example.php bossa_example_display.php]. {{{ 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); } }}} The script calls '''Bossa::script_init()''' to get PHP objects describing the user, the job, and the job instance. '''show_job()''' decodes the job description to get the image URL, and displays the image in an HTML page that lets the user click on the image or on a "No ellipse" button. '''handle_job_completion()''' gets the user's response (from form variables). It calls the '''completed()''' method of the job, passing it a JSON encoding of the response. I then calls '''Bossa::show_next_job()''' to immediately display another job. == Handling completed results == Finally, we need to specify how results are handled. This is specified in [source:/trunk/boinc/html/inc/bossa_example_backend.inc bossa_example_backend.inc]. This defines two functions, which must have names '''X_compare''' and '''X_handle''' where X is the application's short name. The first function compares two instances and decides if they are compatible: {{{ function bossa_example_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; } } }}} In this case, two instances are considered compatible if either * neither of them found an ellipse, or * they both found an ellipse and the centers are within 20 pixels The second function specifies what happens when a job has been completed, i.e. a consensus set has been found: {{{ function bossa_example_handle($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'"); } }}} This function is called with the BossaJob record ($bj) and an array of job instances in the consensus set ($c). In this case, we average the center positions (if an ellipse was found) and store the JSON-encoded result in the '''info''' field of the job record.