changeset 32:75202498bee9

perform mode (no guides at all)
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Tue, 25 Nov 2014 17:03:33 +0000
parents a677c027e3a0
children 93317878abef
files AppCore.mm ExpMessageOrganiser.h ExpMessageOrganiser.mm ExplorePresetManager.mm IntroViewController.mm IntroViewController.xib MessageOrganiser.h MessageOrganiser.mm PDSynthWrapper.h SequenceController.h SequenceController.mm TrainingMessageOrganiser.h TrainingMessageOrganiser.mm TrainingScoreManager.h UI code/3DboxGL.h UI code/3DboxGL.mm UI code/6Dbox.h UI code/6Dbox.mm UI code/IconPanel.mm UI code/sliderPanel.mm UsernameAlertViewController.mm eventLogger.h eventLogger.mm globalVariables.h testApp.h testApp.mm
diffstat 26 files changed, 529 insertions(+), 209 deletions(-) [+]
line wrap: on
line diff
--- a/AppCore.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/AppCore.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -51,7 +51,7 @@
 
 	// open patch
     //patchName = "targetSynth6.pd";
-    patchName = "riftathon_synth.pd";
+    patchName = "riftathon_drum_synth.pd";
 	Patch patch = pd.openPatch(patchName);
 	cout << patch << endl;
 
--- a/ExpMessageOrganiser.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/ExpMessageOrganiser.h	Tue Nov 25 17:03:33 2014 +0000
@@ -26,7 +26,7 @@
     void showCurrentSlot();
     void loadPreset(string pname);
     void buttonPressCallback(int mappingID, int value);
-    void midiFromLeap(int ctl_num, int ctl_val);
+    //void midiFromLeap(int ctl_num, int ctl_val);
 private:
     void loadDefaultSound();
     int numParamsToUse;
--- a/ExpMessageOrganiser.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/ExpMessageOrganiser.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -96,7 +96,10 @@
         
         bool finished = expPresetManager.writeValuesToSlot(candidateSynth.getAllParamValues());
         if(finished){
-            instructionPanel->setLabel("ALL PRESETS MADE");
+            instructionPanel->setText("ALL PRESETS MADE\n Please restart and go to TRAIN stage");
+            instructionPanel->show();
+            bottomPanel->hide();
+
             controlPanel->hide();
             
         }else{
@@ -108,23 +111,3 @@
     
 }
 
-void ExpMessageOrganiser::midiFromLeap(int ctl_num, int ctl_val){
-
-
-    if (!okToGetMidi){
-        return;
-    }
-    vector<int> mids = candidateSynth.getAllMappingIDs();
-    if (ctl_num >= mids.size() || ctl_num < 0) return;
-    
-    candidateSynth.paramChangeCallback(mids[ctl_num], ctl_val);
-    
-    setUIToParam(ctl_num, ctl_val);
-    
-    vector<int> evtData;
-    evtData.push_back(mids[ctl_num]); // or just index?
-    evtData.push_back(ctl_val);
-    
-    eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData);
-    
-}
--- a/ExplorePresetManager.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/ExplorePresetManager.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -114,6 +114,22 @@
     filledSlots = 0;
 }
 //-----------------------------------------------------------------------------
