2008-07-16 04:25:11 +00:00
|
|
|
<?php
|
|
|
|
|
2008-07-17 20:58:42 +00:00
|
|
|
// Bossa example #3 - calibration jobs.
|
|
|
|
// We maintain the following for each user:
|
2008-07-16 04:25:11 +00:00
|
|
|
// nneg # of negative calibration jobs shown
|
|
|
|
// nneg_err # of errors
|
|
|
|
// npos
|
|
|
|
// npos_err
|
|
|
|
//
|
|
|
|
// from these we derive
|
|
|
|
// neg_err_rate
|
|
|
|
// pos_err_rate
|
|
|
|
//
|
|
|
|
// a job is considered done if either
|
|
|
|
// - N instances are positive and match within +- 20 pixels,
|
2008-07-17 20:58:42 +00:00
|
|
|
// and prod(pos_err_rate)<PROB_LIMIT
|
2008-07-30 21:37:41 +00:00
|
|
|
// - N instances are negative
|
2008-07-17 20:58:42 +00:00
|
|
|
// and prod(neg_err_rate)<PROB_LIMIT
|
2008-07-16 04:25:11 +00:00
|
|
|
// - there are 10 finished instances
|
|
|
|
// (in which case the job is marked as inconclusive)
|
|
|
|
|
2008-07-17 20:58:42 +00:00
|
|
|
require_once("../inc/bossa.inc");
|
|
|
|
|
|
|
|
define("PROB_LIMIT", 1e-3);
|
|
|
|
|
2008-07-16 04:25:11 +00:00
|
|
|
function job_show($job, $inst, $user) {
|
2008-07-30 21:37:41 +00:00
|
|
|
$info = $job->get_opaque_data();
|
2008-07-16 04:25:11 +00:00
|
|
|
$path = $info->path;
|
2008-07-20 21:27:44 +00:00
|
|
|
page_head("Find the Ellipse");
|
2008-07-16 04:25:11 +00:00
|
|
|
echo "
|
|
|
|
<form method=get action=bossa_job_finished.php>
|
|
|
|
Click on the center of the ellipse.
|
|
|
|
If you don't see one, click here:
|
|
|
|
<input type=submit name=submit value=None>
|
|
|
|
<br><br>
|
|
|
|
<input type=hidden name=bji value=$inst->id>
|
|
|
|
<input type=image name=pic src=$path>
|
|
|
|
</form>
|
|
|
|
";
|
2008-07-20 21:27:44 +00:00
|
|
|
page_tail();
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function job_issued($job, $inst, $user) {
|
|
|
|
$insts = $job->get_instances();
|
|
|
|
if (count($insts) > 1) {
|
|
|
|
$job->set_priority(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-17 20:58:42 +00:00
|
|
|
function job_finished($job, $inst, $user) {
|
2008-07-16 04:25:11 +00:00
|
|
|
$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');
|
|
|
|
}
|
2008-07-30 21:37:41 +00:00
|
|
|
$inst->set_opaque_data($response);
|
2008-07-16 04:25:11 +00:00
|
|
|
|
2008-07-30 21:37:41 +00:00
|
|
|
// if this is a calibration job, update user's opaque data
|
|
|
|
//
|
2008-07-17 20:58:42 +00:00
|
|
|
if ($job->calibration) {
|
2008-07-18 20:59:59 +00:00
|
|
|
$b = $user->bossa;
|
2008-07-30 21:37:41 +00:00
|
|
|
$info = $job->get_opaque_data();
|
2008-07-17 20:58:42 +00:00
|
|
|
$answer = $info->answer;
|
2008-07-30 21:37:41 +00:00
|
|
|
$u = $b->get_opaque_data();
|
2008-07-18 20:59:59 +00:00
|
|
|
if (!$u) {
|
|
|
|
$u->npos = 0;
|
|
|
|
$u->npos_err = 0;
|
|
|
|
$u->nneg = 0;
|
|
|
|
$u->nneg_err = 0;
|
|
|
|
}
|
2008-07-17 20:58:42 +00:00
|
|
|
if (compatible($response, $answer)) {
|
|
|
|
if ($answer->have_ellipse) {
|
|
|
|
$u->npos++;
|
|
|
|
} else {
|
|
|
|
$u->nneg++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ($answer->have_ellipse) {
|
|
|
|
$u->npos++;
|
|
|
|
$u->npos_err++;
|
|
|
|
} else {
|
|
|
|
$u->nneg++;
|
|
|
|
$u->nneg_err++;
|
|
|
|
}
|
|
|
|
}
|
2008-07-30 21:37:41 +00:00
|
|
|
$b->set_opaque_data($u);
|
2008-07-17 20:58:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-07-30 21:37:41 +00:00
|
|
|
// now see if job is done
|
2008-07-16 04:25:11 +00:00
|
|
|
//
|
|
|
|
$insts = $job->get_finished_instances();
|
|
|
|
$n = count($insts);
|
|
|
|
|
|
|
|
$results = null;
|
2008-07-17 20:58:42 +00:00
|
|
|
$users = null;
|
2008-07-16 04:25:11 +00:00
|
|
|
foreach ($insts as $inst) {
|
2008-07-30 21:37:41 +00:00
|
|
|
$results[] = $inst->get_opaque_data();
|
2008-07-17 20:58:42 +00:00
|
|
|
$u = $inst->get_user();
|
2008-07-30 21:37:41 +00:00
|
|
|
$users[] = $u->bossa->get_opaque_data();
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
2008-07-17 20:58:42 +00:00
|
|
|
|
|
|
|
// see if there's a negative consensus
|
|
|
|
//
|
|
|
|
$prob = 1;
|
|
|
|
for ($i=0; $i<$n; $i++) {
|
|
|
|
$r = $results[$i];
|
|
|
|
if ($r1->have_ellipse) continue;
|
|
|
|
$u = $users[$i];
|
|
|
|
$prob *= $u->neg_err_rate;
|
|
|
|
}
|
|
|
|
if ($prob < PROB_LIMIT) {
|
2008-07-30 21:37:41 +00:00
|
|
|
$job->set_state(BOSSA_JOB_DONE);
|
2008-07-17 20:58:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// see if there's a positive consensus
|
|
|
|
//
|
|
|
|
for ($i=0; $i<$n; $i++) {
|
2008-07-16 04:25:11 +00:00
|
|
|
$r1 = $results[$i];
|
2008-07-17 20:58:42 +00:00
|
|
|
$u = $users[$i];
|
|
|
|
$prob = $u->pos_error_rate;
|
|
|
|
for ($j=0; $j<$n; $j++) {
|
|
|
|
if ($j == $i) continue;
|
2008-07-16 04:25:11 +00:00
|
|
|
$r2 = $results[$j];
|
|
|
|
if (compatible($r1, $r2)) {
|
2008-07-17 20:58:42 +00:00
|
|
|
$u2 = $users[$j];
|
|
|
|
$prob *= $u2->pos_err_rate;
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
2008-07-17 20:58:42 +00:00
|
|
|
}
|
|
|
|
if ($prob < PROB_LIMIT) {
|
2008-07-30 21:37:41 +00:00
|
|
|
$job->set_state(BOSSA_JOB_DONE);
|
2008-07-17 20:58:42 +00:00
|
|
|
return;
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
|
|
|
}
|
2008-07-17 20:58:42 +00:00
|
|
|
|
|
|
|
// see if there are too many instances without a consensus
|
|
|
|
//
|
|
|
|
if ($n >= 10) {
|
2008-07-30 21:37:41 +00:00
|
|
|
$job->set_state(BOSSA_JOB_INCONCLUSIVE);
|
2008-07-17 20:58:42 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-07-30 21:37:41 +00:00
|
|
|
|
|
|
|
// still looking for consensus - get another instance
|
|
|
|
//
|
|
|
|
$job->set_priority(2);
|
|
|
|
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// two results are compatible if neither found an ellipse,
|
|
|
|
// or they both did and centers are within 20 pixels
|
|
|
|
//
|
|
|
|
function compatible($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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function job_timed_out($job, $inst, $user) {
|
|
|
|
$job->set_priority(1);
|
|
|
|
}
|
|
|
|
|
2008-07-20 21:27:44 +00:00
|
|
|
function job_summary($job) {
|
2008-07-30 21:37:41 +00:00
|
|
|
$info = $job->get_opaque_data();
|
2008-07-20 21:27:44 +00:00
|
|
|
return "<a href=".URL_BASE."$info->path>(view image)</a>";
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
|
|
|
|
2008-07-20 21:27:44 +00:00
|
|
|
function instance_summary($info) {
|
2008-07-16 04:25:11 +00:00
|
|
|
if ($info->have_ellipse) {
|
2008-07-20 21:27:44 +00:00
|
|
|
return "ellipse ($info->cx, $info->cy)";
|
2008-07-16 04:25:11 +00:00
|
|
|
} else {
|
2008-07-20 21:27:44 +00:00
|
|
|
return "no ellipse";
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-20 21:27:44 +00:00
|
|
|
function user_summary($user) {
|
2008-07-18 20:59:59 +00:00
|
|
|
$b = $user->bossa;
|
2008-07-30 21:37:41 +00:00
|
|
|
$info = $b->get_opaque_data();
|
2008-07-18 20:59:59 +00:00
|
|
|
if ($info) {
|
|
|
|
if ($info->npos) {
|
|
|
|
$pos_err = $info->npos_err/$info->npos;
|
|
|
|
} else {
|
|
|
|
$pos_err = "---";
|
|
|
|
}
|
|
|
|
if ($info->nneg) {
|
|
|
|
$neg_err = $info->nneg_err/$info->nneg;
|
|
|
|
} else {
|
|
|
|
$neg_err = "---";
|
|
|
|
}
|
2008-07-20 21:27:44 +00:00
|
|
|
return "error rate: positive $pos_err ($info->npos_err/$info->npos),
|
2008-07-18 20:59:59 +00:00
|
|
|
negative $neg_err ($info->nneg_err/$info->nneg)
|
|
|
|
";
|
|
|
|
} else {
|
2008-07-20 21:27:44 +00:00
|
|
|
return "No data";
|
2008-07-18 20:59:59 +00:00
|
|
|
}
|
2008-07-16 04:25:11 +00:00
|
|
|
}
|
2008-07-17 20:58:42 +00:00
|
|
|
|
|
|
|
?>
|