Subversion Repositories public iLand

Rev

Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1
 
678 werner 2
/********************************************************************************************
3
**    iLand - an individual based forest landscape and disturbance model
4
**    http://iland.boku.ac.at
5
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
6
**
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
9
**    the Free Software Foundation, either version 3 of the License, or
10
**    (at your option) any later version.
11
**
12
**    This program is distributed in the hope that it will be useful,
13
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
**    GNU General Public License for more details.
16
**
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/>.
19
********************************************************************************************/
20
 
21
#include "consoleshell.h"
22
 
23
#include <QtCore>
1157 werner 24
#include <QtDebug>
989 werner 25
//#include <QKeyEvent>
678 werner 26
 
27
#include "global.h"
28
#include "model.h"
29
#include "modelcontroller.h"
1182 werner 30
#include "version.h"
678 werner 31
 
32
QTextStream *ConsoleShell::mLogStream = 0;
1087 werner 33
bool ConsoleShell::mFlushLog = false;
678 werner 34
 
679 werner 35
// a try to really get keyboard strokes in console mode...
36
// did not work.
37
class KeyboardTaker : public QThread
38
 {
39
 public:
40
     void run();
41
     bool stop;
42
 };
43
 
44
 void KeyboardTaker::run()
45
 {
46
     stop = false;
47
     QTextStream qin(stdin, QFile::ReadOnly);
48
     while (!stop) {
49
         QString input = qin.read(1);
50
         if (!input.isNull()) {
51
             // .. process input
52
             qWarning() << "input:" << input;
53
         }
54
     }
55
 }
56
 
678 werner 57
ConsoleShell::ConsoleShell()
58
{
59
}
60
 
679 werner 61
/*
62
*/
63
 
678 werner 64
void ConsoleShell::run()
65
{
679 werner 66
 
67
    QString xml_name = QCoreApplication::arguments().at(1);
68
    // get the number of years to run...
69
    bool ok;
70
    int years = QCoreApplication::arguments().at(2).toInt(&ok);
71
    if (years<0 || !ok) {
72
        qDebug() << QCoreApplication::arguments().at(2) << "is an invalid number of years to run!";
994 werner 73
        QCoreApplication::quit();
679 werner 74
        return;
75
    }
76
 
837 werner 77
    if (!QFile::exists(xml_name)) {
78
        qDebug() << "invalid XML project file: " << xml_name;
994 werner 79
        QCoreApplication::quit();
837 werner 80
        return;
81
    }
678 werner 82
    try {
83
 
84
        ModelController iland_model;
1081 werner 85
        GlobalSettings::instance()->setModelController( &iland_model );
678 werner 86
        QObject::connect(&iland_model, SIGNAL(year(int)),SLOT(runYear(int)));
87
        iland_model.setFileName(xml_name);
837 werner 88
        if (iland_model.hasError()) {
89
            qWarning() << "!!!! ERROR !!!!";
90
            qWarning() << iland_model.lastError();
91
            qWarning() << "!!!! ERROR !!!!";
994 werner 92
            QCoreApplication::quit();
837 werner 93
            return;
94
        }
678 werner 95
 
837 werner 96
        mParams.clear();
97
        if (QCoreApplication::arguments().count()>3) {
98
            qWarning() << "set command line values:";
99
            for (int i=3;i<QCoreApplication::arguments().count();++i) {
100
                QString line = QCoreApplication::arguments().at(i);
1157 werner 101
                line = line.remove(QChar('"')); // drop quotes
837 werner 102
                mParams.append(line);
1157 werner 103
                //qDebug() << qPrintable(line);
837 werner 104
                QString key = line.left(line.indexOf('='));
105
                QString value = line.mid(line.indexOf('=')+1);
106
                const_cast<XmlHelper&>(GlobalSettings::instance()->settings()).setNodeValue(key, value);
1157 werner 107
                qWarning() << QString("set '%1' to value '%2'. result: '%3'").arg(key).arg(value).arg(GlobalSettings::instance()->settings().value(key));
837 werner 108
            }
109
        }
1075 werner 110
        setupLogging();
111
 
678 werner 112
        qDebug() << "**************************************************";
113
        qDebug() << "***********     iLand console session     ********";
114
        qDebug() << "**************************************************";
115
 
116
        qWarning() << "*** creating model...";
117
        qWarning() << "**************************************************";
118
 
119
        iland_model.create();
837 werner 120
        if (iland_model.hasError()) {
121
            qWarning() << "!!!! ERROR !!!!";
122
            qWarning() << iland_model.lastError();
123
            qWarning() << "!!!! ERROR !!!!";
994 werner 124
            QCoreApplication::quit();
837 werner 125
            return;
126
        }
127
        runJavascript("onCreate");
678 werner 128
        qWarning() << "**************************************************";
679 werner 129
        qWarning() << "*** running model for" << years << "years";
678 werner 130
        qWarning() << "**************************************************";
131
 
679 werner 132
        iland_model.run(years + 1);
837 werner 133
        if (iland_model.hasError()) {
134
            qWarning() << "!!!! ERROR !!!!";
135
            qWarning() << iland_model.lastError();
136
            qWarning() << "!!!! ERROR !!!!";
994 werner 137
            QCoreApplication::quit();
837 werner 138
            return;
139
        }
140
        runJavascript("onFinish");
679 werner 141
 
678 werner 142
        qWarning() << "**************************************************";
143
        qWarning() << "*** model run finished.";
144
        qWarning() << "**************************************************";
145
 
146
    } catch (const IException &e) {
147
        qWarning() << "*** An exception occured ***";
148
        qWarning() << e.message();
149
    }
150
    catch (const std::exception &e) {
837 werner 151
        qWarning() << "*** An (std)exception occured ***";
678 werner 152
        qWarning() << e.what();
153
    }
154
    QCoreApplication::quit();
155
 
156
 
157
}
158
 