+vector<string> drumPresetNames(){
+    vector<string> vs;
+    
+    vs.push_back("boom kick");
+    vs.push_back("punch kick");
+    vs.push_back("snare");
+    vs.push_back("clap");
+    
+    vs.push_back("closed hihat");
+    vs.push_back("open hihat");
+    vs.push_back("cowbell");
+    vs.push_back("bongo");
+    
+    
+}
+//-----------------------------------------------------------------------------
 
 void ExplorePresetManager::fillSlotsWithLoadedPresets(){
     for(auto pi = thePresets.begin(); pi < thePresets.end(); pi++){
--- a/IntroViewController.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/IntroViewController.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -60,6 +60,10 @@
     ((testApp *)self.theOFAppRef)->interfaceSelected(self.interfaceSelection);
     ((testApp *)self.theOFAppRef)->introHidden(3);
 }
+- (IBAction)enterPerformMode:(id)sender {
+    ((testApp *)self.theOFAppRef)->interfaceSelected(self.interfaceSelection);
+    ((testApp *)self.theOFAppRef)->introHidden(4);
+}
 
 - (IBAction)show:(id)sender
 {
--- a/IntroViewController.xib	Fri Nov 21 17:07:56 2014 +0000
+++ b/IntroViewController.xib	Tue Nov 25 17:03:33 2014 +0000
@@ -52,22 +52,34 @@
                         <action selector="hide:" destination="-1" eventType="touchUpInside" id="pSz-nO-BgA"/>
                     </connections>
                 </button>
-                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Welcome to RIFTATHON." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="39" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="14">
+                <button appearanceType="aqua" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="Lu7-vf-MBo">
+                    <rect key="frame" x="794" y="529" width="152" height="61"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                    <state key="normal" title="PERFORM" backgroundImage="buttron.png">
+                        <color key="titleColor" red="0.28581259669999998" green="0.80918817929999998" blue="0.7302696877" alpha="1" colorSpace="calibratedRGB"/>
+                        <color key="titleShadowColor" red="0.0" green="0.79530400820000002" blue="0.776555734" alpha="1" colorSpace="calibratedRGB"/>
+                    </state>
+                    <connections>
+                        <action selector="enterPerformMode:" destination="-1" eventType="touchUpInside" id="8IK-qh-e6h"/>
+                        <action selector="hide:" destination="-1" eventType="touchUpInside" id="hEY-Hb-kXd"/>
+                    </connections>
+                </button>
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Welcome to the 6 parameter challenge. Please select an interface type and experiment stage. " textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="39" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="14">
                     <rect key="frame" x="158" y="-139" width="773" height="735"/>
                     <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                     <fontDescription key="fontDescription" type="system" pointSize="17"/>
                     <color key="textColor" red="0.72194573409571561" green="1" blue="0.83094137152153613" alpha="1" colorSpace="calibratedRGB"/>
                     <nil key="highlightedColor"/>
                 </label>
-                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="TWEAKATHON" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="50">
-                    <rect key="frame" x="451" y="50" width="134" height="24"/>
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="6 PARAMETER CHALLENGE" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="50">
+                    <rect key="frame" x="392" y="49" width="256" height="24"/>
                     <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                     <fontDescription key="fontDescription" type="system" pointSize="20"/>
                     <color key="textColor" red="0.33826699840000002" green="0.9053322399" blue="1" alpha="1" colorSpace="calibratedRGB"/>
                     <nil key="highlightedColor"/>
                 </label>
                 <segmentedControl appearanceType="aqua" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" id="kLk-IB-COx">
-                    <rect key="frame" x="410" y="370" width="217" height="29"/>
+                    <rect key="frame" x="378" y="370" width="284" height="29"/>
                     <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                     <segments>
                         <segment title="SLIDERS"/>
--- a/MessageOrganiser.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/MessageOrganiser.h	Tue Nov 25 17:03:33 2014 +0000
@@ -68,9 +68,12 @@
     void setBottomPanel(ButtonPanel * ntb);
     void setIconPanel(IconPanel * ip);
     void setInstructionPanel(TextPanel * ip);
+    void setSeqNumPanel(TextPanel * snp);
+    void setScoreNumPanel(TextPanel * snp);
     //-----------------------------------------------------------------------------
     void hideMyPanels();
     void showMyPanels();
+    void midiFromLeap(int ctl_num, int ctl_val);
 protected:
 
     PDSynthWrapper candidateSynth;
@@ -80,7 +83,8 @@
     
     IconPanel* presetIconPanel;
     TextPanel* instructionPanel;
-    
+    TextPanel * seqNumPanel;
+    TextPanel * scoreNumPanel;
     map<int,UIElement*> currentMapping; // could get more sophisticated if not 1-1 ?
     
     vector<int> getMappingIDsFromSynths();
@@ -92,6 +96,10 @@
     // we want to set UI object
     void setUIToParam(int index, int value);
     void mapControlToParam(UIElement* control, int mappingID);
+    
+    void showSeqNum(int num);
+    void showScoreNum(int num);
+    
     //-----------------------------------------------------------------------------
     
     void mapSlidersToParams(vector<UIElement*> elems, vector<int> mids);
--- a/MessageOrganiser.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/MessageOrganiser.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -66,7 +66,24 @@
     instructionPanel->show();
 }
 
-
+void MessageOrganiser::setSeqNumPanel(TextPanel * snp){
+    seqNumPanel = snp;
+}
+void MessageOrganiser::showSeqNum(int num){
+    stringstream s;
+    s << num;
+    seqNumPanel->setText(s.str());
+    seqNumPanel->show();
+}
+void MessageOrganiser::setScoreNumPanel(TextPanel * snp){
+    scoreNumPanel = snp;
+}
+void MessageOrganiser::showScoreNum(int num){
+    stringstream s;
+    s << "SCORE: " << num;
+    scoreNumPanel->setText(s.str());
+    scoreNumPanel->show();
+}
 //-----------------------------------------------------------------------------
 void MessageOrganiser::hideMyPanels(){
     presetIconPanel->hide();
@@ -217,8 +234,9 @@
     // this will actually show sliders with target vals - for "memorisation" purposes mwa heh heh
     // get target values
     // set ui
+    cout << "set slid to targ" << endl;
     vector<int> vals = targetSynth.getAllParamValues();
-    for(int i=1; i < vals.size(); i++){
+    for(int i=0; i < vals.size(); i++){
         setUIToParam(i, vals[i]);
     }
 }
@@ -232,7 +250,7 @@
 //    }
 }
 void MessageOrganiser::setSlidersToDefault(){
-    for(int i=1; i < candidateSynth.getNumParams(); i++){
+    for(int i=0; i < candidateSynth.getNumParams(); i++){
         setUIToParam(i, 0);
         
     }
@@ -247,4 +265,32 @@
     setAllSlidersToValues(rands);
     candidateSynth.setAllParams(rands);
     
+}
+
+
+void MessageOrganiser::midiFromLeap(int ctl_num, int ctl_val){
+    
+    
+    if (!okToGetMidi){
+        return;
+    }
+    vector<int> mids = candidateSynth.getAllMappingIDs();
+    if (ctl_num >= mids.size() || ctl_num < 0) return;
+    
+    if(onlyChangeCandidateOnTrigger){
+
+        candidateSynth.paramChangeCallback(mids[ctl_num], ctl_val, false);
+    }else{
+        candidateSynth.paramChangeCallback(mids[ctl_num], ctl_val, true);
+    }
+    
+
+    setUIToParam(ctl_num, ctl_val);
+    
+    vector<int> evtData;
+    evtData.push_back(mids[ctl_num]); // or just index?
+    evtData.push_back(ctl_val);
+    
+    eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData);
+    
 }
\ No newline at end of file
--- a/PDSynthWrapper.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/PDSynthWrapper.h	Tue Nov 25 17:03:33 2014 +0000
@@ -29,12 +29,13 @@
 
         synthPrefix = sp;
         // init all the params, refer to synth in pd patch
+        // riftathon_drum_synth
         timbreParams.push_back(SynthParam(64,aCore,"Pitch",sp));
-        timbreParams.push_back(SynthParam(64,aCore,"Pulse",sp));
-        timbreParams.push_back(SynthParam(64,aCore,"Attack",sp));
-        timbreParams.push_back(SynthParam(64,aCore,"Decay",sp));
-        timbreParams.push_back(SynthParam(64,aCore,"FiltTyp",sp));
-        timbreParams.push_back(SynthParam(64,aCore,"FiltFrq",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"PenvDecay",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"DecayFM",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"NzFrq1",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"NzFrq2",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"DecayNz",sp));
         
         //timbreParams.push_back(SynthParam(64,aCore,"SPAM",sp));
         //timbreParams.push_back(SynthParam(64,aCore,"FILTH",sp));
--- a/SequenceController.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/SequenceController.h	Tue Nov 25 17:03:33 2014 +0000
@@ -13,10 +13,10 @@
 #include "ofMain.h"
 #include "presetManager.h"
 #include "TrainingScoreManager.h"
-#define MIN_TARGETS_IN_SEQUENCE 2
+#define MIN_TARGETS_IN_SEQUENCE 3
 #define MAX_TARGETS_IN_SEQUENCE 5
-#define MIN_TEMPO   60
-#define MAX_TEMPO   300
+#define MIN_TEMPO   80
+#define MAX_TEMPO   400
 #define NUM_TEMPO_STEPS 12
 #define NUM_PRESETS 8
 #define SPACER_BARS false
@@ -116,23 +116,28 @@
 class SequenceController{
 public:
     SequenceController();
+    void init(bool asoundOnlyMode);
     AnimStep getNextStep();
     void setToStart();
     void stepForward();
     float getStartTickTime();
     void saveResultForCurrentStep(TrainingTestResult result);
     TrainingTestResult getResultForPreviousStep();
+    int getTotNumRuns(){return totNumRuns;};
 private:
     void generateSteps();
     void generateCountIn(int countInLength);
     void generateARun(int run, int numInSequence);
+    void generateASoundOnlyRun(int run, int numInSequence);
     vector<int> randomSequence(int numInSequence);
-    
+    vector<int> nonRandomSequence(int numInSequence);
     int getRandomButNot(int max, vector<int> notThese);
 protected:
     vector<AnimStep> steps;
     vector<AnimStep>::iterator currentStep;
     float tempoInc;
+    bool soundOnlyMode;
+    int totNumRuns;
 };
 
 #endif /* defined(__riftathon__SequenceGenerator__) */
--- a/SequenceController.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/SequenceController.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -155,10 +155,16 @@
 //=================================================================
 
 SequenceController::SequenceController(){
+
+};
+//-------------------------------------------------------------------
+void SequenceController::init(bool asoundOnlyMode){
+    soundOnlyMode = asoundOnlyMode;
     tempoInc = float(MAX_TEMPO - MIN_TEMPO) / float(NUM_TEMPO_STEPS);
     generateSteps();
     setToStart();
 };
+//-------------------------------------------------------------------
 AnimStep SequenceController::getNextStep(){
     
     currentStep++;
@@ -193,12 +199,17 @@
     
     for(int numInSequence = MIN_TARGETS_IN_SEQUENCE; numInSequence <= MAX_TARGETS_IN_SEQUENCE; numInSequence++){
         generateCountIn(1);
-        generateARun(run, numInSequence);
         
+        if (soundOnlyMode){
+            generateASoundOnlyRun(run, numInSequence);
+        }else{
+            generateARun(run, numInSequence);
+        }
         steps.back().isLastOfRun = true;
         run++;
         cout << "-generate run finished-" << endl;
     }
+    totNumRuns = run;
     steps.back().isLastOfAll = true;
 };
 
@@ -230,6 +241,101 @@
     return stepPresetIndices;
 }
 
