Subversion Repositories public iLand

Rev

Rev 278 | Rev 295 | 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);
59
    if (mEngine->hasUncaughtException())
60
        return QString( "Script Error occured: %1").arg( mEngine->uncaughtException().toString());
61
    else
62
        return QString();
63
}
64
 
185 werner 65
Management::Management()
66
{
67
    // setup the engine
68
    mEngine = new QScriptEngine();
69
    QScriptValue objectValue = mEngine->newQObject(this);
216 werner 70
    QScriptValue dbgprint = mEngine->newFunction(script_debug);
294 werner 71
    QScriptValue sinclude = mEngine->newFunction(script_include);
72
    QScriptValue alert = mEngine->newFunction(script_alert);
185 werner 73
    mEngine->globalObject().setProperty("management", objectValue);
216 werner 74
    mEngine->globalObject().setProperty("print",dbgprint);
294 werner 75
    mEngine->globalObject().setProperty("include",sinclude);
76
    mEngine->globalObject().setProperty("alert", alert);
247 werner 77
 
78
    // globals object: instatiate here, but ownership goes to script engine
79
    ScriptGlobal *global = new ScriptGlobal();
80
    QScriptValue glb = mEngine->newQObject(global,QScriptEngine::ScriptOwnership);
81
    mEngine->globalObject().setProperty("Globals", glb);
242 werner 82
    // other object types
83
    ClimateConverter::addToScriptEngine(*mEngine);
245 werner 84
    CSVFile::addToScriptEngine(*mEngine);
216 werner 85
 
247 werner 86
 
185 werner 87
}
88
 
89
Management::~Management()
90
{
91
    delete mEngine;
92
}
93
 
94
void Management::loadScript(const QString &fileName)
95
{
216 werner 96
    mScriptFile = fileName;
185 werner 97
    QString program = Helper::loadTextFile(fileName);
98
    if (program.isEmpty())
99
        return;
100
 
101
    mEngine->evaluate(program);
102
    qDebug() << "management script loaded";
103
    if (mEngine->hasUncaughtException())
104
        qDebug() << "Script Error occured: " << mEngine->uncaughtExceptionBacktrace();
105
 
106
}
107
 
108
void Management::remain(int number)
109
{
110
    qDebug() << "remain called (number): " << number;
186 werner 111
    Model *m = GlobalSettings::instance()->model();
112
    AllTreeIterator at(m);
113
    QList<Tree*> trees;
114
    while (Tree *t=at.next())
115
        trees.push_back(t);
116
    int to_kill = trees.count() - number;
117
    qDebug() << trees.count() << " standing, targetsize" << number << ", hence " << to_kill << "trees to remove";
118
    for (int i=0;i<to_kill;i++) {
187 iland 119
        int index = irandom(0, trees.count());
278 werner 120
        trees[index]->remove();
186 werner 121
        trees.removeAt(index);
122
    }
123
    mRemoved += to_kill;
185 werner 124
}
125
 
126
 
252 werner 127
void Management::kill()
128
{
129
    for (int i=0;i<mTrees.count();i++)
278 werner 130
        mTrees[i].first->remove();
252 werner 131
    mTrees.clear();
132
}
133
 
216 werner 134
// from the range percentile range pctfrom to pctto (each 1..100)
135
int Management::kill(int pctfrom, int pctto, int number)
136
{
137
    if (mTrees.isEmpty())
138
        return 0;
139
    int index_from = limit(int(pctfrom/100. * mTrees.count()), 0, mTrees.count());
140
    int index_to = limit(int(pctto/100. * mTrees.count()), 0, mTrees.count());
141
    if (index_from>=index_to)
142
        return 0;
217 werner 143
    qDebug() << "attempting to remove" << number << "trees between indices" << index_from << "and" << index_to;
216 werner 144
    int i;
145
    int count = number;
217 werner 146
    if (index_to-index_from <= number)  {
216 werner 147
        // kill all
148
        for (i=index_from; i<index_to; i++)
278 werner 149
            mTrees.at(i).first->remove();
216 werner 150
        count = index_to - index_from;
151
    } else {
152
        // kill randomly the provided number
153
        int cancel = 1000;
154
        while(number>=0) {
155
            int rnd_index = irandom(index_from, index_to);
156
            if (mTrees[rnd_index].first->isDead()) {
157
                if (--cancel<0) {
158
                    qDebug() << "Management::kill: canceling search." << number << "trees left.";
217 werner 159
                    count-=number; // not all trees were killed
216 werner 160
                    break;
161
                }
162
                continue;
163
            }
164
            cancel = 1000;
165
            number--;
278 werner 166
            mTrees[rnd_index].first->remove();
216 werner 167
        }
168
    }
217 werner 169
    qDebug() << count << "removed.";
216 werner 170
    return count; // killed
171
}
172
 
