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