+vector<int> SequenceController::nonRandomSequence(int numInSequence){
+    vector<int> stepPresetIndices;
+    // get some random ints
+    for(int n=0; n < numInSequence; n++){
+        int nextPreset = n;
+        stepPresetIndices.push_back(nextPreset);
+        cout << nextPreset << ",";
+    }
+    
+    return stepPresetIndices;
+}
+
+//-------------------------------------------------------------------
+void SequenceController::generateASoundOnlyRun(int run, int numInSequence){
+    
+    // here the preview is sound only
+    float curTempo = MIN_TEMPO;
+    int seqNo = 0;
+    AnimStep nextStep;
+    for(int tempoLevel = 0; tempoLevel < NUM_TEMPO_STEPS; tempoLevel++){
+        // first we have a preparation count in
+        nextStep.presetIndex = -1; // minus one means "blank"
+        nextStep.runNumber = run;
+        nextStep.seqNumber = seqNo;
+        nextStep.whichInSequence = 0;
+        nextStep.tempo = curTempo;
+        nextStep.showsGuides = true; // guide shown for neutral point
+        nextStep.type = AnimStep::PREVIEW_NEUTRAL_COUNT;
+        nextStep.showsResultsAtEnd = false;
+        steps.push_back(nextStep);
+        
+        // generate a sequence of random preset indices
+        vector<int> stepPresetIndices = randomSequence(numInSequence);
+        nextStep.thisSequence = stepPresetIndices;
+        
+        // make preview sequence
+        int n = 0;
+        for(auto si = stepPresetIndices.begin(); si < stepPresetIndices.end(); si++){
+            // put loader
+            
+            nextStep.presetIndex = *si;
+            nextStep.runNumber = run;
+            nextStep.seqNumber = seqNo;
+            nextStep.whichInSequence = n;
+            nextStep.tempo = curTempo;
+            nextStep.showsGuides = false;
+            nextStep.showsIcons = false;
+            nextStep.showsResultsAtEnd = false;
+            nextStep.type = AnimStep::PREVIEW_MOVE;
+            steps.push_back(nextStep);
+            
+            if (SPACER_BARS){
+                nextStep.type = AnimStep::PREVIEW_HIT;
+                steps.push_back(nextStep);
+            }
+            n++;
+        }
+        
+        // move back to neutral
+        nextStep.presetIndex = -1;
+        nextStep.type = AnimStep::PREVIEW_MOVE;
+        nextStep.showsResultsAtEnd = false;
+        steps.push_back(nextStep);
+        
+        // make matching sequence WITHOUT icon seq help
+        n = 0;
+        for(auto si = stepPresetIndices.begin(); si < stepPresetIndices.end(); si++){
+            // put loader
+            
+            nextStep.presetIndex = *si;
+            nextStep.whichInSequence = n;
+            
+            nextStep.showsGuides = false;
+            
+            nextStep.type = AnimStep::MATCHING_MOVE;
+            nextStep.showsResultsAtEnd = true;
+            nextStep.showsIcons = false;
+            steps.push_back(nextStep);
+
+            n++;
+            
+        }
+        
+        nextStep.type = AnimStep::MATCHING_HIT;
+        nextStep.showsResultsAtEnd = false;
+        steps.push_back(nextStep);
+        
+        steps.back().isLastOfSeq = true;
+        curTempo += tempoInc;
+        seqNo++;
+    }
+    // shows last result ?
+    nextStep.type = AnimStep::MATCHING_NEUTRAL_COUNT;
+    steps.push_back(nextStep);
+}
 //-------------------------------------------------------------------
 
 void SequenceController::generateARun(int run, int numInSequence){
--- a/TrainingMessageOrganiser.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/TrainingMessageOrganiser.h	Tue Nov 25 17:03:33 2014 +0000
@@ -17,12 +17,15 @@
 #include "TextPanel.h"
 #include "TrainingScoreManager.h"
 #include "6Dbox.h"
+#include "eventLogger.h"
+
 extern ExplorePresetManager expPresetManager;
+extern EventLogger eventLogger;
 
 class TrainingMessageOrganiser : public MessageOrganiser {
 public:
     int numParamsToUse;
-    void init( PDSynthWrapper& cs, PDSynthWrapper& ts);
+    void init( PDSynthWrapper& cs, PDSynthWrapper& ts, bool soundOnlyMode);
     void setMiddlePanel(TextPanel* tp);
     void setup(controlPanelType whichInterfaceAreWeUsing);
     vector<int> getMappingIDsFromSynths();
@@ -31,7 +34,7 @@
     void onNextTickAnim(int tickNumber);
     
     void showMyPanels();
-    void midiFromLeap(int ctl_num, int ctl_val);
+    //void midiFromLeap(int ctl_num, int ctl_val);
     //-----------------------------------------------------------------------
 protected:
     void showUserHowTheyDid();
@@ -46,10 +49,11 @@
     }
     void updateCountdown(int n);
     void lastOfAll();
-    void lastOfRun();
+    void lastOfRun(int which);
     void showCountdown();
     void hideSliders();
     void showsTarget();
+    void logNewStep(AnimStep newStep);
     TrainingTestResult doResults(AnimStep newStep,
                                  Preset * currentTargetPreset,
                                  vector<int> startingPosition,
--- a/TrainingMessageOrganiser.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/TrainingMessageOrganiser.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -8,7 +8,7 @@
 
 #include "TrainingMessageOrganiser.h"
 
-void TrainingMessageOrganiser::init( PDSynthWrapper& cs, PDSynthWrapper& ts){
+void TrainingMessageOrganiser::init( PDSynthWrapper& cs, PDSynthWrapper& ts, bool soundOnlyMode){
     
     MessageOrganiser::init(cs,ts);
     
@@ -17,6 +17,9 @@
     candidateSynth.registerForTicks(callback);
     
     numParamsToUse = TOTAL_NUM_PARAMS;
+
+    sequenceController.init(soundOnlyMode);
+
     
 }
 
@@ -38,6 +41,7 @@
     bottomPanel->show();
     controlPanel->show();
     middlePanel->show();
+    okToGetMidi = true; // enables check that hand moves on startup?
 }
 
 //-----------------------------------------------------------------------
@@ -57,28 +61,7 @@
     
 }
 
-//-----------------------------------------------------------------------------
-void TrainingMessageOrganiser::midiFromLeap(int ctl_num, int ctl_val){
-    
-    if (!okToGetMidi){
-        return;
-    }
-    vector<int> mids = candidateSynth.getAllMappingIDs();
-    if (ctl_num >= mids.size() || ctl_num < 0) return;
-    
-    paramChangeCallback(mids[ctl_num], ctl_val );
-    
-    //candidateSynth.paramChangeCallback(mids[ctl_num], ctl_val);
-    
-    setUIToParam(ctl_num, ctl_val);
-    
-    vector<int> evtData;
-    evtData.push_back(mids[ctl_num]); // or just index?
-    evtData.push_back(ctl_val);
-    
-    eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData);
-    
-}
+
 //-----------------------------------------------------------------------------
 
 void TrainingMessageOrganiser::buttonPressCallback(int mappingID, int value){
@@ -118,24 +101,44 @@
     }
     
 }
