annotate TestController.h @ 52:89944ab3e129 tip

fix oF linker errors ios8
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Tue, 03 Feb 2015 13:18:23 +0000
parents 2bd658b44c2d
children
rev   line source
rt300@0 1 //
rt300@0 2 // TestController.h
rt300@0 3 // tweakathlon
rt300@0 4 //
rt300@0 5 // Created by Robert Tubb on 16/01/2014.
rt300@0 6 //
rt300@5 7
rt300@5 8
rt300@5 9 // controller for as-long-as-it-takes, arbitrary target tests
rt300@0 10
rt300@0 11 #ifndef __tweakathlon__TestController__
rt300@0 12 #define __tweakathlon__TestController__
rt300@0 13
rt300@0 14 #include <iostream>
rt300@0 15 #include "ofMain.h"
rt300@0 16 #include "globalVariables.h"
rt300@0 17 #include "boost/foreach.hpp"
rt300@0 18 #include "boost/bind.hpp"
rt300@0 19 #include "boost/function.hpp"
rt300@0 20 #include "timeController.h"
rt300@22 21 #include "algorithms.h"
rt300@0 22 #include <functional>
rt300@0 23 #include <algorithm> // std::transform
rt300@0 24
rt300@0 25 //-------------------------------------------------------------
rt300@0 26
rt300@0 27 struct TestResult{
rt300@0 28 float realDistanceToTarget;
rt300@0 29 int targetBandHit; // eg bullseye = 0 edge = 7
rt300@0 30 TimerMillisec timeTaken;
rt300@0 31 int timeWindowHit; // eg < 5s = 0
rt300@0 32 int dimensionMult;
rt300@0 33 int score;
rt300@0 34 string displayText;
rt300@0 35 };
rt300@0 36
rt300@0 37 //-------------------------------------------------------------
rt300@0 38 // tests, once genrated by the testcontroller get passed around and used to set synths and so on
rt300@0 39 //-------------------------------------------------------------
rt300@0 40 class Test {
rt300@0 41 public:
rt300@0 42 Test(){
rt300@0 43 //?
rt300@0 44 identifyingLetter = '?';
rt300@0 45 timeGiven = 0;
rt300@0 46 panelType= SEQUENTIAL;
rt300@0 47 numDimensions = 0;
rt300@0 48
rt300@0 49 generateListOfControls();
rt300@0 50 makeRandomTarget();
rt300@0 51 setCandidateToTarget();
rt300@0 52 randomParamSelection(numDimensions);
rt300@0 53 randomiseCandidate();
rt300@0 54 scored = true;
rt300@0 55 withHint = false;
rt300@0 56 memoryTest = false;
rt300@0 57 targetPlaysLeft = 2; // only decr if memory test
rt300@0 58 };
rt300@0 59 // test with random params
rt300@0 60 Test(char letter, int atimeGiven, controlPanelType apanelType, int anumDimensions){
rt300@0 61 // init the stuff
rt300@0 62 //cout << "Making test " << letter << endl;
rt300@0 63
rt300@0 64 identifyingLetter = letter;
rt300@0 65 timeGiven = atimeGiven;
rt300@0 66 panelType= apanelType;
rt300@0 67 numDimensions = anumDimensions;
rt300@0 68
rt300@0 69 generateListOfControls();
rt300@0 70 makeRandomTarget();
rt300@0 71 setCandidateToTarget();
rt300@0 72 randomParamSelection(numDimensions);
rt300@0 73 randomiseCandidate();
rt300@0 74 scored = true;
rt300@0 75 };
rt300@0 76 // constructor that copies params from other test, pass em in
rt300@0 77 // also serves as a constructor that passes in specific settings
rt300@0 78 Test(char letter, int atimeGiven, controlPanelType apanelType, int anumDimensions, vector<int> aTargetValues, vector<int> aCandidateValues, vector<bool> adjustables){
rt300@0 79 identifyingLetter = letter;
rt300@0 80 timeGiven = atimeGiven;
rt300@0 81 panelType= apanelType;
rt300@0 82 numDimensions = anumDimensions;
rt300@0 83
rt300@0 84 whichCandidateParamAdjustable = adjustables;
rt300@0 85 generateListOfControls();
rt300@0 86 targetParams = aTargetValues;
rt300@0 87 candidateParams = aCandidateValues;
rt300@0 88 scored = true;
rt300@0 89
rt300@0 90 }
rt300@0 91 // constructot that enables you to set the space the test is carried out in but not start
rt300@0 92 Test(char letter, int aTimeGiven, controlPanelType pType, int aNumDimensions, vector<bool> adjustables){
rt300@0 93 identifyingLetter = letter;
rt300@0 94 timeGiven = aTimeGiven;
rt300@0 95 panelType= pType;
rt300@0 96 numDimensions = aNumDimensions;
rt300@0 97
rt300@0 98 generateListOfControls();
rt300@0 99 makeRandomTarget();
rt300@0 100 setCandidateToTarget();
rt300@0 101 whichCandidateParamAdjustable = adjustables;
rt300@0 102 randomiseCandidate();
rt300@0 103 scored = true;
rt300@0 104 }
rt300@0 105
rt300@0 106
rt300@0 107
rt300@0 108 // constructor that takes target values, but leaves those not adjustable
rt300@0 109 Test(char letter, int aTimeGiven, controlPanelType pType, int aNumDimensions, vector<bool> adjustables, vector<int> aTargetValues){
rt300@0 110 identifyingLetter = letter;
rt300@0 111 timeGiven = aTimeGiven;
rt300@0 112 panelType= pType;
rt300@0 113 numDimensions = aNumDimensions;
rt300@0 114
rt300@0 115 generateListOfControls();
rt300@0 116 targetParams = aTargetValues;
rt300@0 117 whichCandidateParamAdjustable = adjustables;
rt300@0 118 randomiseTargetAdjustable();
rt300@0 119 setCandidateToTarget();
rt300@0 120
rt300@0 121 randomiseCandidate();
rt300@0 122 scored = true;
rt300@0 123 }
rt300@0 124
rt300@0 125 // the one that is called from generate some tests!!
rt300@0 126 Test(char letter, int aTimeGiven, controlPanelType pType, int aNumDimensions, vector<bool> adjustables, vector<int> aTargetValues, bool ascored = true, bool ahint = false, bool aMemoryTest = false){
rt300@0 127 identifyingLetter = letter;
rt300@0 128 timeGiven = aTimeGiven;
rt300@0 129 panelType= pType;
rt300@0 130 numDimensions = aNumDimensions;
rt300@0 131
rt300@0 132 generateListOfControls();
rt300@0 133 targetParams = aTargetValues;
rt300@0 134 whichCandidateParamAdjustable = adjustables;
rt300@0 135 randomiseTargetAdjustable();
rt300@0 136 setCandidateToTarget();
rt300@0 137
rt300@0 138 randomiseCandidate();
rt300@0 139 scored = ascored;
rt300@0 140 withHint = ahint;
rt300@0 141 memoryTest = aMemoryTest;
rt300@0 142 targetPlaysLeft = 1; // only decr if memory test
rt300@0 143 };
rt300@0 144 bool isWithHint(){
rt300@0 145 return withHint;
rt300@0 146 };
rt300@0 147 bool isMemoryTest(){
rt300@0 148 return memoryTest;
rt300@0 149 };
rt300@0 150 bool isPractice(){
rt300@0 151 return !scored;
rt300@0 152 };
rt300@34 153
rt300@0 154
rt300@0 155 TestResult getScoreForAnswer(vector<int> answer, TimerMillisec timeTaken) const {
rt300@0 156 TestResult result;
rt300@0 157 stringstream msg;
rt300@0 158 int score = 0;
rt300@0 159 // work out euc distance from actual point
rt300@0 160 //for_each(answer.begin(),answer.end(),printThing<int>());
rt300@0 161 //for_each(targetParams.begin(),targetParams.end(),printThing<int>());
rt300@0 162 float dist = euclideanDistance(targetParams, answer);
rt300@0 163 auto dimComp = sqrt(numDimensions);
rt300@0 164 int band = -1;
rt300@0 165 if (dist < TARGET_SCORE_CC_BAND*dimComp){
rt300@0 166 score = 50;
rt300@0 167 band = 1;
rt300@0 168
rt300@0 169 msg << "DOUBLE BULLSEYE!" << endl;
rt300@0 170
rt300@0 171
rt300@0 172 }else if (dist < TARGET_SCORE_CC_BAND*2*dimComp){
rt300@0 173
rt300@0 174 score = 25;
rt300@0 175 band = 2;
rt300@0 176
rt300@0 177 msg << "SINGLE BULLSEYE!" << endl;
rt300@0 178
rt300@0 179 }else if (dist < TARGET_SCORE_CC_BAND*3*dimComp){
rt300@0 180
rt300@0 181 score = 15;
rt300@0 182 band = 3;
rt300@0 183 msg << "CLOSE..." << endl;
rt300@0 184
rt300@0 185 }else if (dist < TARGET_SCORE_CC_BAND*4*dimComp){
rt300@0 186 score = 5;
rt300@0 187 band = 4;
rt300@0 188 msg << "OK...ISH" << endl;
rt300@0 189
rt300@0 190 }else if (dist < TARGET_SCORE_CC_BAND*6*dimComp){ // 30
rt300@0 191 score = 2;
rt300@0 192 band = 5;
rt300@0 193 msg << "MEDIOCRE" << endl;
rt300@0 194
rt300@0 195 }else if (dist < TARGET_SCORE_CC_BAND*9*dimComp){ // 45
rt300@0 196 score = 1;
rt300@0 197 band = 6;
rt300@0 198 msg << "POOR..." << endl;
rt300@0 199
rt300@0 200 }else{
rt300@0 201 score = 0;
rt300@0 202 band = 7;
rt300@0 203 msg << "MISSED COMPLETELY!" << endl;
rt300@0 204
rt300@0 205
rt300@0 206 }
rt300@0 207 msg << "Distance from target: " << dist << endl;
rt300@0 208 msg << "Basic Score: " << score << endl;
rt300@0 209 msg << "-----" << endl;
rt300@0 210 msg << "Time taken: " << timeTaken/1000.0 << endl;
rt300@0 211 int window = -1;
rt300@0 212 if (timeTaken < 5000){
rt300@0 213 msg << "Under 5 seconds: 10x bonus" << endl;
rt300@0 214 score *= 10;
rt300@0 215 window = 1;
rt300@0 216 }else if (timeTaken < 10000){
rt300@0 217 msg << "Under 10 seconds: 5x bonus" << endl;
rt300@0 218 score *= 5;
rt300@0 219 window = 2;
rt300@0 220 }else if (timeTaken < 15000){
rt300@0 221 msg << "Under 15 seconds: 3x bonus" << endl;
rt300@0 222 score *=3;
rt300@0 223 window = 3;
rt300@0 224 }else if (timeTaken < 20000){
rt300@0 225 msg << "Under 20 seconds: 2x bonus" << endl;
rt300@0 226 score *=2;
rt300@0 227 window = 4;
rt300@0 228 }else if (timeTaken < 20000){
rt300@0 229 msg << "Under 25 seconds: no bonus" << endl;
rt300@0 230 score *=2;
rt300@0 231 window = 4;
rt300@0 232 }else if (timeTaken > 30000){
rt300@0 233 msg << "Over 30 seconds: TOO LATE!" << endl;
rt300@0 234 score *=0;
rt300@0 235 window = 4;
rt300@0 236 }
rt300@0 237 score *= numDimensions; // dimension bonus
rt300@0 238 msg << numDimensions*numDimensions << "X Dimension bonus" << endl;
rt300@0 239 msg << "-----" << endl;
rt300@0 240 if (!scored){
rt300@0 241
rt300@0 242 msg << "PRACTICE RUN, scored: " << score << endl;
rt300@0 243 score = 0;
rt300@0 244 }else{
rt300@0 245 msg << "Total: " << score << endl;
rt300@0 246 }
rt300@0 247 result.realDistanceToTarget = dist;
rt300@0 248 result.targetBandHit = band; // eg bullseye = 0 edge = 7
rt300@0 249 result.timeTaken = timeTaken;
rt300@0 250 result.timeWindowHit = window; // eg < 5s = 0
rt300@0 251 result.dimensionMult = numDimensions*numDimensions;
rt300@0 252 result.score = score;
rt300@0 253 result.displayText = msg.str();
rt300@0 254
rt300@0 255
rt300@0 256 return result;
rt300@0 257 }
rt300@0 258
rt300@0 259 vector<int> getChangeableIndices() {
rt300@0 260 vector<int> ids;
rt300@0 261 for(int i=0; i< whichCandidateParamAdjustable.size();i++){
rt300@0 262 if (whichCandidateParamAdjustable[i]){
rt300@0 263 ids.push_back(i);
rt300@0 264 }
rt300@0 265 }
rt300@0 266 return ids;
rt300@0 267 };
rt300@0 268 vector<int> getTargetValues() const{
rt300@0 269 return targetParams;
rt300@0 270
rt300@0 271 };
rt300@0 272 vector<int> getStartingCandidateValues() const{
rt300@0 273 return candidateParams;
rt300@0 274
rt300@0 275 };
rt300@0 276
rt300@0 277 int getNumDimensions() const{
rt300@0 278 return numDimensions;
rt300@0 279 }
rt300@0 280 char getTestLetter() const{
rt300@0 281 return identifyingLetter;
rt300@0 282 }
rt300@0 283 vector<bool> getAdjustableMask() const{
rt300@0 284 return whichCandidateParamAdjustable;
rt300@0 285 }
rt300@0 286 vector<controllerType> getListOfControlTypes() const{
rt300@0 287 return listOfControls;
rt300@0 288 }
rt300@0 289 controlPanelType getControlPanelType() const{
rt300@0 290 return panelType;
rt300@0 291 };
rt300@0 292 string getTestTypeAdvanceWarning(){
rt300@2 293
rt300@0 294 stringstream msg;
rt300@0 295
rt300@0 296 msg << "Next test: " << endl << endl;
rt300@0 297 if (panelType == REVISITABLE){
rt300@0 298 msg << "Sliders " << " x " << numDimensions << endl;
rt300@0 299 }
rt300@0 300 if (panelType == SIMULTANEOUS && numDimensions == 2){
rt300@0 301 msg << "XY pad " << endl;
rt300@0 302 }
rt300@0 303 if (panelType == SIMULTANEOUS && numDimensions == 3){
rt300@0 304 msg << "LEAP MOTION 3D -> -> -> -> ->" << endl;
rt300@0 305 }
rt300@2 306 if (panelType == REVISITABLE && numDimensions > 3){
rt300@2 307 msg << numDimensions << " DOF. The new frontier." << endl;
rt300@2 308 }
rt300@0 309 if (isMemoryTest()){
rt300@0 310 msg << endl << "MEMORY TEST - ONE TARGET LISTEN ONLY!!" << endl;
rt300@0 311 }
rt300@0 312 if (!scored){
rt300@0 313 msg << "PRACTICE RUN" << endl;
rt300@0 314 }
rt300@0 315
rt300@0 316 return msg.str();
rt300@0 317 };
rt300@0 318 bool checkTargetPlaysRemaining(){
rt300@0 319 if (isMemoryTest()){
rt300@0 320 targetPlaysLeft--;
rt300@0 321 if (targetPlaysLeft <= 0){
rt300@0 322 return false;
rt300@0 323 }
rt300@0 324
rt300@0 325 }
rt300@0 326 return true;
rt300@0 327 }
rt300@0 328 int getTargetPlaysLeft(){
rt300@0 329 return targetPlaysLeft;
rt300@0 330 }
rt300@0 331
rt300@0 332 private:
rt300@0 333 char identifyingLetter;
rt300@0 334 int timeGiven;
rt300@0 335 int timeElapsed;
rt300@0 336 controlPanelType panelType;
rt300@0 337 vector<controllerType> listOfControls;
rt300@0 338 int numDimensions;
rt300@0 339 vector<int> targetParams;
rt300@0 340 vector<int> candidateParams;
rt300@0 341 vector<bool> whichCandidateParamAdjustable;
rt300@0 342 int targetPlaysLeft;
rt300@0 343 bool scored, withHint, memoryTest;
rt300@0 344
rt300@0 345
rt300@0 346 void setCandidateToTarget(){
rt300@0 347
rt300@0 348 for(vector<int>::iterator ii = targetParams.begin(); ii < targetParams.end(); ii++){
rt300@0 349 candidateParams.push_back(*ii);
rt300@0 350 }
rt300@0 351 };
rt300@0 352
rt300@0 353 void generateListOfControls(){
rt300@0 354 // need ?
rt300@0 355 if(panelType == SEQUENTIAL || panelType == REVISITABLE){
rt300@0 356 for(int i=0;i<numDimensions;i++){
rt300@0 357 listOfControls.push_back(SLIDER);
rt300@0 358 }
rt300@0 359 }else{ // panelType == SIMULTANEOUS
rt300@0 360 if(numDimensions == 2){
rt300@0 361 listOfControls.push_back(XYPAD);
rt300@0 362 }
rt300@0 363 if(numDimensions == 3){
rt300@0 364 listOfControls.push_back(LEAP3D);
rt300@0 365
rt300@0 366 }
rt300@0 367 if(numDimensions == 4){
rt300@0 368 listOfControls.push_back(XYPAD);
rt300@0 369 listOfControls.push_back(XYPAD);
rt300@0 370 }
rt300@0 371
rt300@0 372 }
rt300@0 373 };
rt300@0 374
rt300@0 375 void makeRandomTarget(){
rt300@0 376 targetParams.clear();
rt300@0 377 for(int i=0;i<TOTAL_NUM_PARAMS; i++){
rt300@0 378 int n = ofRandom(0,127); // why does this consistently come out the same??
rt300@0 379 targetParams.push_back(n);
rt300@0 380
rt300@0 381 }
rt300@0 382
rt300@0 383 };
rt300@0 384
rt300@0 385
rt300@0 386 void randomiseCandidate(){
rt300@0 387 // randomises only those who are adjustable
rt300@0 388 // needs to be more than a certain distance (1/3 of total = 40?)
rt300@0 389 float reasonableDistance = 40.0*sqrt(numDimensions);
rt300@0 390 bool notFarEnough = true;
rt300@0 391 while (notFarEnough){
rt300@0 392 transform(candidateParams.begin(),
rt300@0 393 candidateParams.end(),
rt300@0 394 whichCandidateParamAdjustable.begin(),
rt300@0 395 candidateParams.begin(),
rt300@0 396 randomiseCCValIf<int>());
rt300@0 397 notFarEnough = ( euclideanDistance(candidateParams,targetParams) < reasonableDistance );
rt300@0 398 }
rt300@0 399 cout << "Test distance = " << euclideanDistance(candidateParams,targetParams) << endl;
rt300@0 400
rt300@0 401 };
rt300@0 402
rt300@0 403 void randomiseTargetAdjustable(){
rt300@0 404 // randomises only those who are adjustable, in the case where we want exactly the same space
rt300@0 405 // i.e. original target was fed in
rt300@0 406 transform(targetParams.begin(),
rt300@0 407 targetParams.end(),
rt300@0 408 whichCandidateParamAdjustable.begin(),
rt300@0 409 targetParams.begin(),
rt300@0 410 randomiseCCValIf<int>());
rt300@0 411
rt300@0 412
rt300@0 413 };
rt300@0 414
rt300@0 415 // select a few params that will be the ones to chng
rt300@0 416 void randomParamSelection(int numToChange){
rt300@0 417
rt300@0 418 for(int i= 0; i<numToChange; i++){
rt300@0 419 whichCandidateParamAdjustable.push_back(true);
rt300@0 420 }
rt300@0 421 for(int i= 0; i<(TOTAL_NUM_PARAMS - numToChange); i++){
rt300@0 422 whichCandidateParamAdjustable.push_back(false);
rt300@0 423 }
rt300@0 424 random_shuffle(whichCandidateParamAdjustable.begin(), whichCandidateParamAdjustable.end());
rt300@0 425 //for_each(whichCandidateParamAdjustable.begin(), whichCandidateParamAdjustable.end(), printThing<int>());
rt300@0 426
rt300@0 427 };
rt300@0 428
rt300@0 429
rt300@0 430 };
rt300@0 431 //-------------------------------------------------------------
rt300@0 432 //-------------------------------------------------------------
rt300@0 433
rt300@0 434
rt300@0 435 class TestController {
rt300@0 436 public:
rt300@0 437 static const int numDifferentTests;
rt300@0 438 static const int totalNumTests;
rt300@0 439 vector<Test>::iterator currentTest;
rt300@0 440 TestController(){
rt300@0 441
rt300@2 442 // int howManyTests,
rt300@2 443 // int numDimensions,
rt300@2 444 // controlPanelType panelType,
rt300@2 445 // int whichSpace,
rt300@2 446 // bool scored,
rt300@2 447 // bool aHint,
rt300@2 448 // bool aMemoryTest){
rt300@0 449
rt300@42 450 generateSomeTests(2, 6, REVISITABLE,1, true, false, false);
rt300@42 451 generateSomeTests(2, 6, SIMULTANEOUS,1, true, false, false);
rt300@0 452
rt300@0 453 currentTest = testList.begin()-1; // dont do this
rt300@0 454 scoreRunningTotal = 0;
rt300@0 455 };
rt300@0 456
rt300@0 457
rt300@0 458 bool isLastTest(){
rt300@0 459 if (currentTest == testList.end()-1){
rt300@0 460 return true;
rt300@0 461 }
rt300@0 462 return false;
rt300@0 463 }
rt300@0 464 Test goToNextTest(){
rt300@0 465
rt300@0 466 if (currentTest < testList.end()-1){
rt300@0 467 currentTest++;
rt300@0 468 cout << "***************** NEXT TEST : " << (*currentTest).getTestLetter() << endl;
rt300@0 469 // return a copy
rt300@0 470 // (*currentTest).logThisTestSetup();
rt300@0 471
rt300@0 472 return *currentTest;
rt300@0 473
rt300@0 474 }else{
rt300@0 475 cout << "Sequence finished!!!!!!" << endl;
rt300@0 476 Test dummyTest;
rt300@0 477 return dummyTest;
rt300@0 478 }
rt300@0 479 };
rt300@0 480
rt300@0 481 Test getCurrentTest(){
rt300@0 482 // check for valid current test?
rt300@0 483 return *currentTest;
rt300@0 484 }
rt300@0 485
rt300@0 486 Test* getCurrentTestPtr(){
rt300@0 487 // check for valid current test?
rt300@0 488 if (currentTest < testList.end() && currentTest >= testList.begin()){
rt300@0 489 return &(*currentTest);
rt300@0 490 }else{
rt300@0 491 return NULL;
rt300@0 492 }
rt300@0 493 }
rt300@0 494 //
rt300@0 495 TestResult submitAnswer(vector<int> answer, TimerMillisec timeTaken){
rt300@0 496 TestResult result;
rt300@0 497 result = (*currentTest).getScoreForAnswer(answer, timeTaken);
rt300@0 498 scoreRunningTotal += result.score;
rt300@0 499 return result;
rt300@0 500 }
rt300@0 501 vector<controllerType> getCurrentListOfControls(){
rt300@0 502 return (*currentTest).getListOfControlTypes();
rt300@0 503 }
rt300@0 504 int getScoreRunningTotal(){
rt300@0 505 return scoreRunningTotal;
rt300@0 506 };
rt300@0 507 char getCurrentTestLetter(){
rt300@0 508 return (*currentTest).getTestLetter();
rt300@0 509 };
rt300@0 510 controlPanelType getCurrentPanelType(){
rt300@0 511 return (*currentTest).getControlPanelType();
rt300@0 512 };
rt300@0 513 vector<int> getCurrentChangeableParams(){
rt300@0 514 return (*currentTest).getChangeableIndices();
rt300@0 515 }
rt300@0 516 private:
rt300@0 517 void generate2DRandomTests();
rt300@0 518 void generate1DSpecificTests();
rt300@0 519 void generate2DSpecificTests();
rt300@0 520 void generate3DSpecificTests();
rt300@0 521 void generate4DTests();
rt300@42 522
rt300@0 523 void generateSomeTests(int howManyTests, int dimensions, controlPanelType panelType, int whichSpace, bool scored = true,bool aHint = false, bool aMemoryTest = false);
rt300@0 524
rt300@0 525 void generateTestSequence(){
rt300@0 526
rt300@0 527 };
rt300@0 528 //aregaergeargera
rt300@0 529 vector<Test> testList;
rt300@0 530
rt300@0 531 long scoreRunningTotal;
rt300@0 532
rt300@0 533
rt300@0 534 };
rt300@0 535
rt300@0 536
rt300@0 537
rt300@0 538
rt300@0 539 #endif /* defined(__tweakathlon__TestController__) */