/** * @RDE_HEADER@ * State Machine handler for Exercise Control * $Id$ * $HeadURL$ * $Author$ */ #include "exercise_state_machine.h" #include "exercise_state_manager.h" #include "exercise_state_base.h" #include "object_exercise.h" #include "settings.h" #include "logger.h" namespace ExerciseManagement { ExerciseStateMachine::ExerciseStateMachine(ObjectExercise* objExe, QObject *parent) : QObject(parent) , m_stateManager(new ExerciseStateManager(objExe, this)) , m_stateMachine(new QStateMachine(this)) , m_exercise(objExe) , m_logger(getLogger("ExerciseStateMachine")) { qRegisterMetaType("ExerciseManagement::ExerciseState"); m_exerciseStates.insert(ExerciseState::Unknown, new Unknown(m_exercise)); m_exerciseStates.insert(ExerciseState::Created, new Creation(m_exercise)); m_exerciseStates.insert(ExerciseState::Started, new Start(m_exercise)); m_exerciseStates.insert(ExerciseState::Stopped, new Stop(m_exercise)); m_exerciseStates.insert(ExerciseState::Paused, new Pause(m_exercise)); m_exerciseStates.insert(ExerciseState::Terminated, new Terminate(m_exercise)); // Define transitions from one state to the other // ---------------------------------------------------------------------------------------------------------- // ** Unknown // => Created m_exerciseStates[ExerciseState::Unknown]->addTransition(m_stateManager, &ExerciseStateManager::stateCreated, m_exerciseStates[ExerciseState::Created]); // ** Created // => Started m_exerciseStates[ExerciseState::Created]->addTransition(m_stateManager, &ExerciseStateManager::stateStarted, m_exerciseStates[ExerciseState::Started]); // => Terminated m_exerciseStates[ExerciseState::Created]->addTransition(m_stateManager, &ExerciseStateManager::stateTerminated, m_exerciseStates[ExerciseState::Terminated]); // ** Started // => Paused m_exerciseStates[ExerciseState::Started]->addTransition(m_stateManager, &ExerciseStateManager::statePaused, m_exerciseStates[ExerciseState::Paused]); // => Stopped m_exerciseStates[ExerciseState::Started]->addTransition(m_stateManager, &ExerciseStateManager::stateStopped, m_exerciseStates[ExerciseState::Stopped]); // ** Paused // => Stopped m_exerciseStates[ExerciseState::Paused]->addTransition(m_stateManager, &ExerciseStateManager::stateStopped, m_exerciseStates[ExerciseState::Stopped]); // => Resumed (= Started) m_exerciseStates[ExerciseState::Paused]->addTransition(m_stateManager, &ExerciseStateManager::stateStarted, m_exerciseStates[ExerciseState::Started]); // ** Stopped // => Terminated m_exerciseStates[ExerciseState::Stopped]->addTransition(m_stateManager, &ExerciseStateManager::stateTerminated, m_exerciseStates[ExerciseState::Terminated]); // ** Terminated // => Stopped if ( ExerciseManagement::Settings::enableExerciseTerminatedToStopped()) { m_exerciseStates[ExerciseState::Terminated]->addTransition(m_stateManager, &ExerciseStateManager::stateStopped, m_exerciseStates[ExerciseState::Stopped]); } // ---------------------------------------------------------------------------------------------------------- //States zur StateMachine hinzufügen for (ExerciseStateBase *state : qAsConst(m_exerciseStates)) { DEBUG_LOG(m_logger) << "Ex " << exerciseId() << ": state: " << state->exerciseState(); m_stateMachine->addState(state); connect(state, &ExerciseStateBase::entered, this, &ExerciseStateMachine::onEnteredState); } DEBUG_LOG(m_logger) << "Ex " << exerciseId() << ": Constructor ExerciseStateMachine: size m_exerciseStates = " << m_exerciseStates.size(); } ExerciseStateMachine::~ExerciseStateMachine() { qDeleteAll(m_exerciseStates); delete m_stateManager; delete m_stateMachine; } bool ExerciseStateMachine::init() { if (m_stateMachine->isRunning()) return false; DEBUG_LOG(m_logger) << "Ex " << exerciseId() << ": Init ExerciseStateMachine "; // initialise current exerciseState ExerciseStateBase *currentExerciseState = getStateFromId(m_exercise->exerciseState()); DEBUG_LOG(m_logger) << "Ex " << exerciseId() << ": State = " << ExerciseStateManager::toString(m_exercise->exerciseState()); m_stateMachine->setInitialState(currentExerciseState); m_stateMachine->start(); m_stateManager->setInitial(m_exercise->exerciseState()); DEBUG_LOG(m_logger) << "Ex " << exerciseId() << ": ==> Done Init ExerciseStateMachine "; return true; } ExerciseManagement::ExerciseState ExerciseStateMachine::getCurrentState() { return m_exercise->exerciseState(); } bool ExerciseStateMachine::switchToState(ExerciseState newExerciseState) { return m_stateManager->triggerSwitchState(newExerciseState); } void ExerciseStateMachine::onEnteredState() { DEBUG_LOG(m_logger) << "Ex " << exerciseId() << ": ExerciseStateMachine - onEnteredState"; ExerciseStateBase *s = qobject_cast(sender()); if (!s) return; DEBUG_LOG(m_logger) << "Ex " << exerciseId() << ": ExerciseStateBase : " << s->exerciseState(); m_stateManager->setCurrent(s->exerciseState()); emit exerciseStateChanged(s->exerciseState()); } //---------------------------------------- ExerciseStateBase* ExerciseStateMachine::getStateFromId(ExerciseState exerciseState) { ExerciseStateBase *s = m_exerciseStates.value(exerciseState); if (!s) s = m_exerciseStates.value(ExerciseState::Unknown); return s; } //---------------------------------------- int ExerciseStateMachine::exerciseId() const { return m_exercise ? m_exercise->id() : -1; } } // namespace ExerciseManagement