-void TrainingMessageOrganiser::lastOfRun(){
+void TrainingMessageOrganiser::lastOfRun(int which){
     candidateSynth.stopMetronome();
-    cout << "FINISHED RUN" << endl;
+    stringstream s;
+    
+    s << "FINISHED RUN " << which << " OF " << sequenceController.getTotNumRuns() << endl;
     controlPanel->hide();
     middlePanel->setColor(ofColor::white);
     middlePanel->setText("FINISHED RUN");
     middlePanel->show();
+    //playCandidateButton->setLabel("NEXT");
     bottomPanel->show();
+    seqNumPanel->hide();
 }
 void TrainingMessageOrganiser::lastOfAll(){
     candidateSynth.stopMetronome();
     cout << "FINISHED BLOCK" << endl;
     controlPanel->hide();
     middlePanel->setColor(ofColor::white);
-    middlePanel->setText("FINISHED BLOCK");
+    middlePanel->setText("FINISHED BLOCK!");
     middlePanel->show();
     bottomPanel->show();
 }
+
+void TrainingMessageOrganiser::logNewStep(AnimStep newStep){
+    
+    vector<int> details;
+    
+    details.push_back(int(newStep.type));
+    details.push_back(newStep.whichInSequence);
+    details.push_back(newStep.showsGuides);
+    details.push_back(newStep.showsIcons);
+    details.push_back(newStep.presetIndex);
+    details.push_back(newStep.tempo);
+    
+    eventLogger.logEvent(NEW_STEP, details);
+    
+}
+
 //-----------------------------------------------------------------------------
 void TrainingMessageOrganiser::onNextTickAnim(int tickNumber){
     static AnimStep oldStep;
@@ -178,12 +181,14 @@
     
     AnimStep newStep = sequenceController.getNextStep();
     
+    logNewStep(newStep);
+    
     if(newStep.isLastOfAll){
         lastOfAll();
         return;
     }
     if(newStep.isLastOfRun){
-        lastOfRun();
+        lastOfRun(newStep.runNumber);
         return;
     }
     
@@ -229,7 +234,7 @@
 }
 //-----------------------------------------------------------------------------
 void TrainingMessageOrganiser::previewNeutralCount(AnimStep newStep){
-    
+    okToGetMidi = false;
 
     middlePanel->hide();
     
@@ -251,13 +256,14 @@
     targetSynth.setAllParams(newTargetValues);
     candidateSynth.setAllParams(newTargetValues);
     
-    displayInstructions("preview Neutral Count");
-    
+    displayInstructions("Get ready for preview");
+    seqNumPanel->hide();
     oldTargetValues = newTargetValues;
 }
 //-----------------------------------------------------------------------------
 void TrainingMessageOrganiser::previewMove(AnimStep newStep){
-    controlPanel->setValues(oldTargetValues);
+    //controlPanel->setValues(oldTargetValues);
+    okToGetMidi = false;
     targetSynth.trigger(); // PLAYS LAST TARGET (but it doesn't?)
     Preset * currentTargetPreset;
     if(newStep.presetIndex == -1){
@@ -265,42 +271,75 @@
     }else{
         
         currentTargetPreset =  expPresetManager.getPresetAtIndex(newStep.presetIndex);
+        if (currentTargetPreset == NULL){
+            displayInstructions("No stored preset!\n please restart and choose EXP");
+            candidateSynth.stopMetronome();
+            return;
+        }
     }
     vector<int> newTargetValues = currentTargetPreset->getValues();
     
     targetSynth.setAllParamsWithoutSend(newTargetValues);
     
     // show icon and guides
-    presetIconPanel->setTextAndImage(currentTargetPreset->name, currentTargetPreset->getImage(), false);
+    if (newStep.showsGuides){ // always show neutral one
+        
+        // show where we're going
+        controlPanel->setAndShowHint(newTargetValues, currentTargetPreset->getImage());
+        
+        // show how to get there
+        controlPanel->animateToNewValues(newTargetValues, newStep.getTimeBetweenTicks()*4);
+        controlPanel->showValueIndicators(true); // for animation
+        controlPanel->setActive(false);
+    }else{
+        // We're in PERFORM mode
+        if (newStep.presetIndex == -1){
+            // last step of preview , can show neutral to give idea of when things happen
+            // also allow interaction so that neutral can be prepared
+            controlPanel->setAndShowHint(newTargetValues, currentTargetPreset->getImage());
+            // TODO set value to neutral too
+            controlPanel->showValueIndicators(true);
+            okToGetMidi = true;
+            controlPanel->setActive(true);
+        }else{
+            // empty box
+            controlPanel->showHint(false);
+            controlPanel->showValueIndicators(false);
+            controlPanel->setActive(false);
+        }
+    }
+    
     if (newStep.showsIcons){
+        presetIconPanel->setTextAndImage(currentTargetPreset->name, currentTargetPreset->getImage(), false);
         presetIconPanel->show();
     }else{
         presetIconPanel->hide();
     }
     controlPanel->show();
     
-    controlPanel->showValueIndicators(true);
-    controlPanel->setActive(false);
     
-    // show where we're going
-    controlPanel->setAndShowHint(newTargetValues, currentTargetPreset->getImage());
     
-    // show how to get there
-    controlPanel->animateToNewValues(newTargetValues, newStep.getTimeBetweenTicks()*4);
-    displayInstructions("preview Move");
-    
+
+    stringstream instruct;
+    instruct << "PREVIEW" << endl;;
+    instruct << newStep.whichInSequence+1 << endl;
+    displayInstructions(instruct.str());
+    showSeqNum(newStep.whichInSequence+1);
     oldTargetValues = newTargetValues;
 }
 //-----------------------------------------------------------------------------
+// lest setep of preview seq - plays moves back to neutral pos?
 void TrainingMessageOrganiser::previewHit(AnimStep newStep){
     Preset * currentTargetPreset;
+    okToGetMidi = false;
     currentTargetPreset =  expPresetManager.getPresetAtIndex(newStep.presetIndex);
     vector<int> newTargetValues = currentTargetPreset->getValues();
     
     targetSynth.setAllParams(newTargetValues);
     
-    // your hand hidden
-    controlPanel->showValueIndicators(false);
+    // your hand shows!?
+    controlPanel->showValueIndicators(true);
+    okToGetMidi = true;
     //
     presetIconPanel->setTextAndImage(currentTargetPreset->name, currentTargetPreset->getImage(), false);
     presetIconPanel->show();
@@ -316,7 +355,7 @@
 //-----------------------------------------------------------------------------
 void TrainingMessageOrganiser::guidedMove(AnimStep newStep){
     targetSynth.trigger(); // PLAYS LAST TARGET (?)
-    
+    triggerCandidateSound();
     middlePanel->hide();
     
     Preset * currentTargetPreset;
@@ -344,7 +383,12 @@
     controlPanel->showValueIndicators(true);
     okToGetMidi = true;
     
-    displayInstructions("GUIDED MOVE");
+    stringstream instruct;
+    instruct << "GUIDED MOVE" << endl;;
+    instruct << newStep.whichInSequence+1 << endl;
+    displayInstructions(instruct.str());
+    
+    showSeqNum(newStep.whichInSequence+1);
 
     oldTargetValues = newTargetValues;
 }
@@ -364,7 +408,7 @@
     
     targetSynth.setAllParamsWithoutSend(newTargetValues);
     triggerCandidateSound();
-    
+    targetSynth.trigger();
     displayInstructions("GUIDED HIT");
     vector<int> startPosition = expPresetManager.getNeutralPreset()->getValues();
     
@@ -389,7 +433,7 @@
     okToGetMidi = true;
     
         displayInstructions("Match Count");
-    
+    seqNumPanel->hide();
     oldTargetValues = newTargetValues;
 }
 //-----------------------------------------------------------------------------
@@ -426,11 +470,14 @@
         presetIconPanel->hide();
     }
     // show your hand and allow movement
