00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_VISX_TRIAL_CC_UTC20050626084015_DEFINED
00035 #define GROOVX_VISX_TRIAL_CC_UTC20050626084015_DEFINED
00036
00037 #include "trial.h"
00038
00039 #include "gfx/canvas.h"
00040 #include "gfx/gxshapekit.h"
00041
00042 #include "io/readutils.h"
00043 #include "io/writeutils.h"
00044
00045 #include "nub/log.h"
00046 #include "nub/ref.h"
00047
00048 #include "rutz/fstring.h"
00049 #include "rutz/iter.h"
00050 #include "rutz/scopedptr.h"
00051 #include "rutz/sfmt.h"
00052
00053 #include "tcl-gfx/toglet.h"
00054
00055 #include "visx/response.h"
00056 #include "visx/responsehandler.h"
00057 #include "visx/timinghdlr.h"
00058
00059 #include <sstream>
00060 #include <vector>
00061
00062 #define GVX_DYNAMIC_TRACE_EXPR Trial::tracer.status()
00063 #include "rutz/trace.h"
00064 #include "rutz/debug.h"
00065 GVX_DBG_REGISTER
00066
00067 using rutz::fstring;
00068
00069 using nub::ref;
00070 using nub::soft_ref;
00071
00072 rutz::tracer Trial::tracer;
00073
00075
00076
00077
00079
00080 namespace dummy_namespace_to_avoid_gcc411_bug_trial_cc
00081 {
00082 const io::version_id TRIAL_SVID = 5;
00083
00084 struct ActiveState
00085 {
00086 ActiveState(Trial* tr,
00087 Element* p, soft_ref<Toglet> w,
00088 ref<ResponseHandler> r, ref<TimingHdlr> t) :
00089 trial(tr),
00090 parent(p),
00091 widget(w),
00092 rh(r),
00093 th(t),
00094 status(Element::CHILD_OK)
00095 {
00096 GVX_PRECONDITION(parent != 0);
00097 nub::logging::add_obj_scope(*trial);
00098 }
00099
00100 ~ActiveState()
00101 {
00102 nub::logging::remove_obj_scope(*trial);
00103 }
00104
00105 Trial* trial;
00106 Element* parent;
00107 soft_ref<Toglet> widget;
00108 ref<ResponseHandler> rh;
00109 ref<TimingHdlr> th;
00110 Element::ChildStatus status;
00111 };
00112 }
00113
00114 using namespace dummy_namespace_to_avoid_gcc411_bug_trial_cc;
00115
00117
00118
00119
00121
00122 class Trial::Impl
00123 {
00124 private:
00125 Impl(const Impl&);
00126 Impl& operator=(const Impl&);
00127
00128 public:
00129 Impl(Trial* t) :
00130 owner(t),
00131 correctResponse(Response::ALWAYS_CORRECT),
00132 gxNodes(),
00133 currentNode(0),
00134 responses(),
00135 trialType(-1),
00136 rh(),
00137 th(),
00138 info(),
00139 activeState(0)
00140 {}
00141
00142 Trial* owner;
00143
00144 int correctResponse;
00145
00146 typedef std::vector<ref<GxNode> > GxNodes;
00147 GxNodes gxNodes;
00148
00149 unsigned int currentNode;
00150
00151 std::vector<Response> responses;
00152
00153 int trialType;
00154 soft_ref<ResponseHandler> rh;
00155 soft_ref<TimingHdlr> th;
00156
00157 fstring info;
00158
00159 rutz::scoped_ptr<ActiveState> activeState;
00160
00161 bool isActive() const { return activeState.get() != 0; }
00162
00163 void becomeActive(Element* parent, soft_ref<Toglet> widget)
00164 {
00165 activeState.reset(new ActiveState(owner, parent, widget, rh, th));
00166 }
00167
00168 void becomeInactive()
00169 {
00170 activeState.reset(0);
00171 }
00172
00173 void installCurrentNode() const
00174 {
00175 GVX_PRECONDITION( isActive() );
00176 if (activeState->widget.is_valid() && currentNode < gxNodes.size())
00177 {
00178 activeState->widget->setDrawable(gxNodes[currentNode]);
00179 nub::log(rutz::sfmt("current node is %s",
00180 gxNodes[currentNode]->unique_name().c_str()));
00181 }
00182 }
00183 };
00184
00186
00187
00188
00190
00192
00194
00195 const FieldMap& Trial::classFields()
00196 {
00197 static const Field FIELD_ARRAY[] =
00198 {
00199 Field("tType", &Trial::trialType, &Trial::setType,
00200 -1, -10, 10, 1, Field::NEW_GROUP)
00201 };
00202
00203 static FieldMap TRIAL_FIELDS(FIELD_ARRAY);
00204
00205 return TRIAL_FIELDS;
00206 }
00207
00208 Trial* Trial::make()
00209 {
00210 GVX_TRACE("Trial::make");
00211 return new Trial;
00212 }
00213
00214 Trial::Trial() :
00215 FieldContainer(0),
00216 rep( new Impl(this) )
00217 {
00218 GVX_TRACE("Trial::Trial()");
00219
00220 setFieldMap(Trial::classFields());
00221 }
00222
00223 Trial::~Trial() throw()
00224 {
00225 GVX_TRACE("Trial::~Trial");
00226 delete rep;
00227 }
00228
00229 io::version_id Trial::class_version_id() const
00230 { return TRIAL_SVID; }
00231
00232 void Trial::read_from(io::reader& reader)
00233 {
00234 GVX_TRACE("Trial::read_from");
00235
00236 rep->becomeInactive();
00237
00238 reader.ensure_version_id("Trial", 5,
00239 "Try cvs tag xml_conversion_20040526",
00240 SRC_POS);
00241
00242 rep->gxNodes.clear();
00243 io::read_utils::read_object_seq<GxNode>
00244 (reader, "gxObjects", std::back_inserter(rep->gxNodes));
00245
00246 rep->responses.clear();
00247 io::read_utils::read_value_obj_seq<Response>
00248 (reader, "responses", std::back_inserter(rep->responses));
00249
00250 reader.read_value("correctResponse", rep->correctResponse);
00251
00252 reader.read_value("type", rep->trialType);
00253
00254 rep->rh = dyn_cast<ResponseHandler>(reader.read_weak_object("rh"));
00255 rep->th = dyn_cast<TimingHdlr>(reader.read_weak_object("th"));
00256
00257 reader.read_value("info", rep->info);
00258 }
00259
00260 void Trial::write_to(io::writer& writer) const
00261 {
00262 GVX_TRACE("Trial::write_to");
00263
00264 writer.ensure_output_version_id("Trial", TRIAL_SVID, 5,
00265 "Try groovx0.8a3", SRC_POS);
00266
00267 io::write_utils::write_object_seq(writer, "gxObjects",
00268 rep->gxNodes.begin(),
00269 rep->gxNodes.end());
00270
00271 io::write_utils::write_value_obj_seq(writer, "responses",
00272 rep->responses.begin(),
00273 rep->responses.end());
00274
00275 writer.write_value("correctResponse", rep->correctResponse);
00276
00277 writer.write_value("type", rep->trialType);
00278
00279 writer.write_object("rh", rep->rh);
00280 writer.write_object("th", rep->th);
00281
00282 writer.write_value("info", rep->info);
00283 }
00284
00285 const soft_ref<Toglet>& Trial::getWidget() const
00286 {
00287 GVX_PRECONDITION( rep->isActive() );
00288 return rep->activeState->widget;
00289 }
00290
00291 int Trial::getCorrectResponse() const
00292 { return rep->correctResponse; }
00293
00294 void Trial::setCorrectResponse(int response)
00295 { rep->correctResponse = response; }
00296
00297
00298 ref<ResponseHandler> Trial::getResponseHandler() const
00299 { return ref<ResponseHandler>(rep->rh); }
00300
00301 void Trial::setResponseHandler(ref<ResponseHandler> rh)
00302 { rep->rh = soft_ref<ResponseHandler>(rh); }
00303
00304
00305 ref<TimingHdlr> Trial::getTimingHdlr() const
00306 { return ref<TimingHdlr>(rep->th); }
00307
00308 void Trial::setTimingHdlr(ref<TimingHdlr> th)
00309 { rep->th = soft_ref<TimingHdlr>(th); }
00310
00311
00312 int Trial::trialType() const
00313 { return rep->trialType; }
00314
00315 void Trial::setType(int t)
00316 { rep->trialType = t; }
00317
00318
00319 fstring Trial::vxInfo() const
00320 {
00321 GVX_TRACE("Trial::vxInfo");
00322 if (rep->info.is_empty())
00323 return stdInfo();
00324
00325 return rep->info;
00326 }
00327
00328 int Trial::lastResponse() const
00329 {
00330 GVX_TRACE("Trial::lastResponse");
00331
00332 if (rep->responses.empty())
00333 throw rutz::error("the trial has no responses yet", SRC_POS);
00334
00335 return rep->responses.back().val();
00336 }
00337
00338 void Trial::vxUndo()
00339 {
00340 GVX_TRACE("Trial::vxUndo");
00341 if ( !rep->responses.empty() )
00342 rep->responses.pop_back();
00343 }
00344
00345 rutz::fwd_iter<Response> Trial::responses() const
00346 {
00347 GVX_TRACE("Trial::responses");
00348 return rutz::fwd_iter<Response>
00349 (rep->responses.begin(), rep->responses.end());
00350 }
00351
00352 unsigned int Trial::numResponses() const
00353 { return rep->responses.size(); }
00354
00355 void Trial::clearResponses()
00356 { rep->responses.clear(); }
00357
00358 double Trial::avgResponse() const
00359 {
00360 GVX_TRACE("Trial::avgResponse");
00361 int sum = 0;
00362 for (std::vector<Response>::const_iterator ii = rep->responses.begin();
00363 ii != rep->responses.end();
00364 ++ii)
00365 {
00366 sum += ii->val();
00367 }
00368 return (rep->responses.size() > 0) ? double(sum)/rep->responses.size() : 0.0;
00369 }
00370
00371 double Trial::avgRespTime() const
00372 {
00373 GVX_TRACE("Trial::avgRespTime");
00374 int sum = 0;
00375 for (std::vector<Response>::const_iterator ii = rep->responses.begin();
00376 ii != rep->responses.end();
00377 ++ii)
00378 {
00379 sum += ii->msec();
00380
00381 dbg_eval(3, sum);
00382 dbg_eval_nl(3, sum/rep->responses.size());
00383 }
00384 return (rep->responses.size() > 0) ? double(sum)/rep->responses.size() : 0.0;
00385 }
00386
00387
00388 void Trial::addNode(ref<GxNode> item)
00389 {
00390 GVX_TRACE("Trial::addNode");
00391 rep->gxNodes.push_back(item);
00392 }
00393
00394 void Trial::trNextNode()
00395 {
00396 GVX_TRACE("Trial::trNextNode");
00397 setCurrentNode(rep->currentNode+1);
00398 }
00399
00400 rutz::fwd_iter<ref<GxNode> > Trial::nodes() const
00401 {
00402 GVX_TRACE("Trial::nodes");
00403 return rutz::fwd_iter<ref<GxNode> >
00404 (rep->gxNodes.begin(), rep->gxNodes.end());
00405 }
00406
00407 unsigned int Trial::getCurrentNode() const
00408 {
00409 GVX_TRACE("Trial::getCurrentNode");
00410 return rep->currentNode;
00411 }
00412
00413 void Trial::setCurrentNode(unsigned int nodeNumber)
00414 {
00415 GVX_TRACE("Trial::setCurrentNode");
00416 if (nodeNumber >= rep->gxNodes.size())
00417 {
00418 throw rutz::error(rutz::sfmt("invalid node number %u",
00419 nodeNumber), SRC_POS);
00420 }
00421 rep->currentNode = nodeNumber;
00422 }
00423
00424 void Trial::clearObjs()
00425 {
00426 GVX_TRACE("Trial::clearObjs");
00427 rep->gxNodes.clear();
00428 }
00429
00430 fstring Trial::stdInfo() const
00431 {
00432 GVX_TRACE("Trial::stdInfo");
00433
00434 std::ostringstream objids;
00435 std::ostringstream cats;
00436
00437 for (Impl::GxNodes::const_iterator
00438 ii = rep->gxNodes.begin(),
00439 end = rep->gxNodes.end();
00440 ii != end;
00441 ++ii)
00442 {
00443 for (rutz::fwd_iter<const ref<GxNode> > tr((*ii)->deepChildren());
00444 tr.is_valid();
00445 tr.next())
00446 {
00447 const GxShapeKit* g =
00448 dynamic_cast<const GxShapeKit*>((*tr).get());
00449
00450 if (g)
00451 {
00452 objids << " " << g->unique_name();
00453 cats << " " << g->category();
00454 }
00455 }
00456 }
00457
00458 return rutz::sfmt("trial type == %d, objs ==%s, categories == %s",
00459 rep->trialType,
00460 objids.str().c_str(),
00461 cats.str().c_str());
00462 }
00463
00464 void Trial::setInfo(fstring info)
00465 {
00466 GVX_TRACE("Trial::setInfo");
00467 rep->info = info;
00468 }
00469
00470
00471 void Trial::vxRun(Element& parent)
00472 {
00473 GVX_TRACE("Trial::vxRun");
00474
00475 GVX_PRECONDITION(&parent != 0);
00476
00477 soft_ref<Toglet> widget = parent.getWidget();
00478
00479 GVX_PRECONDITION(widget.is_valid());
00480
00481 if ( rep->rh.is_invalid() || rep->th.is_invalid() )
00482 {
00483 throw rutz::error("the trial did not have a valid timing handler "
00484 "and response handler", SRC_POS);
00485 }
00486
00487 rep->becomeActive(&parent, widget);
00488
00489 nub::log( vxInfo() );
00490
00491 rep->currentNode = 0;
00492
00493 rep->activeState->rh->rhBeginTrial(widget, *this);
00494 rep->activeState->th->thBeginTrial(*this);
00495 }
00496
00497 double Trial::trElapsedMsec()
00498 {
00499 GVX_TRACE("Trial::trElapsedMsec");
00500
00501 GVX_PRECONDITION( rep->isActive() );
00502
00503 return rep->activeState->th->getElapsedMsec();
00504 }
00505
00506 void Trial::trAbortTrial()
00507 {
00508 GVX_TRACE("Trial::trAbortTrial");
00509
00510 GVX_PRECONDITION( rep->isActive() );
00511
00512 nub::log("trAbortTrial");
00513
00514 rep->activeState->status = CHILD_ABORTED;
00515 rep->activeState->rh->rhAbortTrial();
00516 rep->activeState->th->thAbortTrial();
00517 }
00518
00519 void Trial::vxReturn(ChildStatus )
00520 {
00521
00522 GVX_ASSERT(false);
00523 }
00524
00525 void Trial::trEndTrial()
00526 {
00527 GVX_TRACE("Trial::trEndTrial");
00528
00529 GVX_PRECONDITION( rep->isActive() );
00530
00531 nub::log("Trial::trEndTrial");
00532
00533 rep->activeState->rh->rhEndTrial();
00534 rep->activeState->th->thEndTrial();
00535 rep->activeState->parent->vxEndTrialHook();
00536
00537 Element* parent = rep->activeState->parent;
00538 Element::ChildStatus status = rep->activeState->status;
00539
00540 rep->becomeInactive();
00541
00542 parent->vxReturn(status);
00543 }
00544
00545 void Trial::vxHalt() const
00546 {
00547 GVX_TRACE("Trial::vxHalt");
00548
00549 if (!rep->isActive()) return;
00550
00551 nub::log("Trial::vxHalt");
00552
00553 if (rep->activeState->widget.is_valid())
00554 rep->activeState->widget->undraw();
00555
00556 rep->activeState->rh->rhHaltExpt();
00557 rep->activeState->th->thHaltExpt();
00558
00559 rep->becomeInactive();
00560 }
00561
00562 void Trial::vxReset()
00563 {
00564 GVX_TRACE("Trial::vxReset");
00565 rep->responses.clear();
00566 }
00567
00568 void Trial::trProcessResponse(Response& response)
00569 {
00570 GVX_TRACE("Trial::trProcessResponse");
00571
00572 GVX_PRECONDITION( rep->isActive() );
00573
00574 nub::log("trProcessResponse");
00575
00576 rep->responses.push_back(response);
00577
00578 dbg_eval(3, rep->correctResponse);
00579 dbg_eval_nl(3, response.val());
00580
00581 rep->activeState->th->thResponseSeen();
00582
00583
00584
00585 if (!response.matchesCorrectValue(rep->correctResponse))
00586 {
00587 rep->activeState->status = CHILD_REPEAT;
00588 }
00589 }
00590
00591 void Trial::trDraw()
00592 {
00593 GVX_TRACE("Trial::trDraw");
00594 soft_ref<Toglet> widget = getWidget();
00595 if (widget.is_valid())
00596 {
00597 rep->installCurrentNode();
00598 widget->setVisibility(true);
00599 widget->fullRender();
00600 }
00601 }
00602
00603 void Trial::trRender()
00604 {
00605 GVX_TRACE("Trial::trRender");
00606 soft_ref<Toglet> widget = getWidget();
00607 if (widget.is_valid())
00608 {
00609 rep->installCurrentNode();
00610 widget->setVisibility(true);
00611 widget->render();
00612 }
00613 }
00614
00615 void Trial::trUndraw()
00616 {
00617 GVX_TRACE("Trial::trUndraw");
00618 soft_ref<Toglet> widget = getWidget();
00619 if (widget.is_valid())
00620 widget->undraw();
00621 }
00622
00623 void Trial::trSwapBuffers()
00624 {
00625 GVX_TRACE("Trial::trSwapBuffers");
00626 soft_ref<Toglet> widget = getWidget();
00627 if (widget.is_valid())
00628 widget->swapBuffers();
00629 }
00630
00631 void Trial::trRenderBack()
00632 {
00633 GVX_TRACE("Trial::trRenderBack");
00634 soft_ref<Toglet> widget = getWidget();
00635 if (widget.is_valid())
00636 widget->getCanvas()->drawOnBackBuffer();
00637 }
00638
00639 void Trial::trRenderFront()
00640 {
00641 GVX_TRACE("Trial::trRenderFront");
00642 soft_ref<Toglet> widget = getWidget();
00643 if (widget.is_valid())
00644 widget->getCanvas()->drawOnFrontBuffer();
00645 }
00646
00647 void Trial::trClearBuffer()
00648 {
00649 GVX_TRACE("Trial::trClearBuffer");
00650 soft_ref<Toglet> widget = getWidget();
00651 if (widget.is_valid())
00652 widget->clearscreen();
00653 }
00654
00655 void Trial::trFinishDrawing()
00656 {
00657 GVX_TRACE("Trial::trFinishDrawing");
00658 soft_ref<Toglet> widget = getWidget();
00659 if (widget.is_valid())
00660 widget->getCanvas()->finishDrawing();
00661 }
00662
00663
00664 void Trial::trAllowResponses()
00665 {
00666 GVX_TRACE("Trial::trAllowResponses");
00667
00668 GVX_PRECONDITION( rep->isActive() );
00669
00670 nub::log("trAllowResponses");
00671
00672 rep->activeState->rh->rhAllowResponses
00673 (rep->activeState->widget, *this);
00674 }
00675
00676 void Trial::trDenyResponses()
00677 {
00678 GVX_TRACE("Trial::trDenyResponses");
00679
00680 GVX_PRECONDITION( rep->isActive() );
00681
00682 nub::log("trDenyResponses");
00683
00684 rep->activeState->rh->rhDenyResponses();
00685 }
00686
00687 static const char __attribute__((used)) vcid_groovx_visx_trial_cc_utc20050626084015[] = "$Id: trial.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00688 #endif // !GROOVX_VISX_TRIAL_CC_UTC20050626084015_DEFINED