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 @@
from dataclasses import dataclass
import datetime
import decimal
import dateutil.tz
import email.message
import email.headerregistry
......@@ -12,13 +13,14 @@ import re
import secrets
import subprocess
import sys
from typing import Any, Optional, NoReturn
from typing import Any, Optional, NoReturn, Tuple
import textwrap
import urllib.parse
import mo
import mo.db as db
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
current_log_user: Optional[db.User] = None
......@@ -209,3 +211,35 @@ def normalize_grade(grade: str) -> int:
return -1
except ValueError:
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