Skip to content

Commit fa06059

Browse files
Split points evenly when scores not defined in config.yml (#48)
* Split points evenly when they are not defined in config * Add tests for set_scores function * Refactor print message Co-authored-by: Tomasz Nowak <[email protected]> * Print scores only if they are not found in config * Move warning about points not summing to 100 * Remove unnecessary new line * Bump version for release --------- Co-authored-by: Tomasz Nowak <[email protected]>
1 parent 4f488e9 commit fa06059

File tree

4 files changed

+90
-19
lines changed

4 files changed

+90
-19
lines changed

src/sinol_make/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from sinol_make import util
55

6-
__version__ = "1.2.0"
6+
__version__ = "1.2.1"
77

88
def configure_parsers():
99
parser = argparse.ArgumentParser(

src/sinol_make/commands/run/__init__.py

+43-18
Original file line numberDiff line numberDiff line change
@@ -451,10 +451,10 @@ def print_stream(*values, end='\n'):
451451
def calculate_points(self, results):
452452
points = 0
453453
for group, result in results.items():
454-
if group != 0 and group not in self.config["scores"]:
454+
if group != 0 and group not in self.scores:
455455
util.exit_with_error(f'Group {group} doesn\'t have points specified in config file.')
456456
if result == "OK" and group != 0:
457-
points += self.config["scores"][group]
457+
points += self.scores[group]
458458
return points
459459

460460

@@ -647,6 +647,46 @@ def validate_arguments(self, args):
647647

648648
return compilers, timetool_path
649649

650+
def set_scores(self):
651+
self.tests = package_util.get_tests(self.args.tests)
652+
self.groups = list(sorted(set([self.get_group(test) for test in self.tests])))
653+
self.scores = collections.defaultdict(int)
654+
655+
if 'scores' not in self.config.keys():
656+
print(util.warning('Scores are not defined in config.yml. Points will be assigned equally to all groups.'))
657+
num_groups = len(self.groups)
658+
self.scores = {}
659+
if self.groups[0] == 0:
660+
num_groups -= 1
661+
self.scores[0] = 0
662+
663+
points_per_group = 100 // num_groups
664+
for group in self.groups:
665+
if group == 0:
666+
continue
667+
self.scores[group] = points_per_group
668+
669+
if points_per_group * num_groups != 100:
670+
self.scores[self.groups[-1]] += 100 - points_per_group * num_groups
671+
672+
print("Points will be assigned as follows:")
673+
total_score = 0
674+
for group in self.scores:
675+
print("%2d: %3d" % (group, self.scores[group]))
676+
total_score += self.scores[group]
677+
print()
678+
else:
679+
total_score = 0
680+
for group in self.config["scores"]:
681+
self.scores[group] = self.config["scores"][group]
682+
total_score += self.scores[group]
683+
684+
if total_score != 100:
685+
print(util.warning("WARN: Scores sum up to %d instead of 100." % total_score))
686+
print()
687+
688+
self.possible_score = self.get_possible_score(self.groups)
689+
650690
def run(self, args):
651691
if not util.check_if_project():
652692
print(util.warning('You are not in a project directory (couldn\'t find config.yml in current directory).'))
@@ -665,8 +705,6 @@ def run(self, args):
665705
util.exit_with_error('Time limit was not defined in config.yml.')
666706
if not 'memory_limit' in self.config.keys():
667707
util.exit_with_error('Memory limit was not defined in config.yml.')
668-
if not 'scores' in self.config.keys():
669-
util.exit_with_error('Scores were not defined in config.yml.')
670708

671709
self.compilers, self.timetool_path = self.validate_arguments(args)
672710

@@ -687,18 +725,8 @@ def run(self, args):
687725
else:
688726
print(f'Memory limit: {self.memory_limit} kB',
689727
util.warning(("[originally was %.1f kb]" % config_memory_limit)))
690-
self.scores = collections.defaultdict(int)
691-
print("Scores:")
692-
total_score = 0
693-
for group in self.config["scores"]:
694-
self.scores[group] = self.config["scores"][group]
695-
print("%2d: %3d" % (group, self.scores[group]))
696-
total_score += self.scores[group]
697-
if total_score != 100:
698-
print(util.warning("WARN: Scores sum up to %d (instead of 100)." % total_score))
699-
print()
700728

701-
self.tests = package_util.get_tests(args.tests)
729+
self.set_scores()
702730

703731
if len(self.tests) > 0:
704732
print(util.bold('Tests that will be run:'), ' '.join([self.extract_file_name(test) for test in self.tests]))
@@ -709,9 +737,6 @@ def run(self, args):
709737
else:
710738
print(util.warning('There are no tests to run.'))
711739

712-
self.groups = list(sorted(set([self.get_group(test) for test in self.tests])))
713-
self.possible_score = self.get_possible_score(self.groups)
714-
715740
solutions = self.get_solutions(self.args.solutions)
716741
results = self.compile_and_run(solutions)
717742
validation_results = self.validate_expected_scores(results)

tests/commands/run/test_integration.py

+23
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,26 @@ def test_weak_compilation_flags(create_package):
162162
args = parser.parse_args(["run", "--weak_compilation_flags", "--time_tool", "time"])
163163
command = Command()
164164
command.run(args)
165+
166+
167+
@pytest.mark.parametrize("create_package", [get_simple_package_path()], indirect=True)
168+
def test_no_scores(capsys, create_package, time_tool):
169+
"""
170+
Test with no scores key in config.yml.
171+
"""
172+
package_path = create_package
173+
command = get_command()
174+
create_ins_outs(package_path)
175+
176+
config_path = os.path.join(package_path, "config.yml")
177+
config = yaml.load(open(config_path, "r"), Loader=yaml.SafeLoader)
178+
del config["scores"]
179+
open(config_path, "w").write(yaml.dump(config))
180+
181+
parser = configure_parsers()
182+
args = parser.parse_args(["run", "--time_tool", time_tool])
183+
command = Command()
184+
command.run(args)
185+
186+
out = capsys.readouterr().out
187+
assert "Scores are not defined in config.yml. Points will be assigned equally to all groups." in out

tests/commands/run/test_unit.py

+23
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def test_execution(create_package, time_tool):
6060
def test_calculate_points():
6161
os.chdir(get_simple_package_path())
6262
command = get_command()
63+
command.scores = command.config["scores"]
6364

6465
assert command.calculate_points({1: "OK", 2: "OK", 3: "OK", 4: "OK"}) == 100
6566
assert command.calculate_points({1: "OK", 2: "OK", 3: "OK", 4: "WA"}) == 75
@@ -394,3 +395,25 @@ def test_print_expected_scores_diff(capsys, create_package):
394395
"points": 75
395396
}
396397
}
398+
399+
400+
@pytest.mark.parametrize("create_package", [get_simple_package_path()], indirect=["create_package"])
401+
def test_set_scores(create_package):
402+
"""
403+
Test set_scores function.
404+
"""
405+
package_path = create_package
406+
command = get_command(package_path)
407+
command.args = argparse.Namespace(tests=["in/abc0a.in", "in/abc1a.in", "in/abc2a.in", "in/abc3a.in", "in/abc4a.in",
408+
"in/abc5a.in", "in/abc6a.in"])
409+
del command.config["scores"]
410+
command.set_scores()
411+
assert command.scores == {
412+
0: 0,
413+
1: 16,
414+
2: 16,
415+
3: 16,
416+
4: 16,
417+
5: 16,
418+
6: 20
419+
}

0 commit comments

Comments
 (0)