Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add batch grade abstract from tcframe scripts #182

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions .github/workflows/main.yml

This file was deleted.

4 changes: 2 additions & 2 deletions include/tcframe/driver/TestCaseDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class TestCaseDriver {
IOManipulator* ioManipulator,
Verifier* verifier,
MultipleTestCasesConfig multipleTestCasesConfig)
: ioManipulator_(ioManipulator)
, rawIOManipulator_(rawIOManipulator)
: rawIOManipulator_(rawIOManipulator)
, ioManipulator_(ioManipulator)
, verifier_(verifier)
, multipleTestCasesConfig_(move(multipleTestCasesConfig)) {}

Expand Down
21 changes: 14 additions & 7 deletions include/tcframe/runner/grader/Grader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <map>
#include <string>
#include <vector>

#include "GradingOptions.hpp"
#include "GraderLogger.hpp"
#include "TestCaseGrader.hpp"
Expand Down Expand Up @@ -78,7 +77,7 @@ class Grader {
private:
map<int, double> getSubtaskPoints(const GradingOptions& options) {
map<int, double> subtaskPointsByIds;
for (int id = 1; id <= options.subtaskPoints().size(); id++) {
for (unsigned id = 1; id <= options.subtaskPoints().size(); id++) {
subtaskPointsByIds[id] = options.subtaskPoints()[id - 1];
}
if (subtaskPointsByIds.empty()) {
Expand Down Expand Up @@ -107,21 +106,29 @@ class Grader {
.build();
gradeTestCase(testCase, options, verdictsBySubtaskId);
} else {
bool skipping = 0;
for (const TestCase& testCase : testGroup.testCases()) {
gradeTestCase(testCase, options, verdictsBySubtaskId);
TestCaseVerdict verdict = gradeTestCase(testCase, options, verdictsBySubtaskId, skipping);
if(verdict.verdict().code() != "OK" && verdict.verdict().code() != "AC") {
// comment this code if you dont want to skip
skipping = 1;
}
}
}
}

void gradeTestCase(
TestCaseVerdict gradeTestCase(
const TestCase& testCase,
const GradingOptions& options,
map<int, vector<TestCaseVerdict>>& verdictsBySubtaskId) {

TestCaseVerdict verdict = testCaseGrader_->grade(testCase, options);
map<int, vector<TestCaseVerdict>>& verdictsBySubtaskId,
bool skipTestCase = 0) {
TestCaseVerdict verdict;
if(skipTestCase) verdict = TestCaseVerdict(Verdict::skip());
else verdict = testCaseGrader_->grade(testCase, options);
for (int subtaskId : testCase.subtaskIds()) {
verdictsBySubtaskId[subtaskId].push_back(verdict);
}
return verdict;
}
};

Expand Down
3 changes: 2 additions & 1 deletion include/tcframe/runner/os/OperatingSystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class OperatingSystem {

private:
static void runCommand(const string& command) {
system(command.c_str());
int val = system(command.c_str());
std::cerr << "[tcframe] exit code: " << val << "\n";
}
};

Expand Down
4 changes: 4 additions & 0 deletions include/tcframe/runner/verdict/Verdict.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ struct Verdict {
return {"ERR", "Internal Error", 99};
}

static Verdict skip() {
return {"SKIP", "Skipped", -1};
}

const string& code() const {
return code_;
}
Expand Down
4 changes: 2 additions & 2 deletions include/tcframe/spec/constraint/Subtask.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ struct Subtask {

Subtask(int id, double points, vector<Constraint> constraints)
: id_(id)
, points_(points)
, constraints_(move(constraints)) {}
, constraints_(move(constraints))
, points_(points) {}

int id() const {
return id_;
Expand Down
10 changes: 5 additions & 5 deletions include/tcframe/spec/core/Magic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ namespace tcframe {
struct VectorSize {
function<int()> size;

explicit VectorSize(function<int()> size)
: size(move(size)) {}
explicit VectorSize(function<int()> _size)
: size(move(_size)) {}
};

template<typename T>
Expand All @@ -55,9 +55,9 @@ struct MatrixSize {
function<int()> rows;
function<int()> columns;

MatrixSize(function<int()> rows, function<int()> columns)
: rows(move(rows))
, columns(move(columns)) {}
MatrixSize(function<int()> _rows, function<int()> _columns)
: rows(move(_rows))
, columns(move(_columns)) {}
};

class VariableNamesExtractor {
Expand Down
4 changes: 2 additions & 2 deletions include/tcframe/spec/io/IOFormat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct IOFormat {
if (a.size() != b.size()) {
return false;
}
for (int i = 0; i < a.size(); i++) {
for (unsigned i = 0; i < a.size(); i++) {
if (!a[i]->equals(b[i])) {
return false;
}
Expand All @@ -61,7 +61,7 @@ struct IOFormat {
if (a.size() != b.size()) {
return false;
}
for (int i = 0; i < a.size(); i++) {
for (unsigned i = 0; i < a.size(); i++) {
if (!equals(a[i], b[i])) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion include/tcframe/spec/io/LinesIOSegment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct LinesIOSegment : public IOSegment {
if (variables_.size() != o.variables_.size()) {
return false;
}
for (int i = 0; i < variables_.size(); i++) {
for (unsigned i = 0; i < variables_.size(); i++) {
if (!variables_[i]->equals(o.variables_[i])) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion include/tcframe/spec/io/LinesIOSegmentManipulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class LinesIOSegmentManipulator {

int size = getSize(segment);
for (int j = 0; j < size; j++) {
for (int i = 0; i < segment->variables().size(); i++) {
for (unsigned i = 0; i < segment->variables().size(); i++) {
Variable *variable = segment->variables()[i];
if (variable->type() == VariableType::VECTOR) {
if (i > 0) {
Expand Down
8 changes: 7 additions & 1 deletion include/tcframe/spec/random/Random.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <random>

using std::mt19937;
using std::mt19937_64;
using std::random_shuffle;
using std::uniform_real_distribution;
using std::uniform_int_distribution;

Expand Down Expand Up @@ -47,8 +49,12 @@ class Random {
std::shuffle(first, last, engine);
}

mt19937_64 *getEngine() {
return &engine;
}

private:
mt19937 engine;
mt19937_64 engine;
};

}
1 change: 0 additions & 1 deletion include/tcframe/spec/variable/Vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ class RawVectorImpl : public VectorImpl<string> {
, var_(&var) {}

void parseAndAddElementFrom(istream* in) {
int index = size();
string element;
Variable::parseRawLine(in, element);
var_->push_back(element);
Expand Down
91 changes: 91 additions & 0 deletions scripts/genConfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import re
import json

def custom_json_dump(obj, indent=2):
def serialize(obj, indent_level=0):
ind = ' ' * indent * indent_level
if (isinstance(obj, list)) and all(isinstance(i, (int, float, str)) for i in obj):
return '[' + ', '.join(json.dumps(i) for i in obj) + ']'
elif isinstance(obj, dict):
items = [f'"{k}": {serialize(v, indent_level+1)}' for k, v in obj.items()]
return '{\n' + ',\n'.join(ind + ' ' + item for item in items) + '\n' + ind + '}'
elif isinstance(obj, list):
items = [f'{serialize(v, indent_level+1)}' for v in obj]
return '[\n' + ',\n'.join(ind + ' ' + item for item in items) + '\n' + ind + ']'
else:
return json.dumps(obj)
return serialize(obj)


def read_spec_file(spec_file_path):
with open(spec_file_path, 'r') as file:
return file.read()

def matcher_extract(matches):
subtask_match_dict = dict()
for num, sub in matches:
content = []
try:
content = list(map(int, sub.replace(' ', '').replace('{', '').replace('}', '').split(',')))
except Exception as e:
content = []
subtask_match_dict[int(num)] = content

return subtask_match_dict

def extractor(spec_content, front, back):
matches = re.findall(front + r'(\d+)[\s\S.]+?' + back + r'\((.*?)\)', spec_content)
return matcher_extract(matches)

def extract_samples(spec_content):
return extractor(spec_content, 'SampleTestCase', 'Subtasks')

def extract_test_groups(spec_content):
return extractor(spec_content, 'TestGroup', 'Subtasks')

def extract_points(spec_content):
return extractor(spec_content, 'Subtask', 'Points')

def extract_time_limit(spec_content):
time_limit = re.search(r'TimeLimit\((\d+)\);', spec_content)
return int(time_limit.group(1)) if time_limit else 0

def extract_memory_limit(spec_content):
memory_limit = re.search(r'MemoryLimit\((\d+)\);', spec_content)
return int(memory_limit.group(1)) if memory_limit else 0

def extract_interactive(spec_content):
is_interactive = re.search(r'InteractiveEvaluator', spec_content)
return True if is_interactive else False


def generate_subtask_dict(spec_file_path):
spec_content = read_spec_file(spec_file_path)
points = extract_points(spec_content)
test_groups = extract_test_groups(spec_content)
samples = extract_samples(spec_content)
subtask_dict = {
"time_limit": extract_time_limit(spec_content),
"memory_limit": extract_memory_limit(spec_content),
"samples": [None]*max(samples.keys()),
"test_groups": [None]*max(test_groups.keys()),
"points": [0]*max(points.keys()),
"interactive": extract_interactive(spec_content)
}

for i, test_group in enumerate(test_groups, start=1):
subtask_dict["test_groups"][test_group-1] = test_groups[test_group]

for i, sample in enumerate(samples, start=1):
subtask_dict["samples"][sample-1] = samples[sample]

for i, point in enumerate(points, start=1):
subtask_dict["points"][point-1] = points[point][0]

return subtask_dict

if __name__ == "__main__":
spec_file_path = "spec.cpp" # replace with your file path
subtask_dict = generate_subtask_dict(spec_file_path)
with open('config.json', 'w') as file:
print(custom_json_dump(subtask_dict, 2), file=file)
Loading