/***************************************************************************
This file is part of Project Lemon
Copyright (C) 2011 Zhipeng Jia
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
***************************************************************************/
/**
* task.cpp @Project Lemon+
* Update 2018 Dust1404
**/
/**
* task.cpp @Project LemonLime
* Update 2019 iotang
**/
#include "task.h"
#include "testcase.h"
#include "settings.h"
#include "compiler.h"
Task::Task(QObject *parent) :
QObject(parent)
{
taskType = Traditional;
comparisonMode = IgnoreSpacesMode;
diffArguments = "--ignore-space-change --text --brief";
realPrecision = 3;
standardInputCheck = false;
standardOutputCheck = false;
subFolderCheck = false;
}
auto Task::getTestCaseList() const -> const QList &
{
return testCaseList;
}
auto Task::getProblemTile() const -> const QString &
{
return problemTitle;
}
auto Task::getSubFolderCheck() const -> bool
{
return subFolderCheck;
}
auto Task::getSourceFileName() const -> const QString &
{
return sourceFileName;
}
auto Task::getInputFileName() const -> const QString &
{
return inputFileName;
}
auto Task::getOutputFileName() const -> const QString &
{
return outputFileName;
}
auto Task::getStandardInputCheck() const -> bool
{
return standardInputCheck;
}
auto Task::getStandardOutputCheck() const -> bool
{
return standardOutputCheck;
}
auto Task::getTaskType() const -> Task::TaskType
{
return taskType;
}
auto Task::getComparisonMode() const -> Task::ComparisonMode
{
return comparisonMode;
}
auto Task::getDiffArguments() const -> const QString &
{
return diffArguments;
}
auto Task::getRealPrecision() const -> int
{
return realPrecision;
}
auto Task::getSpecialJudge() const -> const QString &
{
return specialJudge;
}
auto Task::getInteractor() const -> const QString &
{
return interactor;
}
auto Task::getInteractorName() const -> const QString &
{
return interactorName;
}
auto Task::getGrader() const -> const QString &
{
return grader;
}
auto Task::getCompilerConfiguration(const QString &compilerName) const -> QString
{
return compilerConfiguration.value(compilerName);
}
auto Task::getAnswerFileExtension() const -> const QString &
{
return answerFileExtension;
}
auto Task::getSourceFilesPath() const -> const QStringList &
{
return sourceFilesPath;
}
auto Task::getSourceFilesName() const -> const QStringList &
{
return sourceFilesName;
}
auto Task::getGraderFilesPath() const -> const QStringList &
{
return graderFilesPath;
}
auto Task::getGraderFilesName() const -> const QStringList &
{
return graderFilesName;
}
void Task::setProblemTitle(const QString &title)
{
bool changed = problemTitle != title;
problemTitle = title;
if (changed) emit problemTitleChanged(title);
}
void Task::setSubFolderCheck(bool check)
{
subFolderCheck = check;
}
void Task::setSourceFileName(const QString &fileName)
{
sourceFileName = fileName;
}
void Task::setInputFileName(const QString &fileName)
{
inputFileName = fileName;
}
void Task::setOutputFileName(const QString &fileName)
{
outputFileName = fileName;
}
void Task::setStandardInputCheck(bool check)
{
standardInputCheck = check;
}
void Task::setStandardOutputCheck(bool check)
{
standardOutputCheck = check;
}
void Task::setTaskType(Task::TaskType type)
{
taskType = type;
}
void Task::setComparisonMode(Task::ComparisonMode mode)
{
comparisonMode = mode;
}
void Task::setDiffArguments(const QString &argumentsList)
{
diffArguments = argumentsList;
}
void Task::setRealPrecision(int precision)
{
realPrecision = precision;
}
void Task::setSpecialJudge(const QString &fileName)
{
specialJudge = fileName;
}
void Task::setInteractor(const QString &fileName)
{
interactor = fileName;
}
void Task::setInteractorName(const QString &fileName)
{
interactorName = fileName;
}
void Task::setGrader(const QString &fileName)
{
grader = fileName;
}
void Task::setCompilerConfiguration(const QString &compiler, const QString &configuration)
{
compilerConfiguration.insert(compiler, configuration);
}
void Task::setAnswerFileExtension(const QString &extension)
{
answerFileExtension = extension;
}
void Task::setSourceFilesPath(const QStringList &pathList)
{
sourceFilesPath = pathList;
}
void Task::setSourceFilesName(const QStringList &nameList)
{
sourceFilesName = nameList;
}
void Task::setGraderFilesPath(const QStringList &pathList)
{
graderFilesPath = pathList;
}
void Task::setGraderFilesName(const QStringList &nameList)
{
graderFilesName = nameList;
}
void Task::appendSourceFiles(const QString &path, const QString &name)
{
sourceFilesPath.append(path);
sourceFilesName.append(name);
}
void Task::appendGraderFiles(const QString &path, const QString &name)
{
graderFilesPath.append(path);
graderFilesName.append(name);
}
void Task::removeSourceFilesAt(int num)
{
if (num < sourceFilesPath.length())
{
sourceFilesPath.removeAt(num);
sourceFilesName.removeAt(num);
}
}
void Task::removeGraderFilesAt(int num)
{
if (num < graderFilesPath.length())
{
graderFilesPath.removeAt(num);
graderFilesName.removeAt(num);
}
}
void Task::addTestCase(TestCase *testCase)
{
testCase->setParent(this);
testCase->setIndex(testCaseList.size() + 1);
testCaseList.append(testCase);
}
auto Task::getTestCase(int index) const -> TestCase *
{
if (0 <= index && index < testCaseList.size())
{
return testCaseList[index];
}
return nullptr;
}
void Task::deleteTestCase(int index)
{
if (0 <= index && index < testCaseList.size())
{
for (int i = index; i < testCaseList.size(); ++i)
testCaseList[i]->clearDependenceSubtask();
delete testCaseList[index];
testCaseList.removeAt(index);
}
}
void Task::refreshCompilerConfiguration(Settings *settings)
{
QList compilerList = settings->getCompilerList();
QStringList compilerNames;
for (auto &i : compilerList)
compilerNames.append(i->getCompilerName());
QMap::iterator p;
for (p = compilerConfiguration.begin(); p != compilerConfiguration.end();)
{
if (! compilerNames.contains(p.key()))
{
p = compilerConfiguration.erase(p);
}
else
{
++p;
}
}
for (auto &i : compilerList)
{
if (compilerConfiguration.contains(i->getCompilerName()))
{
const QString &config = compilerConfiguration.value(i->getCompilerName());
const QStringList &configurationNames = i->getConfigurationNames();
if (! configurationNames.contains(config))
{
compilerConfiguration.insert(i->getCompilerName(), "default");
}
}
else
{
compilerConfiguration.insert(i->getCompilerName(), "default");
}
}
emit compilerConfigurationRefreshed();
}
auto Task::getTotalTimeLimit() const -> int
{
int total = 0;
for (auto i : testCaseList)
{
total += i->getTimeLimit() * i->getInputFiles().size();
}
return total;
}
auto Task::getTotalScore() const -> int
{
int total = 0;
for (auto i : testCaseList)
{
total += i->getFullScore();
}
return total;
}
void Task::writeToStream(QDataStream &out)
{
out << problemTitle;
out << sourceFileName;
out << inputFileName;
out << outputFileName;
out << standardInputCheck;
out << standardOutputCheck;
out << (static_cast(taskType) | ((static_cast(subFolderCheck)) << 8));
out << int (comparisonMode);
out << diffArguments;
out << realPrecision;
QString _specialJudge = specialJudge;
_specialJudge.replace(QDir::separator(), '/');
out << _specialJudge;
if (taskType == Task::Interaction)
{
QString _temp = interactor;
_temp.replace(QDir::separator(), '/');
out << _temp;
_temp = grader;
_temp.replace(QDir::separator(), '/');
out << _temp;
out << interactorName;
}
if (taskType == Task::Communication)
{
out << sourceFilesPath.length();
for (int i = 0; i < sourceFilesPath.length(); i++)
{
QString temp = sourceFilesPath[i];
temp.replace(QDir::separator(), '/');
out << temp;
temp = sourceFilesName[i];
temp.replace(QDir::separator(), '/');
out << temp;
}
out << graderFilesPath.length();
for (int i = 0; i < graderFilesPath.length(); i++)
{
QString temp = graderFilesPath[i];
temp.replace(QDir::separator(), '/');
out << temp;
temp = graderFilesName[i];
temp.replace(QDir::separator(), '/');
out << temp;
}
}
out << compilerConfiguration;
out << answerFileExtension;
out << testCaseList.size();
for (auto &i : testCaseList)
{
i->writeToStream(out);
}
}
void Task::readFromStream(QDataStream &in)
{
int tmp;
int count;
in >> problemTitle;
in >> sourceFileName;
in >> inputFileName;
in >> outputFileName;
in >> standardInputCheck;
in >> standardOutputCheck;
in >> tmp;
taskType = TaskType(tmp & 0xFF);
subFolderCheck = tmp >> 8;
in >> tmp;
comparisonMode = ComparisonMode(tmp);
in >> diffArguments;
in >> realPrecision;
in >> specialJudge;
specialJudge.replace('/', QDir::separator());
if (taskType == Task::Interaction)
{
in >> interactor;
interactor.replace('/', QDir::separator());
in >> grader;
grader.replace('/', QDir::separator());
in >> interactorName;
}
if (taskType == Task::Communication)
{
int length;
in >> length;
sourceFilesPath.clear();
sourceFilesName.clear();
for (int i = 0; i < length; i++)
{
QString temp;
in >> temp;
temp.replace('/', QDir::separator());
sourceFilesPath.append(temp);
in >> temp;
temp.replace('/', QDir::separator());
sourceFilesName.append(temp);
}
in >> length;
graderFilesPath.clear();
graderFilesName.clear();
for (int i = 0; i < length; i++)
{
QString temp;
in >> temp;
temp.replace('/', QDir::separator());
graderFilesPath.append(temp);
in >> temp;
temp.replace('/', QDir::separator());
graderFilesName.append(temp);
}
}
in >> compilerConfiguration;
in >> answerFileExtension;
in >> count;
for (int i = 0; i < count; i ++)
{
auto *newTestCase = new TestCase(this);
newTestCase->readFromStream(in);
newTestCase->setIndex(testCaseList.size() + 1);
testCaseList.append(newTestCase);
}
}