ToyRepeatedActionScheduler.cpp
5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//
//  ToyRepeatedActionScheduler.cpp
//  SteveMaggieCpp
//
//  Created by Katarzyna Kalinowska-Górska on 27.05.2017.
//
//
#include <stdio.h>
#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<void(float)> 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");
}