159
void ConsoleShell::runYear(int year)
160
{
1157 werner 161
    printf("%s: simulating year %d ...\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), year-1);
678 werner 162
}
163
 
1157 werner 164
static QMutex qdebug_mutex;
780 werner 165
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
678 werner 166
 {
780 werner 167
    Q_UNUSED(context);
168
    QMutexLocker m(&qdebug_mutex);
678 werner 169
 
170
    switch (type) {
1157 werner 171
    case QtDebugMsg:
678 werner 172
        *ConsoleShell::logStream() << msg << endl;
1087 werner 173
        if (ConsoleShell::flush())
1157 werner 174
            ConsoleShell::logStream()->flush();
175
        break;
176
    case QtWarningMsg:
678 werner 177
        *ConsoleShell::logStream() << msg << endl;
1087 werner 178
        if (ConsoleShell::flush())
1157 werner 179
            ConsoleShell::logStream()->flush();
180
        printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data());
181
        break;
182
// available from qt5.5
183
//    case QtInfoMsg:
184
//        *ConsoleShell::logStream() << msg << endl;
185
//        if (ConsoleShell::flush())
186
//            ConsoleShell::logStream()->flush();
187
//        printf("%s: %s\n", QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit().data(), msg.toLocal8Bit().data());
678 werner 188
 
1157 werner 189
//        break;
190
    case QtCriticalMsg:
678 werner 191
        *ConsoleShell::logStream() << msg << endl;
1087 werner 192
        if (ConsoleShell::flush())
1157 werner 193
            ConsoleShell::logStream()->flush();
984 werner 194
        printf("Critical: %s\n", msg.toLocal8Bit().data());
1157 werner 195
        break;
196
    case QtFatalMsg:
678 werner 197
        *ConsoleShell::logStream() << msg << endl;
1087 werner 198
        if (ConsoleShell::flush())
1157 werner 199
            ConsoleShell::logStream()->flush();
984 werner 200
        printf("Fatal: %s\n", msg.toLocal8Bit().data());
1157 werner 201
    }
678 werner 202
 }
203
 
204
 
205
void ConsoleShell::setupLogging()
206
{
207
    if (mLogStream) {
208
        if (mLogStream->device())
209
            delete mLogStream->device();
210
        delete mLogStream;
211
        mLogStream = NULL;
212
    }
213
 
214
    QString fname = GlobalSettings::instance()->settings().value("system.logging.logFile", "logfile.txt");
1087 werner 215
    mFlushLog = GlobalSettings::instance()->settings().valueBool("system.logging.flush");
678 werner 216
    QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
217
    fname.replace("$date$", timestamp);
218
    fname = GlobalSettings::instance()->path(fname, "log");
219
    QFile *file = new QFile(fname);
220
 
221
    if (!file->open(QIODevice::WriteOnly)) {
222
        qDebug() << "cannot open logfile" << fname;
223
    } else {
224
        qDebug() << "Log output is redirected to logfile" << fname;
225
        mLogStream = new QTextStream(file);
226
    }
780 werner 227
    qInstallMessageHandler(myMessageOutput);
678 werner 228
 
229
 
230
}
231
 
837 werner 232
void ConsoleShell::runJavascript(const QString key)
233
{
234
    for (int i=0;i<mParams.count(); ++i) {
235
        QString line=mParams[i];
236
        QString pkey = line.left(line.indexOf('='));
237
        if (pkey == key) {
238
            QString command = line.mid(line.indexOf('=')+1);
239
            // execute the function
240
            qWarning() << "executing trigger" << key;
241
            qWarning() << GlobalSettings::instance()->executeJavascript(command);
242
        }
243
    }
244
 
245
 
246
}
247