Subversion Repositories public iLand

Rev

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