Skip to content

Commit 6ad024c

Browse files
committed
refactor scoreboard: replace threads-config.yml with points-info.yml; extend scoring with reports section
1 parent c03fa17 commit 6ad024c

File tree

16 files changed

+392
-84
lines changed

16 files changed

+392
-84
lines changed

scoreboard/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Generates `output_directory/index.html` with the scoreboard.
1616

1717
## Configuration
1818

19-
- `data/threads-config.yml` - Task points, deadlines, penalties
19+
- `data/points-info.yml` - Task points, deadlines, penalties
2020
- `data/plagiarism.yml` - Flagged submissions
2121

2222
## Testing

scoreboard/assign_variant.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# file: assign_variant.py
2+
"""
3+
Deterministic variant assignment from Full Name + Group
4+
with the repository name as the ONLY salt.
5+
6+
Algorithm:
7+
1) Normalize strings (NFKC, trim, lowercase, map 'ё'->'е', collapse spaces).
8+
2) Build a key: "surname|name|patronymic|group|repo".
9+
3) SHA-256(key) -> big integer -> modulo `num_variants`.
10+
11+
Properties:
12+
- Stable: same inputs → same output.
13+
- Uniform: modulo of a cryptographic hash distributes evenly.
14+
- Note: Without the full group roster, zero collisions cannot be *guaranteed*
15+
(birthday paradox). This is intended for “approximately unique” per-group use.
16+
17+
Usage:
18+
from assign_variant import assign_variant
19+
v = assign_variant(
20+
surname="Petrov",
21+
name="Pyotr",
22+
patronymic="Petrovich",
23+
group="MEN-201",
24+
repo="learning-process/parallel_programming_course",
25+
num_variants=31, # produces values in 0..30
26+
)
27+
print(v)
28+
"""
29+
30+
from __future__ import annotations
31+
32+
import hashlib
33+
import re
34+
import unicodedata
35+
from typing import Optional
36+
37+
__all__ = ["assign_variant", "normalize"]
38+
39+
40+
def normalize(s: Optional[str]) -> str:
41+
"""
42+
Normalize a string:
43+
- Unicode NFKC,
44+
- trim,
45+
- lowercase,
46+
- map Cyrillic 'ё' -> 'е' (common normalization in Russian names),
47+
- collapse multiple spaces to a single space.
48+
49+
None -> '' (empty string).
50+
"""
51+
if not s:
52+
return ""
53+
s = unicodedata.normalize("NFKC", s).strip().lower()
54+
s = s.replace("ё", "е")
55+
s = re.sub(r"\s+", " ", s)
56+
return s
57+
58+
59+
def _hash_int(key: str) -> int:
60+
"""Return SHA-256(key) as a big integer."""
61+
return int.from_bytes(hashlib.sha256(key.encode("utf-8")).digest(), "big")
62+
63+
64+
def assign_variant(
65+
surname: str,
66+
name: str,
67+
group: str,
68+
repo: str,
69+
patronymic: Optional[str] = "",
70+
num_variants: int = 31,
71+
) -> int:
72+
"""
73+
Deterministically returns a variant index in [0 .. num_variants-1]
74+
based on (surname, name, patronymic, group) and the repository name (repo)
75+
as the sole salt.
76+
77+
:param surname: Last name
78+
:param name: First name
79+
:param group: Group identifier (e.g., "MEN-201")
80+
:param repo: Repository name used as salt (e.g., "org/repo" or just "repo")
81+
:param patronymic: Middle name / patronymic (optional)
82+
:param num_variants: Total number of variants (> 0). Output range: 0..num_variants-1
83+
:return: int — the variant index
84+
"""
85+
if not isinstance(num_variants, int) or num_variants < 1:
86+
raise ValueError("num_variants must be a positive integer (> 0)")
87+
if not repo or not isinstance(repo, str):
88+
raise ValueError("repo must be a non-empty string")
89+
90+
key = "|".join(
91+
(
92+
normalize(surname),
93+
normalize(name),
94+
normalize(patronymic),
95+
normalize(group),
96+
normalize(repo),
97+
)
98+
)
99+
h = _hash_int(key)
100+
return h % num_variants
101+
102+
103+
# Minimal self-check when executed directly (no CLI arguments).
104+
if __name__ == "__main__":
105+
def demo():
106+
print("Demo: deterministic assignment\n")
107+
108+
v1 = assign_variant(
109+
surname="Петров",
110+
name="Пётр",
111+
patronymic="Петрович",
112+
group="МЕН-201",
113+
repo="learning-process/parallel_programming_course",
114+
num_variants=31,
115+
)
116+
# Different casing/spacing/ё→е should not change the result:
117+
v2 = assign_variant(
118+
surname="ПЕТРОВ",
119+
name="петр ",
120+
patronymic="пЕТРОВИЧ",
121+
group=" мен-201 ",
122+
repo="learning-process/parallel_programming_course",
123+
num_variants=31,
124+
)
125+
assert v1 == v2, "Normalization should make results identical"
126+
127+
v_other_repo = assign_variant(
128+
surname="Petrov",
129+
name="Pyotr",
130+
patronymic="Petrovich",
131+
group="MEN-201",
132+
repo="learning-process/ppc_2025_fall", # different salt → likely different value
133+
num_variants=31,
134+
)
135+
136+
print(f"Variant (repo=A): {v1}")
137+
print(f"Variant (same inputs, normalized): {v2}")
138+
print(f"Variant (repo=B): {v_other_repo}")
139+
print("\nOK: deterministic & normalized.")
140+
141+
demo()

scoreboard/data/performance.yml

Lines changed: 0 additions & 1 deletion
This file was deleted.

scoreboard/data/plagiarism.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,11 @@ plagiarism:
66
stl: []
77
tbb: []
88
all: []
9+
10+
deadlines:
11+
mpi: "2025-12-31"
12+
omp: "2025-12-31"
13+
seq: "2025-12-31"
14+
stl: "2025-12-31"
15+
tbb: "2025-12-31"
16+
all: "2025-12-31"

scoreboard/data/points-info.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
processes:
2+
semester_total: 70
3+
tasks:
4+
- name: mpi_task_1
5+
mpi:
6+
- S: 8
7+
- A: 0
8+
seq:
9+
- S: 2
10+
R: 2
11+
variants_max: 27
12+
Total: 12
13+
- name: mpi_task_2
14+
mpi:
15+
- S: 12
16+
- A: 5
17+
seq:
18+
- S: 3
19+
R: 3
20+
variants_max: 23
21+
Total: 23
22+
- name: mpi_task_3
23+
mpi:
24+
- S: 16
25+
- A: 10
26+
seq:
27+
- S: 4
28+
R: 5
29+
variants_max: 32
30+
Total: 35
31+
threads:
32+
semester_total: 64
33+
variants_max: 30
34+
tasks:
35+
- name: seq
36+
S: 4
37+
R: 1
38+
Total: 5
39+
- name: omp
40+
S: 6
41+
A: 3
42+
R: 2
43+
Total: 11
44+
- name: tbb
45+
S: 6
46+
A: 3
47+
R: 2
48+
Total: 11
49+
- name: stl
50+
S: 8
51+
A: 6
52+
R: 2
53+
Total: 16
54+
- name: all
55+
S: 10
56+
A: 8
57+
R: 3
58+
Total: 21
59+
efficiency:
60+
num_proc: 4
61+
plagiarism:
62+
coefficient: 0.5
63+
note: "Penalty P = -coefficient * S (scoreboard notation)"

scoreboard/data/threads-config.yml

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)