Skip to content

Commit 665024a

Browse files
Dodano kompaktową checklistę na górze README
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
1 parent 1747222 commit 665024a

File tree

5 files changed

+393
-3
lines changed

5 files changed

+393
-3
lines changed

.github/workflows/checklist.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
run: |
2727
git config user.name "github-actions[bot]"
2828
git config user.email "github-actions[bot]@users.noreply.github.com"
29-
git add README.md checklista/tasks.json
29+
git add README.md checklista/tasks.json checklista/oi_progress.svg
3030
# Amend the last commit and add the bot as a co-author
3131
git commit --amend --no-edit -m "$(git log -1 --pretty=%B)
3232

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
![Progres OI](checklista/oi_progress.svg)
2+
13
# Materiały przygotowujące do Olimpiady Informatycznej.
24

35
## Repozytorium ma na celu:

checklista/gen_svg.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import json
2+
3+
# --- wczytywanie danych ---
4+
with open("tasks.json", "r", encoding="utf-8") as f:
5+
data = json.load(f)
6+
7+
MAX_ETAP = {1: 150, 2: 157, 3: 200}
8+
9+
def etap1_tasks(edycja):
10+
if edycja == 1: return 3
11+
if edycja <= 9: return 4
12+
if edycja <= 31: return 5
13+
return 6
14+
15+
def etap2_tasks(edycja):
16+
if edycja == 1: return 3
17+
if edycja == 3: return 4
18+
return 5
19+
20+
def etap3_tasks(edycja):
21+
if edycja == 27: return 0
22+
if edycja == 1: return 4
23+
if edycja in [2,3]: return 5
24+
if edycja in [6,7,8,9,10,11,13,14,15,16,24]: return 6
25+
if edycja == 25: return 8
26+
return 7
27+
28+
MAX_EDYCJA_ETAP = {etap: {edycja: 0 for edycja in range(1,33)} for etap in [1,2,3]}
29+
MAX_EDYCJA = {i: etap1_tasks(i)+etap2_tasks(i)+etap3_tasks(i) for i in range(1,33)}
30+
for edycja in range(1,33):
31+
MAX_EDYCJA_ETAP[1][edycja] = etap1_tasks(edycja)
32+
MAX_EDYCJA_ETAP[2][edycja] = etap2_tasks(edycja)
33+
MAX_EDYCJA_ETAP[3][edycja] = etap3_tasks(edycja)
34+
35+
# --- liczniki ---
36+
wbite_etap = {i:0 for i in range(1,4)}
37+
wbite_edycja = {i:0 for i in range(1,33)}
38+
wbite_etap_edycja = {etap: {edycja:0 for edycja in range(1,33)} for etap in [1,2,3]}
39+
40+
for entry in data.values():
41+
etap = entry["etap"]
42+
edycja = entry["edycja"]
43+
punkty = entry["punkty"]
44+
if punkty == 100:
45+
wbite_etap[etap] += 1
46+
wbite_edycja[edycja] += 1
47+
wbite_etap_edycja[etap][edycja] += 1
48+
49+
def percent(numerator, denominator):
50+
return int(100 * numerator / denominator) if denominator else 0
51+
52+
def color_for_pct(pct):
53+
if pct >= 100:
54+
return "gold"
55+
elif pct > 0:
56+
alpha = pct / 100
57+
return f'rgba(0,255,0,{alpha:.2f})'
58+
else:
59+
return 'rgba(0,0,0,0)'
60+
61+
def to_roman(n):
62+
vals = [
63+
(10, "X"), (9, "IX"), (8, "VIII"), (7,"VII"), (6,"VI"),
64+
(5,"V"), (4,"IV"), (3,"III"), (2,"II"), (1,"I")
65+
]
66+
res = ""
67+
for val, sym in vals:
68+
while n >= val:
69+
res += sym
70+
n -= val
71+
return res
72+
73+
UNIT = 20
74+
GAP = 3
75+
BLOCK_GAP = 20
76+
CENTRAL_SCALE = 3
77+
num_editions = len(MAX_EDYCJA)
78+
79+
central_size = 3*UNIT + 2*GAP
80+
width = central_size + BLOCK_GAP + 2*UNIT + BLOCK_GAP + num_editions*(UNIT+GAP) + 20
81+
height = central_size + 15 # zostawimy miejsce na rzymskie cyfry
82+
83+
total_done = sum(wbite_etap.values())
84+
total_max = sum(MAX_ETAP.values())
85+
center_pct = percent(total_done, total_max)
86+
87+
svg_parts = [f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}">']
88+
89+
# centralny kwadrat
90+
svg_parts.append(f'<rect x="0" y="0" width="{central_size}" height="{central_size}" fill="{color_for_pct(center_pct)}" stroke="white" stroke-width="1"/>')
91+
svg_parts.append(f'<text x="{central_size/2}" y="{central_size/2}" text-anchor="middle" dominant-baseline="middle" font-size="20" fill="white" font-family="monospace">{center_pct}%</text>')
92+
93+
# prostokąty etapów z napisami
94+
etap_labels = {1: "I", 2: "II", 3: "III"}
95+
x0 = central_size + BLOCK_GAP + 4
96+
for i, etap in enumerate([1,2,3]):
97+
y0 = i*(UNIT + GAP)
98+
pct = percent(wbite_etap[etap], MAX_ETAP[etap])
99+
svg_parts.append(f'<rect x="{x0}" y="{y0}" width="{2*UNIT}" height="{UNIT}" fill="{color_for_pct(pct)}" stroke="white" stroke-width="1">')
100+
svg_parts.append(f'<title>{etap} Etap – {pct}%</title></rect>')
101+
# numer etapu.
102+
svg_parts.append(f'<text x="{x0 - (BLOCK_GAP + 4) / 2}" y="{y0 + UNIT/2}" text-anchor="middle" dominant-baseline="middle" font-size="10" fill="white" font-family="monospace">{etap_labels[etap]}</text>')
103+
# procent w środku boxa.
104+
svg_parts.append(f'<text x="{x0 + UNIT}" y="{y0 + UNIT/2}" text-anchor="middle" dominant-baseline="middle" font-size="10" fill="white" font-family="monospace">{pct}%</text>')
105+
106+
# kwadraty edycji z tooltipami
107+
x0 = central_size + BLOCK_GAP / 2 + 2*UNIT + BLOCK_GAP
108+
for e_idx, edycja in enumerate(range(1, num_editions+1)):
109+
x_pos = x0 + e_idx*(UNIT+GAP)
110+
for etap in [1,2,3]:
111+
y0 = (etap-1)*(UNIT + GAP)
112+
pct = percent(wbite_etap_edycja[etap][edycja], MAX_EDYCJA_ETAP[etap][edycja])
113+
svg_parts.append(f'<rect x="{x_pos}" y="{y0}" width="{UNIT}" height="{UNIT}" fill="{color_for_pct(pct)}" stroke="white" stroke-width="1">')
114+
svg_parts.append(f'<title>{etap} Etap {edycja} OI – {pct}%</title></rect>')
115+
# rzymska cyfra pod kolumną
116+
svg_parts.append(f'<text x="{x_pos + UNIT/2}" y="{central_size + 12}" text-anchor="middle" dominant-baseline="middle" font-size="5" fill="white" font-family="monospace">{to_roman(edycja)}</text>')
117+
118+
svg_parts.append('</svg>')
119+
120+
with open("oi_progress.svg", "w", encoding="utf-8") as f:
121+
f.write("\n".join(svg_parts))
122+

0 commit comments

Comments
 (0)