// // ToyRepeatedActionScheduler.cpp // SteveMaggieCpp // // Created by Katarzyna Kalinowska-Górska on 27.05.2017. // // #include #include "ToyRepeatedActionScheduler.h" #include "ToyActionParser.h" #include "ToyJSONParseUtils.h" #include "ToyMiscUtils.h" #include "ToyValueStorage.h" void ToyRepeatedActionScheduler::clearAllScheduledActions(ActionParseDelegate* parseDelegate) { for(auto pair : _scheduledActionsData){ parseDelegate->unschedule(pair.second.callbackKey); ToyValueStorage::getInstance().removeStoredValue(pair.second.storedValueKey, parseDelegate->getToyValueStorageContainerName()); } _scheduledActionsData.clear(); _waitingFunctions.clear(); } //todo write all the stuff we can put to the repeated saction e.g. stpCondition (??) cocos2d::Action* ToyRepeatedActionScheduler::scheduleActionIfNeeded(const rapidjson::Value& jsonActionObject, ActionParseDelegate* parseDelegate, bool notifyDelegateWhenFinished){ // if given action is a repeated action and it is not already scheduled if(this->isActionValidRepeatedAction(jsonActionObject)){ std::string actionTag = jsonActionObject["repeatActionTag"].GetString(); if(_scheduledActionsData.find(actionTag) == _scheduledActionsData.end()){ auto storedValueKey = ToyValueStorage::getInstance().storeValue(jsonActionObject, parseDelegate->getToyValueStorageContainerName()); auto repeatedFunction = [&](float dt, std::string pStoredValueKey, ActionParseDelegate* pParseDelegate, bool pNotifyDelegate){ auto& actionParser = ToyActionParser::getInstance(); auto storedJsonActionObject = ToyValueStorage::getInstance().getStoredValue(pStoredValueKey, pParseDelegate->getToyValueStorageContainerName()); std::string stopCondition; if(ToyJSONParseUtils::hasMemberBool(*storedJsonActionObject, "stopCondition")){ stopCondition = ToyMiscUtils::boolToString((*storedJsonActionObject)["stopCondition"].GetBool()); } else { stopCondition = (*storedJsonActionObject)["stopCondition"].GetString(); } std::string repeatActionTag = (*storedJsonActionObject)["repeatActionTag"].GetString(); if(actionParser.checkCondition(stopCondition, pParseDelegate) == true){ pParseDelegate->unschedule(repeatActionTag); _scheduledActionsData.erase(repeatActionTag); ToyValueStorage::getInstance().removeStoredValue(pStoredValueKey, pParseDelegate->getToyValueStorageContainerName()); } else { auto repeatIntervalSeconds = (*storedJsonActionObject)["repeatIntervalSeconds"].GetFloat(); auto repeatTimeSinceUserInteraction = (*storedJsonActionObject)["repeatTimeSinceUserInteraction"].GetFloat(); auto now = cocos2d::utils::getTimeInMilliseconds(); auto timeSinceLastRun = _scheduledActionsData[repeatActionTag].lastTimeRun == -1 ? repeatIntervalSeconds + 1 : (now - _scheduledActionsData[repeatActionTag].lastTimeRun)/1000; auto lastTouchTime = pParseDelegate->getLastScreenTouchTime(); auto timeSinceLastUserTouch = lastTouchTime == -1 ? repeatIntervalSeconds + 1 : (now - lastTouchTime)/1000.0; if(_scheduledActionsData.find(repeatActionTag) != _scheduledActionsData.end() && (timeSinceLastRun >= repeatIntervalSeconds && timeSinceLastUserTouch >= repeatTimeSinceUserInteraction)){ actionParser.parseAndRunAction(*storedJsonActionObject, pParseDelegate, pNotifyDelegate); if(_scheduledActionsData.find(repeatActionTag) != _scheduledActionsData.end()){ _scheduledActionsData[repeatActionTag].lastTimeRun = now; } } } }; std::function boundRepeatedFunction = std::bind(repeatedFunction, std::placeholders::_1, storedValueKey, parseDelegate, notifyDelegateWhenFinished); _waitingFunctions.insert({actionTag, boundRepeatedFunction}); auto actionFunction = [&](std::string pStoredValueKey, std::string pActionTag, ActionParseDelegate* pParseDelegate){ // log("scheduling repeated funciton"); ScheduledActionsData data; data.lastTimeRun = -1; data.callbackKey = pActionTag; data.storedValueKey = pStoredValueKey; _scheduledActionsData[pActionTag] = data; if(_waitingFunctions.find(pActionTag) != _waitingFunctions.end()){ auto pRepeatedFunction = _waitingFunctions.at(pActionTag); pParseDelegate->schedule(pRepeatedFunction, pActionTag, 1); _waitingFunctions.erase(pActionTag); } }; return ToyActionParser::getInstance().embedFunctionInAction(std::bind(actionFunction, storedValueKey, actionTag, parseDelegate), jsonActionObject, parseDelegate, notifyDelegateWhenFinished); } } return NULL; } bool ToyRepeatedActionScheduler::isActionValidRepeatedAction(const rapidjson::Value& jsonActionObject) { //todo maybe introduce such method to all parsed actions return ToyJSONParseUtils::checkMemberBool(jsonActionObject, "repeat", true) && ToyJSONParseUtils::hasMemberFloat(jsonActionObject, "repeatIntervalSeconds") && ToyJSONParseUtils::hasMemberString(jsonActionObject, "repeatActionTag"); }