-    //controlPanel->showIndicator(true);
+    controlPanel->showValueIndicators(true);
     okToGetMidi = true;
     
-    displayInstructions("Match MOVE");
-
+    stringstream instruct;
+    instruct << "MATCHING" << endl;;
+    instruct << newStep.whichInSequence+1 << endl;
+    displayInstructions(instruct.str());
+    showSeqNum(newStep.whichInSequence+1);
     // trigger where we're at at the moment
     triggerCandidateSound();
 
@@ -447,14 +494,15 @@
     
     // show your hand and allow movement (so you can set off to next target??)
     //box6D->showIndicator(true);
-    okToGetMidi = true;
+    stringstream instruct;
+    instruct << "MATCHING FINISHED" << endl;;
+    instruct << newStep.whichInSequence+1 << endl;
+    displayInstructions(instruct.str());
+    showSeqNum(newStep.whichInSequence+1);
     
-    targetSynth.setAllParams(newTargetValues);
-    triggerCandidateSound();
-    
-    displayInstructions("Match FINISHED");
     vector<int> startPosition = expPresetManager.getNeutralPreset()->getValues();
     controlPanel->setHintNoShow(newTargetValues, currentTargetPreset->getImage());
+    
 
     oldTargetValues = newTargetValues;
 }
@@ -476,6 +524,8 @@
 
     displayInstructions(result.displayText);
     
+    showScoreNum(trainingScoreManager.getScore());
+    
     return result;
 }
 
--- a/TrainingScoreManager.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/TrainingScoreManager.h	Tue Nov 25 17:03:33 2014 +0000
@@ -14,6 +14,9 @@
 //#include "SequenceController.h"
 #include "algorithms.h"
 #include "globalVariables.h"
+#include "eventLogger.h"
+
+extern EventLogger eventLogger;
 //-------------------------------------------------------------
 
 struct TrainingTestResult{
@@ -31,7 +34,8 @@
     // equiv of score bit of testController
 public:
     
-    TrainingTestResult getScoreForAnswer(vector<int> targetParams, vector<int> startPosition, vector<int> answer, int timeAllowed) const {
+    
+    TrainingTestResult getScoreForAnswer(vector<int> targetParams, vector<int> startPosition, vector<int> answer, int timeAllowed) {
         TrainingTestResult result;
         stringstream msg;
         int score = 0;
@@ -43,8 +47,6 @@
         
         float TP = calculateThroughput(TOTAL_NUM_PARAMS, dist, initDist, timeAllowed/1000.);
         
-        cout << TP << endl;
-        
         auto dimComp = sqrt(TOTAL_NUM_PARAMS);
         int band = -1;
         if (dist < TARGET_SCORE_CC_BAND*dimComp){
@@ -90,7 +92,7 @@
             
         }
         msg << "Distance from target: " << dist << endl;
-        msg << "Basic Score: " << round(TP*10) << endl;
+        msg << "Score: " << round(TP*10) << endl;
         msg << "-----" << endl;
         msg << "Time allowed: " << timeAllowed/1000.0 << endl;
 
@@ -117,17 +119,35 @@
         }
         result.colorBand = c;
 
+        totalScored += score;
+        
+        vector<int> details;
+        details.push_back(result.realDistanceToTarget);
+        details.push_back(result.targetBandHit);
+        details.push_back(result.timeAllowed);
+        details.push_back(result.score); // 10 x throughput
+        
+        eventLogger.logEvent(TRAINING_RESULT, details);
+        
         
         return result;
     }
+    
+    int getScore(){return totalScored;};
+    
 private:
+    
+    
     float calculateThroughput(int numDims, float endDistance, float startDistance, float time) const{
         
         float ISSR = numDims * log2( startDistance / endDistance);
+        cout << "==========Result======= " << endl;
         cout << "start: " << startDistance << endl;
         cout << "end:   " << endDistance << endl;
         cout << "ISSR:  " << ISSR << endl;
+        cout << "time:  " << time << endl;
         float TP = ISSR / time;
+        cout << "TP:  " << TP << endl;
         return TP;
     }
     float euclideanDistance(vector<int> v1, vector<int> v2) const{
@@ -146,6 +166,7 @@
         return sqrt(ans);
         
     };
+    int totalScored;
     
 };
 #endif /* defined(__riftathon__TrainingScoreManager__) */
