Rev 420 | Rev 552 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | |||
185 | werner | 2 | #include "global.h" |
3 | #include "management.h" |
||
4 | #include "helper.h" |
||
186 | werner | 5 | #include "model.h" |
189 | iland | 6 | #include "resourceunit.h" |
186 | werner | 7 | #include "tree.h" |
216 | werner | 8 | #include "expressionwrapper.h" |
186 | werner | 9 | |
242 | werner | 10 | #include "climateconverter.h" |
245 | werner | 11 | #include "csvfile.h" |
247 | werner | 12 | #include "scriptglobal.h" |
186 | werner | 13 | |
185 | werner | 14 | #include <QtScript> |
216 | werner | 15 | #include <QTextEdit> |
16 | QObject *Management::scriptOutput = 0; |
||
185 | werner | 17 | |
216 | werner | 18 | QScriptValue script_debug(QScriptContext *ctx, QScriptEngine *eng) |
294 | werner | 19 | { |
20 | QString value; |
||
21 | for (int i = 0; i < ctx->argumentCount(); ++i) { |
||
22 | if (i > 0) |
||
23 | value.append(" "); |
||
24 | value.append(ctx->argument(i).toString()); |
||
25 | } |
||
26 | if (Management::scriptOutput) { |
||
27 | QTextEdit *e = qobject_cast<QTextEdit*>(Management::scriptOutput); |
||
28 | if (e) |
||
29 | e->append(value); |
||
30 | } else { |
||
31 | qDebug() << "Script:" << value; |
||
32 | } |
||
33 | return eng->undefinedValue(); |
||
34 | } |
||
186 | werner | 35 | |
294 | werner | 36 | QScriptValue script_include(QScriptContext *ctx, QScriptEngine *eng) |
37 | { |
||
38 | QString fileName = ctx->argument(0).toString(); |
||
39 | QString path =GlobalSettings::instance()->path(fileName, "script") ; |
||
40 | QString includeFile=Helper::loadTextFile(path); |
||
41 | eng->evaluate(includeFile, fileName); |
||
42 | if (eng->hasUncaughtException()) |
||
43 | qDebug() << "Error in include:" << eng->uncaughtException().toString(); |
||
44 | return QScriptValue(); |
||
45 | } |
||
46 | |||
47 | QScriptValue script_alert(QScriptContext *ctx, QScriptEngine *eng) |
||
48 | { |
||
49 | QString value = ctx->argument(0).toString(); |
||
50 | Helper::msg(value); |
||
51 | return eng->undefinedValue(); |
||
52 | } |
||
216 | werner | 53 | // global output function |
54 | QString Management::executeScript(QString cmd) |
||
55 | { |
||
56 | DebugTimer t("execute javascript"); |
||
57 | if (mEngine) |
||
58 | mEngine->evaluate(cmd); |
||
295 | werner | 59 | if (mEngine->hasUncaughtException()) { |
321 | werner | 60 | //int line = mEngine->uncaughtExceptionLineNumber(); |
295 | werner | 61 | QString msg = QString( "Script Error occured: %1\n").arg( mEngine->uncaughtException().toString()); |
62 | msg+=mEngine->uncaughtExceptionBacktrace().join("\n"); |
||
63 | return msg; |
||
64 | } else { |
||
216 | werner | 65 | return QString(); |
295 | werner | 66 | } |
216 | werner | 67 | } |
68 | |||
185 | werner | 69 | Management::Management() |
70 | { |
||
71 | // setup the engine |
||
72 | mEngine = new QScriptEngine(); |
||
73 | QScriptValue objectValue = mEngine->newQObject(this); |
||
216 | werner | 74 | QScriptValue dbgprint = mEngine->newFunction(script_debug); |
294 | werner | 75 | QScriptValue sinclude = mEngine->newFunction(script_include); |
76 | QScriptValue alert = mEngine->newFunction(script_alert); |
||
185 | werner | 77 | mEngine->globalObject().setProperty("management", objectValue); |
216 | werner | 78 | mEngine->globalObject().setProperty("print",dbgprint); |
294 | werner | 79 | mEngine->globalObject().setProperty("include",sinclude); |
80 | mEngine->globalObject().setProperty("alert", alert); |
||
247 | werner | 81 | |
82 | // globals object: instatiate here, but ownership goes to script engine |
||
83 | ScriptGlobal *global = new ScriptGlobal(); |
||
84 | QScriptValue glb = mEngine->newQObject(global,QScriptEngine::ScriptOwnership); |
||
85 | mEngine->globalObject().setProperty("Globals", glb); |
||
242 | werner | 86 | // other object types |
87 | ClimateConverter::addToScriptEngine(*mEngine); |
||
245 | werner | 88 | CSVFile::addToScriptEngine(*mEngine); |
216 | werner | 89 | |
247 | werner | 90 | |
185 | werner | 91 | } |
92 | |||
93 | Management::~Management() |
||
94 | { |
||
95 | delete mEngine; |
||
96 | } |
||
97 | |||
98 | void Management::loadScript(const QString &fileName) |
||
99 | { |
||
216 | werner | 100 | mScriptFile = fileName; |
185 | werner | 101 | QString program = Helper::loadTextFile(fileName); |
102 | if (program.isEmpty()) |
||
103 | return; |
||
104 | |||
105 | mEngine->evaluate(program); |
||
106 | qDebug() << "management script loaded"; |
||
107 | if (mEngine->hasUncaughtException()) |
||
108 | qDebug() << "Script Error occured: " << mEngine->uncaughtExceptionBacktrace(); |
||
109 | |||
110 | } |
||
111 | |||
112 | void Management::remain(int number) |
||
113 | { |
||
114 | qDebug() << "remain called (number): " << number; |
||
186 | werner | 115 | Model *m = GlobalSettings::instance()->model(); |
116 | AllTreeIterator at(m); |
||
117 | QList<Tree*> trees; |
||
118 | while (Tree *t=at.next()) |
||
119 | trees.push_back(t); |
||
120 | int to_kill = trees.count() - number; |
||
121 | qDebug() << trees.count() << " standing, targetsize" << number << ", hence " << to_kill << "trees to remove"; |
||
122 | for (int i=0;i<to_kill;i++) { |
||
349 | werner | 123 | int index = irandom(0, trees.count()-1); |
278 | werner | 124 | trees[index]->remove(); |
186 | werner | 125 | trees.removeAt(index); |
126 | } |
||
127 | mRemoved += to_kill; |
||
185 | werner | 128 | } |
129 | |||
130 | |||
252 | werner | 131 | void Management::kill() |
132 | { |
||
133 | for (int i=0;i<mTrees.count();i++) |
||
278 | werner | 134 | mTrees[i].first->remove(); |
252 | werner | 135 | mTrees.clear(); |
136 | } |
||
137 | |||
216 | werner | 138 | // from the range percentile range pctfrom to pctto (each 1..100) |
139 | int Management::kill(int pctfrom, int pctto, int number) |
||
140 | { |
||
141 | if (mTrees.isEmpty()) |
||
142 | return 0; |
||
143 | int index_from = limit(int(pctfrom/100. * mTrees.count()), 0, mTrees.count()); |
||
346 | werner | 144 | int index_to = limit(int(pctto/100. * mTrees.count()), 0, mTrees.count()-1); |
216 | werner | 145 | if (index_from>=index_to) |
146 | return 0; |
||
217 | werner | 147 | qDebug() << "attempting to remove" << number << "trees between indices" << index_from << "and" << index_to; |
216 | werner | 148 | int i; |
149 | int count = number; |
||
217 | werner | 150 | if (index_to-index_from <= number) { |
216 | werner | 151 | // kill all |
152 | for (i=index_from; i<index_to; i++) |
||
278 | werner | 153 | mTrees.at(i).first->remove(); |
216 | werner | 154 | count = index_to - index_from; |
155 | } else { |
||
156 | // kill randomly the provided number |
||
157 | int cancel = 1000; |
||
158 | while(number>=0) { |
||
159 | int rnd_index = irandom(index_from, index_to); |
||
160 | if (mTrees[rnd_index].first->isDead()) { |
||
161 | if (--cancel<0) { |
||
162 | qDebug() << "Management::kill: canceling search." << number << "trees left."; |
||
217 | werner | 163 | count-=number; // not all trees were killed |
216 | werner | 164 | break; |
165 | } |
||
166 | continue; |
||
167 | } |
||
168 | cancel = 1000; |
||
169 | number--; |
||
278 | werner | 170 | mTrees[rnd_index].first->remove(); |
216 | werner | 171 | } |
172 | } |
||
217 | werner | 173 | qDebug() << count << "removed."; |
216 | werner | 174 | return count; // killed |
175 | } |
||
176 | |||
185 | werner | 177 | void Management::run() |
178 | { |
||
216 | werner | 179 | mTrees.clear(); |
186 | werner | 180 | mRemoved=0; |
185 | werner | 181 | qDebug() << "Management::run() called"; |
182 | QScriptValue mgmt = mEngine->globalObject().property("manage"); |
||
183 | int year = GlobalSettings::instance()->currentYear(); |
||
184 | mgmt.call(QScriptValue(), QScriptValueList()<<year); |
||
185 | if (mEngine->hasUncaughtException()) |
||
186 | qDebug() << "Script Error occured: " << mEngine->uncaughtExceptionBacktrace(); |
||
187 | |||
186 | werner | 188 | if (mRemoved>0) { |
187 | iland | 189 | foreach(ResourceUnit *ru, GlobalSettings::instance()->model()->ruList()) |
186 | werner | 190 | ru->cleanTreeList(); |
191 | } |
||
185 | werner | 192 | } |
216 | werner | 193 | |
250 | werner | 194 | int Management::filter(QVariantList idList) |
195 | { |
||
389 | werner | 196 | QVector<int> ids; |
250 | werner | 197 | foreach(const QVariant &v, idList) |
389 | werner | 198 | if (!v.isNull()) |
199 | ids << v.toInt(); |
||
200 | // QHash<int, int> ids; |
||
201 | // foreach(const QVariant &v, idList) |
||
202 | // ids[v.toInt()] = 1; |
||
216 | werner | 203 | |
250 | werner | 204 | QList<QPair<Tree*, double> >::iterator tp=mTrees.begin(); |
205 | while (tp!=mTrees.end()) { |
||
206 | if (!ids.contains(tp->first->id()) ) |
||
207 | tp = mTrees.erase(tp); |
||
208 | else |
||
209 | tp++; |
||
210 | } |
||
389 | werner | 211 | qDebug() << "Management::filter by id-list:" << mTrees.count(); |
250 | werner | 212 | return mTrees.count(); |
213 | } |
||
214 | |||
215 | int Management::filter(QString filter) |
||
216 | { |
||
217 | TreeWrapper tw; |
||
218 | Expression expr(filter,&tw); |
||
219 | qDebug() << "filtering with" << filter; |
||
220 | QList<QPair<Tree*, double> >::iterator tp=mTrees.begin(); |
||
221 | while (tp!=mTrees.end()) { |
||
222 | tw.setTree(tp->first); |
||
420 | werner | 223 | if (!expr.calculate(tw)) |
224 | tp = mTrees.erase(tp); |
||
250 | werner | 225 | else |
226 | tp++; |
||
227 | } |
||
228 | return mTrees.count(); |
||
229 | } |
||
230 | |||
294 | werner | 231 | int Management::load(int ruindex) |
232 | { |
||
233 | Model *m = GlobalSettings::instance()->model(); |
||
234 | ResourceUnit *ru = m->ru(ruindex); |
||
235 | if (!ru) |
||
236 | return -1; |
||
237 | mTrees.clear(); |
||
238 | for (int i=0;i<ru->trees().count();i++) |
||
239 | mTrees.push_back(QPair<Tree*,double>(ru->tree(i), 0.)); |
||
240 | return mTrees.count(); |
||
241 | } |
||
242 | |||
216 | werner | 243 | int Management::load(QString filter) |
244 | { |
||
245 | TreeWrapper tw; |
||
246 | Model *m = GlobalSettings::instance()->model(); |
||
247 | mTrees.clear(); |
||
248 | AllTreeIterator at(m); |
||
249 | if (filter.isEmpty()) { |
||
250 | while (Tree *t=at.next()) |
||
251 | if (!t->isDead()) |
||
252 | mTrees.push_back(QPair<Tree*, double>(t, 0.)); |
||
253 | } else { |
||
254 | Expression expr(filter,&tw); |
||
255 | qDebug() << "filtering with" << filter; |
||
256 | while (Tree *t=at.next()) { |
||
257 | tw.setTree(t); |
||
258 | if (!t->isDead() && expr.execute()) |
||
259 | mTrees.push_back(QPair<Tree*, double>(t, 0.)); |
||
260 | } |
||
261 | } |
||
262 | return mTrees.count(); |
||
263 | } |
||
264 | |||
544 | werner | 265 | void Management::loadFromTreeList(QList<Tree*>tree_list) |
266 | { |
||
267 | mTrees.clear(); |
||
268 | for (int i=0;i<tree_list.count();++i) |
||
269 | mTrees.append(QPair<Tree*, double>(tree_list[i], 0.)); |
||
270 | } |
||
271 | |||
216 | werner | 272 | bool treePairValue(const QPair<Tree*, double> &p1, const QPair<Tree*, double> &p2) |
273 | { |
||
274 | return p1.second < p2.second; |
||
275 | } |
||
276 | |||
277 | void Management::sort(QString statement) |
||
278 | { |
||
279 | TreeWrapper tw; |
||
280 | Expression sorter(statement, &tw); |
||
281 | // fill the "value" part of the tree storage with a value for each tree |
||
282 | for (int i=0;i<mTrees.count(); ++i) { |
||
283 | tw.setTree(mTrees.at(i).first); |
||
284 | mTrees[i].second = sorter.execute(); |
||
285 | } |
||
286 | // now sort the list.... |
||
287 | qSort(mTrees.begin(), mTrees.end(), treePairValue); |
||
288 | } |
||
289 | |||
290 | double Management::percentile(int pct) |
||
291 | { |
||
292 | if (mTrees.count()==0) |
||
293 | return -1.; |
||
294 | int idx = int( (pct/100.) * mTrees.count()); |
||
295 | if (idx>=0 && idx<mTrees.count()) |
||
296 | return mTrees.at(idx).second; |
||
297 | else |
||
298 | return -1; |
||
299 | } |