From 305f526fa8de13867404f11be4fcd0d7e5a2180a Mon Sep 17 00:00:00 2001 From: MPIBR-kretschmerf Date: Wed, 7 Sep 2016 15:59:35 +0200 Subject: [PATCH] Moved statemachine to separate class --- StateMachineController.cpp | 173 ++++++++++++++++++++ StateMachineController.h | 79 +++++++++ mainwindow.cpp | 320 ++++--------------------------------- mainwindow.h | 57 +------ 4 files changed, 288 insertions(+), 341 deletions(-) create mode 100644 StateMachineController.cpp create mode 100644 StateMachineController.h diff --git a/StateMachineController.cpp b/StateMachineController.cpp new file mode 100644 index 0000000..97f1c2b --- /dev/null +++ b/StateMachineController.cpp @@ -0,0 +1,173 @@ +#include "StateMachineController.h" + +StateMachineController::StateMachineController(QWidget *parent) +{ + // seed randomizer + srand(time(0)); +// //timerDialog = new TimerDialog(); + + mainTimer = new QTimer(this); + mainTimer->setSingleShot(true); + + // Create and start the state machine + setupStateMachine(); + +} + +void StateMachineController::setupStateMachine() +{ + stateMachine = new QStateMachine(this); + + // Create the two top-level states + QState *runningState = new QState(stateMachine); + QState *pausedState = new QState(stateMachine); + + // set up state machine + QState *state_preDelay = new QState(runningState); + QState *state_iti = new QState(runningState); + QState *state_userReaction = new QState(runningState); + QState *state_acquisitionBaseline = new QState(runningState); + QState *state_sound = new QState(runningState); + + QHistoryState *historyState = new QHistoryState(runningState); + + /** + * Depending on whether we are in runningState or pausedState, the 'paused' property + * of the object will be set to false/true. + */ + + runningState->assignProperty(this, "paused", false); + pausedState->assignProperty(this, "paused", true); + + state_preDelay->addTransition(mainTimer, SIGNAL(timeout()), state_iti); + state_iti->addTransition(mainTimer, SIGNAL(timeout()), state_userReaction); + state_userReaction->addTransition(mainTimer, SIGNAL(timeout()), state_acquisitionBaseline); + state_acquisitionBaseline->addTransition(mainTimer, SIGNAL(timeout()), state_sound); + state_sound->addTransition(mainTimer, SIGNAL(timeout()), state_iti); + + /** + * If we are in runningState and the pauseRequested() signal is emitted (that happens + * when the pause() slot has been invoked) then we go to the pausedState. + * If we are now in the pausedState and the pauseRequested() signal is emitted again, + * we go to the historyState which will forward us to the phase state we have been in + * when we left the runningState. + */ + runningState->addTransition(this, SIGNAL(pauseRequested()), pausedState); + pausedState->addTransition(this, SIGNAL(pauseRequested()), historyState); + + // Define which child state should be the initial state + runningState->setInitialState(state_preDelay); + stateMachine->setInitialState(runningState); + + // connect states to functions for starting timers + // state pre delay + connect(state_preDelay, SIGNAL(entered()), this, SLOT(onStatePreDelayEntered())); + //connect(state_preDelay, SIGNAL(entered()), mainTimer, SLOT(start())); // start timer on state entered + // state ITI + connect(state_iti, SIGNAL(entered()), this, SLOT(onStateItiEntered())); + //connect(state_iti, SIGNAL(entered()), mainTimer, SLOT(start())); + // state user reaction + connect(state_userReaction, SIGNAL(entered()), this, SLOT(onStateUserReactionEntered())); + /////connect(state_userReaction, SIGNAL(exited()), timerDialog, SLOT(removeTimer())); + //connect(state_userReaction, SIGNAL(entered()), mainTimer, SLOT(start())); + // state baseline + connect(state_acquisitionBaseline, SIGNAL(entered()), this, SLOT(onStateAcquisitionBaselineEntered())); + //connect(state_acquisitionBaseline, SIGNAL(entered()), mainTimer, SLOT(start())); + // state sound + connect(state_sound, SIGNAL(entered()), this, SLOT(onStateSoundEntered())); + //connect(state_sound, SIGNAL(entered()), mainTimer, SLOT(start())); + connect(state_sound, SIGNAL(exited()), this, SLOT(onStateSoundExited())); + +} + +void StateMachineController::runStateMachine() +{ + trialsCurrent = 1; // set index for first trial (1-based) + trialsTotal = trialSequence.length(); + + // start state machine + stateMachine->start(); +} + + +void StateMachineController::onStatePreDelayEntered() +{ + qDebug() << "Pre delay"; + emit(statusMessage("Pre delay running")); + + mainTimer->setInterval(preDelay * 1000); + mainTimer->start(); +} + +void StateMachineController::onStateItiEntered() +{ + qDebug() << "Entered Iti"; + emit(statusMessage("Starting trial begin")); + + double nextItiValue = itiSequence.at(trialsCurrent - 1); // -1 because trialsCurrent is 1-based + mainTimer->setInterval(nextItiValue * 1000); + mainTimer->start(); + +} + +void StateMachineController::onStateUserReactionEntered() +{ +// timerDialog->removeTimer(); // remove previous timer dialog +// timerDialog->setUpTimer(userReaction); +// timerDialog->show(); +// timerDialog->startTimer(); + + qDebug()<< "Starting user reaction"; + emit(statusMessage("Starting user reaction")); + + mainTimer->setInterval(userReaction * 1000); + mainTimer->start(); +} + +void StateMachineController::onStateAcquisitionBaselineEntered() +{ + qDebug()<< "Starting baseline"; + + emit(statusMessage("Starting baseline")); + + mainTimer->setInterval(preImaq * 1000); + mainTimer->start(); +} + +void StateMachineController::onStateSoundEntered() +{ + + int soundType = trialSequence.first(); + trialSequence.pop_front(); + + if (soundType == 1) { + mainTimer->setInterval(soundDurationPositive * 1000); + //state_sound->assignProperty(mainTimer, "interval", (soundDurationPositive * 1000)); + } else if (soundType == 0) { + mainTimer->setInterval(soundDurationNegative * 1000); + //state_sound->assignProperty(mainTimer, "interval", (soundDurationNegative * 1000)); + } + mainTimer->start(); + + qDebug()<< "Starting sound"; + emit(statusMessage("Starting sound")); + +} + +void StateMachineController::onStateSoundExited() +{ + qDebug()<< "Finished sound"; + emit(statusMessage("Finished sound")); + // go to next trial + if(trialsCurrent < trialsTotal) { + //increase trial index + trialsCurrent++; + // or terminate + } else { + mainTimer->stop(); + stateMachine->stop(); + qDebug() << "Terminated"; + //ui->statusBar->showMessage("Terminated"); + //ui->pushButton_Run->setText("Run"); + } +} diff --git a/StateMachineController.h b/StateMachineController.h new file mode 100644 index 0000000..a6cb390 --- /dev/null +++ b/StateMachineController.h @@ -0,0 +1,79 @@ +#ifndef STATEMACHINECONTROLLER_H +#define STATEMACHINECONTROLLER_H +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include //std::random_shuffle + +class StateMachineController : public QObject +{ + Q_OBJECT + +public: + explicit StateMachineController(QWidget *parent = 0); + + double preDelay = -1; + double iti = -1; + double userReaction = 30; //sec + double preImaq = -1; + double soundDurationPositive = -1; + double soundDurationNegative = -1; + + QVector trialSequence; + QVector itiSequence; + + void setupStateMachine(); + void runStateMachine(); + +private: + // state machine + QStateMachine *stateMachine; + QState *state_preDelay; + QState *state_iti; + QState *state_userReaction; + QState *state_acquisitionBaseline; + QState *state_sound; + + bool m_paused; + + // the timer that triggers the state changes + QTimer *mainTimer; + + int trialsTotal = -1; + int trialsCurrent = -1; // is gonna be 1-based, so first trial has index 1 + + +public slots: + void onStatePreDelayEntered(); + void onStateItiEntered(); + void onStateUserReactionEntered(); + void onStateAcquisitionBaselineEntered(); + void onStateSoundEntered(); + void onStateSoundExited(); + + + + +signals: + void statusMessage(QString); + +Q_SIGNALS: + // change notification signals for the state properties + void pausedChanged(); + /** + * This signal is emitted when the pause() slot is invoked and is used + * by the internal state machine only. + */ + void pauseRequested(); + + +}; + +#endif // STATEMACHINECONTROLLER_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 888fcc1..88a0e0e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -4,22 +4,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), - ui(new Ui::MainWindow), - m_paused(false), - mainTimer(new QTimer(this)) + ui(new Ui::MainWindow) { - // seed randomizer - srand(time(0)); - ui->setupUi(this); - - timerDialog = new TimerDialog(); - - mainTimer->setSingleShot(true); - - // Create and start the state machine - setupStateMachine(); + ui->setupUi(this); } MainWindow::~MainWindow() @@ -27,85 +16,12 @@ MainWindow::~MainWindow() delete ui; } -void MainWindow::setupStateMachine() -{ - stateMachine = new QStateMachine(this); - - // Create the two top-level states - QState *runningState = new QState(stateMachine); - QState *pausedState = new QState(stateMachine); - - // set up state machine - QState *state_preDelay = new QState(runningState); - QState *state_iti = new QState(runningState); - QState *state_userReaction = new QState(runningState); - QState *state_acquisitionBaseline = new QState(runningState); - QState *state_sound = new QState(runningState); - - QHistoryState *historyState = new QHistoryState(runningState); - - /** - * Depending on whether we are in runningState or pausedState, the 'paused' property - * of the object will be set to false/true. - */ - - runningState->assignProperty(this, "paused", false); - pausedState->assignProperty(this, "paused", true); - - state_preDelay->addTransition(mainTimer, SIGNAL(timeout()), state_iti); - state_iti->addTransition(mainTimer, SIGNAL(timeout()), state_userReaction); - state_userReaction->addTransition(mainTimer, SIGNAL(timeout()), state_acquisitionBaseline); - state_acquisitionBaseline->addTransition(mainTimer, SIGNAL(timeout()), state_sound); - state_sound->addTransition(mainTimer, SIGNAL(timeout()), state_iti); - - /** - * If we are in runningState and the pauseRequested() signal is emitted (that happens - * when the pause() slot has been invoked) then we go to the pausedState. - * If we are now in the pausedState and the pauseRequested() signal is emitted again, - * we go to the historyState which will forward us to the phase state we have been in - * when we left the runningState. - */ - runningState->addTransition(this, SIGNAL(pauseRequested()), pausedState); - pausedState->addTransition(this, SIGNAL(pauseRequested()), historyState); - - // Define which child state should be the initial state - runningState->setInitialState(state_preDelay); - stateMachine->setInitialState(runningState); - - // connect states to functions for starting timers - // state pre delay - connect(state_preDelay, SIGNAL(entered()), this, SLOT(onStatePreDelayEntered())); - //connect(state_preDelay, SIGNAL(entered()), mainTimer, SLOT(start())); // start timer on state entered - // state ITI - connect(state_iti, SIGNAL(entered()), this, SLOT(onStateItiEntered())); - //connect(state_iti, SIGNAL(entered()), mainTimer, SLOT(start())); - // state user reaction - connect(state_userReaction, SIGNAL(entered()), this, SLOT(onStateUserReactionEntered())); - connect(state_userReaction, SIGNAL(exited()), timerDialog, SLOT(removeTimer())); - //connect(state_userReaction, SIGNAL(entered()), mainTimer, SLOT(start())); - // state baseline - connect(state_acquisitionBaseline, SIGNAL(entered()), this, SLOT(onStateAcquisitionBaselineEntered())); - //connect(state_acquisitionBaseline, SIGNAL(entered()), mainTimer, SLOT(start())); - // state sound - connect(state_sound, SIGNAL(entered()), this, SLOT(onStateSoundEntered())); - //connect(state_sound, SIGNAL(entered()), mainTimer, SLOT(start())); - connect(state_sound, SIGNAL(exited()), this, SLOT(onStateSoundExited())); - -} void MainWindow::on_pushButton_Run_clicked() { ui->pushButton_Run->setDisabled(true); ui->statusBar->showMessage("Running"); - preDelay = ui->lineEdit_preDelay->text().toDouble(); - //iti = ui->lineEdit_iti->text().toDouble(); - preImaq = ui->lineEdit_preImaq->text().toDouble(); - soundDurationPositive = ui->lineEdit_soundDurationPositive->text().toDouble(); - soundDurationNegative = ui->lineEdit_soundDurationNegative->text().toDouble(); - repeatPositive = ui->lineEdit_repeatPositive->text().toDouble(); - repeatNegative = ui->lineEdit_repeatNegative->text().toDouble(); - int sorting; switch(ui->comboBox_trialSequence->currentIndex()){ case 0: @@ -121,15 +37,19 @@ void MainWindow::on_pushButton_Run_clicked() sorting = ORDERED; } - trialSequence = generateTrialSequence(sorting, repeatPositive, repeatNegative); - trialsTotal = trialSequence.length(); +// int trialsTotal = trialSequence.length(); - itiSequence = generateItiSequence(); - trialsCurrent = 1; // set index for first trial (1-based) - // start state machine - stateMachine->start(); + smc.preImaq = ui->lineEdit_preImaq->text().toDouble(); + smc.preDelay = ui->lineEdit_preDelay->text().toDouble(); + smc.soundDurationPositive = ui->lineEdit_soundDurationPositive->text().toDouble(); + smc.soundDurationNegative = ui->lineEdit_soundDurationNegative->text().toDouble(); + smc.userReaction = userReaction; + smc.trialSequence = generateTrialSequence(sorting, ui->lineEdit_repeatPositive->text().toDouble(), ui->lineEdit_repeatNegative->text().toDouble()); + smc.itiSequence = generateItiSequence(userReaction, ui->lineEdit_iti->text(), ui->lineEdit_preImaq->text().toDouble(), ui->lineEdit_repeatPositive->text().toDouble(), ui->lineEdit_repeatNegative->text().toDouble()); + + smc.runStateMachine(); } void MainWindow::on_pushButton_Pause_toggled(bool checked) @@ -153,108 +73,33 @@ void MainWindow::on_pushButton_Pause_toggled(bool checked) bool MainWindow::paused() const { - return m_paused; + return false;//m_paused; } void MainWindow::setPaused(bool paused) { - if (m_paused != paused) { - m_paused = paused; - emit pausedChanged(); - } +// if (m_paused != paused) { +// m_paused = paused; +// emit pausedChanged(); +// } } void MainWindow::pause() { - emit pauseRequested(); + //emit pauseRequested(); } void MainWindow::on_pushButton_Stop_clicked() { - timerDialog->removeTimer(); - mainTimer->stop(); - stateMachine->stop(); +// timerDialog->removeTimer(); +// mainTimer->stop(); +// stateMachine->stop(); qDebug() << "Stopped and terminated"; ui->statusBar->showMessage("Stopped and terminated"); ui->pushButton_Run->setDisabled(false); } -QVector MainWindow::generateTrialSequence(int sorting, int repeatPositive, int repeatNegative) -{ - QVector trialSequence; - int currentRepeatPositive; - int currentRepeatNegative; - - switch(sorting){ - case ORDERED: - currentRepeatPositive = 1; - currentRepeatNegative = 1; - while(currentRepeatPositive <= repeatPositive || currentRepeatNegative <= repeatNegative) { - if(currentRepeatPositive <= repeatPositive) { - trialSequence.append(1); - currentRepeatPositive++; - } - if(currentRepeatNegative <= repeatNegative) { - trialSequence.append(0); - currentRepeatNegative++; - } - } - break; - case SORTED: - for (currentRepeatPositive = 1; currentRepeatPositive <= repeatPositive; ++currentRepeatPositive) { - trialSequence.append(1); - } - for (currentRepeatNegative = 1; currentRepeatNegative <= repeatNegative; ++currentRepeatNegative) { - trialSequence.append(0); - } - break; - case SHUFFLED: - for (currentRepeatPositive = 1; currentRepeatPositive <= repeatPositive; ++currentRepeatPositive) { - trialSequence.append(1); - } - for (currentRepeatNegative = 1; currentRepeatNegative <= repeatNegative; ++currentRepeatNegative) { - trialSequence.append(0); - } - // shuffle trial sequence - std::random_shuffle(trialSequence.begin(), trialSequence.end(), randomGenerator); - break; - default: - for (currentRepeatPositive = 1; currentRepeatPositive <= repeatPositive; ++currentRepeatPositive) { - trialSequence.append(1); - for (currentRepeatNegative = 1; currentRepeatNegative <= repeatNegative; ++currentRepeatNegative) { - trialSequence.append(0); - } - } - } - //qDebug() << trialSequence; - return trialSequence; - -} - -QVector MainWindow::generateItiSequence() -{ - QVector itiSequence; - int itiSequenceLength = repeatPositive + repeatNegative; - - QString lineEdit_iti_str = ui->lineEdit_iti->text(); - if(!lineEdit_iti_str.isEmpty()) { - if(lineEdit_iti_str.contains(',')) { - QStringList iti_range = lineEdit_iti_str.split(','); - double itiValueMin = iti_range.first().toDouble() - userReaction - preImaq; - double itiValueMax = iti_range.last().toDouble() - userReaction - preImaq; - for (int itiSequenceElement = 0; itiSequenceElement < itiSequenceLength; ++itiSequenceElement) { - itiSequence.append(randomMinMax(itiValueMin, itiValueMax)); - } - } else { - double itiValue = lineEdit_iti_str.toDouble() - userReaction - preImaq; - for (int itiSequenceElement = 0; itiSequenceElement < itiSequenceLength; ++itiSequenceElement) { - itiSequence.append(itiValue); - } - } - } - return itiSequence; -} void MainWindow::on_buttonSelectDir_clicked() { @@ -334,87 +179,6 @@ void MainWindow::on_pushButton_selectFileNegative_clicked() } } -void MainWindow::onStatePreDelayEntered() -{ - qDebug() << "Pre delay"; - ui->statusBar->showMessage("Pre delay running"); - - mainTimer->setInterval(preDelay * 1000); - mainTimer->start(); -} - -void MainWindow::onStateItiEntered() -{ - qDebug() << "Entered Iti"; - ui->statusBar->showMessage("Starting trial begin"); - - double nextItiValue = itiSequence.at(trialsCurrent - 1); // -1 because trialsCurrent is 1-based - mainTimer->setInterval(nextItiValue * 1000); - mainTimer->start(); - -} - -void MainWindow::onStateUserReactionEntered() -{ - timerDialog->removeTimer(); // remove previous timer dialog - timerDialog->setUpTimer(userReaction); - timerDialog->show(); - timerDialog->startTimer(); - - qDebug()<< "Starting user reaction"; - ui->statusBar->showMessage("Starting user reaction"); - ui->statusBar->showMessage("Waiting for user reaction"); - - mainTimer->setInterval(userReaction * 1000); - mainTimer->start(); -} - -void MainWindow::onStateAcquisitionBaselineEntered() -{ - qDebug()<< "Starting baseline"; - ui->statusBar->showMessage("Starting baseline"); - - mainTimer->setInterval(preImaq * 1000); - mainTimer->start(); -} - -void MainWindow::onStateSoundEntered() -{ - - int soundType = trialSequence.first(); - trialSequence.pop_front(); - - if (soundType == 1) { - mainTimer->setInterval(soundDurationPositive * 1000); - //state_sound->assignProperty(mainTimer, "interval", (soundDurationPositive * 1000)); - } else if (soundType == 0) { - mainTimer->setInterval(soundDurationNegative * 1000); - //state_sound->assignProperty(mainTimer, "interval", (soundDurationNegative * 1000)); - } - mainTimer->start(); - - qDebug()<< "Starting sound"; - ui->statusBar->showMessage("Starting sound"); - -} - -void MainWindow::onStateSoundExited() -{ - qDebug()<< "Finished sound"; - ui->statusBar->showMessage("Finished sound"); - // go to next trial - if(trialsCurrent < trialsTotal) { - //increase trial index - trialsCurrent++; - // or terminate - } else { - mainTimer->stop(); - stateMachine->stop(); - qDebug() << "Terminated"; - ui->statusBar->showMessage("Terminated"); - ui->pushButton_Run->setText("Run"); - } -} void MainWindow::on_checkBox_itiExternal_clicked(bool checked) { @@ -437,51 +201,31 @@ void MainWindow::on_checkBox_itiExternal_clicked(bool checked) void MainWindow::on_lineEdit_iti_editingFinished() { - QString lineEdit_iti_str = ui->lineEdit_iti->text(); - - if(!lineEdit_iti_str.isEmpty()) { - - if(lineEdit_iti_str.contains(',')) { - QStringList iti_range = lineEdit_iti_str.split(','); - iti = randomMinMax(iti_range.first().toDouble(), iti_range.last().toDouble()); - if(!isItiHighEnough()) { - updateIti(); - } - } else { - iti = lineEdit_iti_str.toDouble(); - if(!isItiHighEnough()) { - updateIti(); - } - } - - } + updateIti(); } void MainWindow::on_lineEdit_preImaq_editingFinished() { - preImaq = ui->lineEdit_preImaq->text().toDouble(); - - if(!ui->lineEdit_preImaq->text().isEmpty() && !isItiHighEnough()) { - updateIti(); - } -} -bool MainWindow::isItiHighEnough() -{ - return (iti >= (userReaction + preImaq)); + updateIti(); } void MainWindow::updateIti() { + double preImaq = ui->lineEdit_preImaq->text().toDouble(); + QString lineEdit_iti_str = ui->lineEdit_iti->text(); if(!lineEdit_iti_str.isEmpty()) { if(lineEdit_iti_str.contains(',')) { QStringList iti_range = lineEdit_iti_str.split(','); - iti = randomMinMax((iti_range.first().toDouble() + userReaction + preImaq), (iti_range.last().toDouble() + userReaction + preImaq)); - ui->lineEdit_iti->setText(QString("%1,%2").arg(QString::number(iti_range.first().toDouble() + userReaction + preImaq), QString::number(iti_range.last().toDouble() + userReaction + preImaq))); + double iti = randomMinMax(iti_range.first().toDouble(), iti_range.last().toDouble()); + if(iti < userReaction + preImaq){ + ui->lineEdit_iti->setText(QString("%1,%2").arg(QString::number(iti_range.first().toDouble() + userReaction + preImaq), QString::number(iti_range.last().toDouble() + userReaction + preImaq))); + } } else { - iti = iti + userReaction + preImaq; - ui->lineEdit_iti->setText(QString::number(iti)); + if(ui->lineEdit_iti->text().toDouble() < userReaction + preImaq){ + ui->lineEdit_iti->setText(QString::number(ui->lineEdit_iti->text().toDouble() + userReaction + preImaq)); + } } } } diff --git a/mainwindow.h b/mainwindow.h index f081e4b..1483799 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -4,18 +4,10 @@ #include #include #include -#include #include #include -#include -#include -#include -#include //std::random_shuffle #include "timerdialog.h" -#include -#include -#include - +#include "StateMachineController.h" // values for trial sequence sorting enum SORTING {ORDERED, SORTED, SHUFFLED}; @@ -30,7 +22,7 @@ class MainWindow : public QMainWindow Q_OBJECT // the state property that reflects whether the traffic light is currently paused - Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) + //Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) public: explicit MainWindow(QWidget *parent = 0); @@ -48,12 +40,6 @@ private slots: void on_pushButton_selectFileNegative_clicked(); - void onStatePreDelayEntered(); - void onStateItiEntered(); - void onStateUserReactionEntered(); - void onStateAcquisitionBaselineEntered(); - void onStateSoundEntered(); - void onStateSoundExited(); void pause(); @@ -67,63 +53,28 @@ private slots: void on_lineEdit_preImaq_editingFinished(); -Q_SIGNALS: - // change notification signals for the state properties - void pausedChanged(); - /** - * This signal is emitted when the pause() slot is invoked and is used - * by the internal state machine only. - */ - void pauseRequested(); private: Ui::MainWindow *ui; - void setupStateMachine(); + StateMachineController smc; - bool isItiHighEnough(); void updateIti(); + const double userReaction = 30; //sec // default directory const QString DEFAULT_DIR_KEY = "/home"; // Application settings to store last used directory for select dialog QSettings appSettings; - - TimerDialog *timerDialog; - double preDelay = -1; - double iti = -1; - const double userReaction = 30; //sec - double preImaq = -1; - double soundDurationPositive = -1; - double soundDurationNegative = -1; - int repeatPositive = -1; - int repeatNegative = -1; QString selectedDirectory; QString selectedPositiveFileName; QString selectedNegativeFileName; - QVector generateTrialSequence(int sorting, int repeatPositive, int repeatNegative); - QVector generateItiSequence(); - - QVector trialSequence; - int trialsTotal = -1; - int trialsCurrent = -1; // is gonna be 1-based, so first trial has index 1 - QVector itiSequence; - // state machine - QStateMachine *stateMachine; - QState *state_preDelay; - QState *state_iti; - QState *state_userReaction; - QState *state_acquisitionBaseline; - QState *state_sound; - bool m_paused; - // the timer that triggers the state changes - QTimer *mainTimer; }; #endif // MAINWINDOW_H