Subversion Repositories public iLand

Rev

Rev 218 | Rev 223 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1
 
105 Werner 2
/** ModelController is a helper class used to
3
  control the flow of operations during a model run.
4
  Really useful???? or a dispatcher???
5
  */
128 Werner 6
 
105 Werner 7
#include "global.h"
8
#include "modelcontroller.h"
128 Werner 9
#include <QObject>
105 Werner 10
 
11
#include "model.h"
128 Werner 12
#include "helper.h"
165 werner 13
#include "expression.h"
161 werner 14
#include "expressionwrapper.h"
176 werner 15
#include "../output/outputmanager.h"
105 Werner 16
 
17
ModelController::ModelController()
18
{
128 Werner 19
    mModel = NULL;
105 Werner 20
}
128 Werner 21
 
22
ModelController::~ModelController()
23
{
24
    destroy();
25
}
26
 
27
 
145 Werner 28
bool ModelController::canCreate()
128 Werner 29
{
129 Werner 30
    if (mModel)
128 Werner 31
        return false;
32
    return true;
33
}
34
 
145 Werner 35
bool ModelController::canDestroy()
128 Werner 36
{
37
    return mModel != NULL;
38
}
39
 
145 Werner 40
bool ModelController::canRun()
128 Werner 41
{
42
    if (mModel && mModel->isSetup())
43
        return true;
44
    return false;
45
}
46
 
145 Werner 47
bool ModelController::isRunning()
128 Werner 48
{
162 werner 49
 return GlobalSettings::instance()->currentYear()>0;
128 Werner 50
}
51
 
52
 
53
void ModelController::setFileName(QString initFileName)
54
{
55
    mInitFile = initFileName;
56
    try {
57
        GlobalSettings::instance()->loadProjectFile(mInitFile);
58
    } catch(const IException &e) {
59
        QString error_msg = e.toString();
60
        Helper::msg(error_msg);
61
        qDebug() << error_msg;
62
    }
63
}
64
 
65
void ModelController::create()
66
{
67
    if (!canCreate())
68
        return;
69
    try {
70
    mModel = new Model();
71
    mModel->loadProject();
176 werner 72
    // setup outputs
73
    GlobalSettings::instance()->outputManager()->setup();
136 Werner 74
 
129 Werner 75
    if (mModel->isSetup())
76
        mModel->beforeRun();
164 werner 77
        GlobalSettings::instance()->clearDebugLists();
128 Werner 78
    } catch(const IException &e) {
79
        QString error_msg = e.toString();
80
        Helper::msg(error_msg);
81
        qDebug() << error_msg;
82
    }
83
}
84
 
85
void ModelController::destroy()
86
{
87
    if (canDestroy()) {
88
        delete mModel;
89
        mModel = 0;
162 werner 90
        GlobalSettings::instance()->setCurrentYear(0);
128 Werner 91
        qDebug() << "ModelController: Model destroyed.";
92
    }
93
}
222 werner 94
 
95
void ModelController::run(int years)
128 Werner 96
{
222 werner 97
    if (!canRun())
98
        return;
99
    DebugTimer many_runs(QString("Timer for %1 runs").arg(years));
100
    many_runs.setAsWarning();
101
 
102
    DebugTimer::clearAllTimers();
103
    for (int i=0;i<years;i++) {
104
        runYear();
105
        emit year(i);
128 Werner 106
    }
222 werner 107
    GlobalSettings::instance()->outputManager()->save();
108
    DebugTimer::printAllTimers();
109
    emit finished(QString());
110
 
128 Werner 111
}
112
 
113
void ModelController::runYear()
114
{
115
    if (!canRun()) return;
171 werner 116
    if (GlobalSettings::instance()->settings().paramValueBool("debug_clear"))
164 werner 117
        GlobalSettings::instance()->clearDebugLists();  // clear debug data
161 werner 118
 
128 Werner 119
    try {
120
        mModel->runYear();
162 werner 121
        fetchDynamicOutput();
128 Werner 122
    } catch(const IException &e) {
123
        QString error_msg = e.toString();
124
        Helper::msg(error_msg);
125
        qDebug() << error_msg;
126
    }
127
}
128
 
222 werner 129
bool ModelController::pause()
130
{
131
    return true;
132
}
128 Werner 133
 