185 werner 173
void Management::run()
174
{
216 werner 175
    mTrees.clear();
186 werner 176
    mRemoved=0;
185 werner 177
    qDebug() << "Management::run() called";
178
    QScriptValue mgmt = mEngine->globalObject().property("manage");
179
    int year = GlobalSettings::instance()->currentYear();
180
    mgmt.call(QScriptValue(), QScriptValueList()<<year);
181
    if (mEngine->hasUncaughtException())
182
        qDebug() << "Script Error occured: " << mEngine->uncaughtExceptionBacktrace();
183
 
186 werner 184
    if (mRemoved>0) {
187 iland 185
        foreach(ResourceUnit *ru, GlobalSettings::instance()->model()->ruList())
186 werner 186
           ru->cleanTreeList();
187
   }
185 werner 188
}
216 werner 189
 
250 werner 190
int Management::filter(QVariantList idList)
191
{
192
    QHash<int, int> ids;
193
    foreach(const QVariant &v, idList)
194
        ids[v.toInt()] = 1;
216 werner 195
 
250 werner 196
    QList<QPair<Tree*, double> >::iterator tp=mTrees.begin();
197
    while (tp!=mTrees.end()) {
198
        if (!ids.contains(tp->first->id()) )
199
            tp = mTrees.erase(tp);
200
        else
201
            tp++;
202
    }
203
    return mTrees.count();
204
}
205
 
206
int Management::filter(QString filter)
207
{
208
    TreeWrapper tw;
209
    Expression expr(filter,&tw);
210
    qDebug() << "filtering with" << filter;
211
    QList<QPair<Tree*, double> >::iterator tp=mTrees.begin();
212
    while (tp!=mTrees.end()) {
213
        tw.setTree(tp->first);
214
        if (!expr.execute())
215
             tp = mTrees.erase(tp);
216
        else
217
            tp++;
218
    }
219
    return mTrees.count();
220
}
221
 
294 werner 222
int Management::load(int ruindex)
223
{
224
    Model *m = GlobalSettings::instance()->model();
225
    ResourceUnit *ru = m->ru(ruindex);
226
    if (!ru)
227
        return -1;
228
    mTrees.clear();
229
    for (int i=0;i<ru->trees().count();i++)
230
        mTrees.push_back(QPair<Tree*,double>(ru->tree(i), 0.));
231
    return mTrees.count();
232
}
233
 
216 werner 234
int Management::load(QString filter)
235
{
236
    TreeWrapper tw;
237
    Model *m = GlobalSettings::instance()->model();
238
    mTrees.clear();
239
    AllTreeIterator at(m);
240
    if (filter.isEmpty()) {
241
        while (Tree *t=at.next())
242
            if (!t->isDead())
243
                mTrees.push_back(QPair<Tree*, double>(t, 0.));
244
    } else {
245
        Expression expr(filter,&tw);
246
        qDebug() << "filtering with" << filter;
247
        while (Tree *t=at.next()) {
248
            tw.setTree(t);
249
            if (!t->isDead() && expr.execute())
250
                mTrees.push_back(QPair<Tree*, double>(t, 0.));
251
        }
252
    }
253
    return mTrees.count();
254
}
255
 
256
bool treePairValue(const QPair<Tree*, double> &p1, const QPair<Tree*, double> &p2)
257
{
258
    return p1.second < p2.second;
259
}
260
 
261
void Management::sort(QString statement)
262
{
263
    TreeWrapper tw;
264
    Expression sorter(statement, &tw);
265
    // fill the "value" part of the tree storage with a value for each tree
266
    for (int i=0;i<mTrees.count(); ++i) {
267
        tw.setTree(mTrees.at(i).first);
268
        mTrees[i].second = sorter.execute();
269
   }
270
   // now sort the list....
271
   qSort(mTrees.begin(), mTrees.end(), treePairValue);
272
}
273
 
274
double Management::percentile(int pct)
275
{
276
    if (mTrees.count()==0)
277
        return -1.;
278
    int idx = int( (pct/100.) * mTrees.count());
279
    if (idx>=0 && idx<mTrees.count())
280
        return mTrees.at(idx).second;
281
    else
282
        return -1;
283
}