rt300@8: // rt300@14: // SequenceGenerator.h rt300@8: // riftathon rt300@8: // rt300@14: // Created by Robert Tubb on 21/10/2014. rt300@8: // rt300@8: // rt300@8: rt300@14: #ifndef __riftathon__SequenceGenerator__ rt300@14: #define __riftathon__SequenceGenerator__ rt300@8: rt300@8: #include rt300@14: #include "ofMain.h" rt300@8: rt300@14: #define MIN_TARGETS_IN_SEQUENCE 3 rt300@14: #define MAX_TARGETS_IN_SEQUENCE 5 rt300@10: #define MIN_TEMPO 80 rt300@14: #define MAX_TEMPO 150 rt300@14: #define NUM_TEMPO_STEPS 16 rt300@14: #define NUM_PRESETS 8 rt300@10: rt300@14: class Step{ rt300@13: public: rt300@14: typedef enum {COUNT_IN, PREVIEW_DISPLAY, PREVIEW_PLAY, MATCHING_INTERACTION, MATCHING_RESULT} stepTypes; rt300@14: // gui display rt300@14: bool showsTargetIcon; rt300@14: bool showsControlSettings; rt300@14: bool showsControlGuides; rt300@14: bool showsMatchResults; rt300@14: // gui input rt300@14: bool allowsCandidateControl; rt300@14: // sound rt300@14: bool playsTarget; rt300@14: bool playsCandidate; rt300@14: // control flow rt300@14: stepTypes type; rt300@14: bool isPreview; rt300@14: rt300@14: int seqNumber; rt300@14: int runNumber; rt300@14: bool isLastOfSeq; rt300@14: bool isLastOfRun; rt300@14: bool playsMetroClick; rt300@14: int tempo; rt300@14: // preset info rt300@14: int presetIndex; rt300@14: int numInSequence; rt300@14: bool isLastOfAll; rt300@14: rt300@14: Step(){ rt300@14: type = COUNT_IN; rt300@13: rt300@14: showsTargetIcon = false; rt300@14: showsControlSettings = false; rt300@14: showsControlGuides = false; rt300@14: showsMatchResults = false; rt300@14: isPreview = false; rt300@14: rt300@14: allowsCandidateControl = false; rt300@14: playsTarget = false; rt300@14: playsCandidate = false; rt300@14: rt300@14: playsMetroClick = true; rt300@14: rt300@14: isLastOfSeq = false; rt300@14: isLastOfRun = false; rt300@14: isLastOfAll = false; rt300@14: presetIndex = -1; rt300@14: seqNumber = -1; rt300@14: runNumber = -1; rt300@14: rt300@14: tempo = MIN_TEMPO; rt300@13: } rt300@14: void setAsPreviewShower(){ rt300@14: type = PREVIEW_DISPLAY; rt300@14: showsTargetIcon = true; rt300@14: showsControlSettings = true; rt300@14: showsMatchResults = false; rt300@14: isPreview = true; rt300@13: rt300@14: allowsCandidateControl = false; rt300@14: playsTarget = true; rt300@14: playsCandidate = false; rt300@14: playsMetroClick = false; rt300@14: } rt300@14: void setAsPreviewPlayer(){ rt300@14: type = PREVIEW_PLAY; rt300@14: showsTargetIcon = true; rt300@14: showsControlSettings = false; rt300@14: showsMatchResults = false; rt300@14: isPreview = true; rt300@13: rt300@14: allowsCandidateControl = false; rt300@14: playsTarget = true; rt300@14: playsCandidate = false; rt300@13: rt300@14: playsMetroClick = false; rt300@14: } rt300@14: void setAsMatchingPreparer(){ rt300@14: type = MATCHING_INTERACTION; rt300@14: showsTargetIcon = true; rt300@14: showsControlSettings = false; rt300@14: showsControlGuides = true; rt300@14: showsMatchResults = false; rt300@14: isPreview = false; rt300@14: rt300@14: allowsCandidateControl = true; rt300@14: playsTarget = false; rt300@14: playsCandidate = false; rt300@14: rt300@14: playsMetroClick = false; rt300@14: } rt300@14: void setAsMatchingReckoner(){ rt300@14: type = MATCHING_RESULT; rt300@14: showsTargetIcon = true; rt300@14: showsControlSettings = false; rt300@14: showsControlGuides = true; rt300@14: showsMatchResults = true; // shows how far off you were? rt300@14: isPreview = false; rt300@14: rt300@14: allowsCandidateControl = false; rt300@14: playsTarget = false; rt300@14: playsCandidate = true; rt300@14: rt300@14: playsMetroClick = false; rt300@13: } rt300@13: rt300@14: float getTimeBetweenTicks(){ rt300@14: return 1000. * (60.0/tempo); rt300@14: } rt300@13: }; rt300@13: rt300@10: class SequenceController{ rt300@10: public: rt300@10: SequenceController(){ rt300@13: tempoInc = float(MAX_TEMPO - MIN_TEMPO) / float(NUM_TEMPO_STEPS); rt300@14: generateSteps(); rt300@14: setToStart(); rt300@10: }; rt300@14: Step getNextStep(){ rt300@13: rt300@14: currentStep++; rt300@14: if ((*currentStep).isLastOfRun){ rt300@14: // uh rt300@13: } rt300@14: if ((*currentStep).isLastOfSeq){ rt300@13: rt300@14: } rt300@14: return (*currentStep); rt300@14: rt300@14: }; rt300@14: void setToStart(){ rt300@14: currentStep = steps.begin(); rt300@14: } rt300@14: void stepForward(){ rt300@14: currentStep++; rt300@14: }; rt300@14: float getStartTickTime(){ rt300@14: return 1000. * (60.0/MIN_TEMPO); rt300@14: } rt300@14: private: rt300@14: void generateSteps(){ rt300@14: srand (time(NULL)); rt300@14: rt300@14: int run = 0; rt300@14: rt300@14: rt300@14: rt300@14: for(int numInSequence = MIN_TARGETS_IN_SEQUENCE; numInSequence <= MAX_TARGETS_IN_SEQUENCE; numInSequence++){ rt300@14: generateCountIn(2); rt300@14: generateARun(run, numInSequence); rt300@14: rt300@14: steps.back().isLastOfRun = true; rt300@14: run++; rt300@14: cout << "-generate run finished-" << endl; rt300@14: } rt300@14: steps.back().isLastOfAll = true; rt300@14: }; rt300@14: void generateCountIn(int countInLength){ rt300@14: Step countStep; rt300@14: for (int i = 0; i < countInLength; i++){ rt300@14: countStep.numInSequence = countInLength - i + 1; rt300@14: steps.push_back(countStep); rt300@14: rt300@14: } rt300@14: }; rt300@14: void generateARun(int run, int numInSequence){ rt300@14: float curTempo = MIN_TEMPO; rt300@14: int seqNo = 0; rt300@14: rt300@14: for(int tempoLevel = 0; tempoLevel < NUM_TEMPO_STEPS; tempoLevel++){ rt300@14: rt300@14: vector stepPreset; rt300@14: rt300@14: // get some random ints rt300@14: for(int n=0; n < numInSequence; n++){ rt300@14: int nextPreset = getRandomButNot(NUM_PRESETS,stepPreset); rt300@14: stepPreset.push_back(nextPreset); rt300@14: cout << nextPreset << ","; rt300@14: } rt300@14: // put preview rt300@14: Step nextStep; rt300@14: rt300@14: int n = 0; rt300@14: for(auto si = stepPreset.begin(); si < stepPreset.end(); si++){ rt300@14: // put loader rt300@13: rt300@14: nextStep.presetIndex = *si; rt300@14: nextStep.runNumber = run; rt300@14: nextStep.seqNumber = seqNo; rt300@14: nextStep.numInSequence = n; rt300@14: nextStep.tempo = curTempo; rt300@14: nextStep.setAsPreviewShower(); rt300@14: steps.push_back(nextStep); rt300@14: rt300@14: // put player rt300@14: // rt300@14: // nextStep.setAsPreviewPlayer(); rt300@14: // steps.push_back(nextStep); rt300@14: n++; rt300@13: } rt300@14: // last one in sequence allows control ? rt300@14: steps.back().allowsCandidateControl = true; rt300@14: // put in matching sequence rt300@14: n = 0; rt300@14: for(auto si = stepPreset.begin(); si < stepPreset.end(); si++){ rt300@14: // put loader rt300@14: rt300@14: nextStep.presetIndex = *si; rt300@14: nextStep.numInSequence = n; rt300@14: nextStep.setAsMatchingPreparer(); rt300@14: steps.push_back(nextStep); rt300@14: rt300@14: // put player rt300@14: rt300@14: nextStep.setAsMatchingReckoner(); rt300@14: steps.push_back(nextStep); rt300@14: n++; rt300@14: } rt300@14: rt300@14: steps.back().isLastOfSeq = true; rt300@14: curTempo += tempoInc; rt300@14: seqNo++; rt300@14: cout << endl; rt300@14: rt300@13: } rt300@10: rt300@13: } rt300@14: rt300@14: rt300@10: int getRandomButNot(int max, vector notThese){ rt300@10: rt300@10: bool there = true; rt300@13: int randomInt = rand() % max; rt300@10: rt300@10: if (notThese.size()){ rt300@14: while(there){ rt300@14: randomInt = rand() % max; rt300@14: vector::iterator result = std::find(notThese.begin(), notThese.end(), randomInt); rt300@14: there = (result != notThese.end()); rt300@14: } rt300@10: } rt300@10: return randomInt; rt300@10: rt300@10: }; rt300@8: rt300@14: vector steps; rt300@14: vector::iterator currentStep; rt300@13: float tempoInc; rt300@8: }; rt300@8: rt300@14: #endif /* defined(__riftathon__SequenceGenerator__) */