/** * AES fire automaton - scheduling fire patterns for multiple effectors * $Id$ * $HeadURL$ * $Author$ */ #include #include #include #include #include #include "../logger.h" #pragma once namespace NGL { class INGLLogger; } namespace AreaEffectSimulation { class AES_COMMON_EXPORT FireAutomaton : public QObject { Q_OBJECT public: FireAutomaton(QObject *parent = nullptr); enum class State { Uninitialized, Stopped, Running, Paused, Stepping }; /* Allowed state transitions: Uninitialized -> Stopped Running -> Stopped Stepping -> Stopped Paused -> Stopped Stopped -> Running Running -> Paused Paused -> Running Stopped -> Stepping */ enum class TimeType { Duration, Cadence }; bool init(int32_t time, TimeType type, int32_t rounds, const QVector& effectorIds, const QString& pattern); State getState() const; signals: void fire(int32_t effectorId); void finished(); public slots: bool start(); void stop(); bool pause(); bool resume(); bool performStep(); private slots: void nextTick(); private: enum class PatternElement { All, AllFill, Next, NextFill, Idle }; static bool patternElementFromString(const QString& str, FireAutomaton::PatternElement& out); bool readPattern(const QString& pattern); bool calculateSchedule(int32_t rounds); void setState(State state); int32_t getMaxTick() const; QVector getEffectorIds(int32_t tick) const; private: QVector m_effectorIds; QVector m_pattern; QVector> m_schedule; QTimer m_timer; int32_t m_nextIdx; int32_t m_tick; int32_t m_durationMSecs; int32_t m_intervalMSecs; int32_t m_remainingTickMSecs; State m_state; LOGGER_T m_logger; }; } // namespace AreaEffectSimulation