Rev 216 | Rev 242 | 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 | |
10 | |||
185 | werner | 11 | #include <QtScript> |
216 | werner | 12 | #include <QTextEdit> |
13 | QObject *Management::scriptOutput = 0; |
||
185 | werner | 14 | |
216 | werner | 15 | QScriptValue script_debug(QScriptContext *ctx, QScriptEngine *eng) |
16 | { |
||
17 | QString value = ctx->argument(0).toString(); |
||
18 | if (Management::scriptOutput) { |
||
19 | QTextEdit *e = qobject_cast<QTextEdit*>(Management::scriptOutput); |
||
20 | if (e) |
||
21 | e->append(value); |
||
22 | } else { |
||
23 | qDebug() << "Script:" << value; |
||
24 | } |
||
25 | return QScriptValue(); |
||
26 | //return ctx->thisObject().property(name); |
||
27 | } |
||
186 | werner | 28 | |
216 | werner | 29 | // global output function |
30 | QString Management::executeScript(QString cmd) |
||
31 | { |
||
32 | DebugTimer t("execute javascript"); |
||
33 | if (mEngine) |
||
34 | mEngine->evaluate(cmd); |
||
35 | if (mEngine->hasUncaughtException()) |
||
36 | return QString( "Script Error occured: %1").arg( mEngine->uncaughtException().toString()); |
||
37 | else |
||
38 | return QString(); |
||
39 | } |
||
40 | |||
185 | werner | 41 | Management::Management() |
42 | { |
||
43 | // setup the engine |
||
44 | mEngine = new QScriptEngine(); |
||
45 | QScriptValue objectValue = mEngine->newQObject(this); |
||
216 | werner | 46 | QScriptValue dbgprint = mEngine->newFunction(script_debug); |
185 | werner | 47 | mEngine->globalObject().setProperty("management", objectValue); |
216 | werner | 48 | mEngine->globalObject().setProperty("print",dbgprint); |
49 | |||
185 | werner | 50 | } |
51 | |||
52 | Management::~Management() |
||
53 | { |
||
54 | delete mEngine; |
||
55 | } |
||
56 | |||
57 | void Management::loadScript(const QString &fileName) |
||
58 | { |
||
216 | werner | 59 | mScriptFile = fileName; |
185 | werner | 60 | QString program = Helper::loadTextFile(fileName); |
61 | if (program.isEmpty()) |
||
62 | return; |
||
63 | |||
64 | mEngine->evaluate(program); |
||
65 | qDebug() << "management script loaded"; |
||
66 | if (mEngine->hasUncaughtException()) |
||
67 | qDebug() << "Script Error occured: " << mEngine->uncaughtExceptionBacktrace(); |
||
68 | |||
69 | } |
||
70 | |||
71 | void Management::remain(int number) |
||
72 | { |
||
73 | qDebug() << "remain called (number): " << number; |
||
186 | werner | 74 | Model *m = GlobalSettings::instance()->model(); |
75 | AllTreeIterator at(m); |
||
76 | QList<Tree*> trees; |
||
77 | while (Tree *t=at.next()) |
||
78 | trees.push_back(t); |
||
79 | int to_kill = trees.count() - number; |
||
80 | qDebug() << trees.count() << " standing, targetsize" << number << ", hence " << to_kill << "trees to remove"; |
||
81 | for (int i=0;i<to_kill;i++) { |
||
187 | iland | 82 | int index = irandom(0, trees.count()); |
186 | werner | 83 | trees[index]->die(); |
84 | trees.removeAt(index); |
||
85 | } |
||
86 | mRemoved += to_kill; |
||
185 | werner | 87 | } |
88 | |||
89 | |||
216 | werner | 90 | // from the range percentile range pctfrom to pctto (each 1..100) |
91 | int Management::kill(int pctfrom, int pctto, int number) |
||
92 | { |
||
93 | if (mTrees.isEmpty()) |
||
94 | return 0; |
||
95 | int index_from = limit(int(pctfrom/100. * mTrees.count()), 0, mTrees.count()); |
||
96 | int index_to = limit(int(pctto/100. * mTrees.count()), 0, mTrees.count()); |
||
97 | if (index_from>=index_to) |
||
98 | return 0; |
||
217 | werner | 99 | qDebug() << "attempting to remove" << number << "trees between indices" << index_from << "and" << index_to; |
216 | werner | 100 | int i; |
101 | int count = number; |
||
217 | werner | 102 | if (index_to-index_from <= number) { |
216 | werner | 103 | // kill all |
104 | for (i=index_from; i<index_to; i++) |
||
105 | mTrees.at(i).first->die(); |
||
106 | count = index_to - index_from; |
||
107 | } else { |
||
108 | // kill randomly the provided number |
||
109 | int cancel = 1000; |
||
110 | while(number>=0) { |
||
111 | int rnd_index = irandom(index_from, index_to); |
||
112 | if (mTrees[rnd_index].first->isDead()) { |
||
113 | if (--cancel<0) { |
||
114 | qDebug() << "Management::kill: canceling search." << number << "trees left."; |
||
217 | werner | 115 | count-=number; // not all trees were killed |
216 | werner | 116 | break; |
117 | } |
||
118 | continue; |
||
119 | } |
||
120 | cancel = 1000; |
||
121 | number--; |
||
122 | mTrees[rnd_index].first->die(); |
||
123 | } |
||
124 | } |
||
217 | werner | 125 | qDebug() << count << "removed."; |
216 | werner | 126 | return count; // killed |
127 | } |
||
128 | |||
185 | werner | 129 | void Management::run() |
130 | { |
||
216 | werner | 131 | mTrees.clear(); |
186 | werner | 132 | mRemoved=0; |
185 | werner | 133 | qDebug() << "Management::run() called"; |
134 | QScriptValue mgmt = mEngine->globalObject().property("manage"); |
||
135 | int year = GlobalSettings::instance()->currentYear(); |
||
136 | mgmt.call(QScriptValue(), QScriptValueList()<<year); |
||
137 | if (mEngine->hasUncaughtException()) |
||
138 | qDebug() << "Script Error occured: " << mEngine->uncaughtExceptionBacktrace(); |
||
139 | |||
186 | werner | 140 | if (mRemoved>0) { |
187 | iland | 141 | foreach(ResourceUnit *ru, GlobalSettings::instance()->model()->ruList()) |
186 | werner | 142 | ru->cleanTreeList(); |
143 | } |
||
185 | werner | 144 | } |
216 | werner | 145 | |
146 | |||
147 | int Management::load(QString filter) |
||
148 | { |
||
149 | TreeWrapper tw; |
||
150 | Model *m = GlobalSettings::instance()->model(); |
||
151 | mTrees.clear(); |
||
152 | AllTreeIterator at(m); |
||
153 | if (filter.isEmpty()) { |
||
154 | while (Tree *t=at.next()) |
||
155 | if (!t->isDead()) |
||
156 | mTrees.push_back(QPair<Tree*, double>(t, 0.)); |
||
157 | } else { |
||
158 | Expression expr(filter,&tw); |
||
159 | qDebug() << "filtering with" << filter; |
||
160 | while (Tree *t=at.next()) { |
||
161 | tw.setTree(t); |
||
162 | if (!t->isDead() && expr.execute()) |
||
163 | mTrees.push_back(QPair<Tree*, double>(t, 0.)); |
||
164 | } |
||
165 | } |
||
166 | return mTrees.count(); |
||
167 | } |
||
168 | |||
169 | bool treePairValue(const QPair<Tree*, double> &p1, const QPair<Tree*, double> &p2) |
||
170 | { |
||
171 | return p1.second < p2.second; |
||
172 | } |
||
173 | |||
174 | void Management::sort(QString statement) |
||
175 | { |
||
176 | TreeWrapper tw; |
||
177 | Expression sorter(statement, &tw); |
||
178 | // fill the "value" part of the tree storage with a value for each tree |
||
179 | for (int i=0;i<mTrees.count(); ++i) { |
||
180 | tw.setTree(mTrees.at(i).first); |
||
181 | mTrees[i].second = sorter.execute(); |
||
182 | } |
||
183 | // now sort the list.... |
||
184 | qSort(mTrees.begin(), mTrees.end(), treePairValue); |
||
185 | } |
||
186 | |||
187 | double Management::percentile(int pct) |
||
188 | { |
||
189 | if (mTrees.count()==0) |
||
190 | return -1.; |
||
191 | int idx = int( (pct/100.) * mTrees.count()); |
||
192 | if (idx>=0 && idx<mTrees.count()) |
||
193 | return mTrees.at(idx).second; |
||
194 | else |
||
195 | return -1; |
||
196 | } |