Mercurial > hg > tweakathon2ios
changeset 9:d5e928887f51
More refactoring.
Mode for Synth value changes only sent to PD on triggering sound.
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Fri, 17 Oct 2014 17:50:41 +0100 |
parents | d59de9fd3496 |
children | e25d2b1b185e |
files | MessageOrganiser.h PDSynthWrapper.h SearchMessageOrganiser.h SynthParam.h TrainingMessageOrganiser.h UsernameAlertViewController.mm eventLogger.h globalVariables.h testApp.h testApp.mm trainingController.h trainingController.mm trainingTestController.h trainingTestController.mm |
diffstat | 14 files changed, 541 insertions(+), 414 deletions(-) [+] |
line wrap: on
line diff
--- a/MessageOrganiser.h Fri Oct 17 16:35:22 2014 +0100 +++ b/MessageOrganiser.h Fri Oct 17 17:50:41 2014 +0100 @@ -63,6 +63,8 @@ void init(PDSynthWrapper& cs, PDSynthWrapper& ts){ candidateSynth = cs; targetSynth = ts; + + onlyChangeCandidateOnTrigger = true; } // could template for ui element type?? void mapButtonToAction(UIElement* control, int mappingID){ @@ -71,16 +73,45 @@ control->addHandler(callbackF, mappingID); currentMapping.insert(std::pair<int,UIElement*>(mappingID,control)); } + void setControlPanel(SliderPanel* p){ // a bit specific?? + panel = p; + + }; + void setBottomPanel(ButtonPanel * ntb){ + bottomPanel = ntb; + }; protected: PDSynthWrapper candidateSynth; PDSynthWrapper targetSynth; + ButtonPanel* bottomPanel; // shows during test : play buttons and submit + SliderPanel* panel; + map<int,UIElement*> currentMapping; // could get more sophisticated if not 1-1 ? - map<int,UIElement*> currentMapping; // could get more sophisticated if not 1-1 ? + void triggerCandidateSound(){ + // log event + sendSynthValuesAgain(); + candidateSynth.trigger(); + eventLogger.logEvent(CANDIDATE_PLAYED); + // flash panel? + panel->flash(); + } - SliderPanel* panel; + void paramChangeCallback(int mappingID, int value){ + + if(onlyChangeCandidateOnTrigger){ + candidateSynth.paramChangeCallback(mappingID, value, false); + }else{ + candidateSynth.paramChangeCallback(mappingID, value, true); + } + vector<int> evtData; + evtData.push_back(mappingID); // or just index? + evtData.push_back(value); + + eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData); + }; void sendSynthValuesAgain(){ candidateSynth.sendAllParams(); @@ -150,9 +181,6 @@ control->setLabel(paramName); }; - virtual void paramChangeCallback(int mappingID, int value){ - // virtual? - }; virtual void buttonPressCallback(int mappingID, int value){ }; @@ -167,6 +195,8 @@ setUIToParam(i, vals[i]); } } + + bool onlyChangeCandidateOnTrigger; };
--- a/PDSynthWrapper.h Fri Oct 17 16:35:22 2014 +0100 +++ b/PDSynthWrapper.h Fri Oct 17 17:50:41 2014 +0100 @@ -126,13 +126,17 @@ return result; } - void paramChangeCallback(int mappingID, int value){ + void paramChangeCallback(int mappingID, int value, bool send = true){ // look for id in params std::vector<SynthParam>::iterator psp; for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){ if ( psp->getID() == mappingID){ - psp->setValue(value); + if (send){ + psp->setValue(value); + }else{ + psp->setValueWithoutSend(value); + } return; } }
--- a/SearchMessageOrganiser.h Fri Oct 17 16:35:22 2014 +0100 +++ b/SearchMessageOrganiser.h Fri Oct 17 17:50:41 2014 +0100 @@ -15,331 +15,12 @@ class SearchMessageOrganiser : public MessageOrganiser { public: - - - -protected: - - - TimeController altPlaybackController; - - TestController* testController; - Buttron* newTestButton; - //Buttron* submitButton; - - ButtonPanel* bottomPanel; // shows during test : play buttons and submit - Buttron* targetPlayButton; // so we can hide target in memory test. this pointer stuff is getting out of hand - CountdownText* countdownPanel; - TargetSymbol* targetSymbol; - Leap3DBoxGL* box3D; - TextPanel* scorePanel; - TextPanel* finishPanel; - AppModeChangeFunction testAppModeChange; - - //int scoreRunningTotal; - TimerID currentSoundPlayTimer; - - int alternationSpeed; // ms between cand and target - bool playingAlternating; - - bool okToGetLeapMidi; - - -// protected methods - void testsFinished(){ - panel->hide(); - bottomPanel->hide(); - newTestButton->hide(); - - vector<int> eData; - eData.push_back(testController->getScoreRunningTotal()); - eventLogger.logEvent(ALL_TESTS_COMPLETED, eData); - - // TODO set final score screen txt to testController->getScoreRunningTotal() - finishPanel->show(); - - string user = eventLogger.getUsername(); - stringstream s; - s << "Experiment completed" - << endl << endl - << "You scored: " << testController->getScoreRunningTotal() << " well done " << user << endl << endl - << "to retake test please close " << endl << endl - << "the app and restart with username<num test>"; - finishPanel->setText(s.str()); - // get test app to do something... - - eventLogger.saveSessionToFile(); - }; - - void setupNewTest(){ - // get mapping for new test and make sure we have right controls and stuff - - - Test newTest = testController->goToNextTest(); - - // V0.2 put details about what kind of test it is - vector<int> eData; - eData.push_back(newTest.isPractice()); - eData.push_back(newTest.isWithHint()); - eData.push_back(newTest.isMemoryTest()); - eventLogger.logEvent(NEW_TEST, eData); - - - vector<int> mappingIDsForChangeableParams = setSynthsUpForNewTest(newTest); - - vector<UIElement*> UIElemHandles = panel->generateControls(testController->getCurrentListOfControls(), testController->getCurrentPanelType()); - - mapUIToNewTestParams(UIElemHandles, mappingIDsForChangeableParams); - - countdownPanel->setTestTypeString(newTest.getTestTypeAdvanceWarning()); - - - }; - void startNewTest(){ - Test t = testController->getCurrentTest(); - - countdownPanel->hide(); - panel->show(); - panel->setActive(true); - if(t.isWithHint()){ - panel->showHint(true); - } - - bottomPanel->show(); - targetPlayButton->show(); // incase it was memory test - if (t.isMemoryTest()){ - targetPlayButton->setLabel("Memorise!"); - }else{ - targetPlayButton->setLabel("Target"); - } - //startAlternatingPlayback(); - //timeController.scheduleEvent(boost::bind(&MessageOrganiser::sendSynthValuesAgain, this), 200); - timeController.startStopwatch(); - eventLogger.logEvent(TEST_TIMER_STARTED); - - - if(t.getListOfControlTypes()[0] == LEAP3D){ - okToGetLeapMidi = true; - } - }; - - vector<int> setSynthsUpForNewTest(Test newTest){ - targetSynth.setAllParams(newTest.getTargetValues()); - eventLogger.logEvent(TARGET_PARAM_SET, newTest.getTargetValues()); // unless something goes wrong in setAllParams - - candidateSynth.setAllParams(newTest.getStartingCandidateValues()); - eventLogger.logEvent(CANDIDATE_PARAM_SET,newTest.getStartingCandidateValues()); - - // eventLogger.logEvent(NEW_TARGET_PARAMS, vector<int> ); - // eventLogger.logEvent(NEW_CANDIDATE_PARAMS, vector<int> ); - - vector<int> mids = candidateSynth.getMappingIDForIndices(newTest.getChangeableIndices()); - - eventLogger.logEvent(CANDIDATE_CHANGEABLE_IDX, newTest.getChangeableIndices()); - eventLogger.logEvent(CANDIDATE_MAPPING_IDS, mids); - - return mids; - }; - - - // could have been cleverer. takes forever due to searching ??? - void mapUIToNewTestParams(vector<UIElement*> elems, vector<int> mids){ - - vector<UIElement*>::iterator elit; - vector<int> typeListLog; - int i = 0; - for(elit=elems.begin(); elit<elems.end();elit++){ - if ( (*elit)->getType() == XYPAD){ - if(i+1 >= mids.size()){ - cout << "ERROR ERROR: too many controls for mapping IDs" << endl; - } - - ButtronXY* theXY = (ButtronXY*)(*elit); - mapXYToParams(theXY, mids[i], mids[i+1]); - theXY->setValueAndScale(candidateSynth.getParamValueForID(mids[i]), candidateSynth.getParamValueForID(mids[i+1])); - theXY->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])) - ,targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i+1]))); - i+=2; - typeListLog.push_back(int(XYPAD)); - }else if ( (*elit)->getType() == SLIDER){ - if(i >= mids.size()){ - - cout << "ERROR ERROR: too many controls for mapping IDs: " << mids.size() << endl; - } - - ButtronSlider* theSlider = (ButtronSlider*)(*elit); - mapControlToParam((*elit), mids[i]); - theSlider->setValueAndScale(candidateSynth.getParamValueForID(mids[i])); - cout << "Hint Value " << targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])) << endl; - theSlider->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i]))); - i++; - typeListLog.push_back(int(SLIDER)); - }else if ( (*elit)->getType() == LEAP3D ){ - set3Dbox((Leap3DBoxGL*)(*elit)); - // UH - string nameX = candidateSynth.getNameForMappingID(mids[i]); - box3D->setHintValue(0,targetSynth.getParamValueFromName(nameX)); - box3D->setValueAndScale(0, candidateSynth.getParamValueForID(mids[i])); - i++; - - string nameY = candidateSynth.getNameForMappingID(mids[i]); - box3D->setHintValue(1,targetSynth.getParamValueFromName(nameY)); - box3D->setValueAndScale(1, candidateSynth.getParamValueForID(mids[i])); - i++; - - string nameZ = candidateSynth.getNameForMappingID(mids[i]); - box3D->setHintValue(2,targetSynth.getParamValueFromName(nameZ)); - box3D->setValueAndScale(2, candidateSynth.getParamValueForID(mids[i])); - i++; - - - box3D->setLabels(nameX,nameY,nameZ); - typeListLog.push_back(int(LEAP3D)); - - }else{ - cout << "ERROR ERROR: ui type not handled my mapping function !" << endl; - } - } - - eventLogger.logEvent(CONTROL_LIST,typeListLog); - }; - - // TODO - no, triggering playback needs to be logged - void startAlternatingPlayback(){ - - cout << "start alt playback" << endl; - // use our special timer to fire off play to pd - // sets off timed alternating playback - - playAlternating(); - playingAlternating = true; - - }; - void stopAlternatingPlayback(){ - cout << "stop alt playback" << endl; - // kill the alternation - timeController.cancelEvent(currentSoundPlayTimer); - playingAlternating = false; - }; - - void playAlternating(){ - - static bool alt; - int nextTime; - if (alt){ - targetSynth.trigger(); - // flash the target thingy - targetSymbol->flash(); - nextTime = alternationSpeed*1.503; // gap after target - }else{ - sendSynthValuesAgain(); // and again and again - candidateSynth.trigger(); - panel->flash(); - nextTime = alternationSpeed; - } - alt = !alt; - candidateSynth.setNoteLength(alternationSpeed); - targetSynth.setNoteLength(alternationSpeed); // could be user alterable - currentSoundPlayTimer = timeController.scheduleEvent(boost::bind(&SearchMessageOrganiser::playAlternating,this), nextTime); - - - - }; - - void delayedShowNewTest(){ - newTestButton->show(); - // JUST IN CASE IT CRASHES near end... - //eventLogger.saveSessionToFile(); - }; - void submitSingleControl(){ - // if last one - // submitPressed() - - // else - - // grey out that slider, - // activate next slider and show it's button (same button but moved!???) - - }; - - - void submitPressed(){ - - // depending on mode go to next control - // if(testController->getCurrentPanelType() == SEQUENTIAL){ - // submitSingleControl(); - // return; - // } - // otherwise do this other - or call - - okToGetLeapMidi = false; - - TimerMillisec timeTaken = timeController.stopStopwatch(); - vector<int> answer = candidateSynth.getAllParamValues(); - - eventLogger.logEvent(SUBMIT_PRESSED, answer); //, answer, scoreRunningTotal, time taken (why not?)); - - TestResult result = testController->submitAnswer(answer, timeTaken); // TODO returns all the results - - vector<int> logResult; - logResult.push_back(result.realDistanceToTarget*1000); // measured in milliCC !??! - logResult.push_back(result.timeTaken); // milliseconds - logResult.push_back(result.score); - logResult.push_back(result.targetBandHit); - logResult.push_back(result.timeWindowHit); - - eventLogger.logEvent(DISTANCE_TIME_SCORE, logResult); - - - // gui stuff - different controller? - panel->setActive(false); - panel->showHint(true); // add some encouraging feedback to hint - bottomPanel->hide(); - - showScoreForTest(result); - - stopAlternatingPlayback(); - - // was it the final sumbit? - if(testController->isLastTest()){ - // thats it - show a final score screen etc - timeController.scheduleEvent(boost::bind(&SearchMessageOrganiser::testsFinished, this), 500); - return; - }else{ - timeController.scheduleEvent(boost::bind(&SearchMessageOrganiser::delayedShowNewTest, this), 300); - } - - - }; - - void showScoreForTest(TestResult result){ - scorePanel->setText(result.displayText); - scorePanel->show(); - - ofColor c; - if(result.targetBandHit == 1){ - // yellow red blue - c = ofColor(255,255,0,255); - }else if(result.targetBandHit == 2){ - c = ofColor(255,0,0,255); - }else if(result.targetBandHit == 3){ - c = ofColor(45,45,255,255); - }else if(result.targetBandHit == 4){ - c = ofColor(0,255,0,255); - }else{ - c = ofColor(150,235,200,255); - } - scorePanel->setColor(c); - panel->setHintColor(c); - }; - -public: void init( PDSynthWrapper& cs, PDSynthWrapper& ts){ testController = new TestController; MessageOrganiser::init(cs,ts); - + currentSoundPlayTimer = -1; okToGetLeapMidi = false; @@ -385,13 +66,8 @@ void set3Dbox(Leap3DBoxGL* box){ box3D = box; }; - void setBottomPanel(ButtonPanel * ntb){ - bottomPanel = ntb; - }; - void setControlPanel(SliderPanel* p){ - panel = p; - - }; + + void setCountdownPanel(CountdownText* cd){ countdownPanel = cd; }; @@ -435,7 +111,7 @@ timeController.scheduleEvent(boost::bind(&SearchMessageOrganiser::startNewTest, this), 3000); }; - + void playTargetButtonPressed(){ static int numPlays = 3; @@ -459,9 +135,7 @@ return; } - void playCandidateButtonPressed(){ - // - } + void buttonPressCallback(int mappingID, int value){ if(mappingID == VOLUME_CHANGE_ID){ targetSynth.sendVolume(value); @@ -487,7 +161,7 @@ } return; } - + if (mappingID == RANDOMISE_TARGET_ID){ // bleyeueurrrr targetSynth.randomiseParams(); return; @@ -568,15 +242,6 @@ } } // called from UI - // OVERLOADED - void paramChangeCallback(int mappingID, int value){ - candidateSynth.paramChangeCallback(mappingID, value); - vector<int> evtData; - evtData.push_back(mappingID); // or just index? - evtData.push_back(value); - - eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData); - }; void midiFromLeap(int ctl_num, int ctl_val){ @@ -601,12 +266,325 @@ evtData.push_back(ctl_val); eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData); - + } - + ofTrueTypeFont verdBig; + +protected: + + + TimeController altPlaybackController; + + TestController* testController; + Buttron* newTestButton; + //Buttron* submitButton; + + + Buttron* targetPlayButton; // so we can hide target in memory test. this pointer stuff is getting out of hand + CountdownText* countdownPanel; + TargetSymbol* targetSymbol; + Leap3DBoxGL* box3D; + TextPanel* scorePanel; + TextPanel* finishPanel; + AppModeChangeFunction testAppModeChange; + + //int scoreRunningTotal; + TimerID currentSoundPlayTimer; + + int alternationSpeed; // ms between cand and target + bool playingAlternating; + + bool okToGetLeapMidi; + + +// protected methods + void testsFinished(){ + panel->hide(); + bottomPanel->hide(); + newTestButton->hide(); + + vector<int> eData; + eData.push_back(testController->getScoreRunningTotal()); + eventLogger.logEvent(ALL_TESTS_COMPLETED, eData); + + // TODO set final score screen txt to testController->getScoreRunningTotal() + finishPanel->show(); + + string user = eventLogger.getUsername(); + stringstream s; + s << "Experiment completed" + << endl << endl + << "You scored: " << testController->getScoreRunningTotal() << " well done " << user << endl << endl + << "to retake test please close " << endl << endl + << "the app and restart with username<num test>"; + finishPanel->setText(s.str()); + // get test app to do something... + + eventLogger.saveSessionToFile(); + }; + + void setupNewTest(){ + // get mapping for new test and make sure we have right controls and stuff + + + Test newTest = testController->goToNextTest(); + + // V0.2 put details about what kind of test it is + vector<int> eData; + eData.push_back(newTest.isPractice()); + eData.push_back(newTest.isWithHint()); + eData.push_back(newTest.isMemoryTest()); + eventLogger.logEvent(NEW_TEST, eData); + + + vector<int> mappingIDsForChangeableParams = setSynthsUpForNewTest(newTest); + + vector<UIElement*> UIElemHandles = panel->generateControls(testController->getCurrentListOfControls(), testController->getCurrentPanelType()); + + mapUIToNewTestParams(UIElemHandles, mappingIDsForChangeableParams); + + countdownPanel->setTestTypeString(newTest.getTestTypeAdvanceWarning()); + + + }; + void startNewTest(){ + Test t = testController->getCurrentTest(); + + countdownPanel->hide(); + panel->show(); + panel->setActive(true); + if(t.isWithHint()){ + panel->showHint(true); + } + + bottomPanel->show(); + targetPlayButton->show(); // incase it was memory test + if (t.isMemoryTest()){ + targetPlayButton->setLabel("Memorise!"); + }else{ + targetPlayButton->setLabel("Target"); + } + + timeController.startStopwatch(); + eventLogger.logEvent(TEST_TIMER_STARTED); + + + if(t.getListOfControlTypes()[0] == LEAP3D){ + okToGetLeapMidi = true; + } + }; + + vector<int> setSynthsUpForNewTest(Test newTest){ + targetSynth.setAllParams(newTest.getTargetValues()); + eventLogger.logEvent(TARGET_PARAM_SET, newTest.getTargetValues()); // unless something goes wrong in setAllParams + + candidateSynth.setAllParams(newTest.getStartingCandidateValues()); + eventLogger.logEvent(CANDIDATE_PARAM_SET,newTest.getStartingCandidateValues()); + + vector<int> mids = candidateSynth.getMappingIDForIndices(newTest.getChangeableIndices()); + + eventLogger.logEvent(CANDIDATE_CHANGEABLE_IDX, newTest.getChangeableIndices()); + eventLogger.logEvent(CANDIDATE_MAPPING_IDS, mids); + + return mids; + }; + + + // could have been cleverer. takes forever due to searching ??? + void mapUIToNewTestParams(vector<UIElement*> elems, vector<int> mids){ + + vector<UIElement*>::iterator elit; + vector<int> typeListLog; + int i = 0; + for(elit=elems.begin(); elit<elems.end();elit++){ + if ( (*elit)->getType() == XYPAD){ + if(i+1 >= mids.size()){ + cout << "ERROR ERROR: too many controls for mapping IDs" << endl; + } + + ButtronXY* theXY = (ButtronXY*)(*elit); + mapXYToParams(theXY, mids[i], mids[i+1]); + theXY->setValueAndScale(candidateSynth.getParamValueForID(mids[i]), candidateSynth.getParamValueForID(mids[i+1])); + theXY->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])) + ,targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i+1]))); + i+=2; + typeListLog.push_back(int(XYPAD)); + }else if ( (*elit)->getType() == SLIDER){ + if(i >= mids.size()){ + + cout << "ERROR ERROR: too many controls for mapping IDs: " << mids.size() << endl; + } + + ButtronSlider* theSlider = (ButtronSlider*)(*elit); + mapControlToParam((*elit), mids[i]); + theSlider->setValueAndScale(candidateSynth.getParamValueForID(mids[i])); + cout << "Hint Value " << targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])) << endl; + theSlider->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i]))); + i++; + typeListLog.push_back(int(SLIDER)); + }else if ( (*elit)->getType() == LEAP3D ){ + set3Dbox((Leap3DBoxGL*)(*elit)); + // UH + string nameX = candidateSynth.getNameForMappingID(mids[i]); + box3D->setHintValue(0,targetSynth.getParamValueFromName(nameX)); + box3D->setValueAndScale(0, candidateSynth.getParamValueForID(mids[i])); + i++; + + string nameY = candidateSynth.getNameForMappingID(mids[i]); + box3D->setHintValue(1,targetSynth.getParamValueFromName(nameY)); + box3D->setValueAndScale(1, candidateSynth.getParamValueForID(mids[i])); + i++; + + string nameZ = candidateSynth.getNameForMappingID(mids[i]); + box3D->setHintValue(2,targetSynth.getParamValueFromName(nameZ)); + box3D->setValueAndScale(2, candidateSynth.getParamValueForID(mids[i])); + i++; + + + box3D->setLabels(nameX,nameY,nameZ); + typeListLog.push_back(int(LEAP3D)); + + }else{ + cout << "ERROR ERROR: ui type not handled my mapping function !" << endl; + } + } + + eventLogger.logEvent(CONTROL_LIST,typeListLog); + }; + + // TODO - no, triggering playback needs to be logged + void startAlternatingPlayback(){ + + cout << "start alt playback" << endl; + // use our special timer to fire off play to pd + // sets off timed alternating playback + + playAlternating(); + playingAlternating = true; + + }; + void stopAlternatingPlayback(){ + cout << "stop alt playback" << endl; + // kill the alternation + timeController.cancelEvent(currentSoundPlayTimer); + playingAlternating = false; + }; + + void playAlternating(){ + + static bool alt; + int nextTime; + if (alt){ + targetSynth.trigger(); + // flash the target thingy + targetSymbol->flash(); + nextTime = alternationSpeed*1.503; // gap after target + }else{ + sendSynthValuesAgain(); // and again and again + candidateSynth.trigger(); + panel->flash(); + nextTime = alternationSpeed; + } + alt = !alt; + candidateSynth.setNoteLength(alternationSpeed); + targetSynth.setNoteLength(alternationSpeed); // could be user alterable + currentSoundPlayTimer = timeController.scheduleEvent(boost::bind(&SearchMessageOrganiser::playAlternating,this), nextTime); + + + + }; + + void delayedShowNewTest(){ + newTestButton->show(); + // JUST IN CASE IT CRASHES near end... + //eventLogger.saveSessionToFile(); + }; + void submitSingleControl(){ + // if last one + // submitPressed() + + // else + + // grey out that slider, + // activate next slider and show it's button (same button but moved!???) + + }; + + + void submitPressed(){ + + // depending on mode go to next control + // if(testController->getCurrentPanelType() == SEQUENTIAL){ + // submitSingleControl(); + // return; + // } + // otherwise do this other - or call + + okToGetLeapMidi = false; + + TimerMillisec timeTaken = timeController.stopStopwatch(); + vector<int> answer = candidateSynth.getAllParamValues(); + + eventLogger.logEvent(SUBMIT_PRESSED, answer); //, answer, scoreRunningTotal, time taken (why not?)); + + TestResult result = testController->submitAnswer(answer, timeTaken); // TODO returns all the results + + vector<int> logResult; + logResult.push_back(result.realDistanceToTarget*1000); // measured in milliCC !??! + logResult.push_back(result.timeTaken); // milliseconds + logResult.push_back(result.score); + logResult.push_back(result.targetBandHit); + logResult.push_back(result.timeWindowHit); + + eventLogger.logEvent(DISTANCE_TIME_SCORE, logResult); + + + // gui stuff - different controller? + panel->setActive(false); + panel->showHint(true); // add some encouraging feedback to hint + bottomPanel->hide(); + + showScoreForTest(result); + + stopAlternatingPlayback(); + + // was it the final sumbit? + if(testController->isLastTest()){ + // thats it - show a final score screen etc + timeController.scheduleEvent(boost::bind(&SearchMessageOrganiser::testsFinished, this), 500); + return; + }else{ + timeController.scheduleEvent(boost::bind(&SearchMessageOrganiser::delayedShowNewTest, this), 300); + } + + + }; + + void showScoreForTest(TestResult result){ + scorePanel->setText(result.displayText); + scorePanel->show(); + + ofColor c; + if(result.targetBandHit == 1){ + // yellow red blue + c = ofColor(255,255,0,255); + }else if(result.targetBandHit == 2){ + c = ofColor(255,0,0,255); + }else if(result.targetBandHit == 3){ + c = ofColor(45,45,255,255); + }else if(result.targetBandHit == 4){ + c = ofColor(0,255,0,255); + }else{ + c = ofColor(150,235,200,255); + } + scorePanel->setColor(c); + panel->setHintColor(c); + }; + + }; #endif /* defined(__riftathon__SearchMessageOrganiser__) */
--- a/SynthParam.h Fri Oct 17 16:35:22 2014 +0100 +++ b/SynthParam.h Fri Oct 17 17:50:41 2014 +0100 @@ -26,9 +26,11 @@ }; void setValue(int i){ value = i; - // TODO should this send an eventlog message? what if called from randomise ? what if different synth? sendToPD(); }; + void setValueWithoutSend(int i){ + value = i; + } int getValue() const{ return value; }
--- a/TrainingMessageOrganiser.h Fri Oct 17 16:35:22 2014 +0100 +++ b/TrainingMessageOrganiser.h Fri Oct 17 17:50:41 2014 +0100 @@ -10,8 +10,91 @@ #define __riftathon__TrainingMessageOrganiser__ #include <iostream> +#include "trainingTestController.h" +#include "MessageOrganiser.h" +class TrainingMessageOrganiser : public MessageOrganiser { +public: + void init( PDSynthWrapper& cs, PDSynthWrapper& ts){ + + trainingTestController = new TrainingTestController; + + MessageOrganiser::init(cs,ts); -class TrainingMessageOrganiser{ + } + void setupDefaultMapping(){ + vector<int> mappingIDsForChangeableParams = getMappingIDsFromSynths(); + + controlPanelType cpt = REVISITABLE; + vector<controllerType> elemList; + for(int i = 0; i < 8; i++){ + elemList.push_back(SLIDER); + } + + vector<UIElement*> UIElemHandles = panel->generateControls(elemList, cpt); + + mapSlidersToParams(UIElemHandles, mappingIDsForChangeableParams); + + bottomPanel->show(); + } + + vector<int> getMappingIDsFromSynths(){ + vector<int> index; + for(int i = 0; i < 8; i++){ + index.push_back(i); + } + vector<int> mids = candidateSynth.getMappingIDForIndices(index); + + return mids; + } + + void setupNewTest(){ + + + }; + +protected: + void mapSlidersToParams(vector<UIElement*> elems, vector<int> mids){ + + vector<UIElement*>::iterator elit; + vector<int> typeListLog; + int i = 0; + for(elit=elems.begin(); elit<elems.end();elit++){ + if ( (*elit)->getType() == SLIDER){ + if(i >= mids.size()){ + + cout << "ERROR ERROR: too many controls for mapping IDs: " << mids.size() << endl; + } + + ButtronSlider* theSlider = (ButtronSlider*)(*elit); + mapControlToParam((*elit), mids[i]); + theSlider->setValueAndScale(candidateSynth.getParamValueForID(mids[i])); + cout << "Hint Value " << targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])) << endl; + theSlider->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i]))); + i++; + typeListLog.push_back(int(SLIDER)); + + }else{ + cout << "ERROR ERROR: ui type not handled my mapping function !" << endl; + } + } + + eventLogger.logEvent(CONTROL_LIST,typeListLog); + }; + + void buttonPressCallback(int mappingID, int value){ + if(mappingID == VOLUME_CHANGE_ID){ + targetSynth.sendVolume(value); + candidateSynth.sendVolume(value); + + } + + if (mappingID == TRIGGER_CANDIDATE_ID){ + triggerCandidateSound(); + return; + } + } + + TrainingTestController* trainingTestController; }; #endif /* defined(__riftathon__TrainingMessageOrganiser__) */
--- a/UsernameAlertViewController.mm Fri Oct 17 16:35:22 2014 +0100 +++ b/UsernameAlertViewController.mm Fri Oct 17 17:50:41 2014 +0100 @@ -62,7 +62,7 @@ }else{ eventLogger.setUsername([userName cStringUsingEncoding:NSASCIIStringEncoding]); - ((testApp *)self.theOFAppRef)->startTheTests(); + ((testApp *)self.theOFAppRef)->usernameEntered(); } [self.alert dismissWithClickedButtonIndex:self.alert.firstOtherButtonIndex animated:YES];
--- a/eventLogger.h Fri Oct 17 16:35:22 2014 +0100 +++ b/eventLogger.h Fri Oct 17 17:50:41 2014 +0100 @@ -62,11 +62,12 @@ ALL_TESTS_COMPLETED, // 16 ? TARGET_PLAYED, // 17 however this happens it might be good to know when this happens CANDIDATE_PLAYED, // 18 - START_THE_TESTS, // 19 probably superfluous + START_THE_SEARCH_TESTS, // 19 probably superfluous CRAP_TEST, // eliminate these coords somehow ??? EMPTY_EVENT, SPEED_CHANGED, // 22 ms between sounds - SAVE_PRESET // 23 save a preset + SAVE_PRESET, // 23 save a preset + START_THE_TRAINING_TESTS, };
--- a/globalVariables.h Fri Oct 17 16:35:22 2014 +0100 +++ b/globalVariables.h Fri Oct 17 17:50:41 2014 +0100 @@ -33,6 +33,8 @@ typedef enum {TOUCH_DOWN, TOUCH_MOVED, TOUCH_UP} touchType; typedef enum {INTRO,QUESTIONNAIRE, HELP, TEST_IN_PROGRESS, SCORE_AND_HINT, COUNT_DOWN, READY_FOR_NEXT} interfaceType; +typedef enum {FAMILIARISATION, EXPRESS, TRAINING, SEARCH} testStages; + typedef enum {SLIDER, XYPAD, BUTTON, LEAP3D} controllerType; typedef enum {SEQUENTIAL, REVISITABLE, SIMULTANEOUS, MULTI_SIMPLE, MULTI_COMPLEX} controlPanelType;
--- a/testApp.h Fri Oct 17 16:35:22 2014 +0100 +++ b/testApp.h Fri Oct 17 17:50:41 2014 +0100 @@ -30,7 +30,6 @@ #include "MessageOrganiser.h" #include "SearchMessageOrganiser.h" #include "TrainingMessageOrganiser.h" -#include "TestController.h" #include "timeController.h" #include <buttonPanel.h> #include "targetSymbol.h" @@ -50,6 +49,8 @@ public: + testStages currentStage; + ofTrueTypeFont verdBig; bool sendMIDIAndOSC; bool paused; @@ -84,8 +85,7 @@ PDSynthWrapper targetSynth; PDSynthWrapper candidateSynth; - - TestController* testController; + //TimeController timeController; interfaceType whichInterfaceShowing, previousInterface; @@ -117,7 +117,8 @@ void showIntro(); void introHidden(); void usernameEntered(); - void startTheTests(); + void startTheSearchTests(); + void startTheTrainingTests(); void showHelp(); void helpHidden(); void setupNewUser();
--- a/testApp.mm Fri Oct 17 16:35:22 2014 +0100 +++ b/testApp.mm Fri Oct 17 17:50:41 2014 +0100 @@ -27,6 +27,7 @@ candidateSynth.init(&core,"candidateSynth"); searchMessageOrganiser.init(targetSynth, candidateSynth); + trainingMessageOrganiser.init(targetSynth,candidateSynth); timeController.init(); initialiseGUIs(); initialiseMIDI(); @@ -66,7 +67,7 @@ ofSoundStreamSetup(2, 2, this, 44100, ofxPd::blockSize()*ticksPerBuffer, 3); if(true){ // force start - startTheTests(); + startTheTrainingTests(); }else{ if(eventLogger.questionnaireCompleted){ // then show play again dialog, and log the test number @@ -124,7 +125,18 @@ //-------------------------------------------------------------- // gui for the main training stage void testApp::setupTrainingViewPanels(){ + UIProps p; + ButtonPanel* bottomButtonPanel = new ButtonPanel(1,160+p.sliderPanelHeight,ofGetWidth(),250,p); + // play and submit are now same thing + Buttron * playCandidateButton = new Buttron(p.buttonWidth*1.4,680, p); + playCandidateButton->setLabel("PLAY"); + trainingMessageOrganiser.mapButtonToAction(playCandidateButton, TRIGGER_CANDIDATE_ID); + bottomButtonPanel->addButton(playCandidateButton); + + trainingMessageOrganiser.setBottomPanel(bottomButtonPanel); + UIElements.push_back(bottomButtonPanel); + bottomButtonPanel->hide(); } //-------------------------------------------------------------- // gui for the old style tweakathlon stage @@ -167,7 +179,7 @@ searchMessageOrganiser.setBottomPanel(bottomButtonPanel); UIElements.push_back(bottomButtonPanel); bottomButtonPanel->showBorder(false); - + bottomButtonPanel->hide(); // - - - - - -- - - OTHER BITS CountdownText * countDownBox = new CountdownText("5" , 500, 380, 455, 455, p); @@ -217,6 +229,7 @@ UIElements.push_back(controlPanel); searchMessageOrganiser.setControlPanel(controlPanel); + trainingMessageOrganiser.setControlPanel(controlPanel); controlPanel->showBorder(true); } //-------------------------------------------------------------- @@ -229,7 +242,7 @@ setupSliderPanel(); - + setupTrainingViewPanels(); } //-------------------------------------------------------------------------- void testApp::initialiseMIDI(){ @@ -376,16 +389,24 @@ void testApp::usernameEntered(){ // display a thing that gives us an option as to which stage to start // EXPLORE, PERFORMANCE TRAINING, SEARCH + + } //-------------------------------------------------------------- -void testApp::startTheTests(){ - eventLogger.logEvent(START_THE_TESTS); +void testApp::startTheSearchTests(){ + eventLogger.logEvent(START_THE_SEARCH_TESTS); whichInterfaceShowing = COUNT_DOWN; // do countdown etc searchMessageOrganiser.countdownToNewTest(); // TODO how is testApp going to kknow whichInterfaceShowing ??? } +void testApp::startTheTrainingTests(){ + eventLogger.logEvent(START_THE_TRAINING_TESTS); + + trainingMessageOrganiser.setupDefaultMapping(); + +} //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::showHelp(){ @@ -486,7 +507,8 @@ //ofLine(0,150,1024,150); //drawWaveform(); - searchMessageOrganiser.drawScore(); + if (currentStage == SEARCH) + searchMessageOrganiser.drawScore(); @@ -642,7 +664,10 @@ int ctl_val = msg.value; // TODO route control change message here //cout << " ctrl : " << ctl_num << " : " << ctl_val << endl; - searchMessageOrganiser.midiFromLeap(ctl_num, ctl_val); + if (currentStage == SEARCH) + searchMessageOrganiser.midiFromLeap(ctl_num, ctl_val); + + } }
--- a/trainingController.h Fri Oct 17 16:35:22 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -// -// trainingController.h -// riftathon -// -// Created by Robert Tubb on 10/10/2014. -// -// this controls the sequence fo events, for both the slider UI and the VR one -// it sends and recieves messages from a wrapper, it doesn't care which interface you're using -// it only cares about the sequence of events - - -#ifndef __riftathon__trainingController__ -#define __riftathon__trainingController__ -#include "presetManager.h" -#include <iostream> - -// include message types ( or use defines? ) these message type should be sendable by osc / midi -class TrainingController { - - vector<Preset> presetSequence; - - // inputs - void soundSubmitted(); - void readyForNextSequence(); - - // outputs - void presentTheSequence(); - void showCountdown(); - void startSearch(); - - // - void makePresetSequence(int sequenceLength); - - Preset getRandomPreset(); - - - -}; -#endif /* defined(__riftathon__trainingController__) */
--- a/trainingController.mm Fri Oct 17 16:35:22 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -// -// trainingController.mm -// riftathon -// -// Created by Robert Tubb on 10/10/2014. -// -// - -#include "trainingController.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trainingTestController.h Fri Oct 17 17:50:41 2014 +0100 @@ -0,0 +1,40 @@ +// +// trainingController.h +// riftathon +// +// Created by Robert Tubb on 10/10/2014. +// +// this controls the sequence fo events, for both the slider UI and the VR one +// it sends and recieves messages from a wrapper, it doesn't care which interface you're using +// it only cares about the sequence of events + + +#ifndef __riftathon__trainingController__ +#define __riftathon__trainingController__ +#include "presetManager.h" +#include <iostream> + +// include message types ( or use defines? ) these message type should be sendable by osc / midi +class TrainingTestController { +public: + int numParams; + vector<Preset> presetSequence; + + // inputs + void soundSubmitted(); + void readyForNextSequence(); + + // outputs + void presentTheSequence(); + void showCountdown(); + void startSearch(); + + // + void makePresetSequence(int sequenceLength); + + Preset getRandomPreset(); + + + +}; +#endif /* defined(__riftathon__trainingController__) */