|
10 | 10 |
|
11 | 11 | from pythonlings.core.exercise import Exercise, RunResult |
12 | 12 | from pythonlings.core.runner import run as run_exercise |
13 | | -from pythonlings.core.state import next_pending, save as save_state |
| 13 | +from pythonlings.core.state import completed_count, next_pending, save as save_state |
14 | 14 | from pythonlings.widgets.editor_pane import EditorPane |
15 | 15 | from pythonlings.widgets.exercise_tree import ExerciseTree |
16 | 16 | from pythonlings.widgets.output_panel import OutputPanel |
|
19 | 19 | _DEBOUNCE_SECONDS = 0.6 |
20 | 20 |
|
21 | 21 |
|
| 22 | +def celebration_message(total: int) -> str: |
| 23 | + """Message shown when every exercise in the curriculum is complete.""" |
| 24 | + return ( |
| 25 | + f"🎉 You finished all {total} pythonlings exercises! 🎉\n\n" |
| 26 | + "That's the whole curriculum — nicely done.\n" |
| 27 | + f"Share it: \"I just completed all {total} pythonlings Python exercises 🎉\"\n" |
| 28 | + "If pythonlings helped, a ⭐ on GitHub or a contribution is hugely appreciated.\n\n" |
| 29 | + "Press Ctrl+Q to quit, or F4 to revisit topics." |
| 30 | + ) |
| 31 | + |
| 32 | + |
22 | 33 | class TrackScreen(Screen[None]): |
23 | 34 | """One topic's linear track: editor + output + auto-save loop.""" |
24 | 35 |
|
@@ -82,7 +93,13 @@ def _initial_exercise(self) -> str | None: |
82 | 93 | def _render_state(self) -> None: |
83 | 94 | exs = self._exercises() |
84 | 95 | done = sum(1 for ex in exs if ex.name in self.app.state.completed) |
85 | | - self.query_one(ProgressBar).update_progress(done, len(exs)) |
| 96 | + all_exercises = self.app.manifest.exercises |
| 97 | + overall_done = completed_count( |
| 98 | + (ex.name for ex in all_exercises), self.app.state.completed |
| 99 | + ) |
| 100 | + self.query_one(ProgressBar).update_progress( |
| 101 | + done, len(exs), overall_done, len(all_exercises) |
| 102 | + ) |
86 | 103 | self.query_one(ExerciseTree).render_topic( |
87 | 104 | self.topic, exs, self.app.state.completed, self.current |
88 | 105 | ) |
@@ -175,9 +192,15 @@ def _apply_result(self, exercise: Exercise, result: RunResult) -> None: |
175 | 192 | self._render_state() |
176 | 193 | if self.current is None: |
177 | 194 | self._record_resume(None) |
178 | | - self.query_one(OutputPanel).show_final( |
179 | | - f"Topic '{self.topic}' complete — press F4 for topics." |
180 | | - ) |
| 195 | + all_exercises = self.app.manifest.exercises |
| 196 | + if next_pending(all_exercises, self.app.state.completed) is None: |
| 197 | + self.query_one(OutputPanel).show_final( |
| 198 | + celebration_message(len(all_exercises)) |
| 199 | + ) |
| 200 | + else: |
| 201 | + self.query_one(OutputPanel).show_final( |
| 202 | + f"Topic '{self.topic}' complete — press F4 for topics." |
| 203 | + ) |
181 | 204 | return |
182 | 205 | self._load_current() |
183 | 206 | self._run_current() |
|
0 commit comments