Skip to content

Commit b3b668d

Browse files
committed
make floating point accuracy configurable per question instead of hard coded to 10
1 parent 478817b commit b3b668d

5 files changed

Lines changed: 63 additions & 8 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Add accuracy to question
2+
3+
Revision ID: dbb90e86e357
4+
Revises: 54d9cfe74362
5+
Create Date: 2025-11-26 14:59:58.073951
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
import sqlmodel
13+
14+
15+
# revision identifiers, used by Alembic.
16+
revision: str = 'dbb90e86e357'
17+
down_revision: Union[str, Sequence[str], None] = '54d9cfe74362'
18+
branch_labels: Union[str, Sequence[str], None] = None
19+
depends_on: Union[str, Sequence[str], None] = None
20+
21+
22+
def upgrade() -> None:
23+
"""Upgrade schema."""
24+
# ### commands auto generated by Alembic - please adjust! ###
25+
op.add_column('question', sa.Column('accuracy', sa.Integer(), nullable=False, server_default="10"))
26+
# ### end Alembic commands ###
27+
28+
29+
def downgrade() -> None:
30+
"""Downgrade schema."""
31+
# ### commands auto generated by Alembic - please adjust! ###
32+
op.drop_column('question', 'accuracy')
33+
# ### end Alembic commands ###

app/api/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class QuestionBase(SQLModel):
4141
max_score_display: str
4242
number: int = Field(unique=True)
4343
visible: bool = Field(default=False)
44+
# number of decimals after the point that need to match the solution.
45+
accuracy: int = Field(default=10)
4446

4547

4648
# Shared properties

app/api/routes.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class TeamQuestion:
138138
(
139139
s
140140
for s in question_submissions
141-
if is_answer_correct(s.answer, question.solution)
141+
if is_answer_correct(s.answer, question.solution, question.accuracy)
142142
),
143143
None,
144144
)
@@ -203,7 +203,9 @@ class SubmissionCorrect:
203203
submissions = list(
204204
map(
205205
lambda s: SubmissionCorrect(
206-
s.timestamp, s.answer, is_answer_correct(s.answer, question.solution)
206+
s.timestamp,
207+
s.answer,
208+
is_answer_correct(s.answer, question.solution, question.accuracy),
207209
),
208210
submissions,
209211
)
@@ -356,7 +358,7 @@ class TeamAnswer:
356358
(
357359
s
358360
for s in question_submissions
359-
if is_answer_correct(s.answer, question.solution)
361+
if is_answer_correct(s.answer, question.solution, question.accuracy)
360362
),
361363
None,
362364
)
@@ -754,7 +756,7 @@ async def admin_answers_csv(request: Request, session: SessionDep, auth: AdminDe
754756
team_name,
755757
question_no,
756758
i.answer,
757-
is_answer_correct(question.solution, i.answer),
759+
is_answer_correct(question.solution, i.answer, question.accuracy),
758760
]
759761
)
760762

app/api/utils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def get_question_score(
2222
) -> float:
2323
for submission in question_submissions:
2424
assert submission.question_id == question.id
25-
if is_answer_correct(submission.answer, question.solution):
25+
if is_answer_correct(submission.answer, question.solution, question.accuracy):
2626
return 0.9 ** (len(question_submissions) - 1) * question.max_score
2727

2828
return 0.0
@@ -78,14 +78,14 @@ def encoded_logo(logo: Image.Image) -> str:
7878
return base64.b64encode(bytes.getvalue()).decode()
7979

8080

81-
def is_answer_correct(a: str, b: str) -> bool:
81+
def is_answer_correct(a: str, b: str, accuracy: int = 10) -> bool:
8282
if "." not in a and a == b:
8383
return True
8484
if a.count(".") == 1 and b.count(".") == 1:
8585
split_a = a.split(".")
8686
split_b = b.split(".")
87-
after_decimal_a = textwrap.wrap(split_a[1], 10)[0]
88-
after_decimal_b = textwrap.wrap(split_b[1], 10)[0]
87+
after_decimal_a = textwrap.wrap(split_a[1], accuracy)[0]
88+
after_decimal_b = textwrap.wrap(split_b[1], accuracy)[0]
8989
if split_a[0] == split_b[0] and after_decimal_a == after_decimal_b:
9090
return True
9191
return False

app/templates/pages/admin_question_form.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,24 @@
8484
/>
8585
</label>
8686

87+
<label>
88+
Accuracy
89+
<input
90+
type="number"
91+
name="accuracy"
92+
aria-describedby="accuracy-helper"
93+
required
94+
{% if question %}
95+
value="{{ question.accuracy }}"
96+
{% else %}
97+
value="10"
98+
{% endif %}
99+
/>
100+
<small id="accuracy-helper">
101+
Number of decimals after the point where submissions need to exactly match the given solution.
102+
</small>
103+
</label>
104+
87105
<label>
88106
Visible
89107
<input

0 commit comments

Comments
 (0)