diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index a29644e5..15c44e93 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -144 +149 diff --git a/src/base/LemonConfig.cpp b/src/base/LemonConfig.cpp index ad0d9c95..f71c1a61 100644 --- a/src/base/LemonConfig.cpp +++ b/src/base/LemonConfig.cpp @@ -34,19 +34,42 @@ namespace Lemon::base::config { QJsonArray _compilerList = json["compilerList"].toArray(); compilerList.clear(); compilerList.reserve(_compilerList.size()); - for (int compilerIndex = 0; compilerIndex < _compilerList.size(); ++compilerIndex) { - QJsonObject compilerObject = _compilerList[compilerIndex].toObject(); + for (int i = 0; i < _compilerList.size(); ++i) { + QJsonObject compilerObject = _compilerList[i].toObject(); Compiler *compiler = new Compiler; if (compiler->read(compilerObject) == -1) return -1; compilerList.append(compiler); } - } + } else + return -1; return 0; } void LemonConfigJudge::write(QJsonObject &json) const { - // TODO: Write Config + WRITE_JSON(json, defaultFullScore); + WRITE_JSON(json, defaultTimeLimit); + WRITE_JSON(json, defaultMemoryLimit); + WRITE_JSON(json, compileTimeLimit); + WRITE_JSON(json, specialJudgeTimeLimit); + WRITE_JSON(json, fileSizeLimit); + WRITE_JSON(json, rejudgeTimes); + + WRITE_JSON(json, defaultInputFileExtension); + WRITE_JSON(json, defaultOutputFileExtension); + WRITE_JSON(json, diffPath); + + WRITE_JSON(json, inputFileExtensions); + WRITE_JSON(json, outputFileExtensions); + WRITE_JSON(json, recentContest); + + QJsonArray compilerList; + for (const auto compiler : this->compilerList) { + QJsonObject obj; + compiler->write(obj); + compilerList.append(obj); + } + WRITE_JSON(json, compilerList); } } // namespace Lemon::base::config diff --git a/src/base/LemonUtils.hpp b/src/base/LemonUtils.hpp index feb640bb..29dd3378 100644 --- a/src/base/LemonUtils.hpp +++ b/src/base/LemonUtils.hpp @@ -10,44 +10,44 @@ #include #include #include - +#include namespace Lemon::detail { - inline int JsonReadHelper(QString &val, const QJsonValue &jval) { + inline int jsonReadHelper(QString &val, const QJsonValue &jval) { if (jval.isString()) { val = jval.toString(); return 0; } else return -1; } - inline int JsonReadHelper(int &val, const QJsonValue &jval) { + inline int jsonReadHelper(int &val, const QJsonValue &jval) { if (jval.isDouble()) { val = jval.toInt(); return 0; } else return -1; } - inline int JsonReadHelper(bool &val, const QJsonValue &jval) { + inline int jsonReadHelper(bool &val, const QJsonValue &jval) { if (jval.isBool()) { val = jval.toBool(); return 0; } else return -1; } - inline int JsonReadHelper(double &val, const QJsonValue &jval) { + inline int jsonReadHelper(double &val, const QJsonValue &jval) { if (jval.isDouble()) { val = jval.toDouble(); return 0; } else return -1; } - inline int JsonReadHelper(QJsonObject &val, const QJsonValue &jval) { + inline int jsonReadHelper(QJsonObject &val, const QJsonValue &jval) { if (jval.isObject()) { val = jval.toObject(); return 0; } else return -1; } - inline int JsonReadHelper(QJsonArray &val, const QJsonValue &jval) { + inline int jsonReadHelper(QJsonArray &val, const QJsonValue &jval) { if (jval.isArray()) { val = jval.toArray(); QJsonArray arr; @@ -55,57 +55,92 @@ namespace Lemon::detail { } else return -1; } - inline int JsonReadHelper(ResultState &val, const QJsonValue &jval) { + inline int jsonReadHelper(ResultState &val, const QJsonValue &jval) { int x; - if (JsonReadHelper(x, jval) == -1) + if (jsonReadHelper(x, jval) == -1) return -1; - val = ResultState(x); + val = static_cast(x); return 0; } - inline int JsonReadHelper(CompileState &val, const QJsonValue &jval) { + inline int jsonReadHelper(CompileState &val, const QJsonValue &jval) { int x; - if (JsonReadHelper(x, jval) == -1) + if (jsonReadHelper(x, jval) == -1) return -1; - val = CompileState(x); + val = static_cast(x); return 0; } - template int JsonReadHelper(QList &val, const QJsonValue &jval) { + template int jsonReadHelper(QList &val, const QJsonValue &jval) { QJsonArray arr; - return JsonReadHelper(arr, jval) == -1 || JsonReadHelper(val, arr) == -1 ? -1 : 0; + return jsonReadHelper(arr, jval) == -1 || jsonReadHelper(val, arr) == -1 ? -1 : 0; } - inline int JsonReadHelper(QStringList &val, const QJsonArray &jval) { + inline int jsonReadHelper(QStringList &val, const QJsonArray &jval) { QList s; - if (JsonReadHelper(s, jval) == -1) + if (jsonReadHelper(s, jval) == -1) return -1; val = s; return 0; } - template int JsonReadHelper(QList &val, const QJsonArray &jval) { + template int jsonReadHelper(QList &val, const QJsonArray &jval) { val.clear(); for (auto i : jval) { T x; - if (JsonReadHelper(x, i) == -1) + if (jsonReadHelper(x, i) == -1) return -1; val.append(x); } return 0; } - template int JsonReadHelper(T &val, const QString &name, const QJsonObject &json); - template int JsonReadHelper(T &val, const QString &name, const QJsonObject &json) { + template int jsonReadHelper(T &val, const QString &name, const QJsonObject &json) { if (json.contains(name)) - return JsonReadHelper(val, json[name]); + return jsonReadHelper(val, json[name]); else return -1; } + + template + std::enable_if_t || std::is_floating_point_v || + std::is_same_v, QString> || + std::is_same_v, QJsonArray> || + std::is_same_v, QJsonValue> || + std::is_same_v, QJsonObject>, + void> + jsonWriteHelper(const T &val, QJsonValue &jval) { + jval = val; + } + template + std::enable_if_t, void> jsonWriteHelper(const T &val, QJsonValue &jval) { + jval = static_cast(val); + } + template void jsonWriteHelper(const QList &val, QJsonValue &jval) { + QJsonArray arr; + for (const T &i : val) { + QJsonValue x; + jsonWriteHelper(i, x); + arr.append(x); + } + jval = arr; + } + inline void jsonWriteHelper(const QStringList &val, QJsonValue &jval) { + QList s = val; + jsonWriteHelper(s, jval); + } + template void jsonWriteHelper(const T &val, const QString &name, QJsonObject &json) { + QJsonValue jval; + jsonWriteHelper(val, jval); + json[name] = jval; + } } // namespace Lemon::detail -#define WRITE_JSON(json, ___x) json[#___x] = ___x; -#define WRITE_JSON_STRLIST(json, ___x) json[#___x] = ___x.join(QLatin1Char(';')); + namespace Lemon { template int readJson(T &x, const QString &name, const QJsonObject &json) { - return detail::JsonReadHelper(x, name, json); + return detail::jsonReadHelper(x, name, json); + } + template void writeJson(const T &x, const QString &name, QJsonObject &json) { + detail::jsonWriteHelper(x, name, json); } } // namespace Lemon #define READ_JSON(json, x) Lemon::readJson(x, #x, json) +#define WRITE_JSON(json, x) Lemon::writeJson(x, #x, json) namespace Lemon::common { QStringList GetFileList(const QDir &dir); diff --git a/src/base/compiler.cpp b/src/base/compiler.cpp index 3f989875..b355bd17 100644 --- a/src/base/compiler.cpp +++ b/src/base/compiler.cpp @@ -131,16 +131,14 @@ int Compiler::read(const QJsonObject &json) { READ_JSON(json, compilerArguments); READ_JSON(json, interpreterArguments); - QStringList _environment; - if (json.contains("environment") && json["environment"].isString()) { - _environment = json["environment"].toString().split(QLatin1Char(';'), Qt::SkipEmptyParts); - } + QStringList environment; + READ_JSON(json, environment); - for (auto &i : _environment) { + for (auto &i : environment) { int tmp = i.indexOf('='); QString variable = i.mid(0, tmp); QString value = i.mid(tmp + 1); - environment.insert(variable, value); + this->environment.insert(variable, value); } READ_JSON(json, timeLimitRatio); @@ -150,20 +148,20 @@ int Compiler::read(const QJsonObject &json) { } void Compiler::write(QJsonObject &json) const { - WRITE_JSON(json, compilerType) - WRITE_JSON(json, compilerName) - WRITE_JSON(json, compilerLocation) - WRITE_JSON(json, interpreterLocation) - - WRITE_JSON_STRLIST(json, sourceExtensions) - WRITE_JSON_STRLIST(json, bytecodeExtensions) - WRITE_JSON_STRLIST(json, configurationNames) - WRITE_JSON_STRLIST(json, compilerArguments) - WRITE_JSON_STRLIST(json, interpreterArguments) - - WRITE_JSON_STRLIST(json, environment.toStringList()) - - WRITE_JSON(json, timeLimitRatio) // double - WRITE_JSON(json, memoryLimitRatio) // double - WRITE_JSON(json, disableMemoryLimitCheck) // bool + WRITE_JSON(json, compilerType); + WRITE_JSON(json, compilerName); + WRITE_JSON(json, compilerLocation); + WRITE_JSON(json, interpreterLocation); + + WRITE_JSON(json, sourceExtensions); + WRITE_JSON(json, bytecodeExtensions); + WRITE_JSON(json, configurationNames); + WRITE_JSON(json, compilerArguments); + WRITE_JSON(json, interpreterArguments); + + WRITE_JSON(json, environment.toStringList()); + + WRITE_JSON(json, timeLimitRatio); // double + WRITE_JSON(json, memoryLimitRatio); // double + WRITE_JSON(json, disableMemoryLimitCheck); // bool } diff --git a/src/core/contest.cpp b/src/core/contest.cpp index bb60a659..aef19e1a 100644 --- a/src/core/contest.cpp +++ b/src/core/contest.cpp @@ -354,6 +354,29 @@ void Contest::writeToStream(QDataStream &out) { i->writeToStream(out); } } +void Contest::writeToJson(QJsonObject &out) { + WRITE_JSON(out, contestTitle); + + QJsonArray tasks; + + for (const auto &i : taskList) { + QJsonObject obj; + i->writeToJson(obj); + tasks.append(obj); + } + + WRITE_JSON(out, tasks); + + QJsonArray contestants; + + for (const auto &i : contestantList) { + QJsonObject obj; + i->writeToJson(out); + contestants.append(obj); + } + + WRITE_JSON(out, contestants); +} int Contest::readFromJson(const QJsonObject &in) { READ_JSON(in, contestTitle); diff --git a/src/core/contest.h b/src/core/contest.h index dda4f3a0..e8a2b6b5 100644 --- a/src/core/contest.h +++ b/src/core/contest.h @@ -41,6 +41,7 @@ class Contest : public QObject { void refreshContestantList(); void deleteContestant(const QString &); void writeToStream(QDataStream &); + void writeToJson(QJsonObject &); void readFromStream(QDataStream &); int readFromJson(const QJsonObject &); diff --git a/src/core/contestant.cpp b/src/core/contestant.cpp index f95bb818..95ce9cca 100644 --- a/src/core/contestant.cpp +++ b/src/core/contestant.cpp @@ -176,7 +176,26 @@ auto Contestant::getTotalUsedTime() const -> int { return total; } - +int Contestant::writeToJson(QJsonObject &out) { + WRITE_JSON(out, contestantName); + WRITE_JSON(out, checkJudged); + WRITE_JSON(out, sourceFile); + WRITE_JSON(out, compileMesaage); + WRITE_JSON(out, inputFiles); + WRITE_JSON(out, message); + WRITE_JSON(out, score); + WRITE_JSON(out, timeUsed); + WRITE_JSON(out, memoryUsed); + int judgingTime_date = judgingTime.date().toJulianDay(); + int judgingTime_time = judgingTime.time().msecsSinceStartOfDay(); + int judgingTime_timespec = judgingTime.timeSpec(); + WRITE_JSON(out, judgingTime_date); + WRITE_JSON(out, judgingTime_time); + WRITE_JSON(out, judgingTime_timespec); + WRITE_JSON(out, compileState); + WRITE_JSON(out, result); + return 0; +} void Contestant::writeToStream(QDataStream &out) { out << contestantName; out << checkJudged; diff --git a/src/core/contestant.h b/src/core/contestant.h index 821c7ca8..1f47ead1 100644 --- a/src/core/contestant.h +++ b/src/core/contestant.h @@ -48,6 +48,7 @@ class Contestant : public QObject { void setMemoryUsed(int, const QList> &); void setJudgingTime(QDateTime); + int writeToJson(QJsonObject &); void writeToStream(QDataStream &); int readFromJson(const QJsonObject &); void readFromStream(QDataStream &); diff --git a/src/core/task.cpp b/src/core/task.cpp index d0f34785..3dcb9101 100644 --- a/src/core/task.cpp +++ b/src/core/task.cpp @@ -241,7 +241,74 @@ auto Task::getTotalScore() const -> int { return total; } +int Task::writeToJson(QJsonObject &in) { + WRITE_JSON(in, problemTitle); + WRITE_JSON(in, sourceFileName); + WRITE_JSON(in, inputFileName); + WRITE_JSON(in, outputFileName); + WRITE_JSON(in, standardInputCheck); + WRITE_JSON(in, standardOutputCheck); + WRITE_JSON(in, taskType); + WRITE_JSON(in, subFolderCheck); + WRITE_JSON(in, comparisonMode); + WRITE_JSON(in, diffArguments); + WRITE_JSON(in, realPrecision); + auto specialJudge = this->specialJudge; + specialJudge.replace(QDir::separator(), '/'); + WRITE_JSON(in, specialJudge); + if (taskType == Task::Interaction) { + auto interactor = this->interactor; + interactor.replace(QDir::separator(), '/'); + WRITE_JSON(in, interactor); + auto grader = this->grader; + grader.replace(QDir::separator(), '/'); + WRITE_JSON(in, grader); + WRITE_JSON(in, interactorName); + } + + if (taskType == Task::Communication) { + auto sourceFilesPath = this->sourceFilesPath; + auto sourceFilesName = this->sourceFilesName; + for (auto &filePath : sourceFilesPath) { + filePath.replace(QDir::separator(), '/'); + } + for (auto &fileName : sourceFilesName) { + fileName.replace(QDir::separator(), '/'); + } + WRITE_JSON(in, sourceFilesPath); + WRITE_JSON(in, sourceFilesName); + + auto graderFilesPath = this->graderFilesPath; + auto graderFilesName = this->graderFilesName; + for (auto &filePath : graderFilesPath) { + filePath.replace(QDir::separator(), '/'); + } + for (auto &fileName : graderFilesName) { + fileName.replace(QDir::separator(), '/'); + } + WRITE_JSON(in, graderFilesPath); + WRITE_JSON(in, graderFilesName); + } + + QJsonObject compilerConfiguration; + for (auto [x, y] : this->compilerConfiguration.toStdMap()) { + compilerConfiguration[x] = y; + } + WRITE_JSON(in, compilerConfiguration); + + WRITE_JSON(in, answerFileExtension); + QJsonArray testCases; + + for (const auto &i : testCaseList) { + QJsonObject obj; + i->writeToJson(obj); + testCases.append(obj); + } + + WRITE_JSON(in, testCases); + return 0; +} void Task::writeToStream(QDataStream &out) { out << problemTitle; out << sourceFileName; @@ -308,11 +375,11 @@ int Task::readFromJson(const QJsonObject &in) { READ_JSON(in, standardOutputCheck); int taskType; READ_JSON(in, taskType); - this->taskType = TaskType(taskType); + this->taskType = static_cast(taskType); READ_JSON(in, subFolderCheck); int comparisonMode; READ_JSON(in, comparisonMode); - this->comparisonMode = ComparisonMode(comparisonMode); + this->comparisonMode = static_cast(comparisonMode); READ_JSON(in, diffArguments); READ_JSON(in, realPrecision); READ_JSON(in, specialJudge); diff --git a/src/core/task.h b/src/core/task.h index 74fe53f8..98ee0030 100644 --- a/src/core/task.h +++ b/src/core/task.h @@ -93,6 +93,7 @@ class Task : public QObject { void refreshCompilerConfiguration(Settings *); int getTotalTimeLimit() const; int getTotalScore() const; + int writeToJson(QJsonObject &in); void writeToStream(QDataStream &); int readFromJson(const QJsonObject &); void readFromStream(QDataStream &); diff --git a/src/core/testcase.cpp b/src/core/testcase.cpp index 8fb767f5..81dc2a93 100644 --- a/src/core/testcase.cpp +++ b/src/core/testcase.cpp @@ -106,6 +106,30 @@ void TestCase::deleteSingleCase(int index) { outputFiles.removeAt(index); } +int TestCase::writeToJson(QJsonObject &out) { + WRITE_JSON(out, fullScore); + WRITE_JSON(out, timeLimit); + WRITE_JSON(out, memoryLimit); + + QStringList inputFiles = this->inputFiles; + for (auto &filename : inputFiles) { + filename.replace('/', QDir::separator()); + } + for (int i : qAsConst(dependenceSubtask)) { + inputFiles.push_back(QString("%1_lemon_SUbtaskDEPENDENCE_fLAg").arg(i)); + } + + WRITE_JSON(out, inputFiles); + + QStringList outputFiles = this->outputFiles; + + for (auto &filename : inputFiles) { + filename.replace('/', QDir::separator()); + } + + WRITE_JSON(out, outputFiles); + return 0; +} void TestCase::writeToStream(QDataStream &out) { out << fullScore; out << timeLimit; diff --git a/src/core/testcase.h b/src/core/testcase.h index 394c323a..c06dd98f 100644 --- a/src/core/testcase.h +++ b/src/core/testcase.h @@ -36,6 +36,7 @@ class TestCase : public QObject { bool checkDependenceSubtask(const QStringList &) const; void addSingleCase(const QString &, const QString &); void deleteSingleCase(int); + int writeToJson(QJsonObject &out); void writeToStream(QDataStream &); void readFromStream(QDataStream &); int readFromJson(const QJsonObject &);