Subversion Repositories public iLand

Rev

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

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