trial.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 1999-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Fri Mar 12 17:43:21 1999
00010 // commit: $Id: trial.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/visx/trial.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
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 // File scope data
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 // Trial::Impl class definition
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 // Trial member functions
00188 //
00190 
00192 // creators //
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 /*s*/)
00520 {
00521   // FIXME
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   // If the response was incorrect, we'll ask our parent container to
00584   // kindly repeat this trial
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

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:42 2008 by Doxygen version 1.5.5.