222 werner 134
void ModelController::cancel()
135
{
136
}
161 werner 137
//////////////////////////////////////
138
// dynamic outut
139
//////////////////////////////////////
140
//////////////////////////////////////
141
void ModelController::setupDynamicOutput(QString fieldList)
142
{
171 werner 143
    mDynFieldList.clear();
144
    if (!fieldList.isEmpty()) {
145
        QRegExp rx("((?:\\[.+\\]|\\w+)\\.\\w+)");
146
        int pos=0;
147
        while ((pos = rx.indexIn(fieldList, pos)) != -1) {
148
            mDynFieldList.append(rx.cap(1));
149
            pos += rx.matchedLength();
150
        }
151
 
152
        //mDynFieldList = fieldList.split(QRegExp("(?:\\[.+\\]|\\w+)\\.\\w+"), QString::SkipEmptyParts);
170 werner 153
        mDynFieldList.prepend("count");
154
        mDynFieldList.prepend("year"); // fixed fields.
155
    }
161 werner 156
    mDynData.clear();
157
    mDynData.append(mDynFieldList.join(";"));
158
}
162 werner 159
 
161 werner 160
QString ModelController::dynamicOutput()
161
{
162
    return mDynData.join("\n");
163
}
164
 
218 werner 165
const QStringList aggList = QStringList() << "mean" << "sum" << "min" << "max" << "p25" << "p50" << "p75" << "p5"<< "p10" << "p90" << "p95";
161 werner 166
void ModelController::fetchDynamicOutput()
167
{
168
    if (mDynFieldList.isEmpty())
169
        return;
165 werner 170
    DebugTimer t("dynamic output");
161 werner 171
    QStringList var;
172
    QString lastVar = "";
173
    QVector<double> data;
174
    AllTreeIterator at(mModel);
175
    TreeWrapper tw;
176
    int var_index;
177
    StatData stat;
178
    double value;
179
    QStringList line;
165 werner 180
    Expression custom_expr;
181
    bool simple_expression;
161 werner 182
    foreach (QString field, mDynFieldList) {
163 werner 183
        if (field=="count" || field=="year")
184
            continue;
166 werner 185
        if (field.count()>0 && field.at(0)=='[') {
186
            QRegExp rex("\\[(.+)\\]\\.(\\w+)");
187
            rex.indexIn(field);
188
            var = rex.capturedTexts();
189
            var.pop_front(); // drop first element (contains the full string)
165 werner 190
            simple_expression = false;
191
        } else {
192
            var = field.split(QRegExp("\\W+"), QString::SkipEmptyParts);
193
            simple_expression = true;
194
        }
161 werner 195
        if (var.count()!=2)
196
                throw IException(QString("Invalid variable name for dynamic output:") + field);
197
        if (var.first()!=lastVar) {
198
            // load new field
199
            data.clear();
168 werner 200
            at.reset(); var_index = 0;
165 werner 201
            if (simple_expression) {
202
                var_index = tw.variableIndex(var.first());
166 werner 203
                if (var_index<0)
165 werner 204
                    throw IException(QString("Invalid variable name for dynamic output:") + var.first());
166 werner 205
 
165 werner 206
            } else {
207
                custom_expr.setExpression(var.first());
208
                custom_expr.setModelObject(&tw);
161 werner 209
            }
210
            while (Tree *t = at.next()) {
211
                tw.setTree(t);
165 werner 212
                if (simple_expression)
213
                    value = tw.value(var_index);
214
                else
215
                    value = custom_expr.execute();
166 werner 216
                data.push_back(value);
161 werner 217
            }
218
            stat.setData(data);
219
        }
220
        // fetch data
221
        var_index = aggList.indexOf(var[1]);
222
        switch (var_index) {
223
            case 0: value = stat.mean(); break;
224
            case 1: value = stat.sum(); break;
225
            case 2: value = stat.min(); break;
226
            case 3: value = stat.max(); break;
227
            case 4: value = stat.percentile25(); break;
228
            case 5: value = stat.median(); break;
229
            case 6: value = stat.percentile75(); break;
218 werner 230
            case 7: value = stat.percentile(5); break;
231
            case 8: value = stat.percentile(10); break;
232
            case 9: value = stat.percentile(90); break;
233
            case 10: value = stat.percentile(95); break;
161 werner 234
            default: throw IException(QString("Invalid aggregate expression for dynamic output: %1\nallowed:%2")
235
                                  .arg(var[1]).arg(aggList.join(" ")));
236
        }
237
        line+=QString::number(value);
238
    }
162 werner 239
    line.prepend( QString::number(data.size()) );
240
    line.prepend( QString::number(GlobalSettings::instance()->currentYear()) );
241
    mDynData.append(line.join(";"));
161 werner 242
}