--- a/UI code/3DboxGL.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/UI code/3DboxGL.h	Tue Nov 25 17:03:33 2014 +0000
@@ -224,6 +224,32 @@
 
     };
     
+    
+    void makeTexFace(ofMesh * theMesh, ofPoint LT, ofPoint RT, ofPoint  RB, ofPoint LB){
+        
+        ofPoint texCoordLT = ofPoint(0, 1.);
+        ofPoint texCoordLB = ofPoint(0, 0);
+        ofPoint texCoordRT = ofPoint(1., 1.);
+        ofPoint texCoordRB = ofPoint(1., 0.);
+        
+        theMesh->addVertex(LT);
+        theMesh->addTexCoord(texCoordLT);
+        theMesh->addVertex(LB);
+        theMesh->addTexCoord(texCoordLB);
+        theMesh->addVertex(RB);
+        theMesh->addTexCoord(texCoordRB);
+        
+        
+        
+        theMesh->addVertex(LT);
+        theMesh->addTexCoord(texCoordLT);
+        
+        theMesh->addVertex(RB);
+        theMesh->addTexCoord(texCoordRB);
+        theMesh->addVertex(RT);
+        theMesh->addTexCoord(texCoordRT);
+    }
+    
     float angleX;
     float angleY;
     float depth;
--- a/UI code/3DboxGL.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/UI code/3DboxGL.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -21,7 +21,7 @@
     indicatorColor = ofColor(123, 123, 220);
     // how much to rotate the box
     angleX = -25; // elevation
-    angleY = -14; // yaw
+    angleY = 0; // yaw
     
     depth = width; // its a cube
     
@@ -49,51 +49,9 @@
     
     // now build faces
     // rear
-    boxMesh.addVertex(ltr);
-    boxMesh.addVertex(rtr);
-    boxMesh.addVertex(rbr);
+    makeTexFace(&boxMesh,  rtr, ltr, lbr, rbr);
     
-    boxMesh.addVertex(ltr);
-    boxMesh.addVertex(rbr);
-    boxMesh.addVertex(lbr);
     
-    // left
-    boxMesh.addVertex(ltf);
-    boxMesh.addVertex(ltr);
-    boxMesh.addVertex(lbr);
-    
-    boxMesh.addVertex(ltf);
-    boxMesh.addVertex(lbr);
-    boxMesh.addVertex(lbf);
-    
-    // bottom
-    boxMesh.addVertex(lbf);
-    boxMesh.addVertex(lbr);
-    boxMesh.addVertex(rbr);
-    
-    boxMesh.addVertex(lbf);
-    boxMesh.addVertex(rbr);
-    boxMesh.addVertex(rbf);
-    
-    // top
-//    boxMesh.addVertex(ltr);
-//    boxMesh.addVertex(rtr);
-//    boxMesh.addVertex(rtf);
-//    
-//    boxMesh.addVertex(ltr);
-//    boxMesh.addVertex(rtf);
-//    boxMesh.addVertex(ltf);
-//    
-//    // right
-//    boxMesh.addVertex(rtf);
-//    boxMesh.addVertex(rtr);
-//    boxMesh.addVertex(rbr);
-//    
-//    boxMesh.addVertex(rtf);
-//    boxMesh.addVertex(rbr);
-//    boxMesh.addVertex(rbf);
-    
-    // front
 //    boxMesh.addVertex(ltr);
 //    boxMesh.addVertex(rtr);
 //    boxMesh.addVertex(rbr);
@@ -102,6 +60,29 @@
 //    boxMesh.addVertex(rbr);
 //    boxMesh.addVertex(lbr);
     
+    // left
+    makeTexFace(&boxMesh,   ltr, ltf, lbf,lbr);
+    
+//    boxMesh.addVertex(ltf);
+//    boxMesh.addVertex(ltr);
+//    boxMesh.addVertex(lbr);
+//    
+//    boxMesh.addVertex(ltf);
+//    boxMesh.addVertex(lbr);
+//    boxMesh.addVertex(lbf);
+    
+    // bottom
+    makeTexFace(&boxMesh,   lbr, lbf, rbf,rbr);
+    
+//    boxMesh.addVertex(lbf);
+//    boxMesh.addVertex(lbr);
+//    boxMesh.addVertex(rbr);
+//    
+//    boxMesh.addVertex(lbf);
+//    boxMesh.addVertex(rbr);
+//    boxMesh.addVertex(rbf);
+
+    
     boxMesh.setupIndicesAuto();
     setNormals(boxMesh);
 }
--- a/UI code/6Dbox.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/UI code/6Dbox.h	Tue Nov 25 17:03:33 2014 +0000
@@ -86,7 +86,7 @@
 
     
     void drawIndicatorBlob(float x, float y, float z, ofColor c, bool isHint = false);
-    void draw6DOFIndicatorBlob(float x, float y, float z, ofColor c, float r, float p, float yaw,ofImage* texImg);
+    void draw6DOFIndicatorBlob(float x, float y, float z, ofColor c, float r, float p, float yaw,ofImage* texImg, bool showResultColor = false);
     void setTexture(ofImage* img);
     
     void setValue(int index, int value);
@@ -131,6 +131,7 @@
     ofImage defaultImage;
     ofImage hintImage;
     ofImage* hintImageRef;
+    ofImage wallGrid;
     ofMesh guideHandMesh;
     
     float hw, hh, hl, scale;
--- a/UI code/6Dbox.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/UI code/6Dbox.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -35,13 +35,16 @@
     hw = 0.5;
     hh = 0.15;
     hl = 1.0;
-    scale = 40;
+    scale = 40; 
     
-    string fname = ofFilePath::getAbsolutePath(ofToDataPath("buttron.jpeg"));
+    string fname = ofFilePath::getAbsolutePath(ofToDataPath("buttron.jpg"));
     defaultImage.loadImage(fname);
     
     fname = ofFilePath::getAbsolutePath(ofToDataPath("white.jpeg"));
     hintImage.loadImage(fname);
+
+    fname = ofFilePath::getAbsolutePath(ofToDataPath("wallGrid.jpg"));
+    wallGrid.loadImage(fname);
     
     setTexture(&defaultImage);
     setHintTexture(&hintImage);
@@ -96,8 +99,10 @@
     if(which == 3)      rollVal =  57.3*  (2.0*(val - minVal)/(maxVal - minVal) - 1.0);
     if(which == 4)      pitchVal = - 57.3*  (2.0*(val - minVal)/(maxVal - minVal) - 1.0);
     if(which == 5)      yawVal =   - 57.3*  (2.0*(val - minVal)/(maxVal - minVal) - 1.0);
+
 }
 
