Subversion Repositories public iLand

Rev

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