Skip to content

Commit

Permalink
Preparation for extracting spec.yml
Browse files Browse the repository at this point in the history
  • Loading branch information
fushar committed Sep 9, 2017
1 parent 34e6902 commit c4f7445
Show file tree
Hide file tree
Showing 33 changed files with 386 additions and 368 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ set(INCLUDE
include/tcframe/spec/core/BaseProblemSpec.hpp
include/tcframe/spec/core/Magic.hpp
include/tcframe/spec/core/SeedSetter.hpp
include/tcframe/spec/core/Spec.hpp
include/tcframe/spec/core/SpecYaml.hpp
include/tcframe/spec/exception.hpp
include/tcframe/spec/exception/FormattedError.hpp
include/tcframe/spec/io.hpp
Expand Down
55 changes: 45 additions & 10 deletions include/tcframe/driver/Driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

#include <ostream>
#include <string>
#include <utility>

#include "SlugParser.hpp"
#include "SpecDriver.hpp"
#include "TestCaseDriver.hpp"
#include "tcframe/spec.hpp"

using std::endl;
using std::make_pair;
using std::ostream;
using std::pair;
using std::string;

namespace tcframe {
Expand All @@ -30,19 +33,51 @@ class Driver {
, testSpec_(testSpec) {}

// TODO (fushar): In 2.0, replace this with entry point
virtual SpecDriver* getSpecDriver(const Spec& spec) {
virtual pair<SpecYaml, SpecDriver*> buildSpec() {
SpecYaml spec;
spec.slug = SlugParser::parse(specPath_);

ConstraintSuite constraintSuite = testSpec_->TProblemSpec::buildConstraintSuite();
if (constraintSuite.hasSubtasks()) {
for (const Subtask& subtask : constraintSuite.constraints()) {
if (subtask.id() != Subtask::MAIN_ID) {
SubtaskYaml subtaskYaml;
subtaskYaml.points = subtask.points();
spec.subtasks.push_back(subtaskYaml);
}
}
}

StyleConfig styleConfig = testSpec_->TProblemSpec::buildStyleConfig();
switch (styleConfig.evaluationStyle()) {
case EvaluationStyle::BATCH:
spec.evaluator.slug = "batch";
break;
case EvaluationStyle::INTERACTIVE:
spec.evaluator.slug = "interactive";
break;
}
spec.evaluator.has_tc_output = styleConfig.hasTcOutput();
spec.evaluator.has_scorer = styleConfig.hasScorer();

GradingConfig gradingConfig = testSpec_->TProblemSpec::buildGradingConfig();
spec.limits.time_s = gradingConfig.timeLimit() ;
spec.limits.memory_mb = gradingConfig.memoryLimit();

IOFormat ioFormat = testSpec_->TProblemSpec::buildIOFormat();
MultipleTestCasesConfig multipleTestCasesConfig = testSpec_->TProblemSpec::buildMultipleTestCasesConfig();

auto testCaseDriver = new TestCaseDriver(
new IOManipulator(spec.ioFormat()),
new Verifier(spec.constraintSuite()),
spec.multipleTestCasesConfig());
new IOManipulator(ioFormat),
new Verifier(constraintSuite),
multipleTestCasesConfig);

return new SpecDriver(testCaseDriver, spec.testSuite());
}
TestSuite testSuite = testSpec_->buildTestSuite(spec.slug, constraintSuite.getDefinedSubtaskIds());
SeedSetter* seedSetter = testSpec_->buildSeedSetter();

auto specDriver = new SpecDriver(testCaseDriver, seedSetter, multipleTestCasesConfig, testSuite);

// TODO (fushar): In 2.0, replace this with YAML file
virtual Spec buildSpec() {
string slug = SlugParser::parse(specPath_);
return testSpec_->buildSpec(slug);
return make_pair(spec, specDriver);
}
};

Expand Down
18 changes: 18 additions & 0 deletions include/tcframe/driver/SpecDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace tcframe {
class SpecDriver {
private:
TestCaseDriver* testCaseDriver_;
SeedSetter* seedSetter_;
MultipleTestCasesConfig multipleTestCasesConfig_;
TestSuite testSuite_;

map<string, TestCase> testCasesByName_;
Expand All @@ -29,8 +31,12 @@ class SpecDriver {

SpecDriver(
TestCaseDriver* testCaseDriver,
SeedSetter* seedSetter,
const MultipleTestCasesConfig& multipleTestCasesConfig,
const TestSuite& testSuite)
: testCaseDriver_(testCaseDriver)
, seedSetter_(seedSetter)
, multipleTestCasesConfig_(multipleTestCasesConfig)
, testSuite_(testSuite) {

for (auto& testGroup : testSuite_.testGroups()) {
Expand All @@ -44,6 +50,18 @@ class SpecDriver {
return testSuite_;
}

virtual void setSeed(unsigned seed) {
seedSetter_->setSeed(seed);
}

virtual bool hasMultipleTestCases() {
return multipleTestCasesConfig_.counter();
}

virtual optional<string> getMultipleTestCasesOutputPrefix() {
return multipleTestCasesConfig_.outputPrefix();
}

virtual void generateTestCaseInput(const string& testCaseName, ostream* out) {
testCaseDriver_->generateInput(testCasesByName_[testCaseName], out);
}
Expand Down
12 changes: 12 additions & 0 deletions include/tcframe/runner/client/SpecClient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ class SpecClient {
return specDriver_->getTestSuite();
}

virtual void setSeed(unsigned seed) {
specDriver_->setSeed(seed);
}

virtual bool hasMultipleTestCases() {
return specDriver_->hasMultipleTestCases();
}

virtual optional<string> getMultipleTestCasesOutputPrefix() {
return specDriver_->getMultipleTestCasesOutputPrefix();
}

virtual void generateTestCaseInput(const string& testCaseName, const string& filename) {
ostream* out = os_->openForWriting(filename);
specDriver_->generateTestCaseInput(testCaseName, out);
Expand Down
63 changes: 31 additions & 32 deletions include/tcframe/runner/core/Runner.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <iostream>
#include <utility>

#include "Args.hpp"
#include "ArgsParser.hpp"
Expand All @@ -16,6 +17,7 @@

using std::cout;
using std::endl;
using std::pair;

namespace tcframe {

Expand Down Expand Up @@ -68,13 +70,14 @@ class Runner {

try {
Args args = parseArgs(argc, argv);
Spec spec = buildSpec(runnerLogger);
pair<SpecYaml, SpecDriver*> spec = buildSpec(runnerLogger);
SpecClient* specClient = new SpecClient(spec.second, os_);

int result;
if (args.command() == Args::Command::GENERATE) {
result = generate(args, spec);
result = generate(args, spec.first, specClient);
} else {
result = grade(args, spec);
result = grade(args, spec.first, specClient);
}
cleanUp();
return result;
Expand All @@ -93,7 +96,7 @@ class Runner {
}
}

Spec buildSpec(RunnerLogger* runnerLogger) {
pair<SpecYaml, SpecDriver*> buildSpec(RunnerLogger* runnerLogger) {
try {
return driver_->buildSpec();
} catch (runtime_error& e) {
Expand All @@ -102,72 +105,68 @@ class Runner {
}
}

int generate(const Args& args, const Spec& spec) {
const MultipleTestCasesConfig& multipleTestCasesConfig = spec.multipleTestCasesConfig();

GenerationOptionsBuilder optionsBuilder = GenerationOptionsBuilder(spec.slug())
.setMultipleTestCasesCounter(multipleTestCasesConfig.counter())
.setMultipleTestCasesOutputPrefix(multipleTestCasesConfig.outputPrefix())
int generate(const Args& args, const SpecYaml& spec, SpecClient* specClient) {
GenerationOptionsBuilder optionsBuilder = GenerationOptionsBuilder(spec.slug)
.setSeed(args.seed().value_or(unsigned(RunnerDefaults::SEED)))
.setSolutionCommand(args.solution().value_or(string(RunnerDefaults::SOLUTION_COMMAND)))
.setOutputDir(args.output().value_or(string(RunnerDefaults::OUTPUT_DIR)));

EvaluatorConfig evaluatorConfig = evaluatorRegistry_->getConfig(spec.styleConfig().evaluationStyle());
EvaluatorConfig evaluatorConfig = evaluatorRegistry_->getConfig(spec.evaluator.slug);
if (evaluatorConfig.testCaseOutputType() == TestCaseOutputType::NOT_REQUIRED) {
optionsBuilder.setNeedsOutput(false);
optionsBuilder.setHasTcOutput(false);
} else {
optionsBuilder.setNeedsOutput(spec.styleConfig().needsOutput());
optionsBuilder.setHasTcOutput(spec.evaluator.has_tc_output);
}

GenerationOptions options = optionsBuilder.build();

auto helperCommands = getHelperCommands(args, spec.styleConfig());
auto evaluator = evaluatorRegistry_->get(spec.styleConfig().evaluationStyle(), os_, helperCommands);
auto helperCommands = getHelperCommands(args, spec.evaluator.has_scorer);
auto evaluator = evaluatorRegistry_->get(spec.evaluator.slug, os_, helperCommands);
auto logger = new DefaultGeneratorLogger(loggerEngine_);
auto specClient = new SpecClient(driver_->getSpecDriver(spec), os_);
auto testCaseGenerator = new TestCaseGenerator(specClient, evaluator, logger);
auto generator = generatorFactory_->create(spec.seedSetter(), specClient, testCaseGenerator, os_, logger);
auto generator = generatorFactory_->create(specClient, testCaseGenerator, os_, logger);

return generator->generate(options) ? 0 : 1;
}

int grade(const Args& args, const Spec& spec) {
const MultipleTestCasesConfig& multipleTestCasesConfig = spec.multipleTestCasesConfig();
const GradingConfig& gradingConfig = spec.gradingConfig();

GradingOptionsBuilder optionsBuilder = GradingOptionsBuilder(spec.slug())
.setHasMultipleTestCases((bool) multipleTestCasesConfig.counter())
int grade(const Args& args, const SpecYaml& spec, SpecClient* specClient) {
GradingOptionsBuilder optionsBuilder = GradingOptionsBuilder(spec.slug)
.setSolutionCommand(args.solution().value_or(string(RunnerDefaults::SOLUTION_COMMAND)))
.setOutputDir(args.output().value_or(string(RunnerDefaults::OUTPUT_DIR)));

if (!args.noTimeLimit()) {
optionsBuilder.setTimeLimit(args.timeLimit().value_or(gradingConfig.timeLimit()));
optionsBuilder.setTimeLimit(args.timeLimit().value_or(spec.limits.time_s));
}
if (!args.noMemoryLimit()) {
optionsBuilder.setMemoryLimit(args.memoryLimit().value_or(gradingConfig.memoryLimit()));
optionsBuilder.setMemoryLimit(args.memoryLimit().value_or(spec.limits.memory_mb));
}

vector<double> subtaskPoints;
for (const SubtaskYaml& subtask : spec.subtasks) {
subtaskPoints.push_back(subtask.points);
}
optionsBuilder.setSubtaskPoints(subtaskPoints);

GradingOptions options = optionsBuilder.build();

auto logger = graderLoggerFactory_->create(loggerEngine_, args.brief());
auto helperCommands = getHelperCommands(args, spec.styleConfig());
auto evaluator = evaluatorRegistry_->get(spec.styleConfig().evaluationStyle(), os_, helperCommands);
auto specClient = new SpecClient(driver_->getSpecDriver(spec), os_);
auto helperCommands = getHelperCommands(args, spec.evaluator.has_scorer);
auto evaluator = evaluatorRegistry_->get(spec.evaluator.slug, os_, helperCommands);
auto testCaseGrader = new TestCaseGrader(evaluator, logger);
auto aggregator = aggregatorRegistry_->get(spec.constraintSuite().hasSubtasks());
auto aggregator = aggregatorRegistry_->get(!spec.subtasks.empty());
auto grader = graderFactory_->create(specClient, testCaseGrader, aggregator, logger);

grader->grade(spec.constraintSuite(), options);
grader->grade(options);
return 0;
}

void cleanUp() {
os_->execute(ExecutionRequestBuilder().setCommand("rm __tcframe_*").build());
}

static map<string, string> getHelperCommands(const Args& args, const StyleConfig& styleConfig) {
static map<string, string> getHelperCommands(const Args& args, bool hasScorer) {
map<string, string> helperCommands;
if (styleConfig.needsCustomScorer()) {
if (hasScorer) {
helperCommands["scorer"] = args.scorer().value_or(string(RunnerDefaults::SCORER_COMMAND));
}
helperCommands["communicator"] = args.communicator().value_or(string(RunnerDefaults::COMMUNICATOR_COMMAND));
Expand Down
26 changes: 14 additions & 12 deletions include/tcframe/runner/evaluator/EvaluatorRegistry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,24 @@ class EvaluatorRegistry {
EvaluatorRegistry(EvaluatorHelperRegistry* helperRegistry)
: helperRegistry_(helperRegistry) {}

virtual Evaluator* get(EvaluationStyle style, OperatingSystem* os, const map<string, string>& helperCommands) {
switch (style) {
case EvaluationStyle::BATCH:
return getBatch(os, helperCommands);
case EvaluationStyle::INTERACTIVE:
return getInteractive(os, helperCommands);
virtual Evaluator* get(const string& slug, OperatingSystem* os, const map<string, string>& helperCommands) {
if (slug == "batch") {
return getBatch(os, helperCommands);
}
if (slug == "interactive") {
return getInteractive(os, helperCommands);
}
return nullptr;
}

virtual EvaluatorConfig getConfig(EvaluationStyle style) {
switch (style) {
case EvaluationStyle::BATCH:
return getBatchConfig();
case EvaluationStyle::INTERACTIVE:
return getInteractiveConfig();
virtual EvaluatorConfig getConfig(const string& slug) {
if (slug == "batch") {
return getBatchConfig();
}
if (slug == "interactive") {
return getInteractiveConfig();
}
return EvaluatorConfig();
}

private:
Expand Down

0 comments on commit c4f7445

Please sign in to comment.