+
 void Leap6DBox::makeTexFace(ofPoint LT, ofPoint RT, ofPoint  RB, ofPoint LB){
     
     ofPoint texCoordLT = ofPoint(0, 0.5);
@@ -254,7 +259,10 @@
     
     ofScale(0.7,0.7,0.7);
     ofSetColor(foregroundHi);
+    
+    wallGrid.bind();
     boxMesh.draw();
+    wallGrid.unbind();
     
     // draw indicators
     drawIndicator();
@@ -319,11 +327,14 @@
         draw6DOFIndicatorBlob(x, y, z, c, hintRoll, hintPitch, 	hintYaw, hintImageRef);
 
     }else{
-        draw6DOFIndicatorBlob(x, y, z, c, rollVal, pitchVal, yawVal, defaultHandTextureRef);
-        
+        if (showScoreForFrames){
+            draw6DOFIndicatorBlob(x, y, z, c, rollVal, pitchVal, yawVal, defaultHandTextureRef, true);
+        }else{
+            draw6DOFIndicatorBlob(x, y, z, c, rollVal, pitchVal, yawVal, defaultHandTextureRef);
+        }
     }
 }
-void Leap6DBox::draw6DOFIndicatorBlob(float x, float y, float z, ofColor c, float r, float p, float yaw, ofImage* atexImg){
+void Leap6DBox::draw6DOFIndicatorBlob(float x, float y, float z, ofColor c, float r, float p, float yaw, ofImage* atexImg, bool showResultColor ){
     
     
     static ofMatrix4x4 m;
@@ -340,8 +351,8 @@
     
     ofSetColor(255,255,255);
     // render
-    if (showScoreForFrames == 0){
-    (*atexImg).bind();
+    if (!showResultColor){
+        (*atexImg).bind();
     }else{
         ofSetColor(hintColor);
     }
--- a/UI code/IconPanel.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/UI code/IconPanel.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -40,18 +40,21 @@
     //ofFill();
     //UIElement::draw(); // should do background
     //drawOutline();
+    ofDisableDepthTest();
     if(hasBeenSet){
         drawTexture();
         
         drawTextLabel();
         
+        if(showTick){
+            drawTick();
+        }
+        if(showCross){
+            drawCross();
+        }
+        
     }
-    if(showTick){
-        drawTick();
-    }
-    if(showCross){
-        drawCross();
-    }
+    ofEnableDepthTest();
     
     
 }
@@ -76,7 +79,7 @@
 void IconPanel::drawTexture(){
     float z = 10;
     ofSetColor(255,255,255);
-    textureImage->draw(x+10,y+10,z,width-20,height-20);
+    textureImage->draw(x+30,y+20,z,width-20,height-30);
     ofSetColor(foregroundHi);
 }
 //------------------------------------------------------------------
--- a/UI code/sliderPanel.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/UI code/sliderPanel.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -142,7 +142,7 @@
     if (thisPanelType == LEAP6DOF){ // yeuch
         if (subElements[0]->getType() == LEAP6D){
             Leap6DBox * box = (Leap6DBox*)subElements[0];
-            
+            cout << "set values" << endl;
             box->setValues(vals);
         }
     }else if(thisPanelType == ALL_SLIDERS){
--- a/UsernameAlertViewController.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/UsernameAlertViewController.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -65,7 +65,7 @@
         ((testApp *)self.theOFAppRef)->usernameEntered();
         
     }
-    [self.alert dismissWithClickedButtonIndex:self.alert.firstOtherButtonIndex animated:YES];
+    [self.alert dismissWithClickedButtonIndex:self.alert.firstOtherButtonIndex animated:NO];
     return YES;
 }
 
--- a/eventLogger.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/eventLogger.h	Tue Nov 25 17:03:33 2014 +0000
@@ -27,11 +27,11 @@
 #include "boost/bind.hpp"
 #include "boost/function.hpp"
 #include "Poco/Mutex.h"
-
+	
 #define EVENT_THIN_FACTOR 30
 #define EVENT_LOG_FILENAME "log.json"
 #define UPLOAD_CHUNK_SIZE 1000
-#define SAVE_CHUNK_SIZE 200
+#define SAVE_CHUNK_SIZE 20000
 #define APP_CREATION_TIME 0   // ignore this, pointless
 #define PROGRAM_NAME "RIFTATHON"
 #define PROGRAM_VERSION 0.1
@@ -69,7 +69,13 @@
                 SPEED_CHANGED,              // 22 ms between sounds
                 SAVE_PRESET,                 // 23 save a preset
                 START_THE_TRAINING_TESTS,   // 24 start traning
-                START_THE_EXP_TESTS         // 25 start explore/express
+                START_THE_EXP_TESTS,         // 25 start explore/express
+                START_THE_PERFORMANCE_TESTS,     // 26 starting perf
+    
+    // new stuff for TRaining stage
+                TRAINING_RESULT,
+                NEW_STEP,
+    
     
 };
 
--- a/eventLogger.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/eventLogger.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -477,41 +477,7 @@
     logFile << "";
     logFile.close();
 }
-//---------------------------------------------------------------------------
 
-void EventLogger::exitAndSave(){
-    
-    saveSessionToFile();
-    return;
-    
-    if(!consentGiven){
-        Json::Value jlogs = logsToJson();
-        // try to upload TODO (no - might hang and prevent exit???)
-        
-        // TODO pilot doesn't upload
-        //       uploadEventLog(true);
-        return;
-    }
-    
-    savedInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime);
-    // save user details
-    string fname = ofxiPhoneGetDocumentsDirectory() + userName + '_' + EVENT_LOG_FILENAME;
-    
-    // try to upload
-    // do it sync because event list needs to be cleared to prevent saving on device
-    
-    // TODO for pilot store to ipad
-    // uploadEventLog(false);
-    
-    // write to file
-    // json without the logs that were uploaded!
-    Json::Value jlogs = logsToJson();
-    ofFile logFile(fname,ofFile::WriteOnly);
-    logFile << jlogs;
-    cout << jlogs;
-    logFile.close();
-    
-}
 //---------------------------------------------------------------------------
 
 Json::Value EventLogger::logsToJson(){
@@ -608,3 +574,39 @@
 //    
 //    
 //}
+
+//---------------------------------------------------------------------------
+
+void EventLogger::exitAndSave(){
+    
+    saveSessionToFile();
+    return;
+    
+    if(!consentGiven){
+        Json::Value jlogs = logsToJson();
+        // try to upload TODO (no - might hang and prevent exit???)
+        
+        // TODO pilot doesn't upload
+        //       uploadEventLog(true);
+        return;
+    }
+    
+    savedInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime);
+    // save user details
+    string fname = ofxiPhoneGetDocumentsDirectory() + userName + '_' + EVENT_LOG_FILENAME;
+    
+    // try to upload
+    // do it sync because event list needs to be cleared to prevent saving on device
+    
+    // TODO for pilot store to ipad
+    // uploadEventLog(false);
+    
+    // write to file
+    // json without the logs that were uploaded!
+    Json::Value jlogs = logsToJson();
+    ofFile logFile(fname,ofFile::WriteOnly);
+    logFile << jlogs;
+    cout << jlogs;
+    logFile.close();
+    
+}
\ No newline at end of file
--- a/globalVariables.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/globalVariables.h	Tue Nov 25 17:03:33 2014 +0000
@@ -31,7 +31,7 @@
 // globles
 
 #define TOTAL_NUM_PARAMS 6
