/// <summary> /// Updates SlotEngine with latest PhaseConfig and replace PhaseData object. /// </summary> private void UpdateEngine() { if (InvokeRequired) { Invoke(new VoidDelegate(UpdateEngine), new object[] { }); } else { engine = new SlotsEngine(Phase.Slots, Phase.Schedule); Data = new PhaseData(); } }
/// <summary> /// Main driving logic for slot simulation. /// </summary> /// <param name="sender"></param> private void AdvanceTrial(Button sender) { switch (stage) { case TrialStage.Starting: // check start conditions if (Phase.StartCond[0] == 0) { // start pretrial delay timer stage = TrialStage.PreTrialDelay; if (Phase.StartCond[1] == 0) // check if delay time is 0 { DelayTimer_Tick(null, null); // invoke timer elapsed method to skip timer } else { // set and start timer. DelayTimer.Interval = Phase.StartCond[1] * 1000; DelayTimer.Enabled = true; } } else { // start waiting for start button press stage = TrialStage.WaitingForStartButton; buttons[Phase.StartCond[1]].Enabled = true; buttons[Phase.StartCond[1]].Visible = true; } break; case TrialStage.PreTrialDelay: // delay time is up, trial is now started. stage = TrialStage.Started; AdvanceTrial(null); break; case TrialStage.WaitingForStartButton: // start button pressed, trial is now started. stage = TrialStage.Started; AdvanceTrial(null); break; case TrialStage.Started: // generate slot result result = engine.Roll(); Data.SlotOutcomes.Add(result); // count slots to be pressed numSlots = 0; for (int i = 0; i < 3; i++) { if (Phase.Slots[i]) { numSlots++; } } // determine if we can skip the slot stage if (numSlots == 0) { // enable collect button stage = TrialStage.WaitingForCollectButton; buttons[Phase.RewardButton].Enabled = true; buttons[Phase.RewardButton].Visible = true; // enable timeout button buttons[Phase.TimeoutButton].Enabled = true; buttons[Phase.TimeoutButton].Visible = true; } else { // enable first slot stage = TrialStage.WaitingForSlot; for (int i = 0; i < 3; i++) { if (Phase.Slots[i]) { activeSlot = i; slots[activeSlot].Enabled = true; slots[activeSlot].Visible = true; break; } } // start blinking BlinkTimer.Interval = 1000 / (Looks.SlotsBlinkRate * 2); BlinkTimer.Enabled = true; } break; case TrialStage.WaitingForSlot: // set slot color numSlots--; if (result[numSlots] == 1) { sender.BackColor = Looks.SlotsFGColor; } else { sender.BackColor = Looks.SlotsBGColor; } // determine if we're done with slot stage if (numSlots == 0) { stage = TrialStage.WaitingForCollectButton; if (Phase.StartCond[0] == 1) { // enable roll button buttons[Phase.StartCond[1]].Enabled = true; buttons[Phase.StartCond[1]].Visible = true; } // enable collect button buttons[Phase.RewardButton].Enabled = true; buttons[Phase.RewardButton].Visible = true; // enable timeout button buttons[Phase.TimeoutButton].Enabled = true; buttons[Phase.TimeoutButton].Visible = true; // stop blinking BlinkTimer.Enabled = false; } else { // enable next slot for (int i = activeSlot + 1; i < 3; i++) { if (Phase.Slots[i]) { activeSlot = i; slots[activeSlot].Enabled = true; slots[activeSlot].Visible = true; break; } } } break; case TrialStage.WaitingForCollectButton: Data.SlotsTime.Add(slotsTime); Data.ButtonTime.Add(buttonTime); slotsTime = 0; buttonTime = 0; Data.NumTrials++; UpdateLooks(); bool success = SlotsEngine.CheckRoll(result); int progress; if (success) { Data.NumSuccessStates++; } // handle reroll button first if (sender == buttons[Phase.StartCond[1]] & Phase.StartCond[0] == 1) { Data.TrialResults.Add("skip"); if (success) { Data.NumIncorrect++; } else { Data.NumCorrect++; } progress = CheckProgressCond(); if (progress != 0) { PhaseTransition(progress); } else { // restarting trial stage = TrialStage.WaitingForStartButton; AdvanceTrial(null); } break; } // special cases when timeout and reward buttons are different if (Phase.TimeoutButton != Phase.RewardButton) { if ((sender == buttons[Phase.RewardButton] & success == false) | (sender == buttons[Phase.TimeoutButton] & success == true)) { // trigger timeout Data.TrialResults.Add("timeout"); System.Media.SystemSounds.Hand.Play(); Data.NumIncorrect++; progress = CheckProgressCond(); if (progress != 0) { PhaseTransition(progress); } else { stage = TrialStage.TimeoutDelay; } if (Phase.Timeout == 0) // check if timeout time is 0 { DelayTimer_Tick(null, null); // invoke timer elapsed method to skip timer } else { // set and start timer. DelayTimer.Interval = Phase.Timeout * 1000; DelayTimer.Enabled = true; } break; } if ((sender == buttons[Phase.TimeoutButton] & success == false) | (sender == buttons[Phase.RewardButton] & success == true)) { // dispense reward Data.TrialResults.Add("reward"); System.Media.SystemSounds.Beep.Play(); DispenserInterface.Dispense(Phase.RewardAmount); //MessageBox.Show("Dispensed " + Phase.RewardAmount.ToString() + " pellets."); Data.NumCorrect++; progress = CheckProgressCond(); if (progress != 0) { PhaseTransition(progress); } else { // restarting trial stage = TrialStage.Starting; AdvanceTrial(null); } break; } } else { // base cases if (sender == buttons[Phase.TimeoutButton] & success == false) { // trigger timeout Data.TrialResults.Add("timeout"); System.Media.SystemSounds.Hand.Play(); Data.NumIncorrect++; progress = CheckProgressCond(); if (progress != 0) { PhaseTransition(progress); } else { stage = TrialStage.TimeoutDelay; } if (Phase.Timeout == 0) // check if timeout time is 0 { DelayTimer_Tick(null, null); // invoke timer elapsed method to skip timer } else { // set and start timer. DelayTimer.Interval = Phase.Timeout * 1000; DelayTimer.Enabled = true; } break; } else { if (sender == buttons[Phase.RewardButton] & success == true) { // dispense reward Data.TrialResults.Add("reward"); System.Media.SystemSounds.Beep.Play(); DispenserInterface.Dispense(Phase.RewardAmount); //MessageBox.Show("Dispensed " + Phase.RewardAmount.ToString() + " pellets."); Data.NumCorrect++; progress = CheckProgressCond(); if (progress != 0) { PhaseTransition(progress); } else { // restarting trial stage = TrialStage.Starting; AdvanceTrial(null); } } } } break; case TrialStage.TimeoutDelay: // timeout time is up, restarting trial. stage = TrialStage.Starting; AdvanceTrial(null); break; default: break; } }