Blame
|
1 | # From SRS to Detailed Designs — Data and Logic |
||||||
| 2 | ||||||||
| 3 | The Hamilton and Alexandra College · Year 12 · 2026 |
|||||||
| 4 | ||||||||
| 5 | The [Mock-ups sibling of this page](From%20SRS%20to%20Detailed%20Designs%20-%20Mock-ups) traces a *screen* back to a requirement. This page traces the **data and logic** the same way, using the same real project — `vsd-sat-grader`, the SAT folio grader your teacher actually built. |
|||||||
| 6 | ||||||||
| 7 | C05-1 asks for four data/logic design tools: a **data dictionary**, **IPO charts**, **pseudocode**, and **object descriptions**. The trap is to treat them as four separate deliverables you grind out one after another. They are not. They are **four views of one design**, and the proof is simple: a single sentence from your SRS shows up in all four of them. |
|||||||
| 8 | ||||||||
| 9 | Here is that sentence. It is from §7 (Data model) of the real SRS, quoted exactly: |
|||||||
| 10 | ||||||||
| 11 | > Derived values (bands, calculated scores, totals, ranks) are **computed, never stored**. |
|||||||
| 12 | ||||||||
| 13 | That one rule — *store the inputs, compute everything you can derive from them* — is the spine of this page. We follow it through all four tools, then through the built UI, and you will see the same idea each time wearing a different costume. |
|||||||
| 14 | ||||||||
| 15 | --- |
|||||||
| 16 | ||||||||
| 17 | ## The four tools are one design |
|||||||
| 18 | ||||||||
| 19 | The SRS data model is the source. Each design tool is a different lens on it, and each lens also surfaces in the app you can run. |
|||||||
| 20 | ||||||||
| 21 | ```mermaid |
|||||||
| 22 | flowchart TD |
|||||||
| 23 | SRS["C03 · SRS §7<br/>Data model<br/>'computed, never stored'"] |
|||||||
| 24 | SRS --> DD["Data dictionary<br/><i>what is stored vs derived</i>"] |
|||||||
| 25 | SRS --> OD["Object descriptions<br/><i>attribute vs method</i>"] |
|||||||
| 26 | SRS --> PC["Pseudocode<br/><i>how a value is derived</i>"] |
|||||||
| 27 | SRS --> IPO["IPO charts<br/><i>input → process → output</i>"] |
|||||||
| 28 | DD --> UI["Built UI"] |
|||||||
| 29 | OD --> UI |
|||||||
| 30 | PC --> UI |
|||||||
| 31 | IPO --> UI |
|||||||
| 32 | UI --> SEE["You can see the rule<br/>on screen:<br/>totals, bands, live summary"] |
|||||||
| 33 | ``` |
|||||||
| 34 | ||||||||
| 35 | The four tools answer four questions about the *same* truth — and because the SRS forbids storing derived values, every tool has to agree on which values those are. Disagreement between tools is a design bug. Agreement is traceability. |
|||||||
| 36 | ||||||||
| 37 | --- |
|||||||
| 38 | ||||||||
| 39 | ## Fully worked: "computed, never stored", through all four tools |
|||||||
| 40 | ||||||||
| 41 | We will now walk the one SRS sentence through every tool, quoting each artefact's own wording so you can see the rule restated in each language. |
|||||||
| 42 | ||||||||
| 43 | ### Tool 1 — Data dictionary: a separate section for what is *not* stored |
|||||||
| 44 | ||||||||
|
45 | Before the big table, meet two **complete, small** ones. The real data dictionary opens with these — each just two rows, but already carrying the full six-column format (Field / Data type / Format / Description / Example / Validation). The column set itself is the teaching point: every field, however small, gets a type, a format, an example *and* a validation rule. Both tables verbatim: |
||||||
| 46 | ||||||||
|
47 | > #### 1. Criteria (`CRITERIA`) |
||||||
|
48 | |||||||
| 49 | | Field | Data type | Format / range | Description | Example | Validation | |
|||||||
| 50 | | --- | --- | --- | --- | --- | --- | |
|||||||
| 51 | | `cid` | str | `C` + 2 digits, `C01`–`C10` | Criterion identifier; also keys the rubric filename | `C03` | Must have a matching `data/rubrics/<cid>-rubric.md` | |
|||||||
| 52 | | `name` | str | ≤ 80 chars | Criterion title from the VCAA rubric heading | `Skills in documenting a software requirements specification` | Non-empty | |
|||||||
| 53 | ||||||||
|
54 | > #### 2. Band scale (`BANDS`, `BAND_LABELS`) |
||||||
|
55 | |||||||
| 56 | | Field | Data type | Format / range | Description | Example | Validation | |
|||||||
| 57 | | --- | --- | --- | --- | --- | --- | |
|||||||
| 58 | | `band` | str | `low-high`, 5 fixed values | Rubric band a score falls in: `1-2`, `3-4`, `5-6`, `7-8`, `9-10` | `7-8` | One of the 5 values | |
|||||||
| 59 | | `band_label` | str | band + qualifier | Display label for evidence grids | `7-8 (high)` | Derived 1:1 from `band` | |
|||||||
| 60 | ||||||||
|
61 | Four rows do not look like much — until you see how much of the screen they drive. Here is the Grade tab; look at the labels: |
||||||
| 62 | ||||||||
| 63 |  |
|||||||
| 64 | ||||||||
| 65 | The five **Band** radio buttons (`1-2` … `9-10`) are exactly the five fixed values of `band` — "One of the 5 values", nothing else can exist. And the column headers across both evidence grids — "1-2 (very low)" … "9-10 (very high)" — are `band_label`, the "band + qualifier" display form, "Derived 1:1 from `band`". Two tiny tables, and every band label on the screen is accounted for: the `cid` in the Criteria dropdown comes from the first, every band marking on the page comes from the second. |
|||||||
| 66 | ||||||||
|
67 | That is a complete data dictionary in miniature — you can read it end to end in thirty seconds. Now you are ready for the real thing: §4, the **student record**, the shape that becomes one markdown file per student in Sprint 2. Here is an abbreviated cut — four rows chosen to show the variety the format can carry, each verbatim: |
||||||
| 68 | ||||||||
|
69 | > #### 4. Student record (`MOCK_STUDENTS` → one markdown file per student in Sprint 2) |
||||||
|
70 | |||||||
| 71 | | Field | Data type | Format / range | Description | Example | Validation | |
|||||||
| 72 | | --- | --- | --- | --- | --- | --- | |
|||||||
| 73 | | `student` | str | ≤ 50 chars | Student name; keys the record and the leaderboard | `Cohen` | Unique within cohort; non-empty | |
|||||||
| 74 | | `grades` | dict | keyed by `cid` | Grading record per criterion (absent = not graded yet) | `{"C03": {...}}` | Keys ∈ `CRITERIA` | |
|||||||
| 75 | | `grades[cid].indicator_scores` | list[int \| None] | 0–10 whole numbers, one per indicator | Teacher's score per indicator | `[8, 7]` | Length ≤ indicator count; each 0–10 or empty | |
|||||||
| 76 | | `grades[cid].final` | int \| None | 0–10 | Final criterion score after the teacher reconciles calculated vs AI vs cross-marker; never auto-filled | `8` | 0–10 or absent | |
|||||||
| 77 | ||||||||
| 78 | *… plus 10 more fields (evidence grids, AI score and evidence, cross-mark, reconciliation note, report comment and advice) — read the [full table on GitHub](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/data-dictionary.md).* |
|||||||
| 79 | ||||||||
| 80 | Notice the variety those four rows carry: a simple string with a uniqueness rule (`student`), a dict keyed by criterion (`grades`), a list validated per item (`indicator_scores`), and a nullable int whose description states a *policy* — `final` is "never auto-filled". Same six columns every time. |
|||||||
| 81 | ||||||||
| 82 | So §§1–4 document everything **stored**. The punchline is what comes next: a separate §5 for **derived values** — the things the dictionary deliberately does *not* let you store. The heading is exact: |
|||||||
|
83 | |||||||
|
84 | > #### 5. Derived values (computed, never stored) |
||||||
|
85 | |||||||
| 86 | A few of its rows: |
|||||||
| 87 | ||||||||
| 88 | | Value | Derivation | Example | |
|||||||
| 89 | | --- | --- | --- | |
|||||||
| 90 | | Total 1 | Sum of criterion results for C01–C05 (Unit 3 Outcome 2) | `15` | |
|||||||
| 91 | | Total 2 | Sum of criterion results for C06–C10 (Unit 4 Outcome 1) | `0` | |
|||||||
| 92 | | Rank | Cohort summary row order: sorted by Total, descending | top row | |
|||||||
| 93 | ||||||||
| 94 | Now look at the built Leaderboard. Those rows are not abstractions — they are columns on screen: |
|||||||
| 95 | ||||||||
| 96 |  |
|||||||
| 97 | ||||||||
| 98 | The column headers **Total 1 (C01–C05)**, **Total 2 (C06–C10)** and **Total** are the three data-dictionary rows above, made visible. And the **row order is the derived "Rank"**: Cohen (Total 15) sits above Connor (Total 9) because the table is "sorted by Total, descending" — the app never stores a rank number, it sorts and the position *is* the rank. |
|||||||
| 99 | ||||||||
| 100 | > [!NOTE] |
|||||||
| 101 | > The scores here are **Sprint 1 mock data**, not real grades. Cohen's C03 indicators are `[8, 7]` — the exact example student record shown in the SRS §7 code block. That is why the same numbers reappear throughout this page: they are the SRS's own worked example travelling from artefact to artefact. |
|||||||
| 102 | ||||||||
| 103 | ### Tool 2 — Object descriptions: stored is an attribute, derived is a method |
|||||||
| 104 | ||||||||
| 105 | The object descriptions say the same thing in object-oriented language. Teaching point 3, quoted exactly: |
|||||||
| 106 | ||||||||
| 107 | > **Stored vs derived, as attribute vs method** — `final` is an attribute (a teacher's decision, stored); `calculated()` is a method (a weighted average, derived). This is the class-diagram form of our data rule "derived values are never stored". |
|||||||
| 108 | ||||||||
|
109 | Here are the two classes you have already met in the data dictionary — `Student` and `CriterionGrade` — with the relationships left out so you can concentrate on reading each box: |
||||||
| 110 | ||||||||
| 111 |  |
|||||||
| 112 | ||||||||
| 113 | Read each box top to bottom: the upper compartment is the **attributes** — everything stored, and every one of them is a row you saw in the data dictionary's student record (`indicator_scores`, `ai`, `cross`, `final`, …). The lower compartment is the **methods** — everything derived, and every one of them is a row from the data dictionary's §5 (`calculated`, the totals behind the leaderboard). The horizontal line between the compartments *is* the stored/derived split, drawn in UML. |
|||||||
| 114 | ||||||||
|
115 | So the data dictionary's "stored vs derived" split is the object model's "attribute vs method" split. `final` carries `()` nowhere — it is a value you keep. `calculated()` carries `()` — it is a value you *compute on demand* and throw away. |
||||||
| 116 | ||||||||
| 117 | ### Tool 3 — Pseudocode: how the derived value is actually computed |
|||||||
| 118 | ||||||||
| 119 | The data dictionary says a calculated score *is* derived. The object model says `calculated()` is a method. The pseudocode says **how**. Algorithm 1 derives it, hop by hop, for Cohen's C03 (`[8, 7]`, weights `[60, 40]`): |
|||||||
| 120 | ||||||||
| 121 | - For each scored indicator, add `indicatorScore × weight` to `totalWeighted` and `weight` to `totalWeight`: `8 × 60 = 480`, `7 × 40 = 280`, so `totalWeighted = 760`, `totalWeight = 100`. |
|||||||
| 122 | - `weighted ← totalWeighted / totalWeight` → `760 / 100 = 7.6`. |
|||||||
| 123 | - `RETURN RoundHalfUp(weighted)` → `7.6 → 8`. |
|||||||
| 124 | ||||||||
| 125 | Nothing in that algorithm reads a stored score. It reads the **inputs** (indicator scores, weights) and derives the result fresh every time — exactly what "computed, never stored" demands. |
|||||||
| 126 | ||||||||
| 127 | ### Tool 4 — IPO charts: it can recompute live *because* nothing is stored |
|||||||
| 128 | ||||||||
| 129 | The IPO charts have an event row that only makes sense if derived values are never stored. Quoted exactly from the event-level table: |
|||||||
| 130 | ||||||||
| 131 | > `live_summary` — Recompute the criterion score as indicator scores are typed. |
|||||||
| 132 | ||||||||
| 133 | And a sibling row: |
|||||||
| 134 | ||||||||
| 135 | > `band_of` — Which rubric band a score falls in. |
|||||||
| 136 | ||||||||
| 137 | If the calculated score were stored, you would have to save it before it could update. Because it is derived, the app can **recompute it on every keystroke**. Here is the Grade tab where both rows fire: |
|||||||
| 138 | ||||||||
| 139 |  |
|||||||
| 140 | ||||||||
| 141 | The **7-8 band is highlighted in orange** because `band_of(8)` returns the `7-8` band — that highlight is the `band_of` IPO output rendered on screen. As you type a score, `live_summary` re-derives the criterion score behind the Score tab. Neither value is written to disk until you Save; both are derived live. That is the IPO chart's restatement of the same one rule. |
|||||||
| 142 | ||||||||
| 143 | Four tools, four costumes, one sentence. That is what "four views of one design" means. |
|||||||
| 144 | ||||||||
| 145 | --- |
|||||||
| 146 | ||||||||
| 147 | ## Each tool, anchored to a requirement (your turn to finish each) |
|||||||
| 148 | ||||||||
| 149 | Above, the guidance was full. Below, it fades: each tool gets a short section that names *which requirement it answers*, then ends with **one question** for you to take into your design log. |
|||||||
| 150 | ||||||||
| 151 | ### Data dictionary ← FR2 + SRS §7 |
|||||||
| 152 | ||||||||
| 153 | FR2 quoted exactly: |
|||||||
| 154 | ||||||||
| 155 | > All data is persisted as **markdown files** (one file per student) — the single source of truth, editable by hand or by AI tools. |
|||||||
| 156 | ||||||||
| 157 | "One file per student" is why the data dictionary's §4 documents a single **student record** shape (`student`, `grades`, `comment`, `advice`) rather than a database schema. SRS §7 shows that record as YAML frontmatter; the data dictionary gives each field a type, format, example and validation rule. The frontmatter shape *is* the data dictionary, written out as a file. |
|||||||
| 158 | ||||||||
| 159 | > **Your design log:** find one field in data-dictionary §4 whose **Validation** column would be impossible to enforce if data lived in a database instead of one markdown file per student. (Hint: look at `student` — "Unique within cohort".) |
|||||||
| 160 | ||||||||
| 161 | ### IPO charts ← the context diagram |
|||||||
| 162 | ||||||||
| 163 | You met **context diagrams** back in C02 — one process, the external entities around it, the data flowing in and out. The IPO charts pick up exactly there. The system-level IPO row is built straight from the context diagram: |
|||||||
| 164 | ||||||||
| 165 | | Input | Process | Output | |
|||||||
| 166 | | --- | --- | --- | |
|||||||
| 167 | | Indicator scores + evidence, cross-mark + note, final score + note, report comments (Teacher 1); AI suggested score + evidence (Claude Code, via markdown) | Grade each criterion per indicator; weight indicator scores into calculated criterion scores; support reconciliation; aggregate cohort totals | Rubric descriptors, calculated scores with working, reconcile view, cohort summary (Teacher 1); evidence + rubric + scores as markdown (to Claude Code); final scores + report (to School Report System) | |
|||||||
| 168 | ||||||||
| 169 | The external entities from the context diagram (Teacher 1, Claude Code, the School Report System) reappear here as the *sources* of inputs and the *destinations* of outputs. |
|||||||
| 170 | ||||||||
| 171 | > [!TIP] |
|||||||
| 172 | > The event-level IPO charts are **generated from the app's own event wiring**, so design and build cannot drift apart. The artefact says so: every Gradio handler is `trigger.change(process, [inputs], [outputs])`, so the charts are produced by `tools/generate_ipo.py` and you "regenerate after any wiring change with `uv run python tools/generate_ipo.py`". Change the build, regenerate, the design updates — they are never out of sync. |
|||||||
| 173 | ||||||||
| 174 | Here is one clean event row — `band_of`, the band highlight you saw on the Grade tab: |
|||||||
| 175 | ||||||||
| 176 | | Event (trigger) | Input | Process | Output | |
|||||||
| 177 | | --- | --- | --- | --- | |
|||||||
| 178 | | Indicator score → change ×4 | Indicator score | `band_of` — Which rubric band a score falls in. | Band | |
|||||||
| 179 | ||||||||
| 180 | The big `refresh` row — the one fired by changing student or criterion — has an Output column listing every component on every tab (`Grade 1, Grade 2, … Cohort summary`). It is auto-generated and gloriously long, so it is not reproduced here. Read it in the [full ipo-charts.md on GitHub](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/ipo-charts.md); its length is a feature, not a flaw — it is the machine listing every output one reload must refresh. |
|||||||
| 181 | ||||||||
| 182 | > **Your design log:** the `refresh` row has a huge Output column but a tiny Input column (just Name, Criteria). Why does one small input produce so many outputs? (What does "reload every tab" have to do with NFR1, "fresh reads, no caches"?) |
|||||||
| 183 | ||||||||
| 184 | ### Pseudocode ← FR5 + corrections 06/07 |
|||||||
| 185 | ||||||||
| 186 | FR5 quoted exactly: |
|||||||
| 187 | ||||||||
| 188 | > The app **displays an AI-suggested score + evidence** when present in the markdown (produced externally — see §6). The app is read-only toward these fields. |
|||||||
| 189 | ||||||||
| 190 | The app *shows* the AI score; it never trusts it blindly. Deciding the **final** score is a human job, and the pseudocode has two algorithms precisely to make that split explicit. Algorithm 1 (above) is automated. **Algorithm 2 is a teacher procedure the app deliberately never automates.** Design note 1, quoted exactly: |
|||||||
| 191 | ||||||||
| 192 | > **The final score is never computed** — Algorithm 2 contains teacher decisions ("teacher's choice", "teacher's judgement") by design. The app automates the references, not the judgement. |
|||||||
| 193 | ||||||||
| 194 | The reconcile view is Algorithm 2 on screen: |
|||||||
| 195 | ||||||||
| 196 |  |
|||||||
| 197 | ||||||||
| 198 | Three reference scores are shown side by side — Calculated (8), AI (8), and a place for the cross-mark — and the teacher types the **Final** and a note. The app presents; the human decides. Algorithm 2's decision structure, quoted from the pseudocode: |
|||||||
| 199 | ||||||||
| 200 | ``` |
|||||||
| 201 | IF references = {calculated} THEN // no second opinion available |
|||||||
| 202 | final ← calculated |
|||||||
| 203 | ELSE IF Max(references) − Min(references) = 0 THEN |
|||||||
| 204 | final ← calculated // unanimous |
|||||||
| 205 | ELSE IF Max(references) − Min(references) ≤ 1 THEN |
|||||||
| 206 | final ← teacher's choice IN [Min(references), Max(references)] |
|||||||
| 207 | ELSE |
|||||||
| 208 | // Major disagreement (gap ≥ 2): do not split the difference. |
|||||||
| 209 | final ← teacher's judgement after review |
|||||||
| 210 | END IF |
|||||||
| 211 | ``` |
|||||||
| 212 | ||||||||
| 213 | On screen, Calculated 8 and AI 8 agree — the `Max − Min = 0` branch — so the note reads "AI (8) matches calculated (8) — confirmed." |
|||||||
| 214 | ||||||||
| 215 | > **Your design log:** the last branch forbids "split the difference" when references disagree by 2 or more. Quote design note 3 and explain what a gap of 2 is taken to *mean* about the evidence. |
|||||||
| 216 | ||||||||
| 217 | ### Object descriptions ← the problem domain |
|||||||
| 218 | ||||||||
|
219 | The object descriptions model the **problem domain** — the classes you would design *before* choosing an implementation style. (The real app is built function-over-data, not from these classes; more on that below.) The full class diagram, rendered from the artefact's mermaid source: |
||||||
|
220 | |||||||
|
221 |  |
||||||
|
222 | |||||||
| 223 | Notice the line shapes. Teaching point 1, quoted exactly: |
|||||||
| 224 | ||||||||
| 225 | > **Composition vs association** — a `Student` *owns* their `CriterionGrade`s (delete the student, the grades go too: filled diamond), but a grade merely *refers to* its `Criterion` — the rubric exists independently and is shared by every student (arrow, not diamond). |
|||||||
| 226 | ||||||||
| 227 | So `Student *-- CriterionGrade` is a filled diamond (composition: the grades belong to that student and die with them), while `CriterionGrade --> Criterion` is a plain arrow (association: the rubric is shared, not owned). The diamond is not decoration — it encodes who owns what. |
|||||||
| 228 | ||||||||
| 229 | > **Class discussion** — the app's author chose to *not* build these classes, using dicts and pure functions instead. From the artefact: |
|||||||
| 230 | > |
|||||||
| 231 | > > the implementation chose dicts + pure functions over these classes. What did that trade away (encapsulation, invariants living next to the data) and what did it buy (markdown round-tripping is trivial, functions are easy to unit test, no object/file mapping layer)? Both are valid detailed designs; the object description is how you *communicate* the domain either way. |
|||||||
| 232 | ||||||||
| 233 | --- |
|||||||
| 234 | ||||||||
| 235 | ## Your turn — trace `validation_gap` through three tools |
|||||||
| 236 | ||||||||
| 237 | You have seen "computed, never stored" appear in four tools. Now trace a different idea **yourself**. The anti-AI-cheating check — *the standard observed in class was not reproduced under assessment conditions* — lives, like that sentence, in three artefacts at once: |
|||||||
| 238 | ||||||||
| 239 | 1. **Pseudocode**, as the guard at the top of Algorithm 2: a `FOR EACH indicator` loop that flags `REVIEW` when `HighestBand(indicator.validation) < HighestBand(indicator.observation)` — in [pseudocode-final-score.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/pseudocode-final-score.md). |
|||||||
| 240 | 2. **Object descriptions**, as the method `validation_gap()` on `IndicatorEvidence` — in [object-descriptions.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/object-descriptions.md). |
|||||||
| 241 | 3. **Data dictionary**, as the two evidence fields it compares: `…evidence[i].observation` and `…evidence[i].validation` — in [data-dictionary.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/data-dictionary.md). |
|||||||
| 242 | ||||||||
| 243 | Open all three and answer in your design log: |
|||||||
| 244 | ||||||||
| 245 | 1. The pseudocode guard and the `validation_gap()` method describe the *same* comparison. Quote the condition from each and show they are the same test written two ways. |
|||||||
| 246 | 2. The data dictionary says `validation` is "Evidence under assessment conditions (no AI / outside help); confirms the judgement." Why does a *lower* validation band than observation band suggest a problem worth reviewing? |
|||||||
| 247 | 3. Is `validation_gap` a **stored** value or a **derived** one? Which tool would you cite to justify your answer, and how does that connect back to "computed, never stored"? |
|||||||
| 248 | ||||||||
| 249 | --- |
|||||||
| 250 | ||||||||
| 251 | ## The real files |
|||||||
| 252 | ||||||||
| 253 | Open these on GitHub and read the originals. Each is the artefact a section above quotes. |
|||||||
| 254 | ||||||||
| 255 | | Artefact | Link | |
|||||||
| 256 | | --- | --- | |
|||||||
| 257 | | SRS (FR/NFR tables, §7 data model, MoSCoW scope) | [SRS/SRS.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/SRS/SRS.md) | |
|||||||
| 258 | | Data dictionary (stored §4, derived §5) | [C05/data-dictionary.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/data-dictionary.md) | |
|||||||
| 259 | | IPO charts (system-level + generated event rows) | [C05/ipo-charts.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/ipo-charts.md) | |
|||||||
| 260 | | Pseudocode (Algorithm 1 automated, Algorithm 2 teacher procedure) | [C05/pseudocode-final-score.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/pseudocode-final-score.md) | |
|||||||
| 261 | | Object descriptions (class diagram + teaching points) | [C05/object-descriptions.md](https://github.com/vce-soft-dev/SD26-Students/blob/main/Proj-SAT-Grader-UI/C05/object-descriptions.md) | |
|||||||
| 262 | ||||||||
| 263 | > [!NOTE] |
|||||||
| 264 | > The `SD26-Students` repository is **private**. To open these links you must be signed in to GitHub with your class account. If you get a 404, you are not signed in — log in and try again. |
|||||||
| 265 | ||||||||
| 266 | --- |
|||||||
| 267 | ||||||||
| 268 | ## Check Your Understanding |
|||||||
| 269 | ||||||||
| 270 | 1. One SRS sentence appears in all four design tools. Quote it, then name the **form** it takes in each tool: the data dictionary, the object descriptions, the pseudocode, and the IPO charts. |
|||||||
| 271 | ||||||||
| 272 | >| The sentence is SRS §7: "Derived values (bands, calculated scores, totals, ranks) are computed, never stored." In the **data dictionary** it is a separate §5 "Derived values (computed, never stored)" table. In the **object descriptions** it is the attribute-vs-method split — `final` is a stored attribute, `calculated()` is a derived method. In the **pseudocode** it is Algorithm 1, which derives the calculated score from inputs every time. In the **IPO charts** it is the `live_summary` / `band_of` rows that recompute on every keystroke — only possible because the values are never stored. |
|||||||
| 273 | ||||||||
| 274 | 2. Why is `final` an **attribute** but `calculated()` a **method**? |
|||||||
| 275 | ||||||||
| 276 | >| `final` is the teacher's reconciled decision — a value you *store*, because it cannot be re-derived from anything (it is a judgement). `calculated()` is a weighted average of the indicator scores — a value you *derive on demand* from inputs that already exist, so storing it would break "computed, never stored". Attribute = stored input; method = derived output. |
|||||||
| 277 | ||||||||
| 278 | 3. Algorithm 2 contains the words "teacher's judgement" instead of a formula. Why is that a deliberate design decision, not a missing piece of the algorithm? |
|||||||
| 279 | ||||||||
| 280 | >| Design note 1 says so: "The final score is never computed … the app automates the references, not the judgement." FR5 makes the app read-only toward the AI score, and reconciling calculated vs AI vs cross-mark is a moderation decision a human must own. Replacing the judgement with a formula (e.g. averaging) would make the app decide grades — and design note 3 explicitly forbids averaging across a disagreement of 2 or more, because a large gap signals mis-banded evidence to re-examine, not a number to split. |
|||||||
| 281 | ||||||||
| 282 | 4. What makes the IPO charts unable to drift apart from the build? |
|||||||
| 283 | ||||||||
| 284 | >| They are **generated from the app's own event wiring** by `tools/generate_ipo.py` — each chart is read straight out of the Gradio `trigger.change(process, [inputs], [outputs])` handlers. The build *is* the source of the chart, so you regenerate after any wiring change (`uv run python tools/generate_ipo.py`) and the design updates with it. A hand-written chart can fall out of date; a generated one cannot. |
|||||||
| 285 | ||||||||
| 286 | --- |
|||||||
| 287 | ||||||||
| 288 | ## See also |
|||||||
| 289 | ||||||||
| 290 | - [From SRS to Detailed Designs — Mock-ups](From%20SRS%20to%20Detailed%20Designs%20-%20Mock-ups) — the sibling page: traces a *screen* (FR3, FR9, FR6) from SRS → wireframe → build → correction, where this page traces the *data and logic*. |
|||||||
| 291 | - [Data Dictionary](Data%20Dictionary) — teaches the data-dictionary tool in general (headings, why "format" is not "type"); this page shows it working with the other three on a real project. |
|||||||
| 292 | - [IPO Charts - Process Means Steps](IPO%20Charts%20-%20Process%20Means%20Steps) — teaches the IPO tool in general (Process = numbered steps); this page shows a generated IPO chart in context. |
|||||||
| 293 | - [VCAA Pseudocode Not Python](VCAA%20Pseudocode%20Not%20Python) — teaches language-independent pseudocode in general; this page shows two real algorithms doing the work. |
|||||||
| 294 | - [Object Descriptions and Class Diagrams](Object%20Descriptions%20and%20Class%20Diagrams) — teaches the object-description tool in general (attributes, methods, reading a class diagram); this page shows a real class diagram tied to the data rule. |
|||||||
| 295 | ||||||||
| 296 | --- |
|||||||
| 297 | ||||||||
| 298 | ← Back to [C05 Home](/sd/C05/C05-home) · [VCE Software Development Hub](/sd/VCE%20Software%20Development%20Hub) |
|||||||