-#define TARGET_SCORE_CC_BAND 8 // number of cc vals per target band in dartboard
+#define TARGET_SCORE_CC_BAND 7 // number of cc vals per target band in dartboard
 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;
 
--- a/testApp.h	Fri Nov 21 17:07:56 2014 +0000
+++ b/testApp.h	Tue Nov 25 17:03:33 2014 +0000
@@ -123,6 +123,7 @@
     void startTheSearchTests();
     void startTheTrainingTests();
     void startTheExpTests();
+    void startThePerformanceTests();
     void showHelp();
     void helpHidden();
     void setupNewUser();
--- a/testApp.mm	Fri Nov 21 17:07:56 2014 +0000
+++ b/testApp.mm	Tue Nov 25 17:03:33 2014 +0000
@@ -10,7 +10,7 @@
     
     
     
-    ofxiPhoneSetOrientation( OF_ORIENTATION_90_LEFT );
+    ofxiPhoneSetOrientation( OF_ORIENTATION_90_RIGHT );
     //ofxiPhoneExternalDisplay::mirrorOn();
     [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
 
@@ -24,9 +24,9 @@
     targetSynth.init(&core,"targetSynth");
     candidateSynth.init(&core,"candidateSynth");
     
-    searchMessageOrganiser.init(targetSynth, candidateSynth);
-    trainingMessageOrganiser.init(targetSynth,candidateSynth);
-    expMessageOrganiser.init(targetSynth,candidateSynth);
+//    searchMessageOrganiser.init(targetSynth, candidateSynth);
+//    trainingMessageOrganiser.init(targetSynth,candidateSynth);
+//    expMessageOrganiser.init(targetSynth,candidateSynth);
     
     timeController.init();
     initialiseGUIs();
@@ -123,7 +123,7 @@
     UIElements.push_back(bottomButtonPanel);
     bottomButtonPanel->hide();
     
-    TextPanel * instructionPanel = new TextPanel("Instrcution panel", 10, 50, 300,150,(*props));
+    TextPanel * instructionPanel = new TextPanel("Instruction panel", 10, 50, 300,150,(*props));
     instructionPanel->setFontSize(MEDIUMFONT);
     UIElements.push_back(instructionPanel);
     expMessageOrganiser.setInstructionPanel(instructionPanel);
@@ -137,7 +137,7 @@
     
     // play and submit are now same thing
     Buttron * playCandidateButton = new Buttron(props->buttonWidth*1.4,680, *props);
-    playCandidateButton->setLabel("START");
+    playCandidateButton->setLabel("START RUN");
     trainingMessageOrganiser.mapButtonToAction(playCandidateButton, START_TRAINING_SEQUENCE_ID);
     bottomButtonPanel->addButton(playCandidateButton);
     bottomButtonPanel->hide();
@@ -153,7 +153,7 @@
     trainingMessageOrganiser.setInstructionPanel(instructionPanel);
     instructionPanel->hide();
     
-    TextPanel * middlePanel = new TextPanel("Middle panel", 200, 200, 400,400,(*props));
+    TextPanel * middlePanel = new TextPanel("Middle panel", 400, 400, 400,400,(*props));
     middlePanel->setFontSize(LARGEFONT);
     UIElements.push_back(middlePanel);
     trainingMessageOrganiser.setMiddlePanel(middlePanel);
@@ -271,6 +271,21 @@
     UIElements.push_back(iconPanel);
     iconPanel->hide();
     
+    TextPanel* seqNumPanel = new TextPanel("0",500, 190, 150, 150, *props);
+    trainingMessageOrganiser.setSeqNumPanel(seqNumPanel);
+    expMessageOrganiser.setSeqNumPanel(seqNumPanel);
+    searchMessageOrganiser.setSeqNumPanel(seqNumPanel);
+    seqNumPanel->setFontSize(LARGEFONT);
+    UIElements.push_back(seqNumPanel);
+    seqNumPanel->hide();
+    
+    TextPanel* scoreNumPanel = new TextPanel("SCORE: ",700, 60, 150, 150, *props);
+    trainingMessageOrganiser.setScoreNumPanel(scoreNumPanel);
+    expMessageOrganiser.setScoreNumPanel(scoreNumPanel);
+    searchMessageOrganiser.setScoreNumPanel(scoreNumPanel);
+    scoreNumPanel->setFontSize(LARGEFONT);
+    UIElements.push_back(scoreNumPanel);
+    scoreNumPanel->show();
     
 //    Leap6DBox * box = new Leap6DBox(400 , 210 , (*props).XYsize*0.75,(*props).XYsize*0.75,150,50, *props);
 //    searchMessageOrganiser.setBox(box);
@@ -445,6 +460,9 @@
         startTheTrainingTests();
     }else if(mode == 3){
         startTheSearchTests();
+    }else if(mode == 4){
+        startThePerformanceTests();
+
     }
     
 }
@@ -458,7 +476,7 @@
 }
 //--------------------------------------------------------------
 void testApp::usernameEntered(){
-
+    
     eventLogger.onUsernameEntered();
     expPresetManager.onAppLoad();
     
@@ -468,6 +486,9 @@
 //--------------------------------------------------------------
 void testApp::startTheExpTests(){
     eventLogger.logEvent(START_THE_EXP_TESTS);
+
+    expMessageOrganiser.init(targetSynth,candidateSynth);
+    
     whichInterfaceShowing = COUNT_DOWN;
     // do countdown etc
     
@@ -494,6 +515,17 @@
 void testApp::startTheTrainingTests(){
     eventLogger.logEvent(START_THE_TRAINING_TESTS);
     
+    trainingMessageOrganiser.init(targetSynth,candidateSynth, false);
+    
+    trainingMessageOrganiser.setup(whichInterfaceAreWeUsing);
+    trainingMessageOrganiser.showMyPanels();
+    currentStage = TRAINING;
+}
+void testApp::startThePerformanceTests(){
+    eventLogger.logEvent(START_THE_PERFORMANCE_TESTS);
+    
+    trainingMessageOrganiser.init(targetSynth,candidateSynth, true);
+    
     trainingMessageOrganiser.setup(whichInterfaceAreWeUsing);
     trainingMessageOrganiser.showMyPanels();
     currentStage = TRAINING;
@@ -742,6 +774,7 @@
     // looks out for: 30 31 32... on channel 8
     if(msg.channel == midiChannel && msg.status == MIDI_CONTROL_CHANGE){
         int ctl_num = msg.control - 30;
+
         int ctl_val = msg.value;
         // TODO route control change message here
         //cout << " ctrl : " << ctl_num << " : " << ctl_val << endl;