Refactor question bank feature in spec, update math curriculum status to live, enhance math rendering in frontend, and add new styles for question presentation in SASS. Improve catalog styles for planned chapters and enhance visual elements for better user experience.

This commit is contained in:
Hananoshika Yomaru 2026-05-19 16:08:20 -07:00
parent 2ac34d52fc
commit be5b3dba75
11 changed files with 1096 additions and 18 deletions

View file

@ -0,0 +1,336 @@
+++
title = "Directed numbers, rates & ratios"
description = "Operate with negative numbers and solve ratio, rate, and proportion problems in context."
template = "chapter.html"
weight = 0
[extra]
subject = "math"
chapter_id = "directed-numbers-rates"
strand = "Number & Algebra"
+++
<div class="book-prose">
<p>
Numbers on a line can lie to the <strong>right</strong> of zero (positive) or to the
<strong>left</strong> (negative). Temperatures below freezing, bank overdrafts, and positions
below sea level are everyday examples of <strong>directed numbers</strong>.
</p>
<h2 id="number-line" class="book-prose__heading">The number line</h2>
<p>
On a horizontal number line, moving right means the value <em>increases</em>; moving left means it
<em>decreases</em>. The distance from zero is the <strong>absolute value</strong>
\(|a|\). For example, \(|-5| = 5\) and \(|3| = 3\).
</p>
<div class="book-callout book-callout--formula" role="note">
<p class="book-callout__label">Comparing</p>
<p class="book-formula">
\(a &gt; b\) means \(a\) lies to the right of \(b\). Any negative number is less than any
positive number.
</p>
</div>
<h2 id="adding-subtracting" class="book-prose__heading">Adding and subtracting</h2>
<p>
Think in terms of movement on the line:
</p>
<ul>
<li><strong>\(a + b\)</strong> — start at \(a\), move \(b\) units (right if \(b &gt; 0\), left if \(b &lt; 0\)).</li>
<li><strong>\(a - b\)</strong> — start at \(a\), move \(-b\) units (equivalently, add the opposite of \(b\)).</li>
</ul>
<p>
Subtracting a negative is adding a positive: \(5 - (-3) = 5 + 3 = 8\).
</p>
<h2 id="multiplying-signs" class="book-prose__heading">Multiplying and dividing</h2>
<div class="book-table-wrap">
<table class="book-table">
<thead>
<tr>
<th scope="col">Signs</th>
<th scope="col">Result</th>
</tr>
</thead>
<tbody>
<tr>
<td>positive × positive, negative × negative</td>
<td>positive</td>
</tr>
<tr>
<td>positive × negative (either order)</td>
<td>negative</td>
</tr>
</tbody>
</table>
</div>
<h2 id="ratios" class="book-prose__heading">Ratios</h2>
<p>
A <strong>ratio</strong> compares quantities of the same kind. The ratio \(2:3\) means “2 parts
to 3 parts” — five equal parts in total. To share \(40\) in the ratio \(2:3\), one part is
\(40 \div 5 = 8\), so the shares are \(16\) and \(24\).
</p>
<div class="book-callout book-callout--formula" role="note">
<p class="book-callout__label">Sharing in ratio \(m:n\)</p>
<p class="book-formula">
\[ \text{one part} = \frac{\text{total}}{m+n}, \quad
\text{first share} = \frac{m}{m+n}\times\text{total}, \quad
\text{second share} = \frac{n}{m+n}\times\text{total} \]
</p>
</div>
<h2 id="rates" class="book-prose__heading">Rates</h2>
<p>
A <strong>rate</strong> compares different units. <strong>Speed</strong> is distance per time:
\[ \text{speed} = \frac{\text{distance}}{\text{time}}. \]
A <strong>unit rate</strong> tells “how much per one” — for example \(60\) km in \(1.5\) h gives
\(60 \div 1.5 = 40\) km/h.
</p>
<h2 id="try-it-yourself" class="book-prose__heading">Try it yourself</h2>
<p>
Use the number-line explorer to pick two directed numbers and see their sum on the line. Then try
the ratio sharer in the applications section below.
</p>
</div>
<div class="math-widget-mount" data-widget="number-line" data-pagefind-ignore></div>
<div class="book-prose">
<h2 id="history" class="book-prose__heading">History</h2>
<p>
For much of history, mathematicians treated only positive quantities as numbers. Negative
solutions to equations were often rejected as meaningless. Practical needs — debts, losses,
and temperatures below zero — still pushed people to work with “numbers less than nothing.”
</p>
<figure class="book-figure">
<img
class="book-figure__img"
src="/chapters/math/directed-numbers-rates/directed-numbers-history.png"
alt="Illustrated timeline: ancient rejection of negative roots, Indian and Chinese rules for signed quantities, European skepticism, and the development of ratios from barter to modern rates"
width="960"
height="640"
loading="lazy"
decoding="async"
/>
<figcaption class="book-figure__caption">
A sketch of how directed numbers and ratios were understood — from Greek reluctance to use
negative roots, through Indian and Chinese models of fortune and debt, to modern rates such
as speed and exchange.
</figcaption>
</figure>
<p>
In India around the 7th century, <strong>Brahmagupta</strong> gave rules for operating with
positive and negative quantities (fortunes and debts). Chinese scholars used counting rods with
two colours to represent opposite signs. European acceptance grew slowly; even in the 18th century
some writers called negative roots “false.”
</p>
<p>
Ratios and proportions appear in Babylonian and Egyptian problems (sharing grain, scaling
recipes). The modern notation \(a:b\) and systematic treatment of <strong>unit rates</strong>
became standard as commerce and science needed comparable measures — speed, price per item, and
exchange rates between currencies.
</p>
<h2 id="derivation" class="book-prose__heading">Derivation</h2>
<h3 id="why-minus-times-minus" class="book-prose__heading">Why \((-)\times(-) = (+)\)?</h3>
<p>
One useful pattern: multiplication should keep the rules of arithmetic consistent. For any
real \(a\), you want \(a \times 0 = 0\). Then
\[ a \times 0 = a \times (1 + (-1)) = a\cdot 1 + a\cdot(-1) = a + a\cdot(-1). \]
So \(a\cdot(-1) = -a\). Now apply that twice:
\[ (-a)\cdot(-1) = -((-a)) = a, \]
which shows that multiplying two negatives gives a positive.
</p>
<h3 id="sharing-ratio" class="book-prose__heading">Sharing in the ratio \(m:n\)</h3>
<p>
Suppose a total \(T\) is split into two parts in the ratio \(m:n\). Think of \(m+n\) equal
<em>parts</em>. Each part has size
\[ \frac{T}{m+n}. \]
The first quantity gets \(m\) of those parts:
\[ \frac{m}{m+n}\,T, \]
and the second gets \(\frac{n}{m+n}\,T\). The parts add to \(T\), as required.
</p>
<h3 id="unit-rate" class="book-prose__heading">Unit rate</h3>
<p>
If \(d\) units of quantity are produced in \(t\) units of time, the average rate is
\(d/t\). “Per one hour” means divide by \(t\) when \(t \neq 0\):
\[ \text{rate per unit time} = \frac{d}{t}. \]
Re-arranging gives \(d = \text{rate} \times t\), the formula used for uniform motion.
</p>
<h2 id="checkpoints" class="book-prose__heading">Checkpoints</h2>
<p>
Pause and reason before continuing. Discuss with a partner or write your work in a notebook.
</p>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Without a calculator: is \((-4) + (-7)\) positive or negative? Where do you land if you start
at \(-4\) and move 7 units left?
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Simplify \(6 - (-2)\). Explain using “subtracting a negative is adding a positive.”
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Share \(72\) in the ratio \(5:4\). How many “parts” are there in total?
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
A car travels \(150\) km in \(2.5\) hours. What is the average speed? Which formula did you use?
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Currency A costs \(1.2\) units of Currency B per unit of A. You exchange \(50\) units of A.
How many units of B do you receive?
</p>
</div>
<h2 id="applications" class="book-prose__heading">Applications</h2>
<h3 id="temperature-altitude" class="book-prose__heading">Temperature and altitude</h3>
<p>
A weather station records \(3\,^{\circ}\mathrm{C}\) at noon and the temperature drops
\(8\,^{\circ}\mathrm{C}\) by midnight. The change is \(-8\), so the midnight temperature is
\[ 3 + (-8) = -5\,^{\circ}\mathrm{C}. \]
Altitude above sea level is positive; below sea level (e.g. Dead Sea shore) is negative
elevation relative to sea level.
</p>
<h3 id="sharing-mixture" class="book-prose__heading">Sharing and mixtures</h3>
<p>
Paint is mixed in the ratio blue : white \(= 2:5\). For \(21\) litres total, there are
\(7\) equal parts, each \(3\) litres, giving \(6\) L blue and \(15\) L white.
</p>
<div class="math-widget-mount" data-widget="ratio-demo" data-pagefind-ignore></div>
<h3 id="speed-exchange" class="book-prose__heading">Speed and exchange rates</h3>
<p>
Walking \(6\) km in \(1.5\) h gives speed \(\frac{6}{1.5} = 4\) km/h. An exchange rate of
\(1\) USD \(=\) \(7.8\) HKD means \(100\) USD converts to \(780\) HKD by multiplying by the
unit rate.
</p>
<h2 id="question-bank" class="book-prose__heading">Question bank</h2>
<p>
Work each question, then open the solution to check your reasoning. Difficulty increases
through the sets.
</p>
<h3 id="questions-easy" class="book-prose__heading">Easy</h3>
<details class="book-question">
<summary class="book-question__prompt">Which is larger, \(-3\) or \(-7\)?</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-3\) is larger (lies to the right on the number line).</p>
<p><strong>Explanation:</strong> For negative numbers, the one closer to zero is greater.</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Evaluate \((-2) + 9\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(7\).</p>
<p><strong>Steps:</strong> Start at \(-2\), move 9 units right.</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">\((-4) \times 6 = \) ______</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-24\).</p>
<p><strong>Explanation:</strong> Different signs → negative product.</p>
</div>
</details>
<h3 id="questions-intermediate" class="book-prose__heading">Intermediate</h3>
<details class="book-question">
<summary class="book-question__prompt">Evaluate \(5 - (-3) \times 2\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(11\).</p>
<p><strong>Steps:</strong> \((-3)\times 2 = -6\); then \(5 - (-6) = 5 + 6 = 11\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Divide \(84\) in the ratio \(2:5\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(24\) and \(60\).</p>
<p><strong>Steps:</strong> \(7\) parts; each part \(84 \div 7 = 12\); shares \(24\) and \(60\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">A cyclist goes \(45\) km in \(3\) h. What is the average speed?</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(15\) km/h.</p>
<p><strong>Calculation:</strong> \(45 \div 3 = 15\).</p>
</div>
</details>
<h3 id="questions-difficult" class="book-prose__heading">Difficult</h3>
<details class="book-question">
<summary class="book-question__prompt">The temperature was \(-2\,^{\circ}\mathrm{C}\) and fell by \(9\,^{\circ}\mathrm{C}\). Find the new temperature.</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-11\,^{\circ}\mathrm{C}\).</p>
<p><strong>Steps:</strong> \(-2 + (-9) = -11\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Put in order from smallest to largest: \(-1\), \(0\), \(-\frac{1}{2}\), \(-2\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-2 &lt; -1 &lt; -\frac{1}{2} &lt; 0\).</p>
<p><strong>Explanation:</strong> On the number line, further left means smaller.</p>
</div>
</details>
<h3 id="questions-hardcore" class="book-prose__heading">Hardcore</h3>
<details class="book-question">
<summary class="book-question__prompt">\(A:B = 3:4\) and \(B:C = 2:5\). Find \(A:B:C\) in simplest form.</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(A:B:C = 3:4:10\) after matching \(B\) (multiply first ratio by 2: \(6:8\), second by 4: \(8:20\) → \(6:8:20 = 3:4:10\)).</p>
<p><strong>Steps:</strong> Align \(B\) to LCM 8: \(A:B = 6:8\), \(B:C = 8:20\), so \(A:B:C = 6:8:20 = 3:4:10\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Which situation matches a <em>negative</em> directed number?</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> A bank balance of \(500\) in debt (owe \(500\)) — often modelled as \(-500\).</p>
<p><strong>Explanation:</strong> Debt below zero balance is a standard directed-number model.</p>
</div>
</details>
<h2 id="references" class="book-prose__heading">References</h2>
<ul>
<li>Brahmagupta, <em>Brāhmasphuṭasiddhānta</em> (628 CE) — early rules for signed quantities.</li>
<li>HKDSE Compulsory Part curriculum — Number and Algebra strand (directed numbers, ratios, rates).</li>
</ul>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 KiB

View file

@ -0,0 +1,88 @@
<div class="book-prose">
<p>
Numbers on a line can lie to the <strong>right</strong> of zero (positive) or to the
<strong>left</strong> (negative). Temperatures below freezing, bank overdrafts, and positions
below sea level are everyday examples of <strong>directed numbers</strong>.
</p>
<h2 id="number-line" class="book-prose__heading">The number line</h2>
<p>
On a horizontal number line, moving right means the value <em>increases</em>; moving left means it
<em>decreases</em>. The distance from zero is the <strong>absolute value</strong>
\(|a|\). For example, \(|-5| = 5\) and \(|3| = 3\).
</p>
<div class="book-callout book-callout--formula" role="note">
<p class="book-callout__label">Comparing</p>
<p class="book-formula">
\(a &gt; b\) means \(a\) lies to the right of \(b\). Any negative number is less than any
positive number.
</p>
</div>
<h2 id="adding-subtracting" class="book-prose__heading">Adding and subtracting</h2>
<p>
Think in terms of movement on the line:
</p>
<ul>
<li><strong>\(a + b\)</strong> — start at \(a\), move \(b\) units (right if \(b &gt; 0\), left if \(b &lt; 0\)).</li>
<li><strong>\(a - b\)</strong> — start at \(a\), move \(-b\) units (equivalently, add the opposite of \(b\)).</li>
</ul>
<p>
Subtracting a negative is adding a positive: \(5 - (-3) = 5 + 3 = 8\).
</p>
<h2 id="multiplying-signs" class="book-prose__heading">Multiplying and dividing</h2>
<div class="book-table-wrap">
<table class="book-table">
<thead>
<tr>
<th scope="col">Signs</th>
<th scope="col">Result</th>
</tr>
</thead>
<tbody>
<tr>
<td>positive × positive, negative × negative</td>
<td>positive</td>
</tr>
<tr>
<td>positive × negative (either order)</td>
<td>negative</td>
</tr>
</tbody>
</table>
</div>
<h2 id="ratios" class="book-prose__heading">Ratios</h2>
<p>
A <strong>ratio</strong> compares quantities of the same kind. The ratio \(2:3\) means “2 parts
to 3 parts” — five equal parts in total. To share \(40\) in the ratio \(2:3\), one part is
\(40 \div 5 = 8\), so the shares are \(16\) and \(24\).
</p>
<div class="book-callout book-callout--formula" role="note">
<p class="book-callout__label">Sharing in ratio \(m:n\)</p>
<p class="book-formula">
\[ \text{one part} = \frac{\text{total}}{m+n}, \quad
\text{first share} = \frac{m}{m+n}\times\text{total}, \quad
\text{second share} = \frac{n}{m+n}\times\text{total} \]
</p>
</div>
<h2 id="rates" class="book-prose__heading">Rates</h2>
<p>
A <strong>rate</strong> compares different units. <strong>Speed</strong> is distance per time:
\[ \text{speed} = \frac{\text{distance}}{\text{time}}. \]
A <strong>unit rate</strong> tells “how much per one” — for example \(60\) km in \(1.5\) h gives
\(60 \div 1.5 = 40\) km/h.
</p>
<h2 id="try-it-yourself" class="book-prose__heading">Try it yourself</h2>
<p>
Use the number-line explorer to pick two directed numbers and see their sum on the line. Then try
the ratio sharer in the applications section below.
</p>
</div>
<div class="math-widget-mount" data-widget="number-line" data-pagefind-ignore></div>

View file

@ -0,0 +1,236 @@
<div class="book-prose">
<h2 id="history" class="book-prose__heading">History</h2>
<p>
For much of history, mathematicians treated only positive quantities as numbers. Negative
solutions to equations were often rejected as meaningless. Practical needs — debts, losses,
and temperatures below zero — still pushed people to work with “numbers less than nothing.”
</p>
<figure class="book-figure">
<img
class="book-figure__img"
src="/chapters/math/directed-numbers-rates/directed-numbers-history.png"
alt="Illustrated timeline: ancient rejection of negative roots, Indian and Chinese rules for signed quantities, European skepticism, and the development of ratios from barter to modern rates"
width="960"
height="640"
loading="lazy"
decoding="async"
/>
<figcaption class="book-figure__caption">
A sketch of how directed numbers and ratios were understood — from Greek reluctance to use
negative roots, through Indian and Chinese models of fortune and debt, to modern rates such
as speed and exchange.
</figcaption>
</figure>
<p>
In India around the 7th century, <strong>Brahmagupta</strong> gave rules for operating with
positive and negative quantities (fortunes and debts). Chinese scholars used counting rods with
two colours to represent opposite signs. European acceptance grew slowly; even in the 18th century
some writers called negative roots “false.”
</p>
<p>
Ratios and proportions appear in Babylonian and Egyptian problems (sharing grain, scaling
recipes). The modern notation \(a:b\) and systematic treatment of <strong>unit rates</strong>
became standard as commerce and science needed comparable measures — speed, price per item, and
exchange rates between currencies.
</p>
<h2 id="derivation" class="book-prose__heading">Derivation</h2>
<h3 id="why-minus-times-minus" class="book-prose__heading">Why \((-)\times(-) = (+)\)?</h3>
<p>
One useful pattern: multiplication should keep the rules of arithmetic consistent. For any
real \(a\), you want \(a \times 0 = 0\). Then
\[ a \times 0 = a \times (1 + (-1)) = a\cdot 1 + a\cdot(-1) = a + a\cdot(-1). \]
So \(a\cdot(-1) = -a\). Now apply that twice:
\[ (-a)\cdot(-1) = -((-a)) = a, \]
which shows that multiplying two negatives gives a positive.
</p>
<h3 id="sharing-ratio" class="book-prose__heading">Sharing in the ratio \(m:n\)</h3>
<p>
Suppose a total \(T\) is split into two parts in the ratio \(m:n\). Think of \(m+n\) equal
<em>parts</em>. Each part has size
\[ \frac{T}{m+n}. \]
The first quantity gets \(m\) of those parts:
\[ \frac{m}{m+n}\,T, \]
and the second gets \(\frac{n}{m+n}\,T\). The parts add to \(T\), as required.
</p>
<h3 id="unit-rate" class="book-prose__heading">Unit rate</h3>
<p>
If \(d\) units of quantity are produced in \(t\) units of time, the average rate is
\(d/t\). “Per one hour” means divide by \(t\) when \(t \neq 0\):
\[ \text{rate per unit time} = \frac{d}{t}. \]
Re-arranging gives \(d = \text{rate} \times t\), the formula used for uniform motion.
</p>
<h2 id="checkpoints" class="book-prose__heading">Checkpoints</h2>
<p>
Pause and reason before continuing. Discuss with a partner or write your work in a notebook.
</p>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Without a calculator: is \((-4) + (-7)\) positive or negative? Where do you land if you start
at \(-4\) and move 7 units left?
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Simplify \(6 - (-2)\). Explain using “subtracting a negative is adding a positive.”
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Share \(72\) in the ratio \(5:4\). How many “parts” are there in total?
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
A car travels \(150\) km in \(2.5\) hours. What is the average speed? Which formula did you use?
</p>
</div>
<div class="book-callout" role="note">
<p class="book-callout__label">Checkpoint</p>
<p>
Currency A costs \(1.2\) units of Currency B per unit of A. You exchange \(50\) units of A.
How many units of B do you receive?
</p>
</div>
<h2 id="applications" class="book-prose__heading">Applications</h2>
<h3 id="temperature-altitude" class="book-prose__heading">Temperature and altitude</h3>
<p>
A weather station records \(3\,^{\circ}\mathrm{C}\) at noon and the temperature drops
\(8\,^{\circ}\mathrm{C}\) by midnight. The change is \(-8\), so the midnight temperature is
\[ 3 + (-8) = -5\,^{\circ}\mathrm{C}. \]
Altitude above sea level is positive; below sea level (e.g. Dead Sea shore) is negative
elevation relative to sea level.
</p>
<h3 id="sharing-mixture" class="book-prose__heading">Sharing and mixtures</h3>
<p>
Paint is mixed in the ratio blue : white \(= 2:5\). For \(21\) litres total, there are
\(7\) equal parts, each \(3\) litres, giving \(6\) L blue and \(15\) L white.
</p>
<div class="math-widget-mount" data-widget="ratio-demo" data-pagefind-ignore></div>
<h3 id="speed-exchange" class="book-prose__heading">Speed and exchange rates</h3>
<p>
Walking \(6\) km in \(1.5\) h gives speed \(\frac{6}{1.5} = 4\) km/h. An exchange rate of
\(1\) USD \(=\) \(7.8\) HKD means \(100\) USD converts to \(780\) HKD by multiplying by the
unit rate.
</p>
<h2 id="question-bank" class="book-prose__heading">Question bank</h2>
<p>
Work each question, then open the solution to check your reasoning. Difficulty increases
through the sets.
</p>
<h3 id="questions-easy" class="book-prose__heading">Easy</h3>
<details class="book-question">
<summary class="book-question__prompt">Which is larger, \(-3\) or \(-7\)?</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-3\) is larger (lies to the right on the number line).</p>
<p><strong>Explanation:</strong> For negative numbers, the one closer to zero is greater.</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Evaluate \((-2) + 9\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(7\).</p>
<p><strong>Steps:</strong> Start at \(-2\), move 9 units right.</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">\((-4) \times 6 = \) ______</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-24\).</p>
<p><strong>Explanation:</strong> Different signs → negative product.</p>
</div>
</details>
<h3 id="questions-intermediate" class="book-prose__heading">Intermediate</h3>
<details class="book-question">
<summary class="book-question__prompt">Evaluate \(5 - (-3) \times 2\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(11\).</p>
<p><strong>Steps:</strong> \((-3)\times 2 = -6\); then \(5 - (-6) = 5 + 6 = 11\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Divide \(84\) in the ratio \(2:5\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(24\) and \(60\).</p>
<p><strong>Steps:</strong> \(7\) parts; each part \(84 \div 7 = 12\); shares \(24\) and \(60\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">A cyclist goes \(45\) km in \(3\) h. What is the average speed?</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(15\) km/h.</p>
<p><strong>Calculation:</strong> \(45 \div 3 = 15\).</p>
</div>
</details>
<h3 id="questions-difficult" class="book-prose__heading">Difficult</h3>
<details class="book-question">
<summary class="book-question__prompt">The temperature was \(-2\,^{\circ}\mathrm{C}\) and fell by \(9\,^{\circ}\mathrm{C}\). Find the new temperature.</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-11\,^{\circ}\mathrm{C}\).</p>
<p><strong>Steps:</strong> \(-2 + (-9) = -11\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Put in order from smallest to largest: \(-1\), \(0\), \(-\frac{1}{2}\), \(-2\).</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(-2 &lt; -1 &lt; -\frac{1}{2} &lt; 0\).</p>
<p><strong>Explanation:</strong> On the number line, further left means smaller.</p>
</div>
</details>
<h3 id="questions-hardcore" class="book-prose__heading">Hardcore</h3>
<details class="book-question">
<summary class="book-question__prompt">\(A:B = 3:4\) and \(B:C = 2:5\). Find \(A:B:C\) in simplest form.</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> \(A:B:C = 3:4:10\) after matching \(B\) (multiply first ratio by 2: \(6:8\), second by 4: \(8:20\) → \(6:8:20 = 3:4:10\)).</p>
<p><strong>Steps:</strong> Align \(B\) to LCM 8: \(A:B = 6:8\), \(B:C = 8:20\), so \(A:B:C = 6:8:20 = 3:4:10\).</p>
</div>
</details>
<details class="book-question">
<summary class="book-question__prompt">Which situation matches a <em>negative</em> directed number?</summary>
<div class="book-question__solution">
<p><strong>Answer:</strong> A bank balance of \(500\) in debt (owe \(500\)) — often modelled as \(-500\).</p>
<p><strong>Explanation:</strong> Debt below zero balance is a standard directed-number model.</p>
</div>
</details>
<h2 id="references" class="book-prose__heading">References</h2>
<ul>
<li>Brahmagupta, <em>Brāhmasphuṭasiddhānta</em> (628 CE) — early rules for signed quantities.</li>
<li>HKDSE Compulsory Part curriculum — Number and Algebra strand (directed numbers, ratios, rates).</li>
</ul>
</div>

View file

@ -0,0 +1,182 @@
import katex from "katex";
import { createEffect, createMemo, createSignal } from "solid-js";
import { renderMathInContainer } from "../../../../frontend/src/lib/render-math";
const MIN = -10;
const MAX = 10;
const WIDTH = 400;
const PAD = 28;
const PLOT = WIDTH - 2 * PAD;
function formatNum(n: number) {
if (Number.isInteger(n)) return String(n);
return (Math.round(n * 100) / 100).toString();
}
function renderLatex(latex: string) {
return katex.renderToString(latex, { throwOnError: false, strict: "ignore" });
}
function toX(value: number) {
const t = (value - MIN) / (MAX - MIN);
return PAD + t * PLOT;
}
function NumberLine() {
const [a, setA] = createSignal(3);
const [b, setB] = createSignal(-2);
let canvasRef: HTMLCanvasElement | undefined;
const sum = createMemo(() => a() + b());
const equationHtml = createMemo(() =>
renderLatex(`${formatNum(a())} + (${formatNum(b())}) = ${formatNum(sum())}`)
);
const redraw = () => {
const canvas = canvasRef;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
const h = 120;
const dpr = window.devicePixelRatio || 1;
canvas.width = WIDTH * dpr;
canvas.height = h * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
const style = getComputedStyle(canvas);
const grid = style.getPropertyValue("--math-grid").trim() || "#e5e5e5";
const axis = style.getPropertyValue("--math-axis").trim() || "#a8a29e";
const curve = style.getPropertyValue("--math-curve").trim() || "#9a6b2e";
const root = style.getPropertyValue("--math-root").trim() || "#2563eb";
const vertex = style.getPropertyValue("--math-vertex").trim() || "#4a6b4a";
const bg = style.getPropertyValue("--math-canvas-bg").trim() || "#ffffff";
ctx.fillStyle = bg;
ctx.fillRect(0, 0, WIDTH, h);
const y = h / 2;
ctx.strokeStyle = grid;
ctx.lineWidth = 1;
for (let v = MIN; v <= MAX; v++) {
const x = toX(v);
ctx.beginPath();
ctx.moveTo(x, y - 4);
ctx.lineTo(x, y + 4);
ctx.stroke();
}
ctx.strokeStyle = axis;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(PAD, y);
ctx.lineTo(WIDTH - PAD, y);
ctx.stroke();
ctx.fillStyle = axis;
ctx.font = "10px IBM Plex Mono, monospace";
ctx.textAlign = "center";
for (let v = MIN; v <= MAX; v += 2) {
ctx.fillText(String(v), toX(v), y + 18);
}
const drawTick = (value: number, color: string, radius: number) => {
const x = toX(value);
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
};
const av = a();
const bv = b();
const sv = sum();
drawTick(av, root, 6);
drawTick(bv, vertex, 6);
drawTick(sv, curve, 7);
ctx.strokeStyle = curve;
ctx.lineWidth = 2;
ctx.setLineDash([6, 4]);
ctx.beginPath();
ctx.moveTo(toX(av), y);
ctx.lineTo(toX(sv), y);
ctx.stroke();
ctx.setLineDash([]);
};
createEffect(() => {
a();
b();
sum();
redraw();
});
return (
<section class="math-widget" aria-labelledby="number-line-title">
<h2 id="number-line-title" class="math-widget__title">Number-line addition</h2>
<div class="math-widget__body">
<div class="math-widget__controls">
<div class="scenario-demo__control">
<label class="scenario-demo__label" for="nl-a">
<span>First number a</span>
<span class="scenario-demo__value">{formatNum(a())}</span>
</label>
<input
id="nl-a"
class="scenario-demo__slider"
type="range"
min={MIN}
max={MAX}
step={1}
value={a()}
onInput={(e) => setA(Number(e.currentTarget.value))}
/>
</div>
<div class="scenario-demo__control">
<label class="scenario-demo__label" for="nl-b">
<span>Second number b</span>
<span class="scenario-demo__value">{formatNum(b())}</span>
</label>
<input
id="nl-b"
class="scenario-demo__slider"
type="range"
min={MIN}
max={MAX}
step={1}
value={b()}
onInput={(e) => setB(Number(e.currentTarget.value))}
/>
</div>
</div>
<div class="math-widget__formula" innerHTML={equationHtml()} aria-live="polite" />
<figure class="math-widget__figure">
<canvas
ref={(el) => {
canvasRef = el;
redraw();
}}
class="math-widget__canvas"
width={WIDTH}
height={120}
role="img"
aria-label={`Number line showing ${formatNum(a())} plus ${formatNum(b())} equals ${formatNum(sum())}`}
/>
<figcaption
class="math-widget__caption"
ref={(el) => {
if (el) renderMathInContainer(el);
}}
>
Blue: \(a\). Green: \(b\). Gold: sum \(a+b\). Dashed segment shows the move from \(a\) to
\(a+b\).
</figcaption>
</figure>
</div>
</section>
);
}
export default NumberLine;

View file

@ -0,0 +1,118 @@
import katex from "katex";
import { createMemo, createSignal } from "solid-js";
function formatNum(n: number) {
if (Number.isInteger(n)) return String(n);
return (Math.round(n * 100) / 100).toString();
}
function renderLatex(latex: string) {
return katex.renderToString(latex, { throwOnError: false, strict: "ignore" });
}
function RatioDemo() {
const [partA, setPartA] = createSignal(2);
const [partB, setPartB] = createSignal(5);
const [total, setTotal] = createSignal(28);
const sumParts = createMemo(() => partA() + partB());
const shareA = createMemo(() => (partA() / sumParts()) * total());
const shareB = createMemo(() => (partB() / sumParts()) * total());
const formulaHtml = createMemo(() =>
renderLatex(
`${partA()}:${partB()} \\Rightarrow ${formatNum(shareA())} : ${formatNum(shareB())} \\text{ from total } ${formatNum(total())}`
)
);
return (
<section
class="scenario-demo scenario-demo--ratio"
aria-label="Sharing a total in a given ratio"
>
<div class="scenario-demo__stage scenario-demo__stage--wide">
<p class="scenario-demo__live" aria-live="polite">
Split <strong>{formatNum(total())}</strong> in the ratio{" "}
<strong>
{partA()}:{partB()}
</strong>
. Each of the <strong>{sumParts()}</strong> equal parts has size{" "}
<strong>{formatNum(total() / sumParts())}</strong>.
</p>
<div class="ratio-demo__bars" role="img" aria-hidden="true">
<div
class="ratio-demo__bar ratio-demo__bar--a"
style={{ width: `${(partA() / sumParts()) * 100}%` }}
/>
<div
class="ratio-demo__bar ratio-demo__bar--b"
style={{ width: `${(partB() / sumParts()) * 100}%` }}
/>
</div>
<div class="scenario-demo__control">
<label class="scenario-demo__label" for="ratio-a">
<span>First part of ratio</span>
<span class="scenario-demo__value">{partA()}</span>
</label>
<input
id="ratio-a"
class="scenario-demo__slider"
type="range"
min={1}
max={8}
step={1}
value={partA()}
onInput={(e) => setPartA(Number(e.currentTarget.value))}
/>
</div>
<div class="scenario-demo__control">
<label class="scenario-demo__label" for="ratio-b">
<span>Second part of ratio</span>
<span class="scenario-demo__value">{partB()}</span>
</label>
<input
id="ratio-b"
class="scenario-demo__slider"
type="range"
min={1}
max={8}
step={1}
value={partB()}
onInput={(e) => setPartB(Number(e.currentTarget.value))}
/>
</div>
<div class="scenario-demo__control">
<label class="scenario-demo__label" for="ratio-total">
<span>Total to share</span>
<span class="scenario-demo__value">{formatNum(total())}</span>
</label>
<input
id="ratio-total"
class="scenario-demo__slider"
type="range"
min={10}
max={100}
step={2}
value={total()}
onInput={(e) => setTotal(Number(e.currentTarget.value))}
/>
</div>
</div>
<div class="scenario-demo__panel">
<div class="scenario-demo__formula" innerHTML={formulaHtml()} aria-live="polite" />
<div class="scenario-demo__stats">
<div class="scenario-demo__stat scenario-demo__stat--highlight">
<span class="scenario-demo__stat-label">First share</span>
<span class="scenario-demo__stat-value">{formatNum(shareA())}</span>
</div>
<div class="scenario-demo__stat">
<span class="scenario-demo__stat-label">Second share</span>
<span class="scenario-demo__stat-value">{formatNum(shareB())}</span>
</div>
</div>
</div>
</section>
);
}
export default RatioDemo;

View file

@ -53,7 +53,7 @@
"slug": "directed-numbers-rates",
"title": "Directed numbers, rates & ratios",
"description": "Operate with negative numbers and solve ratio, rate, and proportion problems in context.",
"status": "planned",
"status": "live",
"curriculums": ["DSE"]
},
{

View file

@ -7,12 +7,18 @@ const DELIMITERS = [
{ left: "\\[", right: "\\]", display: true },
];
export function renderBookMath() {
document.querySelectorAll<HTMLElement>(".book-prose, .book-callout").forEach((el) => {
renderMathInElement(el, {
delimiters: DELIMITERS,
throwOnError: false,
strict: "ignore",
});
});
const RENDER_OPTIONS = {
delimiters: DELIMITERS,
throwOnError: false,
strict: "ignore" as const,
};
export function renderMathInContainer(el: HTMLElement) {
renderMathInElement(el, RENDER_OPTIONS);
}
export function renderBookMath() {
document
.querySelectorAll<HTMLElement>(".book-prose, .book-callout, .math-widget__caption")
.forEach(renderMathInContainer);
}

View file

@ -16,12 +16,6 @@ we have a catalog of subjects. Each subject will have chapters. Each chapters ca
we need to have a question bank feature. since this is purely static sites, question answer needs to be determined and able to grade in advanced.
1. multiple-choice
2. short-answer
3. fill-in-the-blank
4. choice
5. ranking
question bank not only show answer but also steps, explanation, calcultion.
## Chapters requirements

View file

@ -375,6 +375,83 @@ a.book-chapter-link:focus-visible {
max-width: 960px;
}
.book-question {
margin: 1rem 0;
border: 1px solid var(--card-border);
border-radius: 12px;
background: var(--card-bg);
}
.book-question__prompt {
position: relative;
padding: 14px 18px 14px 2.75rem;
font-weight: 500;
line-height: 1.55;
cursor: pointer;
list-style: none;
}
.book-question__prompt::-webkit-details-marker {
display: none;
}
.book-question__prompt::marker {
content: "";
}
.book-question__prompt::before {
content: "";
position: absolute;
left: 1.125rem;
top: 1.35em;
width: 0.45em;
height: 0.45em;
border-right: 2px solid var(--accent);
border-bottom: 2px solid var(--accent);
transform: rotate(-45deg);
transition: transform 200ms ease;
}
.book-question[open] .book-question__prompt::before {
top: 1.5em;
transform: rotate(45deg);
}
.book-question__prompt:hover::before,
.book-question__prompt:focus-visible::before {
border-color: var(--ink);
}
.book-question__solution {
padding: 0 18px 16px;
border-top: 1px solid var(--card-border);
font-size: 0.95rem;
color: var(--soft-ink);
}
.book-question__solution p {
margin: 0.75rem 0 0;
}
.ratio-demo__bars {
display: flex;
width: 100%;
max-width: 400px;
height: 28px;
margin: 16px 0 20px;
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--card-border);
}
.ratio-demo__bar--a {
background: var(--math-root, #2563eb);
}
.ratio-demo__bar--b {
background: var(--math-curve, #9a6b2e);
}
.book-page--chapter .book-callout--dse {
max-width: var(--prose-width);
margin-top: 2rem;

View file

@ -453,8 +453,20 @@
:global(.catalog-mermaid-view__svg .plannedNode rect),
:global(.catalog-mermaid-view__svg .plannedNode polygon) {
stroke: color-mix(in srgb, var(--muted) 85%, transparent);
fill: color-mix(in srgb, var(--paper) 92%, var(--muted) 8%);
stroke: color-mix(in srgb, var(--muted) 70%, var(--line));
fill: color-mix(in srgb, var(--paper) 82%, var(--muted) 18%);
}
:global(.catalog-mermaid-view__svg .plannedNode .catalog-mermaid-node__title) {
color: var(--muted);
}
:global(.catalog-mermaid-view__svg .plannedNode .catalog-mermaid-node__description) {
color: color-mix(in srgb, var(--muted) 88%, var(--soft-ink));
}
:global(.catalog-mermaid-view__svg .plannedNode .catalog-badge:not(.book-chapter-badge--planned)) {
opacity: 0.55;
}
:global(.catalog-mermaid-view__svg .edge-path path) {
@ -615,6 +627,16 @@
&:focus-within::before {
background: var(--accent);
}
&:has(.catalog-chapter-card--planned)::before {
background: color-mix(in srgb, var(--muted) 45%, var(--line));
box-shadow: 0 0 0 4px var(--card-bg);
}
&:has(.catalog-chapter-card--planned):hover::before,
&:has(.catalog-chapter-card--planned):focus-within::before {
background: color-mix(in srgb, var(--muted) 45%, var(--line));
}
}
.catalog-chapter-card {
@ -631,8 +653,27 @@
transition: border-color 200ms ease, box-shadow 200ms ease;
&--planned {
opacity: 0.85;
color: var(--muted);
background: color-mix(in srgb, var(--paper) 86%, var(--muted) 14%);
border-color: color-mix(in srgb, var(--line) 65%, transparent);
border-style: dashed;
cursor: default;
.catalog-chapter-card__number,
.catalog-chapter-card__title,
.catalog-chapter-card__description {
color: var(--muted);
}
.catalog-badge:not(.book-chapter-badge--planned) {
opacity: 0.5;
}
.book-chapter-badge--planned {
color: var(--muted);
background: color-mix(in srgb, var(--muted) 16%, transparent);
border: 1px solid color-mix(in srgb, var(--line) 75%, transparent);
}
}
}