Initial decks site
This commit is contained in:
commit
666218035c
25 changed files with 3111 additions and 0 deletions
Binary file not shown.
BIN
learning-outcomes-assessment/assets/clips/attention-reset.mp4
Normal file
BIN
learning-outcomes-assessment/assets/clips/attention-reset.mp4
Normal file
Binary file not shown.
Binary file not shown.
BIN
learning-outcomes-assessment/assets/clips/learning-outcomes.mp4
Normal file
BIN
learning-outcomes-assessment/assets/clips/learning-outcomes.mp4
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
learning-outcomes-assessment/assets/posters/activities.jpg
Normal file
BIN
learning-outcomes-assessment/assets/posters/activities.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
learning-outcomes-assessment/assets/posters/assessment.jpg
Normal file
BIN
learning-outcomes-assessment/assets/posters/assessment.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
learning-outcomes-assessment/assets/posters/attention.jpg
Normal file
BIN
learning-outcomes-assessment/assets/posters/attention.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
learning-outcomes-assessment/assets/posters/motivation.jpg
Normal file
BIN
learning-outcomes-assessment/assets/posters/motivation.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
learning-outcomes-assessment/assets/posters/outcomes.jpg
Normal file
BIN
learning-outcomes-assessment/assets/posters/outcomes.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
BIN
learning-outcomes-assessment/assets/posters/teaching.jpg
Normal file
BIN
learning-outcomes-assessment/assets/posters/teaching.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
462
learning-outcomes-assessment/index.html
Normal file
462
learning-outcomes-assessment/index.html
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Redesign the Course - A Playable Teaching Essay</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="A playable long-form learning experience about moving a course from topic coverage to aligned learning."
|
||||
>
|
||||
<link rel="stylesheet" href="styles.css?v=2">
|
||||
<script defer src="script.js?v=2"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a class="skip-link" href="#main">Skip to the experience</a>
|
||||
<div class="progress-line" aria-hidden="true"><span></span></div>
|
||||
|
||||
<header class="topbar">
|
||||
<a href="#top" class="brand" aria-label="Redesign the Course home">
|
||||
<span class="mark">RC</span>
|
||||
<span>Redesign the Course</span>
|
||||
</a>
|
||||
<nav aria-label="Experience sections">
|
||||
<a href="#diagnose">Diagnose</a>
|
||||
<a href="#outcomes">Outcomes</a>
|
||||
<a href="#alignment">Alignment</a>
|
||||
<a href="#class-session">Class</a>
|
||||
<a href="#feedback">Feedback</a>
|
||||
<a href="#launch">Launch</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
<section class="hero scene" id="top">
|
||||
<div class="hero-copy">
|
||||
<p class="eyebrow">A course-design simulation in essay form</p>
|
||||
<h1>The Course That Covers Everything</h1>
|
||||
<p class="lede">
|
||||
You inherit a course that looks complete. Students still cannot use it. Your job is to
|
||||
redesign one course file, and every choice changes the same first class and the same learner.
|
||||
</p>
|
||||
<div class="hero-actions">
|
||||
<a class="primary-link" href="#diagnose">Open the course file</a>
|
||||
<button type="button" class="ghost-link" data-action="reset">Reset design</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-art" aria-label="A course file being redesigned from topics to learning" role="img">
|
||||
<div class="folder">
|
||||
<div class="folder-tab">Data Structures I</div>
|
||||
<div class="folder-page page-a">
|
||||
<strong>Old syllabus</strong>
|
||||
<span>arrays</span>
|
||||
<span>lists</span>
|
||||
<span>trees</span>
|
||||
<span>graphs</span>
|
||||
<span>hashing</span>
|
||||
</div>
|
||||
<div class="folder-page page-b">
|
||||
<strong>What students must do</strong>
|
||||
<span>choose a structure</span>
|
||||
<span>analyze a tradeoff</span>
|
||||
<span>debug a traversal</span>
|
||||
</div>
|
||||
<div class="learner-note">
|
||||
<b>Maya, week 7</b>
|
||||
<span>I know the names. I do not know when to use them.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="experience-shell">
|
||||
<aside class="course-file" aria-label="Living course file">
|
||||
<div class="file-head">
|
||||
<p class="eyebrow">Living course file</p>
|
||||
<h2>Data Structures I</h2>
|
||||
<p id="fileStatus">Topic coverage is still driving the course.</p>
|
||||
</div>
|
||||
|
||||
<div class="file-section">
|
||||
<h3>Course spine</h3>
|
||||
<dl class="spine-list">
|
||||
<div>
|
||||
<dt>Outcome</dt>
|
||||
<dd id="spineOutcome">not yet written</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Practice</dt>
|
||||
<dd id="spinePractice">mostly listening</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Assessment</dt>
|
||||
<dd id="spineAssessment">midterm plus final</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Feedback</dt>
|
||||
<dd id="spineFeedback">late and scarce</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Motivation</dt>
|
||||
<dd id="spineMotivation">grades carry the message</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="file-section">
|
||||
<h3>Maya's current experience</h3>
|
||||
<div class="learner-state">
|
||||
<div class="state-meter" aria-hidden="true">
|
||||
<span id="meterUse"></span>
|
||||
<span id="meterConfidence"></span>
|
||||
<span id="meterTransfer"></span>
|
||||
</div>
|
||||
<ul id="learnerNotes">
|
||||
<li>She can repeat definitions after lecture.</li>
|
||||
<li>She waits until the exam to find out what counts.</li>
|
||||
<li>She cannot yet transfer the ideas to a new problem.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file-section memory-file">
|
||||
<h3>Memory trace</h3>
|
||||
<div class="memory-row" id="memoryTrace">
|
||||
<span>0 checks settled</span>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<article class="story">
|
||||
<section class="chapter" id="diagnose">
|
||||
<p class="section-number">1 / Diagnose</p>
|
||||
<h2>The first problem is not that the course is empty. It is that the course is full.</h2>
|
||||
<p>
|
||||
The inherited course is familiar: a list of important topics, a lecture for each topic,
|
||||
and two exams. It looks responsible because nothing obvious is missing. It fails quietly
|
||||
because the design never says what students should be able to do with the knowledge.
|
||||
</p>
|
||||
|
||||
<div class="old-course-lab">
|
||||
<div class="topic-board" aria-label="Old topic list">
|
||||
<h3>Old plan</h3>
|
||||
<button type="button" class="topic-pill">arrays</button>
|
||||
<button type="button" class="topic-pill">linked lists</button>
|
||||
<button type="button" class="topic-pill">stacks</button>
|
||||
<button type="button" class="topic-pill">queues</button>
|
||||
<button type="button" class="topic-pill">trees</button>
|
||||
<button type="button" class="topic-pill">graphs</button>
|
||||
<button type="button" class="topic-pill">hashing</button>
|
||||
<button type="button" class="topic-pill">complexity</button>
|
||||
</div>
|
||||
|
||||
<div class="semester-sim">
|
||||
<div class="sim-head">
|
||||
<h3>Run the semester</h3>
|
||||
<button type="button" id="runOldCourse">Run old course</button>
|
||||
</div>
|
||||
<div class="week-track" id="weekTrack" aria-label="Semester timeline"></div>
|
||||
<div class="student-log" id="studentLog" aria-live="polite">
|
||||
<p>Before the run, the course looks complete on paper.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="instructor-note">
|
||||
<div>
|
||||
<p class="eyebrow">Course voice</p>
|
||||
<h3>The course's central turn</h3>
|
||||
<p>
|
||||
Teaching becomes design when the object of attention moves from what the teacher
|
||||
covers to what students learn, practice, and revise.
|
||||
</p>
|
||||
</div>
|
||||
<video controls preload="metadata" poster="assets/posters/teaching.jpg">
|
||||
<source src="assets/clips/teaching-is-for-learning.mp4" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="outcomes">
|
||||
<p class="section-number">2 / Outcomes</p>
|
||||
<h2>Now write the sentence the course has been avoiding.</h2>
|
||||
<p>
|
||||
A learning outcome is not a topic. It is a claim about the student's end state:
|
||||
what the student understands or can do after the course. The sentence has to be
|
||||
visible enough that activities and assessment can answer to it.
|
||||
</p>
|
||||
|
||||
<div class="decision-lab">
|
||||
<div class="prompt-card">
|
||||
<p class="eyebrow">Decision</p>
|
||||
<h3>Which outcome can actually design the course?</h3>
|
||||
<p>Pick one. Watch what it does to the living course file.</p>
|
||||
</div>
|
||||
<div class="choice-grid" id="outcomeChoices">
|
||||
<button type="button" class="choice-card" data-outcome="vague">
|
||||
<span>Students will understand trees, graphs, and hashing.</span>
|
||||
<small>comfortable, but hard to observe</small>
|
||||
</button>
|
||||
<button type="button" class="choice-card" data-outcome="usable">
|
||||
<span>Students will choose and justify a data structure for a stated constraint.</span>
|
||||
<small>observable and course-level</small>
|
||||
</button>
|
||||
<button type="button" class="choice-card" data-outcome="tooBig">
|
||||
<span>Students will design industrial-scale storage systems from scratch.</span>
|
||||
<small>ambitious beyond the course</small>
|
||||
</button>
|
||||
</div>
|
||||
<div class="decision-feedback" id="outcomeFeedback" aria-live="polite">
|
||||
<strong>No outcome chosen yet.</strong>
|
||||
<span>The course still has topics, not a destination.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memory-check" data-check="outcome">
|
||||
<div>
|
||||
<p class="eyebrow">Retrieval check</p>
|
||||
<h3>What does a learning outcome name?</h3>
|
||||
</div>
|
||||
<div class="check-options">
|
||||
<button type="button" data-answer="wrong">The order of lecture topics</button>
|
||||
<button type="button" data-answer="right">The student's end-state knowledge or skill</button>
|
||||
<button type="button" data-answer="wrong">The instructor's teaching style</button>
|
||||
</div>
|
||||
<p class="check-feedback" aria-live="polite">Choose before moving on.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="alignment">
|
||||
<p class="section-number">3 / Alignment</p>
|
||||
<h2>Assessment is the hidden course. Students study what the course rewards.</h2>
|
||||
<p>
|
||||
If the outcome asks students to justify a choice, but the exam rewards definitions,
|
||||
the actual course is definitions. Alignment is not administrative neatness. It is how
|
||||
the course tells students where effort belongs.
|
||||
</p>
|
||||
|
||||
<div class="alignment-studio">
|
||||
<div class="wire-map" aria-label="Alignment map">
|
||||
<svg id="wireSvg" viewBox="0 0 760 420" role="img" aria-label="Outcome, practice, and assessment alignment">
|
||||
<line class="wire wire-a" x1="170" y1="120" x2="380" y2="210"></line>
|
||||
<line class="wire wire-b" x1="590" y1="120" x2="380" y2="210"></line>
|
||||
<line class="wire wire-c" x1="170" y1="310" x2="380" y2="210"></line>
|
||||
<line class="wire wire-d" x1="590" y1="310" x2="380" y2="210"></line>
|
||||
<g class="node node-outcome">
|
||||
<rect x="62" y="62" width="216" height="116" rx="10"></rect>
|
||||
<text x="170" y="111" text-anchor="middle">outcome</text>
|
||||
<text id="mapOutcome" x="170" y="141" text-anchor="middle">not written</text>
|
||||
</g>
|
||||
<g class="node node-practice">
|
||||
<rect x="482" y="62" width="216" height="116" rx="10"></rect>
|
||||
<text x="590" y="111" text-anchor="middle">practice</text>
|
||||
<text id="mapPractice" x="590" y="141" text-anchor="middle">listening</text>
|
||||
</g>
|
||||
<g class="node node-assess">
|
||||
<rect x="62" y="252" width="216" height="116" rx="10"></rect>
|
||||
<text x="170" y="301" text-anchor="middle">assessment</text>
|
||||
<text id="mapAssessment" x="170" y="331" text-anchor="middle">recall exam</text>
|
||||
</g>
|
||||
<g class="node node-learner">
|
||||
<circle cx="380" cy="210" r="70"></circle>
|
||||
<text x="380" y="202" text-anchor="middle">student</text>
|
||||
<text x="380" y="232" text-anchor="middle">effort</text>
|
||||
</g>
|
||||
<g class="node node-feedback">
|
||||
<rect x="482" y="252" width="216" height="116" rx="10"></rect>
|
||||
<text x="590" y="301" text-anchor="middle">feedback</text>
|
||||
<text id="mapFeedback" x="590" y="331" text-anchor="middle">after exam</text>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="alignment-controls">
|
||||
<div>
|
||||
<h3>Choose a practice structure</h3>
|
||||
<div class="select-list" id="practiceChoices">
|
||||
<button type="button" data-practice="lecture">Lecture examples only</button>
|
||||
<button type="button" data-practice="compare">Compare two structures for one constraint</button>
|
||||
<button type="button" data-practice="debug">Debug a bad structure choice in pairs</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Choose an assessment signal</h3>
|
||||
<div class="select-list" id="assessmentChoices">
|
||||
<button type="button" data-assessment="definitions">Define tree, graph, hash table</button>
|
||||
<button type="button" data-assessment="justify">Given a scenario, justify a structure</button>
|
||||
<button type="button" data-assessment="project">Mini-project with design memo</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hidden-course" id="hiddenCourse" aria-live="polite">
|
||||
<strong>The hidden course is still recall.</strong>
|
||||
<span>Students will protect marks by memorizing definitions.</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="class-session">
|
||||
<p class="section-number">4 / Class session</p>
|
||||
<h2>A lecture can stay a lecture. It cannot stay a monologue.</h2>
|
||||
<p>
|
||||
The course's active-learning advice is modest and powerful: every 10 to 15 minutes,
|
||||
ask students to do something with the idea. Predict, compare, explain, answer, reflect.
|
||||
The activity is short because it is not replacing the lecture. It is making the lecture learnable.
|
||||
</p>
|
||||
|
||||
<div class="class-builder">
|
||||
<div class="move-palette">
|
||||
<h3>Choose a move, then place it in the hour</h3>
|
||||
<div class="move-list" id="movePalette">
|
||||
<button type="button" data-move="hook">Opening problem</button>
|
||||
<button type="button" data-move="predict">Prediction</button>
|
||||
<button type="button" data-move="pair">Think-pair-share</button>
|
||||
<button type="button" data-move="quiz">One-minute quiz</button>
|
||||
<button type="button" data-move="paper">Minute paper</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hour-stage">
|
||||
<div class="attention-plot">
|
||||
<svg id="attentionSvg" viewBox="0 0 780 280" role="img" aria-label="Attention and practice during a class hour">
|
||||
<line x1="42" y1="232" x2="742" y2="232"></line>
|
||||
<line x1="42" y1="34" x2="42" y2="232"></line>
|
||||
<path id="attentionCurve"></path>
|
||||
<g id="attentionMarkers"></g>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="slot-row" id="slotRow" aria-label="Class hour slots"></div>
|
||||
<div class="class-feedback" id="classFeedback" aria-live="polite">
|
||||
Place an opening problem and two short thinking moves.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="instructor-note compact-note">
|
||||
<div>
|
||||
<p class="eyebrow">Watch when useful</p>
|
||||
<h3>The 15-minute reset</h3>
|
||||
<p>
|
||||
This clip explains why active lectures use short cycles of attention, activity,
|
||||
and feedback rather than one long stream of explanation.
|
||||
</p>
|
||||
</div>
|
||||
<video controls preload="metadata" poster="assets/posters/attention.jpg">
|
||||
<source src="assets/clips/attention-reset.mp4" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<div class="memory-check" data-check="alignment">
|
||||
<div>
|
||||
<p class="eyebrow">Retrieval check</p>
|
||||
<h3>If a final exam rewards recall, what will students optimize for?</h3>
|
||||
</div>
|
||||
<div class="check-options">
|
||||
<button type="button" data-answer="right">Recall, even if the stated outcome is higher</button>
|
||||
<button type="button" data-answer="wrong">The instructor's private intention</button>
|
||||
<button type="button" data-answer="wrong">Only the in-class activities</button>
|
||||
</div>
|
||||
<p class="check-feedback" aria-live="polite">Choose the signal students can see.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="feedback">
|
||||
<p class="section-number">5 / Feedback</p>
|
||||
<h2>Practice without feedback lets mistakes become architecture.</h2>
|
||||
<p>
|
||||
Formative assessment is valuable because it is frequent, low stakes, and fast enough
|
||||
to change what students do next. Summative assessment still matters, but it cannot be
|
||||
the first moment students learn whether their thinking works.
|
||||
</p>
|
||||
|
||||
<div class="feedback-lab">
|
||||
<div class="misconception-board">
|
||||
<h3>The misconception</h3>
|
||||
<p class="bug-line">"Hash tables are always faster than trees."</p>
|
||||
<div class="persistence-bars" id="persistenceBars" aria-label="Misconception persistence over time"></div>
|
||||
</div>
|
||||
<div class="feedback-choices">
|
||||
<h3>When does feedback arrive?</h3>
|
||||
<button type="button" data-feedback="late">After the midterm</button>
|
||||
<button type="button" data-feedback="quick">Same class, after a comparison quiz</button>
|
||||
<button type="button" data-feedback="revision">Next day, with a revision attempt</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter" id="motivation">
|
||||
<p class="section-number">6 / Motivation</p>
|
||||
<h2>Motivation is designed through value, expectancy, and support.</h2>
|
||||
<p>
|
||||
The student has many goals. Your course competes with all of them. Motivation grows
|
||||
when the outcome has value, the student believes effort can work, and the environment
|
||||
makes support visible.
|
||||
</p>
|
||||
|
||||
<div class="opening-lab">
|
||||
<div class="opening-scene">
|
||||
<h3>Pick the first five minutes of class</h3>
|
||||
<div class="select-list" id="openingChoices">
|
||||
<button type="button" data-opening="rules">Read the grading rules first</button>
|
||||
<button type="button" data-opening="mystery">Show a real design failure and ask what went wrong</button>
|
||||
<button type="button" data-opening="support">Map the outcome, practice route, and help route</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="motivation-response" id="motivationResponse" aria-live="polite">
|
||||
<strong>Maya is waiting to see what this course values.</strong>
|
||||
<span>The opening has not yet told her why effort will be worth it.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memory-check" data-check="motivation">
|
||||
<div>
|
||||
<p class="eyebrow">Retrieval check</p>
|
||||
<h3>What three factors shape motivation in this course?</h3>
|
||||
</div>
|
||||
<div class="check-options">
|
||||
<button type="button" data-answer="wrong">Coverage, speed, difficulty</button>
|
||||
<button type="button" data-answer="right">Value, expectancy, support</button>
|
||||
<button type="button" data-answer="wrong">Attendance, marks, discipline</button>
|
||||
</div>
|
||||
<p class="check-feedback" aria-live="polite">Choose the model that helps a teacher act.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="chapter final-chapter" id="launch">
|
||||
<p class="section-number">7 / Launch</p>
|
||||
<h2>The redesigned course is not prettier. It is more legible to the learner.</h2>
|
||||
<p>
|
||||
You now have the pieces of a first class that tells students what matters, gives them
|
||||
something to do, and shows how feedback will help them improve. The file below is built
|
||||
from your choices.
|
||||
</p>
|
||||
|
||||
<div class="launch-board">
|
||||
<div class="plan-panel">
|
||||
<div class="panel-head">
|
||||
<h3>Your first-class plan</h3>
|
||||
<button type="button" id="copyPlan">Copy plan</button>
|
||||
</div>
|
||||
<pre id="finalPlan" tabindex="0"></pre>
|
||||
<p id="copyStatus" class="copy-status" aria-live="polite">The plan updates as the course file changes.</p>
|
||||
</div>
|
||||
|
||||
<div class="closing-claim">
|
||||
<p class="eyebrow">The durable idea</p>
|
||||
<h3>Teach by designing what students do, think, practice, and revise.</h3>
|
||||
<p>
|
||||
Outcomes name the destination. Activities create practice. Assessment sends the
|
||||
signal. Feedback helps students steer. Motivation keeps effort alive long enough
|
||||
for knowledge to change.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
616
learning-outcomes-assessment/script.js
Normal file
616
learning-outcomes-assessment/script.js
Normal file
|
|
@ -0,0 +1,616 @@
|
|||
/*
|
||||
* ANIMATION STORYBOARD
|
||||
*
|
||||
* 0ms old course run starts, all weeks reset
|
||||
* 260ms next week activates, student log receives one consequence
|
||||
* 1200ms active week reaches exam signal, learner state updates
|
||||
* 2400ms run ends with diagnosis visible in course file
|
||||
*/
|
||||
const TIMING = {
|
||||
oldCourseStep: 260,
|
||||
feedbackDelay: 900
|
||||
};
|
||||
|
||||
const $ = (selector, root = document) => root.querySelector(selector);
|
||||
const $$ = (selector, root = document) => Array.from(root.querySelectorAll(selector));
|
||||
|
||||
const course = {
|
||||
outcome: null,
|
||||
practice: null,
|
||||
assessment: null,
|
||||
feedback: null,
|
||||
opening: null,
|
||||
classMoves: {},
|
||||
memory: new Set()
|
||||
};
|
||||
|
||||
const labels = {
|
||||
outcome: {
|
||||
vague: "understand trees, graphs, and hashing",
|
||||
usable: "choose and justify a data structure for a stated constraint",
|
||||
tooBig: "design industrial-scale storage systems from scratch"
|
||||
},
|
||||
practice: {
|
||||
lecture: "lecture examples only",
|
||||
compare: "compare structures for a constraint",
|
||||
debug: "debug a bad choice in pairs"
|
||||
},
|
||||
assessment: {
|
||||
definitions: "definition-heavy exam",
|
||||
justify: "scenario justification task",
|
||||
project: "mini-project with design memo"
|
||||
},
|
||||
feedback: {
|
||||
late: "after the midterm",
|
||||
quick: "same-class comparison feedback",
|
||||
revision: "revision attempt after feedback"
|
||||
},
|
||||
opening: {
|
||||
rules: "grading rules first",
|
||||
mystery: "real design failure first",
|
||||
support: "outcome, practice, and help route first"
|
||||
},
|
||||
move: {
|
||||
hook: "opening problem",
|
||||
predict: "prediction",
|
||||
pair: "pair talk",
|
||||
quiz: "quick quiz",
|
||||
paper: "minute paper"
|
||||
}
|
||||
};
|
||||
|
||||
function clamp(value, min, max) {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
|
||||
function setText(selector, text) {
|
||||
const node = typeof selector === "string" ? $(selector) : selector;
|
||||
if (node) node.textContent = text;
|
||||
}
|
||||
|
||||
function initProgress() {
|
||||
const bar = $(".progress-line span");
|
||||
const update = () => {
|
||||
const max = document.documentElement.scrollHeight - window.innerHeight;
|
||||
const percent = max <= 0 ? 0 : (window.scrollY / max) * 100;
|
||||
bar.style.width = `${clamp(percent, 0, 100)}%`;
|
||||
};
|
||||
update();
|
||||
window.addEventListener("scroll", update, { passive: true });
|
||||
}
|
||||
|
||||
function initNav() {
|
||||
const links = $$(".topbar nav a");
|
||||
const byId = new Map(links.map((link) => [link.getAttribute("href").slice(1), link]));
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (!entry.isIntersecting) return;
|
||||
links.forEach((link) => link.classList.remove("active"));
|
||||
const link = byId.get(entry.target.id);
|
||||
if (link) link.classList.add("active");
|
||||
});
|
||||
},
|
||||
{ rootMargin: "-36% 0px -54% 0px", threshold: 0.01 }
|
||||
);
|
||||
links.forEach((link) => {
|
||||
const section = $(link.getAttribute("href"));
|
||||
if (section) observer.observe(section);
|
||||
});
|
||||
}
|
||||
|
||||
function initWeeks() {
|
||||
const track = $("#weekTrack");
|
||||
if (!track) return;
|
||||
track.replaceChildren();
|
||||
for (let i = 1; i <= 12; i += 1) {
|
||||
const week = document.createElement("div");
|
||||
week.className = "week";
|
||||
week.textContent = `W${i}`;
|
||||
track.append(week);
|
||||
}
|
||||
}
|
||||
|
||||
function runOldCourse() {
|
||||
const weeks = $$(".week");
|
||||
const log = $("#studentLog");
|
||||
const entries = [
|
||||
"Week 2: Maya copies the list implementation. It works, but she cannot explain the design choice.",
|
||||
"Week 5: Trees arrive. The course has moved on before her earlier misconception is visible.",
|
||||
"Week 8: The midterm asks definitions. Her effort shifts toward remembering names.",
|
||||
"Week 12: She passes many recall items. Transfer is still fragile."
|
||||
];
|
||||
weeks.forEach((week) => week.classList.remove("active"));
|
||||
log.replaceChildren();
|
||||
setText(log.appendChild(document.createElement("p")), "The run starts from the topic list.");
|
||||
|
||||
let i = 0;
|
||||
const timer = window.setInterval(() => {
|
||||
if (i > 0) weeks[i - 1]?.classList.remove("active");
|
||||
if (i >= weeks.length) {
|
||||
window.clearInterval(timer);
|
||||
updateLearnerNotes("diagnosed");
|
||||
updateCourseFile();
|
||||
return;
|
||||
}
|
||||
weeks[i].classList.add("active");
|
||||
if ([1, 4, 7, 11].includes(i)) {
|
||||
const p = document.createElement("p");
|
||||
p.textContent = entries.shift();
|
||||
log.append(p);
|
||||
}
|
||||
i += 1;
|
||||
}, TIMING.oldCourseStep);
|
||||
}
|
||||
|
||||
function outcomeFeedback(kind) {
|
||||
const node = $("#outcomeFeedback");
|
||||
const messages = {
|
||||
vague: [
|
||||
"This is a topic in disguise.",
|
||||
"It does not tell you what students must produce, so assessment will drift."
|
||||
],
|
||||
usable: [
|
||||
"This can design the course.",
|
||||
"It names a student action, a judgment, and a realistic course-level capability."
|
||||
],
|
||||
tooBig: [
|
||||
"This overpromises.",
|
||||
"Ambition helps only when students can practice the component skills inside the course."
|
||||
]
|
||||
};
|
||||
const [title, detail] = messages[kind];
|
||||
node.innerHTML = `<strong>${title}</strong><span>${detail}</span>`;
|
||||
}
|
||||
|
||||
function initOutcomes() {
|
||||
$$("#outcomeChoices .choice-card").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
$$("#outcomeChoices .choice-card").forEach((item) => item.classList.toggle("selected", item === button));
|
||||
course.outcome = button.dataset.outcome;
|
||||
outcomeFeedback(course.outcome);
|
||||
updateLearnerNotes("outcome");
|
||||
updateCourseFile();
|
||||
updateAlignmentMap();
|
||||
updatePlan();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initAlignmentControls() {
|
||||
$$("#practiceChoices button").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
$$("#practiceChoices button").forEach((item) => item.classList.toggle("selected", item === button));
|
||||
course.practice = button.dataset.practice;
|
||||
updateAlignmentMap();
|
||||
updateLearnerNotes("alignment");
|
||||
updateCourseFile();
|
||||
updatePlan();
|
||||
});
|
||||
});
|
||||
$$("#assessmentChoices button").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
$$("#assessmentChoices button").forEach((item) => item.classList.toggle("selected", item === button));
|
||||
course.assessment = button.dataset.assessment;
|
||||
updateAlignmentMap();
|
||||
updateLearnerNotes("alignment");
|
||||
updateCourseFile();
|
||||
updatePlan();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateAlignmentMap() {
|
||||
const outcome = course.outcome ? labels.outcome[course.outcome] : "not written";
|
||||
const practice = course.practice ? labels.practice[course.practice] : "listening";
|
||||
const assessment = course.assessment ? labels.assessment[course.assessment] : "recall exam";
|
||||
const feedback = course.feedback ? labels.feedback[course.feedback] : "after exam";
|
||||
|
||||
setText("#mapOutcome", shorten(outcome, 24));
|
||||
setText("#mapPractice", shorten(practice, 24));
|
||||
setText("#mapAssessment", shorten(assessment, 24));
|
||||
setText("#mapFeedback", shorten(feedback, 24));
|
||||
|
||||
const goodOutcome = course.outcome === "usable";
|
||||
const goodPractice = course.practice === "compare" || course.practice === "debug";
|
||||
const goodAssessment = course.assessment === "justify" || course.assessment === "project";
|
||||
const goodFeedback = course.feedback === "quick" || course.feedback === "revision";
|
||||
|
||||
$(".wire-a")?.classList.toggle("strong", goodOutcome);
|
||||
$(".wire-b")?.classList.toggle("strong", goodPractice);
|
||||
$(".wire-c")?.classList.toggle("strong", goodAssessment);
|
||||
$(".wire-d")?.classList.toggle("strong", goodFeedback);
|
||||
$(".wire-c")?.classList.toggle("warn", course.assessment === "definitions");
|
||||
|
||||
const hidden = $("#hiddenCourse");
|
||||
if (!course.assessment || course.assessment === "definitions") {
|
||||
hidden.classList.remove("good");
|
||||
hidden.innerHTML = "<strong>The hidden course is still recall.</strong><span>Students will protect marks by memorizing definitions.</span>";
|
||||
} else if (goodOutcome && goodPractice && goodAssessment) {
|
||||
hidden.classList.add("good");
|
||||
hidden.innerHTML = "<strong>The hidden course now matches the stated course.</strong><span>Students can see that practice and marks both point toward justified choice.</span>";
|
||||
} else {
|
||||
hidden.classList.remove("good");
|
||||
hidden.innerHTML = "<strong>The signals are mixed.</strong><span>One corner has improved, but students still receive competing messages about effort.</span>";
|
||||
}
|
||||
}
|
||||
|
||||
function shorten(text, limit) {
|
||||
return text.length > limit ? `${text.slice(0, limit - 3)}...` : text;
|
||||
}
|
||||
|
||||
function initClassBuilder() {
|
||||
const palette = $$("#movePalette button");
|
||||
const slotRow = $("#slotRow");
|
||||
let selectedMove = null;
|
||||
|
||||
palette.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
selectedMove = button.dataset.move;
|
||||
palette.forEach((item) => item.classList.toggle("selected", item === button));
|
||||
});
|
||||
});
|
||||
|
||||
slotRow.replaceChildren();
|
||||
[0, 10, 20, 30, 40, 50].forEach((minute) => {
|
||||
const slot = document.createElement("button");
|
||||
slot.type = "button";
|
||||
slot.className = "slot";
|
||||
slot.dataset.minute = String(minute);
|
||||
slot.textContent = `${minute} min`;
|
||||
slot.addEventListener("click", () => {
|
||||
if (!selectedMove) {
|
||||
setText("#classFeedback", "Choose a move first, then place it in the hour.");
|
||||
return;
|
||||
}
|
||||
course.classMoves[minute] = selectedMove;
|
||||
slot.classList.add("filled");
|
||||
slot.textContent = `${minute}: ${labels.move[selectedMove]}`;
|
||||
updateAttention();
|
||||
updateLearnerNotes("class");
|
||||
updateCourseFile();
|
||||
updatePlan();
|
||||
});
|
||||
slotRow.append(slot);
|
||||
});
|
||||
|
||||
updateAttention();
|
||||
}
|
||||
|
||||
function attentionAt(minute) {
|
||||
const placed = Object.entries(course.classMoves)
|
||||
.map(([key, value]) => ({ minute: Number(key), move: value }))
|
||||
.sort((a, b) => a.minute - b.minute);
|
||||
const previous = placed.filter((item) => item.minute <= minute).pop();
|
||||
const since = previous ? minute - previous.minute : minute;
|
||||
const reset = previous && since < 5 ? 11 : 0;
|
||||
const endLift = minute > 54 ? (minute - 54) * 2 : 0;
|
||||
return clamp(86 - since * 2.15 + reset + endLift, 26, 94);
|
||||
}
|
||||
|
||||
function updateAttention() {
|
||||
const path = $("#attentionCurve");
|
||||
const markers = $("#attentionMarkers");
|
||||
if (!path || !markers) return;
|
||||
const points = [];
|
||||
for (let minute = 0; minute <= 60; minute += 2) {
|
||||
const x = 42 + (minute / 60) * 700;
|
||||
const y = 232 - (attentionAt(minute) / 100) * 190;
|
||||
points.push(`${x},${y}`);
|
||||
}
|
||||
path.setAttribute("d", `M ${points.join(" L ")}`);
|
||||
markers.replaceChildren();
|
||||
Object.entries(course.classMoves).forEach(([minute, move]) => {
|
||||
const x = 42 + (Number(minute) / 60) * 700;
|
||||
const y = 232 - (attentionAt(Number(minute)) / 100) * 190;
|
||||
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
||||
circle.setAttribute("cx", x);
|
||||
circle.setAttribute("cy", y);
|
||||
circle.setAttribute("r", 8);
|
||||
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
text.setAttribute("x", x);
|
||||
text.setAttribute("y", y - 15);
|
||||
text.setAttribute("text-anchor", "middle");
|
||||
text.textContent = labels.move[move];
|
||||
markers.append(circle, text);
|
||||
});
|
||||
const moves = Object.values(course.classMoves);
|
||||
const hasHook = moves.includes("hook");
|
||||
const thinkingMoves = moves.filter((move) => ["predict", "pair", "quiz", "paper"].includes(move)).length;
|
||||
if (hasHook && thinkingMoves >= 2) {
|
||||
setText("#classFeedback", "This hour now asks students to predict, explain, or retrieve before the idea goes cold.");
|
||||
} else if (thinkingMoves >= 1) {
|
||||
setText("#classFeedback", "Good start. Add one more thinking move so the middle of the hour does not sag.");
|
||||
} else {
|
||||
setText("#classFeedback", "Place an opening problem and two short thinking moves.");
|
||||
}
|
||||
}
|
||||
|
||||
function initFeedbackLab() {
|
||||
const bars = $("#persistenceBars");
|
||||
bars.replaceChildren();
|
||||
["same day", "one week", "midterm"].forEach((label) => {
|
||||
const row = document.createElement("div");
|
||||
row.className = "persistence-row";
|
||||
row.innerHTML = `<span>${label}</span><div class="bar-shell"><span></span></div>`;
|
||||
bars.append(row);
|
||||
});
|
||||
updatePersistence("late");
|
||||
|
||||
$$(".feedback-choices button").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
$$(".feedback-choices button").forEach((item) => item.classList.toggle("selected", item === button));
|
||||
course.feedback = button.dataset.feedback;
|
||||
updatePersistence(course.feedback);
|
||||
updateAlignmentMap();
|
||||
updateLearnerNotes("feedback");
|
||||
updateCourseFile();
|
||||
updatePlan();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updatePersistence(kind) {
|
||||
const levels = {
|
||||
late: [80, 72, 58],
|
||||
quick: [58, 30, 18],
|
||||
revision: [62, 24, 10]
|
||||
};
|
||||
$$(".bar-shell span").forEach((bar, index) => {
|
||||
bar.style.setProperty("--amount", `${levels[kind][index]}%`);
|
||||
bar.style.background = kind === "late" ? "var(--coral)" : "var(--teal)";
|
||||
});
|
||||
}
|
||||
|
||||
function initOpening() {
|
||||
$$("#openingChoices button").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
$$("#openingChoices button").forEach((item) => item.classList.toggle("selected", item === button));
|
||||
course.opening = button.dataset.opening;
|
||||
const response = $("#motivationResponse");
|
||||
if (course.opening === "rules") {
|
||||
response.classList.remove("good");
|
||||
response.innerHTML = "<strong>Maya hears that marks matter.</strong><span>Value, expectancy, and support are still mostly implicit.</span>";
|
||||
} else if (course.opening === "mystery") {
|
||||
response.classList.add("good");
|
||||
response.innerHTML = "<strong>Maya sees value first.</strong><span>The opening gives the outcome a reason to exist before naming the machinery.</span>";
|
||||
} else {
|
||||
response.classList.add("good");
|
||||
response.innerHTML = "<strong>Maya sees the route.</strong><span>The opening joins value with expectancy: here is the goal, the practice path, and where help lives.</span>";
|
||||
}
|
||||
updateLearnerNotes("motivation");
|
||||
updateCourseFile();
|
||||
updatePlan();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initMemoryChecks() {
|
||||
$$(".memory-check").forEach((check) => {
|
||||
$$("button", check).forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
$$("button", check).forEach((item) => item.classList.remove("correct", "incorrect"));
|
||||
const isRight = button.dataset.answer === "right";
|
||||
button.classList.add(isRight ? "correct" : "incorrect");
|
||||
const feedback = $(".check-feedback", check);
|
||||
if (isRight) {
|
||||
course.memory.add(check.dataset.check);
|
||||
feedback.textContent = "Settled. This will show up in the course file.";
|
||||
} else {
|
||||
feedback.textContent = "Not yet. Try the option that changes what the teacher designs next.";
|
||||
}
|
||||
updateCourseFile();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateLearnerNotes(stage) {
|
||||
const notes = {
|
||||
diagnosed: [
|
||||
"She can repeat definitions after lecture.",
|
||||
"She waits until the exam to find out what counts.",
|
||||
"She cannot yet transfer the ideas to a new problem."
|
||||
],
|
||||
outcome: [
|
||||
course.outcome === "usable" ? "She can see the course is about justified choices, not names alone." : "The destination is still hard to recognize from a student's seat.",
|
||||
"She needs practice that matches the promise.",
|
||||
"The exam will decide what she actually studies."
|
||||
],
|
||||
alignment: [
|
||||
course.practice === "compare" || course.practice === "debug" ? "She has a place to practice choosing, not just hearing." : "She is still mostly watching someone else reason.",
|
||||
course.assessment === "justify" || course.assessment === "project" ? "Marks now reward the capability the outcome names." : "The visible reward still points toward recall.",
|
||||
"Alignment is becoming a message she can read."
|
||||
],
|
||||
class: [
|
||||
Object.values(course.classMoves).length >= 3 ? "She has to predict, explain, and retrieve during class." : "The class has started to ask for thinking, but the rhythm is still thin.",
|
||||
"Short tasks make confusion visible before the exam.",
|
||||
"Attention is being used as a design material."
|
||||
],
|
||||
feedback: [
|
||||
course.feedback === "late" ? "Her misconception survives until the midterm." : "Her misconception gets interrupted while it is still fixable.",
|
||||
"Feedback now changes the next attempt, not just the grade record.",
|
||||
"Formative work has become part of teaching."
|
||||
],
|
||||
motivation: [
|
||||
course.opening === "rules" ? "She hears the grading system first." : "She sees why the outcome matters before the syllabus details.",
|
||||
course.opening === "support" ? "She also sees how effort can succeed." : "Support still needs to be named clearly.",
|
||||
"Motivation is being designed, not wished for."
|
||||
]
|
||||
};
|
||||
const list = $("#learnerNotes");
|
||||
list.replaceChildren();
|
||||
notes[stage].forEach((note) => {
|
||||
const item = document.createElement("li");
|
||||
item.textContent = note;
|
||||
list.append(item);
|
||||
});
|
||||
}
|
||||
|
||||
function designLevels() {
|
||||
let use = 22;
|
||||
let confidence = 18;
|
||||
let transfer = 14;
|
||||
if (course.outcome === "usable") {
|
||||
use += 18;
|
||||
transfer += 16;
|
||||
} else if (course.outcome) {
|
||||
use += 6;
|
||||
}
|
||||
if (course.practice === "compare" || course.practice === "debug") {
|
||||
use += 16;
|
||||
transfer += 14;
|
||||
}
|
||||
if (course.assessment === "justify" || course.assessment === "project") {
|
||||
use += 16;
|
||||
confidence += 14;
|
||||
transfer += 12;
|
||||
}
|
||||
if (Object.values(course.classMoves).length >= 3) {
|
||||
confidence += 14;
|
||||
use += 10;
|
||||
}
|
||||
if (course.feedback === "quick" || course.feedback === "revision") {
|
||||
confidence += 18;
|
||||
transfer += 10;
|
||||
}
|
||||
if (course.opening === "mystery" || course.opening === "support") {
|
||||
confidence += 10;
|
||||
use += 8;
|
||||
}
|
||||
return {
|
||||
use: clamp(use, 8, 96),
|
||||
confidence: clamp(confidence, 8, 96),
|
||||
transfer: clamp(transfer, 8, 96)
|
||||
};
|
||||
}
|
||||
|
||||
function updateCourseFile() {
|
||||
setText("#spineOutcome", course.outcome ? labels.outcome[course.outcome] : "not yet written");
|
||||
setText("#spinePractice", course.practice ? labels.practice[course.practice] : "mostly listening");
|
||||
setText("#spineAssessment", course.assessment ? labels.assessment[course.assessment] : "midterm plus final");
|
||||
setText("#spineFeedback", course.feedback ? labels.feedback[course.feedback] : "late and scarce");
|
||||
setText("#spineMotivation", course.opening ? labels.opening[course.opening] : "grades carry the message");
|
||||
|
||||
const levels = designLevels();
|
||||
$("#meterUse").style.setProperty("--fill", `${levels.use}%`);
|
||||
$("#meterConfidence").style.setProperty("--fill", `${levels.confidence}%`);
|
||||
$("#meterTransfer").style.setProperty("--fill", `${levels.transfer}%`);
|
||||
|
||||
const memory = $("#memoryTrace");
|
||||
memory.replaceChildren();
|
||||
if (course.memory.size === 0) {
|
||||
const span = document.createElement("span");
|
||||
span.textContent = "0 checks settled";
|
||||
memory.append(span);
|
||||
} else {
|
||||
course.memory.forEach((check) => {
|
||||
const span = document.createElement("span");
|
||||
span.className = "settled";
|
||||
span.textContent = check;
|
||||
memory.append(span);
|
||||
});
|
||||
}
|
||||
|
||||
const aligned =
|
||||
course.outcome === "usable" &&
|
||||
(course.practice === "compare" || course.practice === "debug") &&
|
||||
(course.assessment === "justify" || course.assessment === "project") &&
|
||||
(course.feedback === "quick" || course.feedback === "revision");
|
||||
if (aligned) {
|
||||
setText("#fileStatus", "The course now gives students one coherent message.");
|
||||
} else if (course.outcome || course.practice || course.assessment || course.feedback || course.opening) {
|
||||
setText("#fileStatus", "The course is improving, but at least one signal still needs work.");
|
||||
} else {
|
||||
setText("#fileStatus", "Topic coverage is still driving the course.");
|
||||
}
|
||||
}
|
||||
|
||||
function updatePlan() {
|
||||
const moves = Object.entries(course.classMoves)
|
||||
.sort((a, b) => Number(a[0]) - Number(b[0]))
|
||||
.map(([minute, move]) => `${minute} min: ${labels.move[move]}`);
|
||||
const plan = `Data Structures I - first class redesign
|
||||
|
||||
Learning outcome
|
||||
${course.outcome ? labels.outcome[course.outcome] : "Write one observable course outcome before class."}
|
||||
|
||||
Opening
|
||||
${course.opening ? labels.opening[course.opening] : "Open by showing why the outcome matters to a real design problem."}
|
||||
|
||||
In-class practice
|
||||
${moves.length ? moves.join("\n") : "0 min: opening problem\n15 min: prediction\n30 min: think-pair-share\n45 min: one-minute quiz"}
|
||||
|
||||
Assessment signal
|
||||
${course.assessment ? labels.assessment[course.assessment] : "Use a scenario task that asks students to justify a structure."}
|
||||
|
||||
Feedback route
|
||||
${course.feedback ? labels.feedback[course.feedback] : "Give quick formative feedback before the first high-stakes exam."}
|
||||
|
||||
Teacher check
|
||||
Students should leave knowing what they are trying to learn, how they will practice it, how it will be assessed, and where to get help.`;
|
||||
setText("#finalPlan", plan);
|
||||
}
|
||||
|
||||
function initCopy() {
|
||||
$("#copyPlan")?.addEventListener("click", async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText($("#finalPlan").textContent);
|
||||
setText("#copyStatus", "Copied.");
|
||||
} catch {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents($("#finalPlan"));
|
||||
const selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
setText("#copyStatus", "Selected the plan text.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initReset() {
|
||||
$$("[data-action='reset']").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
course.outcome = null;
|
||||
course.practice = null;
|
||||
course.assessment = null;
|
||||
course.feedback = null;
|
||||
course.opening = null;
|
||||
course.classMoves = {};
|
||||
course.memory.clear();
|
||||
$$(".selected, .correct, .incorrect, .filled").forEach((node) => node.classList.remove("selected", "correct", "incorrect", "filled"));
|
||||
$$(".slot").forEach((slot) => {
|
||||
slot.textContent = `${slot.dataset.minute} min`;
|
||||
});
|
||||
updateLearnerNotes("diagnosed");
|
||||
updateAlignmentMap();
|
||||
updateAttention();
|
||||
updatePersistence("late");
|
||||
updateCourseFile();
|
||||
updatePlan();
|
||||
setText("#classFeedback", "Place an opening problem and two short thinking moves.");
|
||||
$("#outcomeFeedback").innerHTML = "<strong>No outcome chosen yet.</strong><span>The course still has topics, not a destination.</span>";
|
||||
$("#motivationResponse").innerHTML = "<strong>Maya is waiting to see what this course values.</strong><span>The opening has not yet told her why effort will be worth it.</span>";
|
||||
$("#hiddenCourse").innerHTML = "<strong>The hidden course is still recall.</strong><span>Students will protect marks by memorizing definitions.</span>";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
initProgress();
|
||||
initNav();
|
||||
initWeeks();
|
||||
initOutcomes();
|
||||
initAlignmentControls();
|
||||
initClassBuilder();
|
||||
initFeedbackLab();
|
||||
initOpening();
|
||||
initMemoryChecks();
|
||||
initCopy();
|
||||
initReset();
|
||||
$("#runOldCourse")?.addEventListener("click", runOldCourse);
|
||||
updateLearnerNotes("diagnosed");
|
||||
updateAlignmentMap();
|
||||
updateCourseFile();
|
||||
updatePlan();
|
||||
});
|
||||
1277
learning-outcomes-assessment/styles.css
Normal file
1277
learning-outcomes-assessment/styles.css
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue