Skip to content
Snippets Groups Projects
Commit d4c9d0fc authored by Jiří Setnička's avatar Jiří Setnička
Browse files

Util: Funkce na parsování a kontrolu bodů

Přijímají body s desetinnou tečkou i čárkou, vrací Decimal. Lze jim dát
úlohu (pro kontrolu maxima) a kolo (pro kontrolu přesnosti bodování).
parent 01dfc3ab
No related branches found
No related tags found
1 merge request!51Desetinné body
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from dataclasses import dataclass from dataclasses import dataclass
import datetime import datetime
import decimal
import dateutil.tz import dateutil.tz
import email.message import email.message
import email.headerregistry import email.headerregistry
...@@ -12,13 +13,14 @@ import re ...@@ -12,13 +13,14 @@ import re
import secrets import secrets
import subprocess import subprocess
import sys import sys
from typing import Any, Optional, NoReturn from typing import Any, Optional, NoReturn, Tuple
import textwrap import textwrap
import urllib.parse import urllib.parse
import mo import mo
import mo.db as db import mo.db as db
import mo.config as config import mo.config as config
from mo.util_format import format_decimal
# Uživatel, který se uvádí jako pachatel v databázovém logu # Uživatel, který se uvádí jako pachatel v databázovém logu
current_log_user: Optional[db.User] = None current_log_user: Optional[db.User] = None
...@@ -209,3 +211,35 @@ def normalize_grade(grade: str) -> int: ...@@ -209,3 +211,35 @@ def normalize_grade(grade: str) -> int:
return -1 return -1
except ValueError: except ValueError:
return -1 return -1
def parse_points(
raw_points: str, for_task: Optional[db.Task] = None, for_round: Optional[db.Round] = None,
) -> Tuple[Optional[decimal.Decimal], Optional[str]]:
"""Naparsuje a zkontroluje body. Vrátí body (jako decimal.Decimal nebo None
při prázdných bodech) a případný error (None pokud nenastal, jinak text chyby)."""
if raw_points == "":
return None, None
try:
points = decimal.Decimal(raw_points.replace(',', '.'))
except decimal.InvalidOperation:
return 0, f"Hodnota '{raw_points}' není číslo"
return points, check_points(points, for_task, for_round)
def check_points(points: decimal.Decimal, for_task: Optional[db.Task] = None, for_round: Optional[db.Round] = None) -> Optional[str]:
"""Zkontroluje body. Pokud je vše ok, tak vrátí None, jinak vrátí text chyby."""
if points < 0:
return f'Nelze zadat záporné body (zadáno {format_decimal(points)})'
if for_task and for_task.max_points is not None and points > for_task.max_points:
return f'Maximální počet bodů za úlohu je {format_decimal(for_task.max_points)}, nelze zadat více (zadáno {format_decimal(points)})'
if for_round and (points % for_round.master.points_step) != 0:
points_step = for_round.master.points_step
if points_step == 1:
return f'Podle nastavení kola lze zadat pouze celé body (hodnota {points} je neplatná)'
elif points_step == 0.5:
return f'Podle nastavení kola nelze zadat body s libovolnými desetinami, pouze půlbody (hodnota {points} je neplatná)'
else:
return f'Podle nastavení kola zadat body jen s krokem {points_step} (hodnota {points} je neplatná)'
return None
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment