|
1 | 1 | import os |
2 | | -import re |
| 2 | +import subprocess |
3 | 3 | from datetime import datetime |
4 | | -from zoneinfo import ZoneInfo # built-in since Python 3.9 |
5 | 4 |
|
6 | 5 | README_PATH = "README.md" |
7 | | -FOLDERS = ["Easy", "Medium", "Hard"] |
8 | | -EXT = ".java" |
9 | 6 |
|
10 | | - |
11 | | -def count_by_folder(): |
12 | | - """Return dict of counts per folder and total, counting EXT files recursively.""" |
13 | | - per = {} |
14 | | - total = 0 |
15 | | - for folder in FOLDERS: |
16 | | - c = 0 |
| 7 | +# Count problems |
| 8 | +def count_problems(): |
| 9 | + count = 0 |
| 10 | + for folder in ["Easy", "Medium", "Hard"]: |
17 | 11 | if os.path.exists(folder): |
18 | | - for root, _, files in os.walk(folder): |
19 | | - for f in files: |
20 | | - if f.endswith(EXT): |
21 | | - c += 1 |
22 | | - per[folder] = c |
23 | | - total += c |
24 | | - per["_total"] = total |
25 | | - return per |
26 | | - |
27 | | - |
28 | | -def human_ist_now(): |
29 | | - """Current IST time in human-readable format.""" |
30 | | - ist = datetime.now(ZoneInfo("Asia/Kolkata")) |
31 | | - return ist.strftime("%d %b %Y, %I:%M %p IST") |
32 | | - |
33 | | - |
34 | | -def replace_line(content: str, label: str, new_line: str) -> tuple[str, bool]: |
35 | | - """ |
36 | | - Replace a line starting with the label. |
37 | | - Works for both placeholder and non-placeholder versions. |
38 | | -
|
39 | | - Examples it will match: |
40 | | - Problems solved: <!--PROBLEMS_COUNT-->3 |
41 | | - Problems solved: 3 |
42 | | - Last updated: <!--LAST_UPDATED-->14 Aug 2025, ... |
43 | | - Last updated: 14 Aug 2025, ... |
44 | | - """ |
45 | | - # 1) Prefer placeholder form |
46 | | - placeholder_patterns = [ |
47 | | - rf"(?mi)^{re.escape(label)}\s*:?\s*<!--PROBLEMS_COUNT-->.*$", |
48 | | - rf"(?mi)^{re.escape(label)}\s*:?\s*<!--LAST_UPDATED-->.*$", |
49 | | - ] |
50 | | - for pat in placeholder_patterns: |
51 | | - new_content, n = re.subn(pat, new_line, content) |
52 | | - if n > 0: |
53 | | - return new_content, True |
54 | | - |
55 | | - # 2) Generic form (no placeholder) |
56 | | - generic_pat = rf"(?mi)^{re.escape(label)}\s*:?.*$" |
57 | | - new_content, n = re.subn(generic_pat, new_line, content) |
58 | | - if n > 0: |
59 | | - return new_content, True |
60 | | - |
61 | | - return content, False |
62 | | - |
63 | | - |
64 | | -def ensure_progress_block(content: str, problems_count: int, updated_time: str) -> str: |
65 | | - """Append a progress block if neither line exists anywhere.""" |
66 | | - block = ( |
67 | | - "\n\n🏆 Progress\n\n" |
68 | | - f"Problems solved: <!--PROBLEMS_COUNT-->{problems_count}\n" |
69 | | - f"Last updated: <!--LAST_UPDATED-->{updated_time}\n" |
| 12 | + for file in os.listdir(folder): |
| 13 | + if os.path.isfile(os.path.join(folder, file)): |
| 14 | + count += 1 |
| 15 | + return count |
| 16 | + |
| 17 | +# Get last commit date (latest in repo) |
| 18 | +def last_updated(): |
| 19 | + result = subprocess.run( |
| 20 | + ["git", "log", "-1", "--format=%cd", "--date=iso"], |
| 21 | + capture_output=True, |
| 22 | + text=True |
70 | 23 | ) |
71 | | - return content + block |
72 | | - |
| 24 | + # Convert to human readable format |
| 25 | + dt = datetime.fromisoformat(result.stdout.strip()) |
| 26 | + return dt.strftime("%d %b %Y, %I:%M %p IST") |
73 | 27 |
|
74 | 28 | def update_readme(): |
75 | | - counts = count_by_folder() |
76 | | - total = counts["_total"] |
77 | | - updated_time = human_ist_now() |
78 | | - |
79 | | - # Debug prints to workflow logs |
80 | | - print("[update_readme] Counts:", counts) |
81 | | - print("[update_readme] Total:", total) |
82 | | - print("[update_readme] Time:", updated_time) |
83 | | - |
84 | 29 | with open(README_PATH, "r", encoding="utf-8") as f: |
85 | 30 | content = f.read() |
86 | 31 |
|
87 | | - # Desired lines |
88 | | - solved_line = f"Problems solved: <!--PROBLEMS_COUNT-->{total}" |
89 | | - time_line = f"Last updated: <!--LAST_UPDATED-->{updated_time}" |
90 | | - |
91 | | - changed = False |
92 | | - |
93 | | - content2, changed1 = replace_line(content, "Problems solved", solved_line) |
94 | | - content = content2 |
95 | | - changed = changed or changed1 |
96 | | - |
97 | | - content2, changed2 = replace_line(content, "Last updated", time_line) |
98 | | - content = content2 |
99 | | - changed = changed or changed2 |
100 | | - |
101 | | - if not (changed1 or changed2): |
102 | | - # Neither line existed — append a fresh block |
103 | | - print("[update_readme] Progress block not found; appending a new one.") |
104 | | - content = ensure_progress_block(content, total, updated_time) |
105 | | - changed = True |
| 32 | + problems_count = count_problems() |
| 33 | + updated_time = last_updated() |
| 34 | + |
| 35 | + # Replace only inside the Progress section |
| 36 | + import re |
| 37 | + content = re.sub( |
| 38 | + r"(## 🏆 Progress\s+Problems solved:).*", |
| 39 | + f"## 🏆 Progress\n\nProblems solved: {problems_count}\nLast updated: {updated_time}", |
| 40 | + content, |
| 41 | + count=1, |
| 42 | + flags=re.DOTALL |
| 43 | + ) |
106 | 44 |
|
107 | 45 | with open(README_PATH, "w", encoding="utf-8") as f: |
108 | 46 | f.write(content) |
109 | 47 |
|
110 | | - # Exit code / message for clarity (not strictly required) |
111 | | - if changed: |
112 | | - print("[update_readme] README.md updated.") |
113 | | - else: |
114 | | - print("[update_readme] No changes required.") |
115 | | - |
116 | | - |
117 | 48 | if __name__ == "__main__": |
118 | 49 | update_readme() |
0 commit comments