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