Subversion Repositories public iLand

Rev

Rev 1034 | Rev 1066 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1034 Rev 1061
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/modelcontroller.cpp':
1
Redirecting to URL 'https://iland.boku.ac.at/svn/iland/tags/release_1.0/src/core/modelcontroller.cpp':
2
/********************************************************************************************
2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
6
**
7
**    This program is free software: you can redistribute it and/or modify
7
**    This program is free software: you can redistribute it and/or modify
8
**    it under the terms of the GNU General Public License as published by
8
**    it under the terms of the GNU General Public License as published by
9
**    the Free Software Foundation, either version 3 of the License, or
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
10
**    (at your option) any later version.
11
**
11
**
12
**    This program is distributed in the hope that it will be useful,
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
15
**    GNU General Public License for more details.
16
**
16
**
17
**    You should have received a copy of the GNU General Public License
17
**    You should have received a copy of the GNU General Public License
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
********************************************************************************************/
19
********************************************************************************************/
20
20
21
/** ModelController is a helper class used to control the flow of operations during a model run.
21
/** ModelController is a helper class used to control the flow of operations during a model run.
22
  The ModelController encapsulates the Model class and is the main control unit. It is used by the
22
  The ModelController encapsulates the Model class and is the main control unit. It is used by the
23
  iLand GUI as well as the command line version (ilandc).
23
  iLand GUI as well as the command line version (ilandc).
24

24

25
  */
25
  */
