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 scoring types GroupSum, GroupSumCond, GroupSumCheck #1251

Open
wants to merge 3 commits into
base: main
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
48 changes: 48 additions & 0 deletions cms/grading/scoretypes/GroupSum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3

# Contest Management System - http://cms-dev.github.io/
# Copyright © 2010-2012 Giovanni Mascellani <[email protected]>
# Copyright © 2010-2018 Stefano Maggiolo <[email protected]>
# Copyright © 2010-2012 Matteo Boscariol <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from . import ScoreTypeGroup


# Dummy function to mark translatable string.
def N_(message):
return message


class GroupSum(ScoreTypeGroup):
"""The score of a submission is the sum of group scores,
and each group score is the sum of testcase scores in the group.

Parameters are [[m, t], ... ] (see ScoreTypeGroup).

"""

def get_public_outcome(self, outcome, unused_parameter):
"""See ScoreTypeGroup."""
if outcome <= 0.0:
return N_("Not correct")
elif outcome >= 1.0:
return N_("Correct")
else:
return N_("Partially correct")

def reduce(self, outcomes, unused_parameter):
"""See ScoreTypeGroup."""
return sum(outcomes) / len(outcomes)
34 changes: 34 additions & 0 deletions cms/grading/scoretypes/GroupSumCheck.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env python3

# Contest Management System - http://cms-dev.github.io/
# Copyright © 2010-2012 Giovanni Mascellani <[email protected]>
# Copyright © 2010-2018 Stefano Maggiolo <[email protected]>
# Copyright © 2010-2012 Matteo Boscariol <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from cms.grading.scoretypes.GroupSum import GroupSum

class GroupSumCheck(GroupSum):
"""The score of a submission is the sum of group scores,
and each group score is the sum of testcase scores in the group,
except when any testcase scores is negative, the total for the
whole group is zero.
"""

def reduce(self, outcomes, parameter):
"""See ScoreTypeGroup."""
if min(outcomes) < 0: return 0.0
return sum(outcomes) / len(outcomes)

62 changes: 62 additions & 0 deletions cms/grading/scoretypes/GroupSumCond.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env python3

# Contest Management System - http://cms-dev.github.io/
# Copyright © 2010-2012 Giovanni Mascellani <[email protected]>
# Copyright © 2010-2018 Stefano Maggiolo <[email protected]>
# Copyright © 2010-2012 Matteo Boscariol <[email protected]>
# Copyright © 2018 Ahto Truu <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from cms.grading.scoretypes.GroupSum import GroupSum

class GroupSumCond(GroupSum):
"""The score of a submission is the sum of group scores,
and each group score is the sum of testcase scores in the group,
except the scores for "conditional" groups are only given if the
solution gets at least some points for the "unconditional" groups.
Parameters are [[m, t, f], ... ]. See ScoreTypeGroup for m and t.
The flag f must be one of "U", "C", "E":
"U" for unconditional group whose score is always counted,
"C" for conditional group whose score is only counted
if the total for unconditional scores is non-zero,
"E" for examples (these typically don't score points, but even
if they do, they do not affect the conditional groups).

"""

def max_scores(self):
score, public_score, headers = GroupSum.max_scores(self)
for st_idx, parameter in enumerate(self.parameters):
if parameter[2] == "C":
headers[st_idx] += " ***"
return score, public_score, headers

def compute_score(self, submission_result):
score, subtasks, public_score, public_subtasks, ranking_details = GroupSum.compute_score(self, submission_result)
if len(subtasks) == len(self.parameters):
u_score = 0
for st_idx, parameter in enumerate(self.parameters):
if parameter[2] == "U":
u_score += subtasks[st_idx]["score_fraction"] * parameter[0]
if u_score == 0:
for st_idx, parameter in enumerate(self.parameters):
if parameter[2] == "C":
st_score = subtasks[st_idx]["score_fraction"] * parameter[0]
score -= st_score
if public_subtasks[st_idx] == subtasks[st_idx]:
public_score -= st_score
ranking_details[st_idx] = "0"
subtasks[st_idx]["score_ignore"] = True
return score, subtasks, public_score, public_subtasks, ranking_details
4 changes: 2 additions & 2 deletions cms/grading/scoretypes/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class ScoreTypeGroup(ScoreTypeAlone):
N_("N/A")
TEMPLATE = """\
{% for st in details %}
{% if "score_fraction" in st %}
{% if "score_ignore" not in st and "score_fraction" in st %}
{% if st["score_fraction"] >= 1.0 %}
<div class="subtask correct">
{% elif st["score_fraction"] <= 0.0 %}
Expand All @@ -220,7 +220,7 @@ class ScoreTypeGroup(ScoreTypeAlone):
<span class="title">
{% trans index=st["idx"] %}Subtask {{ index }}{% endtrans %}
</span>
{% if "score_fraction" in st and "max_score" in st %}
{% if "score_ignore" not in st and "score_fraction" in st and "max_score" in st %}
{% set score = st["score_fraction"] * st["max_score"] %}
<span class="score">
({{ score|round(2)|format_decimal }}
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ def run(self):
"Sum=cms.grading.scoretypes.Sum:Sum",
"GroupMin=cms.grading.scoretypes.GroupMin:GroupMin",
"GroupMul=cms.grading.scoretypes.GroupMul:GroupMul",
"GroupSum=cms.grading.scoretypes.GroupSum:GroupSum",
"GroupSumCheck=cms.grading.scoretypes.GroupSumCheck:GroupSumCheck",
"GroupSumCond=cms.grading.scoretypes.GroupSumCond:GroupSumCond",
"GroupThreshold=cms.grading.scoretypes.GroupThreshold:GroupThreshold",
],
"cms.grading.languages": [
Expand Down