Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1033 | werner | 1 | /******************************************************************************************** |
2 | ** iLand - an individual based forest landscape and disturbance model |
||
3 | ** http://iland.boku.ac.at |
||
4 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl |
||
5 | ** |
||
6 | ** This program is free software: you can redistribute it and/or modify |
||
7 | ** it under the terms of the GNU General Public License as published by |
||
8 | ** the Free Software Foundation, either version 3 of the License, or |
||
9 | ** (at your option) any later version. |
||
10 | ** |
||
11 | ** This program is distributed in the hope that it will be useful, |
||
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | ** GNU General Public License for more details. |
||
15 | ** |
||
16 | ** You should have received a copy of the GNU General Public License |
||
17 | ** along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
18 | ********************************************************************************************/ |
||
807 | werner | 19 | #ifndef ACTIVITY_H |
20 | #define ACTIVITY_H |
||
808 | werner | 21 | #include <QJSValue> |
827 | werner | 22 | #include <QVector> |
924 | werner | 23 | #include <QMap> |
870 | werner | 24 | |
808 | werner | 25 | class Expression; // forward |
870 | werner | 26 | |
907 | werner | 27 | namespace ABE { |
870 | werner | 28 | |
29 | |||
811 | werner | 30 | class FMStand; |
870 | werner | 31 | class FMSTP; |
807 | werner | 32 | |
870 | werner | 33 | |
34 | class Schedule { |
||
35 | public: |
||
36 | // setup and life cycle |
||
37 | Schedule() {} |
||
38 | Schedule(QJSValue &js_value) { clear(); setup(js_value); } |
||
872 | werner | 39 | void clear() { tmin=tmax=topt=-1; tminrel=tmaxrel=toptrel=-1.; force_execution=false; repeat_interval=-1; repeat=false; absolute=false; } |
963 | werner | 40 | void setup(const QJSValue &js_value); |
870 | werner | 41 | QString dump() const; |
42 | // functions |
||
897 | werner | 43 | /// value() evaluates the schedule for the given 'stand'. |
44 | /// return 0..1 (0: no fit, 1: perfect time). |
||
45 | /// Special value -1: expired (i.e. current time past the maximum schedule time). |
||
955 | werner | 46 | double value(const FMStand *stand, const int specific_year=-1); |
872 | werner | 47 | /// gives (fixed) earliest possible execution time |
875 | werner | 48 | double minValue(const double U=100.) const; |
49 | /// returns the latest possible execution time |
||
50 | double maxValue(const double U=100.) const; |
||
910 | werner | 51 | /// returns the "optimal" year, i.e. the first year when prob. to execute is highest. |
52 | double optimalValue(const double U=100.) const; |
||
870 | werner | 53 | // some stuffs |
54 | int tmin; int tmax; int topt; |
||
55 | double tminrel; double tmaxrel; double toptrel; |
||
56 | bool force_execution; |
||
871 | werner | 57 | // repeating |
58 | int repeat_interval; |
||
59 | bool repeat; |
||
872 | werner | 60 | bool absolute; |
870 | werner | 61 | }; |
62 | |||
63 | class Events { |
||
64 | public: |
||
65 | Events() {} |
||
66 | /// clear the list of events |
||
67 | void clear(); |
||
68 | /// setup events from the javascript object |
||
69 | void setup(QJSValue &js_value, QStringList event_names); |
||
891 | werner | 70 | /// execute javascript event /if registered) in the context of the forest stand 'stand'. |
1070 | werner | 71 | QJSValue run(const QString event, FMStand *stand, QJSValueList *params=0); |
891 | werner | 72 | /// returns true, if the event 'event' is available. |
73 | bool hasEvent(const QString &event) const; |
||
870 | werner | 74 | QString dump(); ///< prints some debug info |
75 | private: |
||
887 | werner | 76 | QJSValue mInstance; ///< object holding the events |
77 | QMap<QString, QJSValue> mEvents; ///< list of event names and javascript functions |
||
870 | werner | 78 | }; |
79 | |||
944 | werner | 80 | /** DynamicExpression encapsulates an "expression" that can be either a iLand expression, a constant or a javascript function. |
81 | */ |
||
82 | struct DynamicExpression { |
||
83 | DynamicExpression(): filter_type(ftInvalid), expr(0) {} |
||
84 | ~DynamicExpression(); |
||
963 | werner | 85 | void setup(const QJSValue &js_value); |
944 | werner | 86 | bool evaluate(FMStand *stand) const; |
87 | bool isValid() const { return filter_type!=ftInvalid;} |
||
88 | QString dump() const; |
||
89 | private: |
||
90 | enum { ftInvalid, ftExpression, ftJavascript} filter_type; |
||
91 | Expression *expr; |
||
92 | QJSValue func; |
||
93 | }; |
||
94 | |||
870 | werner | 95 | class Constraints { |
96 | public: |
||
97 | Constraints() {} |
||
98 | void setup(QJSValue &js_value); ///< setup from javascript |
||
889 | werner | 99 | double evaluate(FMStand *stand); ///< run the constraints |
870 | werner | 100 | QStringList dump(); ///< prints some debug info |
101 | private: |
||
944 | werner | 102 | QList<DynamicExpression> mConstraints; |
870 | werner | 103 | }; |
104 | |||
871 | werner | 105 | class Activity; //forward |
106 | /** Activity meta data (enabled, active, ...) that need to be stored |
||
107 | per stand. */ |
||
108 | class ActivityFlags |
||
109 | { |
||
110 | public: |
||
111 | ActivityFlags(): mActivity(0), mFlags(0) {} |
||
112 | ActivityFlags(Activity *act): mActivity(act), mFlags(0) {} |
||
891 | werner | 113 | Activity *activity() const {return mActivity; } |
114 | |||
871 | werner | 115 | bool active() const {return flag(Active); } |
116 | bool enabled() const {return flag(Enabled);} |
||
117 | bool isRepeating() const {return flag(Repeater);} |
||
875 | werner | 118 | bool isPending() const {return flag(Pending); } |
119 | bool isForcedNext() const {return flag(ExecuteNext); } |
||
889 | werner | 120 | bool isFinalHarvest() const {return flag(FinalHarvest); } |
121 | bool isExecuteImmediate() const {return flag(ExecuteImmediate); } |
||
891 | werner | 122 | bool isScheduled() const {return flag(IsScheduled);} |
123 | bool isDoSimulate() const {return flag(DoSimulate);} |
||
905 | werner | 124 | bool isSalvage() const {return flag(IsSalvage);} |
891 | werner | 125 | |
905 | werner | 126 | |
871 | werner | 127 | void setActive(const bool active) { setFlag(Active, active); } |
128 | void setEnabled(const bool enabled) { setFlag(Enabled, enabled); } |
||
129 | void setIsRepeating(const bool repeat) { setFlag(Repeater, repeat); } |
||
875 | werner | 130 | void setIsPending(const bool pending) { setFlag(Pending, pending); } |
131 | void setForceNext(const bool isnext) { setFlag(ExecuteNext, isnext); } |
||
889 | werner | 132 | void setFinalHarvest(const bool isfinal) { setFlag(FinalHarvest, isfinal); } |
133 | void setExecuteImmediate(const bool doexec) { setFlag(ExecuteImmediate, doexec);} |
||
891 | werner | 134 | void setIsScheduled(const bool doschedule) {setFlag(IsScheduled, doschedule); } |
135 | void setDoSimulate(const bool dosimulate) {setFlag(DoSimulate, dosimulate); } |
||
905 | werner | 136 | void setIsSalvage(const bool issalvage) {setFlag(IsSalvage, issalvage); } |
875 | werner | 137 | |
871 | werner | 138 | private: |
875 | werner | 139 | /// (binary coded) flags |
893 | werner | 140 | enum Flags { Active=1, // if false, the activity has already been executed |
875 | werner | 141 | Enabled=2, // if false, the activity can not be executed |
142 | Repeater=4, // if true, the activity is executed |
||
143 | ExecuteNext=8, // this activity should be executed next (kind of "goto" |
||
889 | werner | 144 | ExecuteImmediate=16, // should be executed immediately by the scheduler (e.g. required sanitary cuttings) |
145 | Pending=32, // the activity is currently in the scheduling algorithm |
||
891 | werner | 146 | FinalHarvest=64, // the management of the activity is a "endnutzung" (compared to "vornutzung") |
147 | IsScheduled=128, // the execution time of the activity is scheduled by the Scheduler component |
||
905 | werner | 148 | DoSimulate=256, // the default operation mode of harvests (simulate or not) |
149 | IsSalvage=512 // the activity is triggered by tree mortality events |
||
889 | werner | 150 | }; |
871 | werner | 151 | bool flag(const ActivityFlags::Flags flag) const { return mFlags & flag; } |
152 | void setFlag(const ActivityFlags::Flags flag, const bool value) { if (value) mFlags |= flag; else mFlags &= (flag ^ 0xffffff );} |
||
153 | Activity *mActivity; ///< link to activity |
||
154 | int mFlags; |
||
155 | }; |
||
870 | werner | 156 | |
871 | werner | 157 | |
963 | werner | 158 | |
869 | werner | 159 | /// Activity is the base class for management activities |
807 | werner | 160 | class Activity |
161 | { |
||
162 | public: |
||
891 | werner | 163 | // life cycle |
869 | werner | 164 | Activity(const FMSTP *parent); |
1032 | werner | 165 | virtual ~Activity(); |
891 | werner | 166 | /// Activity factory - create activities for given 'type' |
167 | static Activity *createActivity(const QString &type, FMSTP *stp); |
||
168 | |||
169 | // properties |
||
870 | werner | 170 | enum Phase { Invalid, Tending, Thinning, Regeneration, All }; |
869 | werner | 171 | const FMSTP *program() const { return mProgram; } |
871 | werner | 172 | virtual QString type() const; |
944 | werner | 173 | QString name() const {return mName; } ///< name of the activity as provided by JS |
174 | int index() const { return mIndex; } ///< index of the activity within the STP |
||
910 | werner | 175 | /// get earlist possible scheduled year (relative to rotation begin) |
875 | werner | 176 | int earlistSchedule(const double U=100.) const {return mSchedule.minValue(U); } |
910 | werner | 177 | /// get latest possible scheduled year (relative to rotation begin) |
875 | werner | 178 | int latestSchedule(const double U=100.) const { return mSchedule.maxValue(U); } |
910 | werner | 179 | /// get optimal scheduled year (relative to rotation begin) |
180 | int optimalSchedule(const double U=100.) const { return mSchedule.optimalValue(U); } |
||
901 | werner | 181 | bool isRepeatingActivity() const { return mSchedule.repeat; } |
869 | werner | 182 | // main actions |
870 | werner | 183 | /// setup of the activity (events, schedule, constraints). additional setup in derived classes. |
869 | werner | 184 | virtual void setup(QJSValue value); |
875 | werner | 185 | /// returns a value > 0 if the activity coult be scheduled now |
955 | werner | 186 | virtual double scheduleProbability(FMStand *stand, const int specific_year=-1); |
889 | werner | 187 | /// returns a probability for the activity to be executed (ie all constraints are fulfilled) |
188 | /// return value is 0 if the activity can not be executed (maximum result is 1) |
||
189 | virtual double execeuteProbability(FMStand *stand); |
||
870 | werner | 190 | /// executes the action (usually defined in derived classes) using the context of 'stand'. |
191 | virtual bool execute(FMStand *stand); |
||
891 | werner | 192 | /// executes the evaluation of the forest stand. |
193 | /// returns true, when the stand should enter the scheduler. |
||
194 | virtual bool evaluate(FMStand *stand); |
||
944 | werner | 195 | /// function that evaluates "bound" dynamic expressions |
196 | virtual void evaluateDyanamicExpressions(FMStand *stand); |
||
870 | werner | 197 | /// dumps some information for debugging |
198 | virtual QStringList info(); |
||
869 | werner | 199 | protected: |
870 | werner | 200 | Schedule &schedule() { return mSchedule; } |
201 | Constraints &constraints() { return mConstraints; } |
||
202 | Events &events() { return mEvents; } |
||
911 | werner | 203 | ActivityFlags &standFlags(FMStand *stand=0); |
891 | werner | 204 | ActivityFlags mBaseActivity; // base properties of the activity (that can be changed for each stand) |
951 | werner | 205 | static QStringList mAllowedProperties; // list of properties (e.g. 'schedule') that are parsed by the base activity |
869 | werner | 206 | private: |
871 | werner | 207 | void setIndex(const int index) { mIndex = index; } // used during setup |
208 | void setName(const QString &name) { mName = name; } |
||
944 | werner | 209 | int mIndex; ///< index of the activity within the STP |
871 | werner | 210 | QString mName; ///< the name of the activity; |
870 | werner | 211 | const FMSTP *mProgram; // link to the management programme the activity is part of |
869 | werner | 212 | Schedule mSchedule; // timing of activity |
213 | Constraints mConstraints; // constraining factors |
||
214 | Events mEvents; // action handlers such as "onExecute" |
||
944 | werner | 215 | DynamicExpression mEnabledIf; // enabledIf property (dynamically evaluated) |
871 | werner | 216 | friend class FMSTP; // allow access of STP class to internals |
888 | werner | 217 | friend class FMStand; // allow access of the activity class (e.g for events) |
893 | werner | 218 | friend class ActivityObj; // allow access to scripting function |
869 | werner | 219 | }; |
220 | |||
870 | werner | 221 | } // namespace |
963 | werner | 222 | |
223 | Q_DECLARE_TYPEINFO(ABE::ActivityFlags, Q_PRIMITIVE_TYPE); // declare as POD structure to allow more efficient copying |
||
224 | |||
807 | werner | 225 | #endif // ACTIVITY_H |