26
26
27
#include "global.h"
27
#include "global.h"
28
#include "modelcontroller.h"
28
#include "modelcontroller.h"
29
#include <QObject>
29
#include <QObject>
30
30
31
#include "model.h"
31
#include "model.h"
32
#include "debugtimer.h"
32
#include "debugtimer.h"
33
#include "helper.h"
33
#include "helper.h"
34
#include "expression.h"
34
#include "expression.h"
35
#include "expressionwrapper.h"
35
#include "expressionwrapper.h"
36
#include "../output/outputmanager.h"
36
#include "../output/outputmanager.h"
37
37
38
#include "species.h"
38
#include "species.h"
39
#include "speciesset.h"
39
#include "speciesset.h"
40
#include "mapgrid.h"
40
#include "mapgrid.h"
41
#include "statdata.h"
41
#include "statdata.h"
42
42
43
#ifdef ILAND_GUI
43
#ifdef ILAND_GUI
44
#include "mainwindow.h" // for the debug message buffering
44
#include "mainwindow.h" // for the debug message buffering
45
#endif
45
#endif
46
46
47
ModelController::ModelController()
47
ModelController::ModelController()
48
{
48
{
49
    mModel = NULL;
49
    mModel = NULL;
50
    mPaused = false;
50
    mPaused = false;
51
    mRunning = false;
51
    mRunning = false;
52
    mHasError = false;
52
    mHasError = false;
53
    mYearsToRun = 0;
53
    mYearsToRun = 0;
54
    mViewerWindow = 0;
54
    mViewerWindow = 0;
55
    mDynamicOutputEnabled = false;
55
    mDynamicOutputEnabled = false;
56
}
56
}
57
57
58
ModelController::~ModelController()
58
ModelController::~ModelController()
59
{
59
{
60
    destroy();
60
    destroy();
61
}
61
}
62
62
63
void ModelController::connectSignals()
63
void ModelController::connectSignals()
64
{
64
{
65
    if (!mViewerWindow)
65
    if (!mViewerWindow)
66
        return;
66
        return;
67
#ifdef ILAND_GUI
67
#ifdef ILAND_GUI
68
    connect(this,SIGNAL(bufferLogs(bool)), mViewerWindow, SLOT(bufferedLog(bool)));
68
    connect(this,SIGNAL(bufferLogs(bool)), mViewerWindow, SLOT(bufferedLog(bool)));
69
#endif
69
#endif
70
}
70
}
71
71
72
/// prepare a list of all (active) species
72
/// prepare a list of all (active) species
73
QHash<QString, QString> ModelController::availableSpecies()
73
QHash<QString, QString> ModelController::availableSpecies()
74
{
74
{
75
    QHash<QString, QString> list;
75
    QHash<QString, QString> list;
76
    if (mModel) {
76
    if (mModel) {
77
        SpeciesSet *set = mModel->speciesSet();
77
        SpeciesSet *set = mModel->speciesSet();
78
        if (!set)
78
        if (!set)
79
            throw IException("there are 0 or more than one species sets.");
79
            throw IException("there are 0 or more than one species sets.");
80
        foreach (const Species *s, set->activeSpecies()) {
80
        foreach (const Species *s, set->activeSpecies()) {
81
            list[s->id()] = s->name();
81
            list[s->id()] = s->name();
82
        }
82
        }
83
    }
83
    }
84
    return list;
84
    return list;
85
}
85
}
86
86
87
bool ModelController::canCreate()
87
bool ModelController::canCreate()
88
{
88
{
89
    if (mModel)
89
    if (mModel)
90
        return false;
90
        return false;
91
    return true;
91
    return true;
92
}
92
}
93
93
94
bool ModelController::canDestroy()
94
bool ModelController::canDestroy()
95
{
95
{
96
    return mModel != NULL;
96
    return mModel != NULL;
97
}
97
}
98
98
99
bool ModelController::canRun()
99
bool ModelController::canRun()
100
{
100
{
101
    if (mModel && mModel->isSetup())
101
    if (mModel && mModel->isSetup())
102
        return true;
102
        return true;
103
    return false;
103
    return false;
104
}
104
}
105
105
106
bool ModelController::isRunning()
106
bool ModelController::isRunning()
107
{
107
{
108
    return mRunning;
108
    return mRunning;
109
}
109
}
110
110
111
bool ModelController::isFinished()
111
bool ModelController::isFinished()
112
{
112
{
113
    if (!mModel)
113
    if (!mModel)
114
        return false;
114
        return false;
115
    return canRun() && !isRunning()  && mFinished;
115
    return canRun() && !isRunning()  && mFinished;
116
}
116
}
117
117
118
bool ModelController::isPaused()
118
bool ModelController::isPaused()
119
{
119
{
120
    return mPaused;
120
    return mPaused;
121
}
121
}
122
122
123
int ModelController::currentYear() const
123
int ModelController::currentYear() const
124
{
124
{
125
    return GlobalSettings::instance()->currentYear();
125
    return GlobalSettings::instance()->currentYear();
126
}
126
}
127
127
128
void ModelController::setFileName(QString initFileName)
128
void ModelController::setFileName(QString initFileName)
129
{
129
{
130
    mInitFile = initFileName;
130
    mInitFile = initFileName;
131
    try {
131
    try {
132
        GlobalSettings::instance()->loadProjectFile(mInitFile);
132
        GlobalSettings::instance()->loadProjectFile(mInitFile);
133
    } catch(const IException &e) {
133
    } catch(const IException &e) {
134
        QString error_msg = e.message();
134
        QString error_msg = e.message();
135
        Helper::msg(error_msg);
135
        Helper::msg(error_msg);
136
        mHasError = true;
136
        mHasError = true;
137
        mLastError = error_msg;
137
        mLastError = error_msg;
138
        qDebug() << error_msg;
138
        qDebug() << error_msg;
139
    }
139
    }
140
}
140
}
141
141
142
void ModelController::create()
142
void ModelController::create()
143
{
143
{
144
    if (!canCreate())
144
    if (!canCreate())
145
        return;
145
        return;
146
    emit bufferLogs(true);
146
    emit bufferLogs(true);
147
147
148
    try {
148
    try {
149
        mHasError = false;
149
        mHasError = false;
150
        DebugTimer::clearAllTimers();
150
        DebugTimer::clearAllTimers();
151
        mModel = new Model();
151
        mModel = new Model();
152
        mModel->loadProject();
152
        mModel->loadProject();
153
        if (!mModel->isSetup()) {
153
        if (!mModel->isSetup()) {
154
            mHasError = true;
154
            mHasError = true;
155
            mLastError = "An error occured during the loading of the project. Please check the logs.";
155
            mLastError = "An error occured during the loading of the project. Please check the logs.";
156
            return;
156
            return;
157
        }
157
        }
158
158
159
        // reset clock...
159
        // reset clock...
160
        GlobalSettings::instance()->setCurrentYear(1); // reset clock
160
        GlobalSettings::instance()->setCurrentYear(1); // reset clock
161
        // initialization of trees, output on startup
161
        // initialization of trees, output on startup
162
        mModel->beforeRun();
162
        mModel->beforeRun();
163
    } catch(const IException &e) {
163
    } catch(const IException &e) {
164
        QString error_msg = e.message();
164
        QString error_msg = e.message();
165
        Helper::msg(error_msg);
165
        Helper::msg(error_msg);
166
        mLastError = error_msg;
166
        mLastError = error_msg;
167
        mHasError = true;
167
        mHasError = true;
168
        qDebug() << error_msg;
168
        qDebug() << error_msg;
169
    }
169
    }
170
    emit bufferLogs(false);
170
    emit bufferLogs(false);
171
171
172
    qDebug() << "Model created.";
172
    qDebug() << "Model created.";
173
}
173
}
174
174
175
void ModelController::destroy()
175
void ModelController::destroy()
176
{
176
{
177
    if (canDestroy()) {
177
    if (canDestroy()) {
178
        Model *m = mModel;
178
        Model *m = mModel;
179
        mModel = 0;
179
        mModel = 0;
180
        delete m;
180
        delete m;
181
        GlobalSettings::instance()->setCurrentYear(0);
181
        GlobalSettings::instance()->setCurrentYear(0);
182
        qDebug() << "ModelController: Model destroyed.";
182
        qDebug() << "ModelController: Model destroyed.";
183
    }
183
    }
184
}
184
}
185
185
186
void ModelController::runloop()
186
void ModelController::runloop()
187
{
187
{
188
    static QTime sLastTime = QTime::currentTime();
188
    static QTime sLastTime = QTime::currentTime();
189
#ifdef ILAND_GUI
189
#ifdef ILAND_GUI
190
 //   QApplication::processEvents();
190
 //   QApplication::processEvents();
191
#else
191
#else
192
 //   QCoreApplication::processEvents();
192
 //   QCoreApplication::processEvents();
193
#endif
193
#endif
194
    if (mPaused)
194
    if (mPaused)
195
        return;
195
        return;
196
    bool doStop = false;
196
    bool doStop = false;
197
    mHasError = false;
197
    mHasError = false;
198
    if (GlobalSettings::instance()->currentYear()<=1) {
198
    if (GlobalSettings::instance()->currentYear()<=1) {
199
        sLastTime = QTime::currentTime(); // reset clock at the beginning of the simulation
199
        sLastTime = QTime::currentTime(); // reset clock at the beginning of the simulation
200
    }
200
    }
201
201
202
    if (!mCanceled && GlobalSettings::instance()->currentYear() < mYearsToRun) {
202
    if (!mCanceled && GlobalSettings::instance()->currentYear() < mYearsToRun) {
203
        emit bufferLogs(true);
203
        emit bufferLogs(true);
204
204
205
        mHasError = runYear(); // do the work!
205
        mHasError = runYear(); // do the work!
206
206
207
        mRunning = true;
207
        mRunning = true;
208
        emit year(GlobalSettings::instance()->currentYear());
208
        emit year(GlobalSettings::instance()->currentYear());
209
        if (!mHasError) {
209
        if (!mHasError) {
210
            int elapsed = sLastTime.msecsTo(QTime::currentTime());
210
            int elapsed = sLastTime.msecsTo(QTime::currentTime());
211
            int time=0;
211
            int time=0;
212
            if (currentYear()%50==0 && elapsed>10000)
212
            if (currentYear()%50==0 && elapsed>10000)
213
                time = 100; // a 100ms pause...
213
                time = 100; // a 100ms pause...
214
            if (currentYear()%100==0 && elapsed>10000) {
214
            if (currentYear()%100==0 && elapsed>10000) {
215
                time = 500; // a 500ms pause...
215
                time = 500; // a 500ms pause...
216
            }
216
            }
217
            if (time>0) {
217
            if (time>0) {
218
                sLastTime = QTime::currentTime(); // reset clock
218
                sLastTime = QTime::currentTime(); // reset clock
219
                qDebug() << "--- little break ---- (after " << elapsed << "ms).";
219
                qDebug() << "--- little break ---- (after " << elapsed << "ms).";
220
                //QTimer::singleShot(time,this, SLOT(runloop()));
220
                //QTimer::singleShot(time,this, SLOT(runloop()));
221
            }
221
            }
222
222
223
        } else {
223
        } else {
224
           doStop = true; // an error occured
224
           doStop = true; // an error occured
225
           mLastError = "An error occured while running the model. Please check the logs.";
225
           mLastError = "An error occured while running the model. Please check the logs.";
226
           mHasError = true;
226
           mHasError = true;
227
        }
227
        }
228
228
229
    } else {
229
    } else {
230
        doStop = true; // all years simulated
230
        doStop = true; // all years simulated
231
    }
231
    }
232
232
233
    if (doStop || mCanceled) {
233
    if (doStop || mCanceled) {
234
                // finished
234
                // finished
235
        internalStop();
235
        internalStop();
236
    }
236
    }
237
237
238
#ifdef ILAND_GUI
238
#ifdef ILAND_GUI
239
    QApplication::processEvents();
239
    QApplication::processEvents();
240
#else
240
#else
241
    QCoreApplication::processEvents();
241
    QCoreApplication::processEvents();
242
#endif
242
#endif
243
}
243
}
244
244
245
bool ModelController::internalRun()
245
bool ModelController::internalRun()
246
{
246
{
247
    // main loop
247
    // main loop
248
    try {
248
    try {
249
        while (mRunning && !mPaused &&  !mFinished) {
249
        while (mRunning && !mPaused &&  !mFinished) {
250
            runloop(); // start the running loop
250
            runloop(); // start the running loop
251
        }
251
        }
252
    } catch (IException &e) {
252
    } catch (IException &e) {
253
#ifdef ILAND_GUI
253
#ifdef ILAND_GUI
254
        Helper::msg(e.message());
254
        Helper::msg(e.message());
255
#else
255
#else
256
        qDebug() << e.message();
256
        qDebug() << e.message();
257
#endif
257
#endif
258
258
259
    }
259
    }
260
260
261
    return isFinished();
261
    return isFinished();
262
}
262
}
263
263
264
void ModelController::internalStop()
264
void ModelController::internalStop()
265
{
265
{
266
    if (mRunning) {
266
    if (mRunning) {
267
        GlobalSettings::instance()->outputManager()->save();
267
        GlobalSettings::instance()->outputManager()->save();
268
        DebugTimer::printAllTimers();
268
        DebugTimer::printAllTimers();
269
        mFinished = true;
269
        mFinished = true;
270
    }
270
    }
271
    mRunning = false;
271
    mRunning = false;
272
    mPaused = false; // in any case
272
    mPaused = false; // in any case
273
    emit bufferLogs(false); // stop buffering
273
    emit bufferLogs(false); // stop buffering
274
    emit finished(QString());
274
    emit finished(QString());
275
    emit stateChanged();
275
    emit stateChanged();
276
276
277
}
277
}
278
278
279
void ModelController::run(int years)
279
void ModelController::run(int years)
280
{
280
{
281
    if (!canRun())
281
    if (!canRun())
282
        return;
282
        return;
283
    emit bufferLogs(true); // start buffering
283
    emit bufferLogs(true); // start buffering
284
284
285
    DebugTimer many_runs(QString("Timer for %1 runs").arg(years));
285
    DebugTimer many_runs(QString("Timer for %1 runs").arg(years));
286
    mPaused = false;
286
    mPaused = false;
287
    mFinished = false;
287
    mFinished = false;
288
    mCanceled = false;
288
    mCanceled = false;
289
    mYearsToRun = years;
289
    mYearsToRun = years;
290
    //GlobalSettings::instance()->setCurrentYear(1); // reset clock
290
    //GlobalSettings::instance()->setCurrentYear(1); // reset clock
291
291
292
    DebugTimer::clearAllTimers();
292
    DebugTimer::clearAllTimers();
293
293
294
    mRunning = true;
294
    mRunning = true;
295
    emit stateChanged();
295
    emit stateChanged();
296
296
297
    qDebug() << "ModelControler: runloop started.";
297
    qDebug() << "ModelControler: runloop started.";
298
    internalRun();
298
    internalRun();
299
    emit stateChanged();
299
    emit stateChanged();
300
}
300
}
301
301
302
bool ModelController::runYear()
302
bool ModelController::runYear()
303
{
303
{
304
    if (!canRun()) return false;
304
    if (!canRun()) return false;
305
    DebugTimer t("ModelController:runYear");
305
    DebugTimer t("ModelController:runYear");
306
    qDebug() << "ModelController: run year" << currentYear();
306
    qDebug() << "ModelController: run year" << currentYear();
307
307
308
    if (GlobalSettings::instance()->settings().paramValueBool("debug_clear"))
308
    if (GlobalSettings::instance()->settings().paramValueBool("debug_clear"))
309
        GlobalSettings::instance()->clearDebugLists();  // clear debug data
309
        GlobalSettings::instance()->clearDebugLists();  // clear debug data
310
    bool err=false;
310
    bool err=false;
311
    try {
311
    try {
312
        emit bufferLogs(true);
312
        emit bufferLogs(true);
313
        mModel->runYear();
313
        mModel->runYear();
314
        fetchDynamicOutput();
314
        fetchDynamicOutput();
315
    } catch(const IException &e) {
315
    } catch(const IException &e) {
316
        QString error_msg = e.message();
316
        QString error_msg = e.message();
317
        Helper::msg(error_msg);
317
        Helper::msg(error_msg);
318
        qDebug() << error_msg;
318
        qDebug() << error_msg;
319
        err=true;
319
        err=true;
320
    }
320
    }
321
    emit bufferLogs(false);
321
    emit bufferLogs(false);
322
    return err;
322
    return err;
323
}
323
}
324
324
325
bool ModelController::pause()
325
bool ModelController::pause()
326
{
326
{
327
    if(!isRunning())
327
    if(!isRunning())
328
        return mPaused;
328
        return mPaused;
329
329
330
    if (mPaused) {
330
    if (mPaused) {
331
        // currently in pause - mode -> continue
331
        // currently in pause - mode -> continue
332
        mPaused = false;
332
        mPaused = false;
333
333
334
    } else {
334
    } else {
335
        // currently running -> set to pause mode
335
        // currently running -> set to pause mode
336
        GlobalSettings::instance()->outputManager()->save();
336
        GlobalSettings::instance()->outputManager()->save();
337
        mPaused = true;
337
        mPaused = true;
338
        emit bufferLogs(false);
338
        emit bufferLogs(false);
339
    }
339
    }
340
    emit stateChanged();
340
    emit stateChanged();
341
    return mPaused;
341
    return mPaused;
342
}
342
}
343
343
344
bool ModelController::continueRun()
344
bool ModelController::continueRun()
345
{
345
{
346
    mRunning = true;
346
    mRunning = true;
347
    emit stateChanged();
347
    emit stateChanged();
348
    return internalRun();
348
    return internalRun();
349
}
349
}
350
350
351
void ModelController::cancel()
351
void ModelController::cancel()
352
{
352
{
353
    mCanceled = true;
353
    mCanceled = true;
354
    internalStop();
354
    internalStop();
355
    emit stateChanged();
355
    emit stateChanged();
356
}
356
}
357
357
358
358
359
// this function is called when exceptions occur in multithreaded code.
359
// this function is called when exceptions occur in multithreaded code.
360
QMutex error_mutex;
360
QMutex error_mutex;
361
void ModelController::throwError(const QString msg)
361
void ModelController::throwError(const QString msg)
362
{
362
{
363
    QMutexLocker lock(&error_mutex); // serialize access
363
    QMutexLocker lock(&error_mutex); // serialize access
364
    qDebug() << "ModelController: throwError reached:";
364
    qDebug() << "ModelController: throwError reached:";
365
    qDebug() << msg;
365
    qDebug() << msg;
366
    mLastError = msg;
366
    mLastError = msg;
367
    mHasError = true;
367
    mHasError = true;
368
    emit bufferLogs(false);
368
    emit bufferLogs(false);
369
    emit bufferLogs(true); // start buffering again
369
    emit bufferLogs(true); // start buffering again
370
370
371
    emit finished(msg);
371
    emit finished(msg);
372
    throw IException(msg); // raise error again
372
    throw IException(msg); // raise error again
373
373
374
}
374
}
375
//////////////////////////////////////
375
//////////////////////////////////////
376
// dynamic outut
376
// dynamic outut
377
//////////////////////////////////////
377
//////////////////////////////////////
378
//////////////////////////////////////
378
//////////////////////////////////////
379
void ModelController::setupDynamicOutput(QString fieldList)
379
void ModelController::setupDynamicOutput(QString fieldList)
380
{
380
{
381
    mDynFieldList.clear();
381
    mDynFieldList.clear();
382
    if (!fieldList.isEmpty()) {
382
    if (!fieldList.isEmpty()) {
383
        QRegExp rx("((?:\\[.+\\]|\\w+)\\.\\w+)");
383
        QRegExp rx("((?:\\[.+\\]|\\w+)\\.\\w+)");
384
        int pos=0;
384
        int pos=0;
385
        while ((pos = rx.indexIn(fieldList, pos)) != -1) {
385
        while ((pos = rx.indexIn(fieldList, pos)) != -1) {
386
            mDynFieldList.append(rx.cap(1));
386
            mDynFieldList.append(rx.cap(1));
387
            pos += rx.matchedLength();
387
            pos += rx.matchedLength();
388
        }
388
        }
389
389
390
        //mDynFieldList = fieldList.split(QRegExp("(?:\\[.+\\]|\\w+)\\.\\w+"), QString::SkipEmptyParts);
390
        //mDynFieldList = fieldList.split(QRegExp("(?:\\[.+\\]|\\w+)\\.\\w+"), QString::SkipEmptyParts);
391
        mDynFieldList.prepend("count");
391
        mDynFieldList.prepend("count");
392
        mDynFieldList.prepend("year"); // fixed fields.
392
        mDynFieldList.prepend("year"); // fixed fields.
393
    }
393
    }
394
    mDynData.clear();
394
    mDynData.clear();
395
    mDynData.append(mDynFieldList.join(";"));
395
    mDynData.append(mDynFieldList.join(";"));
396
    mDynamicOutputEnabled = true;
396
    mDynamicOutputEnabled = true;
397
}
397
}
398
398
399
QString ModelController::dynamicOutput()
399
QString ModelController::dynamicOutput()
400
{
400
{
401
    return mDynData.join("\n");
401
    return mDynData.join("\n");
402
}
402
}
403
403
404
const QStringList aggList = QStringList() << "mean" << "sum" << "min" << "max" << "p25" << "p50" << "p75" << "p5"<< "p10" << "p90" << "p95";
404
const QStringList aggList = QStringList() << "mean" << "sum" << "min" << "max" << "p25" << "p50" << "p75" << "p5"<< "p10" << "p90" << "p95";
405
void ModelController::fetchDynamicOutput()
405
void ModelController::fetchDynamicOutput()
406
{
406
{
407
    if (!mDynamicOutputEnabled || mDynFieldList.isEmpty())
407
    if (!mDynamicOutputEnabled || mDynFieldList.isEmpty())
408
        return;
408
        return;
409
    DebugTimer t("dynamic output");
409
    DebugTimer t("dynamic output");
410
    QStringList var;
410
    QStringList var;
411
    QString lastVar = "";
411
    QString lastVar = "";
412
    QVector<double> data;
412
    QVector<double> data;
413
    AllTreeIterator at(mModel);
413
    AllTreeIterator at(mModel);
414
    TreeWrapper tw;
414
    TreeWrapper tw;
415
    int var_index;
415
    int var_index;
416
    StatData stat;
416
    StatData stat;
417
    double value;
417
    double value;
418
    QStringList line;
418
    QStringList line;
419
    Expression custom_expr;
419
    Expression custom_expr;
420
    bool simple_expression;
420
    bool simple_expression;
421
    foreach (QString field, mDynFieldList) {
421
    foreach (QString field, mDynFieldList) {
422
        if (field=="count" || field=="year")
422
        if (field=="count" || field=="year")
423
            continue;
423
            continue;
424
        if (field.count()>0 && field.at(0)=='[') {
424
        if (field.count()>0 && field.at(0)=='[') {
425
            QRegExp rex("\\[(.+)\\]\\.(\\w+)");
425
            QRegExp rex("\\[(.+)\\]\\.(\\w+)");
426
            rex.indexIn(field);
426
            rex.indexIn(field);
427
            var = rex.capturedTexts();
427
            var = rex.capturedTexts();
428
            var.pop_front(); // drop first element (contains the full string)
428
            var.pop_front(); // drop first element (contains the full string)
429
            simple_expression = false;
429
            simple_expression = false;
430
        } else {
430
        } else {
431
            var = field.split(QRegExp("\\W+"), QString::SkipEmptyParts);
431
            var = field.split(QRegExp("\\W+"), QString::SkipEmptyParts);
432
            simple_expression = true;
432
            simple_expression = true;
433
        }
433
        }
434
        if (var.count()!=2)
434
        if (var.count()!=2)
435
                throw IException(QString("Invalid variable name for dynamic output:") + field);
435
                throw IException(QString("Invalid variable name for dynamic output:") + field);
436
        if (var.first()!=lastVar) {
436
        if (var.first()!=lastVar) {
437
            // load new field
437
            // load new field
438
            data.clear();
438
            data.clear();
439
            at.reset(); var_index = 0;
439
            at.reset(); var_index = 0;
440
            if (simple_expression) {
440
            if (simple_expression) {
441
                var_index = tw.variableIndex(var.first());
441
                var_index = tw.variableIndex(var.first());
442
                if (var_index<0)
442
                if (var_index<0)
443
                    throw IException(QString("Invalid variable name for dynamic output:") + var.first());
443
                    throw IException(QString("Invalid variable name for dynamic output:") + var.first());
444
444
445
            } else {
445
            } else {
446
                custom_expr.setExpression(var.first());
446
                custom_expr.setExpression(var.first());
447
                custom_expr.setModelObject(&tw);
447
                custom_expr.setModelObject(&tw);
448
            }
448
            }
449
            while (Tree *t = at.next()) {
449
            while (Tree *t = at.next()) {
450
                tw.setTree(t);
450
                tw.setTree(t);
451
                if (simple_expression)
451
                if (simple_expression)
452
                    value = tw.value(var_index);
452
                    value = tw.value(var_index);
453
                else
453
                else
454
                    value = custom_expr.execute();
454
                    value = custom_expr.execute();
455
                data.push_back(value);
455
                data.push_back(value);
456
            }
456
            }
457
            stat.setData(data);
457
            stat.setData(data);
458
        }
458
        }
459
        // fetch data
459
        // fetch data
460
        var_index = aggList.indexOf(var[1]);
460
        var_index = aggList.indexOf(var[1]);
461
        switch (var_index) {
461
        switch (var_index) {
462
            case 0: value = stat.mean(); break;
462
            case 0: value = stat.mean(); break;
463
            case 1: value = stat.sum(); break;
463
            case 1: value = stat.sum(); break;
464
            case 2: value = stat.min(); break;
464
            case 2: value = stat.min(); break;
465
            case 3: value = stat.max(); break;
465
            case 3: value = stat.max(); break;
466
            case 4: value = stat.percentile25(); break;
466
            case 4: value = stat.percentile25(); break;
467
            case 5: value = stat.median(); break;
467
            case 5: value = stat.median(); break;
468
            case 6: value = stat.percentile75(); break;
468
            case 6: value = stat.percentile75(); break;
469
            case 7: value = stat.percentile(5); break;
469
            case 7: value = stat.percentile(5); break;
470
            case 8: value = stat.percentile(10); break;
470
            case 8: value = stat.percentile(10); break;
471
            case 9: value = stat.percentile(90); break;
471
            case 9: value = stat.percentile(90); break;
472
            case 10: value = stat.percentile(95); break;
472
            case 10: value = stat.percentile(95); break;
473
            default: throw IException(QString("Invalid aggregate expression for dynamic output: %1\nallowed:%2")
473
            default: throw IException(QString("Invalid aggregate expression for dynamic output: %1\nallowed:%2")
474
                                  .arg(var[1]).arg(aggList.join(" ")));
474
                                  .arg(var[1]).arg(aggList.join(" ")));
475
        }
475
        }
476
        line+=QString::number(value);
476
        line+=QString::number(value);
477
    }
477
    }
478
    line.prepend( QString::number(data.size()) );
478
    line.prepend( QString::number(data.size()) );
479
    line.prepend( QString::number(GlobalSettings::instance()->currentYear()) );
479
    line.prepend( QString::number(GlobalSettings::instance()->currentYear()) );
480
    mDynData.append(line.join(";"));
480
    mDynData.append(line.join(";"));
481
}
481
}
482
482
483
void ModelController::saveScreenshot(QString file_name)
483
void ModelController::saveScreenshot(QString file_name)
484
{
484
{
485
#ifdef ILAND_GUI
485
#ifdef ILAND_GUI
486
    if (!mViewerWindow)
486
    if (!mViewerWindow)
487
        return;
487
        return;
488
    QImage img = mViewerWindow->screenshot();
488
    QImage img = mViewerWindow->screenshot();
489
    img.save(file_name);
489
    img.save(file_name);
490
#else
490
#else
491
    Q_UNUSED(file_name);
491
    Q_UNUSED(file_name);
492
#endif
492
#endif
493
}
493
}
494
494
495
void ModelController::paintMap(MapGrid *map, double min_value, double max_value)
495
void ModelController::paintMap(MapGrid *map, double min_value, double max_value)
496
{
496
{
497
#ifdef ILAND_GUI
497
#ifdef ILAND_GUI
498
    if (mViewerWindow) {
498
    if (mViewerWindow) {
499
        mViewerWindow->paintGrid(map, "", GridViewRainbow, min_value, max_value);
499
        mViewerWindow->paintGrid(map, "", GridViewRainbow, min_value, max_value);
500
        qDebug() << "painted map grid" << map->name() << "min-value (blue):" << min_value << "max-value(red):" << max_value;
500
        qDebug() << "painted map grid" << map->name() << "min-value (blue):" << min_value << "max-value(red):" << max_value;
501
    }
501
    }
502
#else
502
#else
503
    Q_UNUSED(map);Q_UNUSED(min_value);Q_UNUSED(max_value);
503
    Q_UNUSED(map);Q_UNUSED(min_value);Q_UNUSED(max_value);
504
#endif
504
#endif
505
}
505
}
506
506
507
void ModelController::addGrid(const FloatGrid *grid, const QString &name, const GridViewType view_type, double min_value, double max_value)
507
void ModelController::addGrid(const FloatGrid *grid, const QString &name, const GridViewType view_type, double min_value, double max_value)
508
{
508
{
509
#ifdef ILAND_GUI
509
#ifdef ILAND_GUI
510
510
511
    if (mViewerWindow) {
511
    if (mViewerWindow) {
512
        mViewerWindow->paintGrid(grid, name, view_type, min_value, max_value);
512
        mViewerWindow->paintGrid(grid, name, view_type, min_value, max_value);
513
        qDebug() << "painted grid min-value (blue):" << min_value << "max-value(red):" << max_value;
513
        qDebug() << "painted grid min-value (blue):" << min_value << "max-value(red):" << max_value;
514
    }
514
    }
515
#else
515
#else
516
    Q_UNUSED(grid); Q_UNUSED(name); Q_UNUSED(view_type); Q_UNUSED(min_value);Q_UNUSED(max_value);
516
    Q_UNUSED(grid); Q_UNUSED(name); Q_UNUSED(view_type); Q_UNUSED(min_value);Q_UNUSED(max_value);
517
#endif
517
#endif
518
}
518
}
519
519
520
void ModelController::addLayers(const LayeredGridBase *layers, const QString &name)
520
void ModelController::addLayers(const LayeredGridBase *layers, const QString &name)
521
{
521
{
522
#ifdef ILAND_GUI
522
#ifdef ILAND_GUI
523
    if (mViewerWindow)
523
    if (mViewerWindow)
524
        mViewerWindow->addLayers(layers, name);
524
        mViewerWindow->addLayers(layers, name);
525
    //qDebug() << layers->names();
525
    //qDebug() << layers->names();
526
#else
526
#else
527
    Q_UNUSED(layers); Q_UNUSED(name);
527
    Q_UNUSED(layers); Q_UNUSED(name);
528
#endif
528
#endif
529
}
529
}
530
void ModelController::removeLayers(const LayeredGridBase *layers)
530
void ModelController::removeLayers(const LayeredGridBase *layers)
531
{
531
{
532
#ifdef ILAND_GUI
532
#ifdef ILAND_GUI
533
    if (mViewerWindow)
533
    if (mViewerWindow)
534
        mViewerWindow->removeLayers(layers);
534
        mViewerWindow->removeLayers(layers);
535
    //qDebug() << layers->names();
535
    //qDebug() << layers->names();
536
#else
536
#else
537
    Q_UNUSED(layers);
537
    Q_UNUSED(layers);
538
#endif
538
#endif
539
}
539
}
540
540
541
void ModelController::setViewport(QPointF center_point, double scale_px_per_m)
541
void ModelController::setViewport(QPointF center_point, double scale_px_per_m)
542
{
542
{
543
#ifdef ILAND_GUI
543
#ifdef ILAND_GUI
544
    if (mViewerWindow)
544
    if (mViewerWindow)
545
        mViewerWindow->setViewport(center_point, scale_px_per_m);
545
        mViewerWindow->setViewport(center_point, scale_px_per_m);
546
#else
546
#else
547
    Q_UNUSED(center_point);Q_UNUSED(scale_px_per_m);
547
    Q_UNUSED(center_point);Q_UNUSED(scale_px_per_m);
-
 
548
#endif
-
 
549
}
-
 
550
-
 
551
void ModelController::setUIShortcuts(QVariantMap shortcuts)
-
 
552
{
-
 
553
#ifdef ILAND_GUI
-
 
554
    if (mViewerWindow)
-
 
555
        mViewerWindow->setUIshortcuts(shortcuts);
-
 
556
#else
-
 
557
    Q_UNUSED(shortcuts);
548
#endif
558
#endif
549
}
559
}
550
560
551
void ModelController::repaint()
561
void ModelController::repaint()
552
{
562
{
553
#ifdef ILAND_GUI
563
#ifdef ILAND_GUI
554
    if (mViewerWindow)
564
    if (mViewerWindow)
555
        mViewerWindow->repaint();
565
        mViewerWindow->repaint();
556
#endif
566
#endif
557
}
567
}
558
568
559
569
560
570
561
571
562
572
563
 
573