wiki:BossaExampleOne

Version 7 (modified by Nicolas, 16 years ago) (diff)

Fix link to bossa_test.php; although it's still not committed.

Bossa tutorial

Create a Bossa server

Install the BOINC software on a Linux system (or run the BOINC server virtual machine in a VMWare player on any computer).

Use 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:

(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: 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, "<download_dir>");
    $config->download_url = parse_config($c, "<download_url>");
    $config->uldl_dir_fanout = parse_config($c, "<uldl_dir_fanout>");
    $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 "
        <form method=get action=bossa_example.php>
        Click on the center of the ellipse.
        If you don't see one, click here:
        <br><br><input type=submit name=submit value=None>
        <input type=hidden name=bji value=$bji->id>
        <input type=hidden name=completion value=1>
        <input type=image name=pic src=$img_url>
        </form>
    ";
}

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'");
}

Attachments (1)

Download all attachments as: .zip