"The Royal Scribe's Secret" — Story-Driven String Indexing & Slicing Module - #80
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a self-contained, story-driven static web module under summership-26-prs/Ayush_Anand/ to teach Python string indexing and slicing through an 8-stage interactive lesson (vanilla HTML/CSS/JS, no backend).
Changes:
- Introduces lesson content/data (
lessonData.js) and a small client-side engine (state, rendering, interactions, navigation). - Adds a themed UI (stone-tablet interactions, progress bar, feedback states) implemented via new CSS and HTML.
- Adds supporting docs (README + product/context/change documents) describing pedagogy, structure, and testing approach.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| summership-26-prs/Ayush_Anand/index.html | Static entrypoint wiring CSS + JS in load order and defining layout shell. |
| summership-26-prs/Ayush_Anand/js/lessonData.js | Stage content, prompts, correct answers, and explanations for the full module. |
| summership-26-prs/Ayush_Anand/js/lessonEngine.js | Step state machine and completion gating for Back/Next navigation. |
| summership-26-prs/Ayush_Anand/js/renderer.js | Renders the current step’s UI and mounts it into the lesson card. |
| summership-26-prs/Ayush_Anand/js/interactions.js | Event handlers, answer checking, feedback, and progression unlock logic. |
| summership-26-prs/Ayush_Anand/js/navigation.js | Progress bar + footer controls and module bootstrapping. |
| summership-26-prs/Ayush_Anand/css/base.css | Global reset, theme tokens, typography, and layout skeleton. |
| summership-26-prs/Ayush_Anand/css/inscription.css | Tablet/inscription visuals, code panel styling, and header/progress styling. |
| summership-26-prs/Ayush_Anand/css/components.css | Reusable UI components (choices, feedback panels, nav buttons, task cards). |
| summership-26-prs/Ayush_Anand/README.md | Usage instructions, learning flow, and module structure overview. |
| summership-26-prs/Ayush_Anand/product.md | Product framing: problem/solution, learner profile, and objectives. |
| summership-26-prs/Ayush_Anand/context.md | Pedagogical and narrative context tying story beats to string concepts. |
| summership-26-prs/Ayush_Anand/change.md | Change log, design decisions, and testing notes for the contribution. |
Suppressed comments (8)
summership-26-prs/Ayush_Anand/README.md:53
- The project structure block lists the root folder as
Royal-Scribes-Secret/, but in this PR the module lives undersummership-26-prs/Ayush_Anand/. Updating the root label avoids confusion when reviewers compare docs to the repo layout.
Royal-Scribes-Secret/
├── index.html
summership-26-prs/Ayush_Anand/js/interactions.js:19
codePanelHtml(..., true)intentionally omitsreveal.explanation, but callers never pass an explanation toreveal(...), so learners never see the stage explanations fromlessonData.js. One fix is to enhancereveal()to insert the explanation (once) when provided.
function reveal(panelId, explanationAfter) {
const panel = document.getElementById(panelId);
if (panel) panel.classList.remove('hidden');
if (explanationAfter) {
const p = document.createElement('p');
summership-26-prs/Ayush_Anand/js/interactions.js:71
- The stage explanation isn’t shown after a correct answer because
reveal('reveal-panel')is called without the explanation text. Passstep.reveal.explanationso learners see the intended concept summary.
tile.classList.add('is-correct');
feedback(feedbackSlot, `Correct — "${step.message[idx]}" is the character at position ${idx}.`, true);
reveal('reveal-panel');
completeAndRefresh(step.id);
summership-26-prs/Ayush_Anand/js/interactions.js:136
- Stage 3’s reveal panel is shown, but its explanation text is never inserted because
reveal('reveal-panel')is called without an explanation. Passstep.reveal.explanationso the slicing explanation appears.
function initSliceChallenge(step, card) {
bindRangeSelector(card, step.message, step.targetStart, step.targetEndInclusive, () => {
reveal('reveal-panel');
completeAndRefresh(step.id);
});
summership-26-prs/Ayush_Anand/js/interactions.js:201
- Stage 4’s second reveal panel (
reveal-panel-word) is shown without insertingwordReveal.explanation, so learners miss the explanation ofmessage[-6:]. Pass the explanation intoreveal(...).
const word = step.message.slice(start, end + 1);
feedback(feedbackSlotWord, `Correct — you selected "${word}", positions ${start} through ${end}.`, true);
reveal('reveal-panel-word');
phase = 'done';
completeAndRefresh(step.id);
summership-26-prs/Ayush_Anand/js/interactions.js:237
- Stage 5 shows the reveal panel but never displays the explanation because
reveal('reveal-panel')is called withoutstep.reveal.explanation.
if (i === step.correctIndex) {
btn.classList.add('is-correct');
feedback(feedbackSlot, 'Correct — read backward, the tablet warns: "BEWARE OF THE SERPENT".', true);
reveal('reveal-panel');
completeAndRefresh(step.id);
} else {
summership-26-prs/Ayush_Anand/js/interactions.js:165
- Stage 4’s first reveal panel is shown without inserting its
lastCharReveal.explanation, so the negative-indexing explanation never appears. Pass the explanation intoreveal(...).
if (idx === step.lastCharTarget) {
tile.classList.add('is-correct');
feedback(feedbackSlot, `Correct — that is the last character, "${step.message[idx]}".`, true);
reveal('reveal-panel');
wordPhase.classList.remove('hidden');
phase = 'last-word';
summership-26-prs/Ayush_Anand/js/interactions.js:273
- Stage 6 shows the reveal panel but never displays the explanation because
reveal('reveal-panel')is called withoutstep.reveal.explanation.
if (solved.size === step.tasks.length) {
reveal('reveal-panel');
completeAndRefresh(step.id);
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| 1. Open `index.html` directly in any modern browser, **or** | ||
| 2. Serve the folder locally, e.g.: | ||
| ``` | ||
| npx serve summership-26-prs/Shiv/Royal-Scribes-Secret | ||
| ``` |
| function feedback(el, message, isSuccess) { | ||
| if (!el) return; | ||
| el.innerHTML = `<div class="feedback-panel ${isSuccess ? 'is-success' : 'is-error'}">${message}</div>`; | ||
| } | ||
|
|
||
| function reveal(panelId, explanationAfter) { | ||
| const panel = document.getElementById(panelId); | ||
| if (panel) panel.classList.remove('hidden'); | ||
| if (explanationAfter) { |
| All files are new; nothing in the existing PyBe application (client, server, or other `summership-26-prs/` contributions) was modified. | ||
|
|
||
| ``` | ||
| summership-26-prs/Shiv/Royal-Scribes-Secret/ |
Overview
This PR adds The Royal Scribe's Secret, a standalone interactive learning module that teaches Python string indexing and slicing through a story-driven experience set in the fictional kingdom of Suryagarh.
Learning Concepts
The module introduces:
Strings as ordered sequences of characters
Positive indexing
Negative indexing
String slicing
Reverse slicing
Basic string manipulation
Learning Flow
The learner progresses through 8 stages:
The Mysterious Inscription
Every Character Has a Place
The Hidden Word
The Scribe's Shortcut
The Reversed Inscription
Repair the Royal Message
Royal Codebreaker Training
The Final Cipher
The module follows a story-first, concept-before-syntax approach, allowing learners to encounter the problem first and discover the corresponding Python concept through guided interaction.
Implementation
The contribution is self-contained under:
summership-26-prs/Ayush_Anand/
It uses vanilla HTML, CSS, and JavaScript and does not require a backend, database, external API, or additional dependencies.
Included documentation:
README.md
product.md
context.md
change.md
Testing
The module was tested through a complete walkthrough of all learning stages, including correct and incorrect answer paths, navigation, practice activities, and the final assessment.