Binary CounterFrom VLECode explanationModel's attributs private: enum State { PASSIVE, ACTIVE }; // parameter double mDuration; // state double mCounter; double mCounter2; double mSigma; State mState; vd::Time mLastTime;
BinaryCounter(const vd::DynamicsInit& init, const vd::InitEventList& events) : vd::Dynamics(init, events) { mDuration = vv::toDouble(events.get("duration")); } virtual ~BinaryCounter() { } There are exactly the same as for the model Generator, the constructor retrieves the duration parameter, and the destructor is empty but obligatory.
virtual vd::Time init(const vd::Time& time) { mSigma = mDuration; mLastTime = time; mState = PASSIVE; mCounter = 0; mCounter2 = 0; return mDuration; } We init the attribute mSigma at parameter duration, mLastime at the start. At the begining of the simulation, we wait an input so we init mState to PASSIVE. We init mCounter and mCounter2 to 0. Finaly, we return infinity to wait indefinitely until a reception of an entry.
virtual void output(const vd::Time& /* time */, vd::ExternalEventList& output) const { if(mCounter == 1){ vd::ExternalEvent* event = new vd::ExternalEvent("out"); event << vd::attribute("in", mCounter); output.addEvent(event); } } If mCounter is equal to 1, it's because we retrieve two 1 in entry during the period of time, so we can return an 1, else we return nothing.
virtual vd::Time timeAdvance() const { switch (mState) { case PASSIVE : return mDuration; case ACTIVE : return mSigma; } } If we have'nt recieved anything, we're just waiting the time given with the parameter mduration. If we already have recieved a 1, we only wait the remaning time before the end of the duration given by the user with mDuration
virtual void internalTransition(const vd::Time& time) { mLastTime = time; mSigma = mDuration; mState = PASSIVE; mCounter = 0; mCounter2 = 0; } The internalTransition happens every time step given in parameter. It attributes the value time to mLastTime, that will allow us the possibility to update mSigma if is an externalTransition. It then resets mSigma with the parameter mduration, sets back mState to PASSIVE and reset mCounter and mCounter2 to 0. L'internalTransition a lieu à chaque laps de temps donné en paramètre. Elle attribut la valeur time à mLastTime ce qui va ensuite nous offrir la possibilité de mettre à jour mSigma si c'est une externalTransition. Il réinitialise ensuite sigma avec le paramètre mduration défini par l'utilisateur et repasse mState à PASSIVE et réinitialise mCounter et mCounter2 à 0.
ExternalTransition virtual void externalTransition(const vd::ExternalEventList& events,const vd::Time& time ) { switch (mState) { case PASSIVE : { vd::ExternalEventList::const_iterator it = events.begin(); while (it != events.end()) { mCounter2 = (*it)->getDoubleAttributeValue("in"); ++it; } mSigma -= time - mLastTime; mLastTime = time; if(mCounter2 == 1){ mState = ACTIVE; } break; } case ACTIVE : { vd::ExternalEventList::const_iterator it = events.begin(); while (it != events.end()) { mCounter2 = (*it)->getDoubleAttributeValue("in"); ++it; } if(mCounter2 == 1){ mCounter=1; mSigma -= time - mLastTime; mLastTime = time; } else{ mSigma -= time - mLastTime; mLastTime = time; } break; } } If we have'nt yet received a 1, we're in the state PASSIVE. Once we receive something, we check if is a one and if so we go in the ACTIVE state. If we recieve or not a 1, we uptade mSigma and mlastTime if we already received a 1 we're in the state ACTIVE. So we look if we receive an other one and if so we set mCounter to 1. Here again, if we receive an 1 or not, we update mSigma and mLastTime.
|