= Bossa reference manual = [BossaIntro Bossa] is a framework for distributed thinking applications. We'll describe Bossa using an example. The example shows users pictures of zeros or ones, and asks the user to identify the number. == Database tables == Until Bossa has good web-based administration tools, you'll often need to directly examine and modify its MySQL database, using the command-line tool 'mysql' or a web-based interface such as [http://www.phpmyadmin.net/ phpMyAdmin]. The database tables used by Bossa (in addition to BOINC's tables for users, teams, etc.) are as follows: '''bossa_app''': || field name || type || meaning || || id || integer || row ID, assigned by MySQL || || create_time || integer || row creation time || || name || varchar(255) || short name (internal use; no spaces) || || user_friendly_name || varchar(255) || user-visible name (spaces OK) || || long_jobs || tinyint || nonzero if user can have > 1 active job || || start_url || varchar(255) || name (relative to project URL) of start script || || deprecated || tinyint || nonzero if deprecated (don't show) || || info || text || information (typically encoded in JSON) such as the criteria for which users to issue jobs to || '''bossa_job''': || field name || type || meaning || || id || integer || row ID, assigned by MySQL || || create_time || integer || row creation time || || name || varchar(255) || a unique name for this job || || app_id || integer || ID of bossa_app || || info || text || job-specific info (file names etc.) typically JSON-encoded || || batch || integer || batch number (use to group jobs) || || time_estimate || integer || number of seconds this job is likely to take || || time_limit || integer || give up if not completed after this number of seconds || || more_needed || tinyint || nonzero if more completed instances of this job are needed || || npending || integer || number of pending instances || || nsuccess || integer || number of successfully completed instances || || nsuccess_needed || integer || required number of successfully completed instances || '''bossa_job_inst''': || field name || type || meaning || || id || integer || row ID, assigned by MySQL || || create_time || integer || row creation time || || job_id || integer || ID of bossa_job || || user_id || integer || ID of user || || finish_time || integer || time when finished, or zero || || info || text || outcome info (usually JSON-encoded) || '''bossa_app_user''': || app_id || integer || ID of bossa_app || || user_id || integer || ID of user || || info || text || description of the user's skill or ranking at a given app, typically JSON-encoded || == Bossa PHP classes == Bossa provides the following classes (in '''html/inc/bossa.inc''' and '''html/inc/bossa_db.inc'''): '''!BossaApp, !BossaJob, !BossaJobInst''':: These correspond to the above tables, and have fields corresponding to each database field. They offer functions to insert, look up, and modify database rows. '''Bossa''':: Utility functions. == Creating a Bossa project == First, [ServerIntro set up a BOINC server] and [MakeProject create a project]. You'll need PHP 5.2 or later (for JSON functions). Say your project is called '''test_project''', your BOINC source directory is '''~/boinc''', and your BOINC projects directory is '''~/projects'''. Create Bossa's database tables as follows: {{{ cd ~/boinc/db mysql test_project < bossa_schema.sql mysql test_project < bossa_constraints.sql }}} Create a Bossa application as follows: {{{ cd ~/projects/test_project/html/ops php bossa_setup_example.php }}} bossa_setup_example.php contains: {{{ $ba = new BossaApp(); $ba->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"; } }}} You can edit this to change the application name and front-end script name, if you like. == Adding jobs == Typically you'll add jobs using a script. Here's an example ('''html/ops/bossa_make_jobs_example.php'''): {{{ 1 app_id = $app->id; 17 $job->batch = 0; 18 $job->time_estimate = 30; 19 $job->time_limit = 600; 20 $job->nsuccess_needed = 3; 21 for ($i=0; $i<10; $i++) { 22 $job->name = "job_$i"; 23 $info = null; 24 $info->number = $i % 2; 25 $job->info = json_encode($info); 26 if (!$job->insert()) { 27 echo "BossaJob::insert failed: ", mysql_error(), "\n"; 28 exit(1); 29 } 30 } 31 } 32 33 make_jobs(); 34 echo "All done.\n"; 35 36 ?> }}} This creates 10 jobs. Each job has an ''info'' field consisting of a JSON-encoded structure consisting of an integer (0 or 1). == Front-end scripts == You develop a '''front-end script''' to show a job instance to a user, and to handle a completed instance. It's handy to put both of these functions in a single file. A front-end script is called with the URL parameter '''bji''' set to a job instance ID. Here's an example ('''html/user/bossa_example.php'''): {{{ 1 finish_time) { 12 error_page("You already finished this job"); 13 } 14 $info = json_decode($bj->info); 15 $img_url = "http://boinc.berkeley.edu/images/number_".$info->number.".jpg"; 16 echo " 17
18 id> 19 20
21 The picture shows a 22
zero 23
one 24
not sure 25

26
27 "; 28 } 29 30 function handle_job_completion($bj, $bji) { 31 $response = null; 32 $response->number = get_int('response'); 33 $bji->info = json_encode($response); 34 $bji->completed($bj); 35 36 // show another job immediately 37 // 38 Bossa::show_next_job($bj); 39 } 40 41 Bossa::script_init($user, $bj, $bji); 42 43 if ($_GET['submit']) { 44 handle_job_completion($bj, $bji); 45 } else { 46 show_job($bj, $bji); 47 } 48 49 ?> }}} Line 41:: Call a Bossa utility function to look up the job instance and make sure that it was issued to the logged-in user. The job instance, job, and user are returned. Line 43:: Branch according to whether we are showing a job or handling the completion of a job. Line 14:: If we're showing a job, decode its ''info'' structure to decide whether to show which picture to show. Lines 17-18:: Task completion will be handled by this script; arrange to pass the job instance ID. Lines 31-33:: Get the user's response, and encode it in JSON. Line 34:: Call a utility function that marks the job instance as completed and updates its database record. Line 38:: Call a utility function that gets another job (if one is available) and shows it to the user.