Commit 3aab9f

2026-08-11 23:24:06 lisa: Add C06 skill-code study pages, linked from the SD hub Eleven pages ported from the applied-computing-au C06-Reference-Godot standard: home page with the 34-code lookup, per-topic pages with labelled GDScript examples, evidence standards, and Check Your Understanding fold blocks. Generated mirror — repo copy is canonical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
/dev/null .. sd/C06/C06-home.md
@@ 0,0 1,88 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# C06 — Skills in Using the Features of the Programming Language
+
+The Hamilton and Alexandra College · Year 12 · 2026
+
+Criterion 6 is graded from **34 skill codes** (C611–C658) across two indicators: using a range of programming-language features, and using appropriate data types, data structures and data sources. Each page below covers one topic: the VCE definition, the GDScript syntax, labelled examples — from the shared **Myki fare app** domain and from the projects we studied in class — and the **evidence standard**: what earns each tick and what does not. Your checkpoint and validation feedback is graded against these pages, so what they say *is* the standard.
+
+---
+
+## Using these pages for your checkpoint
+
+1. Pick a nominated feature you have built.
+
+2. Walk the lookup table below: for each code, open its page and compare your code against the **Earns the tick** line.
+
+3. Label the exact line (`# C626a — selection: …`), and write the *why* comment wherever the code asks for reasoning.
+
+4. Anything you cannot label yet is your to-do list — each page shows the smallest pattern that earns the tick, and the codes climb from very low (C611) to very high (C65x).
+
+## How the codes work
+
+- **Checkpoint sheet:** three boxes per code — label your code `C611a`, `C611b`, `C611c` for your first, second and third nominated feature (102 marks).
+
+- **Validation sheet:** one box per code, ticked only for skills demonstrated **live** during the Live Coding Validation (34 marks) — in the Prove-It's-Yours re-label, the data-layer extension, or a mini-challenge. Practise finding and re-labelling your own code without notes.
+
+- **Label as you code.** A skill the marker cannot find earns nothing — put the code in a comment on the line (or block) that shows it. Every example on these pages carries its own label to model exactly this.
+
+**Levels of performance:** Not shown (0) · 1–2 very low · 3–4 low · 5–6 medium · 7–8 high · 9–10 very high.
+
+## Reasoning-verb ladder (internal documentation codes)
+
+The four "why" codes are the same skill at rising depth. The verb is the standard:
+
+| Code | Level | Verb | Looks like |
+|---|---|---|---|
+| C629 | 3–4 | **outlines** why data types | `# C629 — float: money needs decimal places` |
+| C638 | 5–6 | **identifies** why types *and structures* | a one-line reason on each structure |
+| C645 | 7–8 | **describes** why data sources | a sentence or two per source |
+| C658 | 9–10 | **explains** why all of them | reasons that weigh alternatives ("CSV over XML because …") |
+
+## Code → page lookup
+
+| Code | Level | Skill | Page |
+|---|---|---|---|
+| C611 | 1–2 | instructions | [Instructions and Operators](/sd/C06/Instructions%20and%20Operators) |
+| C612 | 1–2 | arithmetic operators | [Instructions and Operators](/sd/C06/Instructions%20and%20Operators) |
+| C613 | 1–2 | text data | [Data Types](/sd/C06/Data%20Types) |
+| C614 | 1–2 | numeric data | [Data Types](/sd/C06/Data%20Types) |
+| C615 | 1–2 | Boolean data | [Data Types](/sd/C06/Data%20Types) |
+| C621 | 3–4 | local variables | [Local and Global Variables](/sd/C06/Local%20and%20Global%20Variables) |
+| C622 | 3–4 | constants | [Local and Global Variables](/sd/C06/Local%20and%20Global%20Variables) |
+| C623 | 3–4 | logical operators | [Instructions and Operators](/sd/C06/Instructions%20and%20Operators) |
+| C624 | 3–4 | conditional operators | [Instructions and Operators](/sd/C06/Instructions%20and%20Operators) |
+| C625 | 3–4 | sequence | [Control Structures](/sd/C06/Control%20Structures) |
+| C626 | 3–4 | selection | [Control Structures](/sd/C06/Control%20Structures) |
+| C627 | 3–4 | GUIs | [GUI and Controls](/sd/C06/GUI%20and%20Controls) |
+| C628 | 3–4 | data types for local variables | [Local and Global Variables](/sd/C06/Local%20and%20Global%20Variables) |
+| C629 | 3–4 | reasoning — why these data types | [Data Types](/sd/C06/Data%20Types) |
+| C631 | 5–6 | global variables | [Local and Global Variables](/sd/C06/Local%20and%20Global%20Variables) |
+| C632 | 5–6 | iteration / repetition | [Control Structures](/sd/C06/Control%20Structures) |
+| C633 | 5–6 | relevant GUI controls | [GUI and Controls](/sd/C06/GUI%20and%20Controls) |
+| C634 | 5–6 | data types for global variables | [Local and Global Variables](/sd/C06/Local%20and%20Global%20Variables) |
+| C635 | 5–6 | arrays | [Data Structures](/sd/C06/Data%20Structures) |
+| C636 | 5–6 | records | [Data Structures](/sd/C06/Data%20Structures) |
+| C638 | 5–6 | reasoning — why these types and structures | [Data Structures](/sd/C06/Data%20Structures) |
+| C641 | 7–8 | functions | [Functions and Methods](/sd/C06/Functions%20and%20Methods) |
+| C642 | 7–8 | methods | [Functions and Methods](/sd/C06/Functions%20and%20Methods) |
+| C643 | 7–8 | access modifiers | [OOP Concepts](/sd/C06/OOP%20Concepts) |
+| C644 | 7–8 | data types, structures and sources | [Data Sources](/sd/C06/Data%20Sources) |
+| C645 | 7–8 | reasoning — why these data sources | [Data Sources](/sd/C06/Data%20Sources) |
+| C651 | 9–10 | classes | [OOP Concepts](/sd/C06/OOP%20Concepts) |
+| C652 | 9–10 | objects | [OOP Concepts](/sd/C06/OOP%20Concepts) |
+| C653 | 9–10 | abstraction | [OOP Concepts](/sd/C06/OOP%20Concepts) |
+| C654 | 9–10 | encapsulation | [OOP Concepts](/sd/C06/OOP%20Concepts) |
+| C655 | 9–10 | generalisation | [OOP Concepts](/sd/C06/OOP%20Concepts) |
+| C656 | 9–10 | inheritance | [OOP Concepts](/sd/C06/OOP%20Concepts) |
+| C657 | 9–10 | range of types, structures and sources | [Data Sources](/sd/C06/Data%20Sources) |
+| C658 | 9–10 | reasoning — why all of them | [Data Sources](/sd/C06/Data%20Sources) |
+
+Reference-only page with no codes of its own: [Data Type Characteristics](/sd/C06/Data%20Type%20Characteristics) — the input/storage/output table the reasoning codes draw their "why" from.
+
+## Example code
+
+Snippets come from two places, and the pages keep both:
+
+- The **Myki fare app** domain (balance, fares, zones, concession, journeys) — minimal made-for-purpose examples.
+
+- **Real code from the projects studied in class**, attributed in the snippet's first comment line (e.g. `# connect-go-dots — grid.gd`): `connect-go-dots`, `tile-matching-game` and `club-ladder` — plus *non-examples* showing what does not earn a tick (engine methods, engine inheritance). Also worth reading: `dodge-the-creeps`.
/dev/null .. sd/C06/Control Structures.md
@@ 0,0 1,220 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Control Structures — GDScript
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C625 | 3–4 | control structure — sequence |
+| C626 | 3–4 | control structure — selection |
+| C632 | 5–6 | control structure — iteration / repetition |
+
+## C625 — Sequence
+
+**Definition.** A set of instructions that executes line by line in the order that it is written.
+
+Minimum two lines whose order matters — label the start and end:
+
+```gdscript
+# C625 sequence: start
+var zone: int = int($ZoneInput.text)
+var fare: float = FARE_TABLE[zone]
+balance -= fare
+$BalanceLabel.text = "Balance: $%.2f" % balance
+# C625 sequence: end
+```
+
+**Earns the tick:** a labelled block that breaks if you swap two lines. **Doesn't:** one isolated statement (that's C611).
+
+**In connect-go-dots** (`grid.gd`) — store the choice first, then switch screens:
+
+```gdscript
+# connect-go-dots — grid.gd
+func _open(photo: Texture2D) -> void:
+ Shared.photo = photo # C625 sequence: store the choice…
+ get_tree().change_scene_to_file("res://detail.tscn") # …then change scene
+```
+
+## C626 — Selection
+
+**Definition.** A control structure that allows a programmer to write lines of code that are only run when a particular requirement is met.
+
+### If
+
+When condition is met, flow is directed to the alternative instruction.
+
+```gdscript
+if condition: # C626 — selection
+ # code
+```
+
+### If … Then … Else (chained selection)
+
+When condition is met, flow can be directed multiple times. *Chained selection:* more than one condition checked in sequence — each branch can test a different condition, and execution stops at the first branch whose condition is true.
+
+```gdscript
+if condition: # C626 — chained selection
+ # code
+elif other_condition:
+ # code
+else:
+ # code
+```
+
+### Switch or Case (`match`)
+
+Choose between listed alternatives. Unlike chained selection, every case tests the *same* expression for equality against a different value.
+
+```gdscript
+match value: # C626 — selection: match
+ 1:
+ # code
+ 2:
+ # code
+```
+
+**In club-ladder** (`team.gd`) — a real `match`, with the wildcard `_` as the catch-all:
+
+```gdscript
+# club-ladder — team.gd
+func record(result: String) -> void:
+ match result: # C626 — selection: match with a catch-all
+ "win":
+ wins += 1
+ "draw":
+ draws += 1
+ _:
+ losses += 1 # anything that is not a win or a draw
+```
+
+### Myki example
+
+```gdscript
+# C626 selection: pick the fare rule
+if is_concession:
+ fare = FARE_TABLE[zone] * 0.5
+elif is_weekend:
+ fare = WEEKEND_CAP
+else:
+ fare = FARE_TABLE[zone]
+```
+
+*Nested selection* — a selection inside another selection's structure — is also C626 evidence; use the word "nested" in validation.
+
+**Earns the tick:** a condition that changes what runs, demonstrated with both outcomes. An `if` whose `else` can never happen is weak evidence.
+
+**In tile-matching-game** (`game.gd`) — both selection shapes:
+
+```gdscript
+# tile-matching-game — game.gd
+if is_busy or card.is_face_up or card.is_matched: # C626 — guard clause
+ return # bail out early on any bad click
+
+if first_card.pair_id == second_card.pair_id: # C626 — selection: two outcomes
+ _handle_match()
+else:
+ await _handle_mismatch()
+```
+
+## C632 — Iteration / repetition
+
+**Definitions.** *WHILE:* an iteration repeated for as long as a condition is met. *FOR:* an iteration repeated a predefined number of times. *Infinite loop:* an iteration that will never reach the condition upon which it can terminate.
+
+### While …
+
+May not execute to satisfy condition.
+
+```gdscript
+while condition: # C632 — iteration
+ # code
+```
+
+### Do … While
+
+May not execute if condition is not satisfied once.
+
+No `do … while` construct in GDScript — a pre-test `while` loop covers this behaviour:
+
+```gdscript
+while condition: # C632 — iteration
+ # code
+```
+
+### Repeat … Until
+
+Executes at least once. If conditions are not met, there is a possibility of an **infinite loop**.
+
+No `repeat … until` construct in GDScript — emulate a post-test loop with `while true:` and a `break` when the condition is met:
+
+```gdscript
+while true: # C632 — post-test iteration
+ # code
+ if condition:
+ break
+```
+
+### For … Next
+
+A counting loop to be executed a set number of times.
+
+```gdscript
+for i in range(10): # C632 — counting iteration
+ # code
+```
+
+### For … In
+
+A counting loop that iterates over items in an array or list.
+
+```gdscript
+var cats = ["Whiskers", "Fluffy"]
+for cat in cats: # C632 — iteration over an array
+ print(cat)
+```
+
+### Myki example
+
+```gdscript
+# C632 iteration: total up today's journeys
+var total: float = 0.0
+for journey in journeys:
+ total += journey["fare"]
+```
+
+**In connect-go-dots** (`grid.gd`) — one loop wires every photo button:
+
+```gdscript
+# connect-go-dots — grid.gd
+for button in %Photos.get_children(): # C632 — iteration
+ button.pressed.connect(_open.bind(button.texture_normal))
+```
+
+`get_children()` returns an array of the six `TextureButton`s and the loop visits each in turn. (`%Photos` finds the node by its scene-unique name.)
+
+**In tile-matching-game** (`deck.gd`) — a real `while` whose end is guaranteed:
+
+```gdscript
+# tile-matching-game — deck.gd
+while not file.eof_reached(): # C632 — ends when the file runs out of rows
+ var row := file.get_csv_line()
+```
+
+**Earns the tick:** a loop over real data — a `for` over your own array, or a `while` whose condition provably terminates. Be ready to explain *why the loop ends*: the infinite-loop question is a validation favourite.
+
+## Check Your Understanding
+
+1. In a `match`, what does every case compare?
+
+>| ### Answer
+>| The *same* expression against a different value — unlike chained `elif`, where each branch can test something different.
+
+2. GDScript has no `repeat … until`. What is the accepted emulation?
+
+>| ### Answer
+>| `while true:` with `if condition: break` at the end of the body — runs at least once, tests after.
+
+3. What two questions about any loop should you be ready to answer live?
+
+>| ### Answer
+>| What it iterates over, and why it must end.
/dev/null .. sd/C06/Data Sources.md
@@ 0,0 1,207 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Data Sources — GDScript
+
+*VCE scope only. The study design names exactly three data sources: **plain text (TXT), delimited (CSV) and XML files**. JSON, databases (SQLite), REST APIs and Godot's own `.tres`/`.res` resources are **out of scope** — they do not earn source codes, however natural they feel in Godot.*
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C644 | 7–8 | uses appropriate data types, data structures and data sources — *"including plain text, delimited and XML files"* |
+| C645 | 7–8 | describes, in the internal documentation, why the selected data sources were used |
+| C657 | 9–10 | uses a range of data types, data structures and data sources |
+| C658 | 9–10 | explains, in the internal documentation, why the selected data types, data structures and data sources were used |
+
+**Before you build:** a data layer built on JSON, SQLite or `.tres` earns **none** of C644–C658, however natural those feel in Godot — and graders (human or AI) apply that rule mechanically. The sources you demonstrate must be TXT, CSV and/or XML.
+
+## The three sources
+
+**Definitions.**
+
+- *Plain text (TXT) file:* a structured file that contains characters of readable data.
+
+- *CSV:* a comma-separated value file — a delimited file separated by commas. The *delimiter* is the character separating the values. A CSV is a flat table: rows, each row the same fields.
+
+- *XML:* Extensible Markup Language — data in **elements** marked by opening and closing **tags**. Elements can hold other elements, so the data is **nested** rather than flat: a *tree* with a *root element* at the top, and a *prolog* (version, encoding) before the content.
+
+**Know the difference:** `res://` is your project's read-only data; `user://` is the writable save location. Naming that in validation is easy marks. club-ladder runs on exactly this split — the bundled season ships in `res://seasons/`, the player's copy lives at `user://ladder.xml`, and `load_season()` picks between them with one `if FileAccess.file_exists(save_path)`.
+
+## TXT in Godot
+
+```gdscript
+# C644 — TXT source: write
+var file = FileAccess.open("user://balance.txt", FileAccess.WRITE)
+file.store_line(str(balance))
+```
+
+```gdscript
+# C644 — TXT source: read
+var file = FileAccess.open("user://balance.txt", FileAccess.READ)
+balance = float(file.get_line())
+```
+
+## CSV in Godot
+
+`FileAccess` speaks CSV natively — `get_csv_line()` and `store_csv_line()` handle the delimiter for you.
+
+```gdscript
+# C644 — CSV source: read journeys.csv, one journey per row (zone,fare)
+var journeys: Array[Dictionary] = []
+var file = FileAccess.open("user://journeys.csv", FileAccess.READ)
+file.get_csv_line() # skip the header row
+while not file.eof_reached():
+ var row: PackedStringArray = file.get_csv_line()
+ if row.size() >= 2:
+ journeys.append({"zone": int(row[0]), "fare": float(row[1])})
+```
+
+```gdscript
+# C644 — CSV source: write journeys.csv
+var file = FileAccess.open("user://journeys.csv", FileAccess.WRITE)
+file.store_csv_line(PackedStringArray(["zone", "fare"])) # header
+for journey in journeys:
+ file.store_csv_line(PackedStringArray([str(journey["zone"]), str(journey["fare"])]))
+```
+
+**In tile-matching-game** (`deck.gd`) — the whole game is driven by one CSV read; each row becomes a record in an array:
+
+```gdscript
+# tile-matching-game — deck.gd
+var file := FileAccess.open(path, FileAccess.READ) # C644 — CSV source
+var header := file.get_csv_line() # skip the pair,text,image header
+while not file.eof_reached():
+ var row := file.get_csv_line()
+ if row.size() < 2:
+ continue
+ cards.append({"pair": row[0].strip_edges(), "text": row[1].strip_edges()})
+```
+
+The real file (`decks/spanish.csv`):
+
+```csv
+pair,text,image
+dog,perro,
+dog,dog,
+cat,gato,
+cat,cat,
+```
+
+Defensive touches worth copying: check `FileAccess.file_exists(path)` first, skip short rows, `strip_edges()` every field. And a Godot trap: **`.csv` imports as a translation file by default** — select the file, Import tab → *Keep File (exported as is)* → Reimport, or deck loading breaks in exported builds.
+
+## XML in Godot
+
+Read XML with the built-in `XMLParser`. There is no built-in XML *writer* — either write your outputs as TXT/CSV, or build the XML text yourself as club-ladder does below.
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<fares>
+ <fare zone="1" cost="5.30"/>
+ <fare zone="2" cost="8.00"/>
+</fares>
+```
+
+```gdscript
+# C644 — XML source: read fares.xml into a Dictionary (zone → cost)
+var fares: Dictionary = {}
+var parser = XMLParser.new()
+parser.open("res://data/fares.xml")
+while parser.read() == OK:
+ if parser.get_node_type() == XMLParser.NODE_ELEMENT \
+ and parser.get_node_name() == "fare":
+ var zone: int = int(parser.get_named_attribute_value("zone"))
+ fares[zone] = float(parser.get_named_attribute_value("cost"))
+```
+
+Here `<fares>` is the root element and each `<fare>` is a child element carrying its data in attributes.
+
+**In club-ladder** (`season.gd`) — XML both ways, in a studied project. Reading, with a `_attribute()` helper that falls back when a value is missing ("real files are often missing things"):
+
+```gdscript
+# club-ladder — season.gd
+while parser.read() == OK: # C644 — XML source
+ if parser.get_node_type() != XMLParser.NODE_ELEMENT:
+ continue
+ match parser.get_node_name():
+ "season":
+ season.title = _attribute(parser, "title", "Season")
+ "team":
+ var team_name := _attribute(parser, "name", "")
+ if team_name == "":
+ continue # a team with no name is not worth keeping
+ season.teams.append(Team.new(team_name,
+ int(_attribute(parser, "wins", "0")),
+ int(_attribute(parser, "draws", "0")),
+ int(_attribute(parser, "losses", "0"))))
+```
+
+And writing — the season builds the text line by line, escaping XML's five special characters first:
+
+```gdscript
+# club-ladder — season.gd
+lines.append('<season title="%s">' % _escape(title)) # C644 — XML written by hand
+for team in teams:
+ lines.append('\t<team name="%s" wins="%d" draws="%d" losses="%d"/>'
+ % [_escape(team.team_name), team.wins, team.draws, team.losses])
+lines.append("</season>")
+file.store_string("\n".join(lines) + "\n")
+```
+
+A team called "Smith & Sons" would corrupt the file without `_escape()` — and the `&` must be replaced first, or it would mangle the entities just added.
+
+## C644 — Uses appropriate types, structures and sources
+
+Level 7–8 is the three layers working together: a file (**source**) parsed into a **structure** of typed **values** — like the CSV reader above (`journeys.csv` → `Array[Dictionary]` → `int` and `float` fields), labelled:
+
+```gdscript
+# C644 — CSV source → Array[Dictionary] structure → typed values
+```
+
+## C645 — Why these data sources
+
+Level 7–8 asks you to **describe** the reason — a sentence or two per source, in internal documentation:
+
+```gdscript
+# C645 — CSV for journeys: one journey per row with the same two fields;
+# a flat table that also opens in Excel for checking
+```
+
+**Described in the wild:** tile-matching-game's README describes its source choice at exactly this level — the game "reads its cards from a CSV file, so the same game can be re-skinned for any subject … without changing a line of code." One sentence that says why CSV earns its place.
+
+## C657 and C658 — Range, and the full explanation
+
+**C657** (9–10): a **range** — several types, several structures, several sources, each doing a job the others could not. A Myki-app spread using only VCE sources: XML fare table in `res://` (nested: zones × day types), CSV journey log in `user://` (flat table), TXT save file in `user://` (one balance value).
+
+**C658** (9–10): **explains** why — reasons that weigh alternatives:
+
+```gdscript
+# C658 — chose CSV for the journey log: flat table, one row per journey;
+# XML would wrap every value in tags for no gain. Kept the fare table in
+# XML: fares nest by zone then day type, and nesting is what XML does
+# that CSV cannot. TXT for the save file: one value needs no structure.
+```
+
+**Explained in the wild:** `club-ladder/season.gd`'s header comment explains its XML design *by weighing the alternative* — every value is an attribute because "one call gets each one", whereas nested `<name>` tags would mean "tracking which tag you are inside while text arrives separately". That is C658-grade reasoning, written where the marker will find it.
+
+The verb ladder (outlines → identifies → describes → explains) is in the [C06 home page](/sd/C06/C06-home).
+
+## Check Your Understanding
+
+1. Which sources earn C644–C658?
+
+>| ### Answer
+>| Only TXT, CSV and XML. JSON, SQLite and `.tres` earn nothing here.
+
+2. What reads XML in Godot, and what is missing?
+
+>| ### Answer
+>| `XMLParser` reads it; there is no built-in writer — build the text yourself, escaping `&` first.
+
+3. `res://` vs `user://`?
+
+>| ### Answer
+>| `res://` is the project's read-only data; `user://` is the writable save location.
+
+4. You add `fares.csv` to your project and loading breaks in the exported build. First thing to check?
+
+>| ### Answer
+>| The Import setting — Godot treats `.csv` as a translation file by default. Set **Import As: Keep File (exported as is)** and reimport.
/dev/null .. sd/C06/Data Structures.md
@@ 0,0 1,140 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Data Structures — GDScript
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C635 | 5–6 | arrays |
+| C636 | 5–6 | records |
+| C638 | 5–6 | identifies, in the internal documentation, why the selected data types and data structures were used |
+
+**Definition.** A *data structure* is a method of organising data to allow particular operations to be performed on it efficiently.
+
+## C635 — Arrays
+
+**Definition.** A list of elements indexed by position. In most programming languages, the first element has index zero.
+
+```gdscript
+# C635 — Array[float]: fares need decimal places
+var fares: Array[float] = [5.30, 8.00, 11.20]
+
+func show_fare() -> void:
+ $ResultLabel.text = "Zone 1: $" + str(fares[0])
+```
+
+Typed (`Array[float]`) earns it. Bare `var fares = []` does not — no type for the marker to see.
+
+**In tile-matching-game** (`board.gd`) — a typed array of your own class:
+
+```gdscript
+# tile-matching-game — board.gd
+var found: Array[Card] = [] # C635 — Array[Card]: only cards can get in
+for child in get_children():
+ if child is Card:
+ found.append(child)
+```
+
+**Two-dimensional array** — a grid organised into rows and columns, accessed with two indices:
+
+```gdscript
+# C635 — 2D array: fare by [zone][day type], 0 = weekday, 1 = weekend
+var fare_grid: Array = [
+ [5.30, 3.60],
+ [8.00, 5.40],
+]
+
+var weekend_zone2: float = fare_grid[1][1]
+```
+
+## C636 — Records
+
+**Definitions.**
+
+- *Record:* a complete set of fields relating to an entity, such as a person.
+
+- *Field:* a single data item in a record (e.g. `FamilyName`).
+
+GDScript has no `record` keyword — a **Dictionary** is the everyday record, one key per field:
+
+```gdscript
+# C636 — record: one journey, fields of different types
+var journey: Dictionary = {
+ "date": "2026-08-11",
+ "zone": 2,
+ "fare": 8.00,
+ "concession": false,
+}
+
+print(journey["fare"]) # access one field
+```
+
+**In tile-matching-game** (`deck.gd`) — each CSV row becomes a record, and the deck is an array of them:
+
+```gdscript
+# tile-matching-game — deck.gd
+cards.append({
+ "pair": pair, # C636 — fields: which card matches which
+ "text": row[1].strip_edges(),
+ "image": row[2].strip_edges() if row.size() > 2 else "",
+})
+```
+
+An **array of records** is a table — the shape most SAT data layers need:
+
+```gdscript
+# C635 + C636 — a table: array of journey records
+var journeys: Array[Dictionary] = []
+
+func add_journey(zone: int, fare: float) -> void:
+ journeys.append({"zone": zone, "fare": fare})
+```
+
+A **custom class** is the stronger record — typed fields the editor can check — and doubles as level 9–10 evidence (see [OOP Concepts](/sd/C06/OOP%20Concepts)).
+
+**In club-ladder** (`team.gd`) — the class-as-record, real: its own doc comment says "A Team is plain data."
+
+```gdscript
+# club-ladder — team.gd
+class_name Team
+extends RefCounted
+
+var team_name := "" # C636 — the fields of the record
+var wins := 0
+var draws := 0
+var losses := 0
+```
+
+An `Array[Team]` (`season.gd`) is then the table — the class version of the array-of-dictionaries above.
+
+## C638 — Why these types and structures
+
+Level 5–6 asks you to **identify** the reason in internal documentation — one line on each structure:
+
+```gdscript
+# C638 — Array[Dictionary]: journeys arrive one at a time in order (array),
+# and each journey has mixed-type fields (record)
+var journeys: Array[Dictionary] = []
+```
+
+The "why" comes from how the structure behaves — see the input/storage/output table in [Data Type Characteristics](/sd/C06/Data%20Type%20Characteristics).
+
+**Model documentation in the wild:** the header comment of `tile-matching-game/deck.gd` identifies the whole design — one CSV row per card face, rows sharing a `pair` value match — before any code runs. That is C638 done as a file-level comment.
+
+## Check Your Understanding
+
+1. Why does `var scores = []` fail C635?
+
+>| ### Answer
+>| It is untyped — `Array[int]` (or a comment naming the type) is required, so the marker can assess the choice.
+
+2. Name two ways to build a record in GDScript.
+
+>| ### Answer
+>| A Dictionary with one key per field, or a custom class with typed fields (the stronger version).
+
+3. What everyday shape is an "array of records"?
+
+>| ### Answer
+>| A table — one record per row, like journeys or teams.
/dev/null .. sd/C06/Data Type Characteristics.md
@@ 0,0 1,17 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Table 5.1 Characteristics of Data Types and Structures
+
+*Language-agnostic — this table applies unchanged to Godot.*
+
+**Skill-code link.** No tick boxes live on this page, but the reasoning codes — C629 (*outlines*), C638 (*identifies*), C645 (*describes*), C658 (*explains*) — draw their "why" from these characteristics. "float: money needs decimal places" is a storage argument; "CSV: rows of identical fields" is a structure argument.
+
+| Data type/structure | Input | Storage | Output |
+|---|---|---|---|
+| **Character** | Single symbols via keyboard or data files | Numeric codes (e.g. ASCII, Unicode) in memory | Visual symbol representation on screens or printed formats |
+| **String** | Sequences of symbols via user input or data files | Sequence of character codes in contiguous memory, possibly with length or null terminator | Readable format of characters maintaining original order |
+| **Integer** | Decimal representation from users or data sources | Binary format in a fixed number of bits | Decimal or other numeral systems for human readability |
+| **Floating point** | Decimal input with fractional parts | Stored as a base, exponent and sign (e.g. IEEE 754 format) | Decimal or scientific notation respecting precision |
+| **Date/time** | Various string formats or graphical UI selection | Large integer (timestamp) or separate components (year, month, day, etc.) | Formatted strings according to desired date/time format |
+| **One-dimensional array** | Sequential or individual inputs at specific indices | Contiguous memory locations maintaining order by index | List or sequence format in a readable layout |
+| **Two-dimensional array** | Row by row or column by column with two indices | Row-major or column-major order in contiguous memory | Tabular format respecting row and column structure |
+| **Record** | Separate input for each field with varying types | Aggregates of fields in memory, sequential or aligned | Key-value formatted listing of fields and corresponding values |
/dev/null .. sd/C06/Data Types.md
@@ 0,0 1,112 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Data Types — GDScript
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C613 | 1–2 | text data |
+| C614 | 1–2 | numeric data |
+| C615 | 1–2 | Boolean data |
+| C629 | 3–4 | outlines, in the internal documentation, why the selected data types were used |
+
+**Definition.** A *data type* classifies a variable: what data it can contain and how that data can be manipulated.
+
+At level 1–2 the skill is **identifying** the three data families in your own code. Using them with *stated* types is C628/C634 — see [Local and Global Variables](/sd/C06/Local%20and%20Global%20Variables).
+
+**Earns the tick:** one labelled line per family — text, numeric, Boolean — in code that runs.
+
+## C613 — Text data
+
+**Definitions.** *Character:* a single meaningful unit — a letter, digit, punctuation mark, symbol or space. *String:* a sequence of characters.
+
+### Character
+
+GDScript has no separate character type — use a one-character String:
+
+```gdscript
+var chr_var: String = "A" # C613 — text: character
+```
+
+### String
+
+```gdscript
+var str_var: String = "Hello!" # C613 — text: string
+```
+
+## C614 — Numeric data
+
+**Definitions.** *Integer:* whole positive and negative numbers. *Floating point:* computer representation of real numbers, with decimal places. *Numeric:* both families together.
+
+### Integer
+
+```gdscript
+var int_var: int = 42 # C614 — numeric: integer
+```
+
+### Floating point
+
+```gdscript
+var float_var: float = 3.14 # C614 — numeric: floating point
+```
+
+## C615 — Boolean data
+
+**Definition.** A data type with one of two possible values, usually referred to as False and True.
+
+```gdscript
+var bool_var: bool = true # C615 — Boolean
+```
+
+## Spot them in a studied project
+
+```gdscript
+# tile-matching-game — card.gd / game.gd
+var pair_id := "" # C613 — text: a String, inferred from ""
+var score := 0 # C614 — numeric: an int
+@export var flip_back_delay := 1.2 # C614 — numeric: a float
+var is_face_up := false # C615 — Boolean
+```
+
+These use `:=` inference — fine, as long as your comment names the type (see the warning in [Local and Global Variables](/sd/C06/Local%20and%20Global%20Variables)).
+
+## Date/time
+
+No skill code of its own — it counts toward the level 9–10 *range* (C657).
+
+```gdscript
+var dt_var = Time.get_datetime_dict_from_system() # counts toward C657 — range of types
+```
+
+That call returns a Dictionary of year, month, day, hour and so on — which is also a **record**; see [Data Structures](/sd/C06/Data%20Structures).
+
+## C629 — Why these data types
+
+Level 3–4 asks you to **outline** the reason in internal documentation — a phrase is enough:
+
+```gdscript
+var balance: float = 20.00 # C629 — float: money needs decimal places
+var card_id: String = "" # C629 — String: digits never used in a calculation
+```
+
+The reasons come from how each type behaves — the input/storage/output view is in [Data Type Characteristics](/sd/C06/Data%20Type%20Characteristics).
+
+**Also name it when you do it:** *casting* — converting a value from one type to another — is everyday Godot: `int($ZoneInput.text)`, `str(fares[0])`.
+
+## Check Your Understanding
+
+1. Name the three level 1–2 data families and their codes.
+
+>| ### Answer
+>| Text C613, numeric C614, Boolean C615.
+
+2. Why does `var trips = 0` earn nothing for data types?
+
+>| ### Answer
+>| No type is stated or named in a comment — there is nothing for the marker to assess.
+
+3. What is casting? Give one Godot example.
+
+>| ### Answer
+>| Converting a value between types — e.g. `int($ZoneInput.text)` turns the typed text into a number.
/dev/null .. sd/C06/Functions and Methods.md
@@ 0,0 1,114 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Functions and Methods — GDScript
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C641 | 7–8 | functions |
+| C642 | 7–8 | methods |
+
+**The distinction that matters for VCE:** a *function* is a named, reusable block of code; a *method* is a function that belongs to a class, called on an object. In GDScript both use `func` — what earns C642 over C641 is the object it lives on.
+
+## C641 — Functions
+
+**Definitions.**
+
+- *Function:* a sequence of related code that has been given a name that can be called from other points in the source code.
+
+- *Arguments / parameters:* specific inputs passed into a function that act as local, temporary variables.
+
+- *Return value:* a value passed back to the caller, often assigned to a variable or tested in a condition.
+
+```gdscript
+# C641 — function: named, takes parameters, returns a value
+func calculate_fare(zone: int, is_concession: bool) -> float:
+ var fare: float = FARE_TABLE[zone]
+ if is_concession:
+ fare *= 0.5
+ return fare
+```
+
+```gdscript
+# C641 — function call: result assigned and used
+var fare: float = calculate_fare(2, true)
+```
+
+**Earns the tick:** a function with **parameters and a return value, called from elsewhere in the program**. A `func` that Godot calls for you (`_ready`, `_process`) shows the syntax but not the skill — write and call your own.
+
+**In connect-go-dots** (`grid.gd`): `_open(photo: Texture2D)` is a function *you* would label — typed parameter, hooked to every photo button. `_ready()` is not — Godot calls it. `_open` has no return value, so pair it with a returning function (like `calculate_fare` above) for the full tick.
+
+**In tile-matching-game** (`deck.gd` → `game.gd`) — the full tick in real code: typed parameter, typed return, result used:
+
+```gdscript
+# tile-matching-game — deck.gd
+static func load_csv(path: String) -> Array: # C641 — typed parameter and return
+ var cards: Array = []
+ # … one Dictionary per CSV row …
+ return cards
+```
+
+```gdscript
+# tile-matching-game — game.gd
+var all_cards := Deck.load_csv(deck_path) # C641 — call: the result drives the board
+```
+
+**Say the types out loud in validation:** parameters and return are typed (`zone: int`, `-> float`) — that evidence also feeds C628.
+
+## C642 — Methods
+
+**Definition.** An action an object can carry out (e.g. `window.refresh`, `golfClub.swing`).
+
+```gdscript
+class_name MykiCard
+extends RefCounted
+
+var _balance: float = 20.00
+
+# C642 — method: an action the MykiCard object can carry out
+func top_up(amount: float) -> void:
+ if amount > 0:
+ _balance += amount
+
+func get_balance() -> float: # C642 — getter method
+ return _balance
+```
+
+```gdscript
+# C642 — method calls on an object
+var card: MykiCard = MykiCard.new()
+card.top_up(10.0)
+print(card.get_balance())
+```
+
+**Earns the tick:** a method defined **in your own class** and called **through an object** (`card.top_up(...)`). Calling built-in methods (`text.to_upper()`) shows use of the language but the code is for methods you wrote.
+
+**Contrast from connect-go-dots:** `get_children()`, `connect()` and `change_scene_to_file()` are all method calls — on *engine* objects. None earn C642; the tick needs a method on a class you wrote.
+
+**In tile-matching-game** — the positive case: `flip_up()`, `flip_down()` and `mark_matched()` are defined in `card.gd` (a class you wrote) and called through objects in `game.gd`:
+
+```gdscript
+# tile-matching-game — game.gd
+first_card.mark_matched() # C642 — your method, called on your object
+second_card.mark_matched()
+```
+
+**Ladder up:** methods on your own class are the doorway to level 9–10 — classes (C651), objects (C652) and encapsulation (C654) live in [OOP Concepts](/sd/C06/OOP%20Concepts).
+
+## Check Your Understanding
+
+1. Why does `_ready()` not earn C641?
+
+>| ### Answer
+>| Godot calls it for you — the tick needs a function you wrote *and* call yourself.
+
+2. What three ingredients make full C641 evidence?
+
+>| ### Answer
+>| Typed parameter(s), a return value that gets used, and a call from elsewhere in the program.
+
+3. What turns a function into a C642 method?
+
+>| ### Answer
+>| It is defined in your own class and called through an object — `card.top_up(10.0)`.
/dev/null .. sd/C06/GUI and Controls.md
@@ 0,0 1,119 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# GUI — Godot Control Nodes
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C627 | 3–4 | graphical user interfaces (GUIs) |
+| C633 | 5–6 | relevant GUI controls |
+
+**The two codes in one line:** C627 — your program *has* a working GUI built from Control nodes. C633 — you chose the *right* control for each piece of data and wired it up with signals and runtime property changes.
+
+## C627 — Graphical user interfaces
+
+**Definition.** A type of user interface that allows users to interact through visual elements such as windows, icons and buttons.
+
+In Godot a GUI is a scene of **Control nodes**:
+
+```text
+Main (Control)
+├── ZoneInput (LineEdit)
+├── CalculateButton (Button)
+└── ResultLabel (Label)
+```
+
+```gdscript
+extends Control
+# C627 — GUI: this scene of Control nodes is the user interface
+```
+
+**Earns the tick:** the program runs with a usable interface built from Control nodes — input, action, output visible on screen.
+
+**In connect-go-dots** — the gallery screen (`grid.tscn`):
+
+```text
+Gallery (Control)
+└── Margin (MarginContainer)
+ └── Rows (VBoxContainer)
+ ├── Title (Label)
+ └── Photos (GridContainer, 3 columns)
+ ├── Photo1 (TextureButton)
+ ├── …
+ └── Photo6 (TextureButton)
+```
+
+The containers (`MarginContainer`, `VBoxContainer`, `GridContainer`) do the layout, so the controls stay aligned at any window size.
+
+## C633 — Relevant GUI controls
+
+A control is *relevant* when it matches the data it collects or shows. You make it work by listening to its **signals** and changing its **properties** while the program runs.
+
+| Data | Relevant control |
+|---|---|
+| A number (zone, top-up amount) | `SpinBox` |
+| Yes/no (concession) | `CheckButton` |
+| Free text (card ID) | `LineEdit` |
+| One choice from a list (ticket type) | `OptionButton` |
+| An action ("Calculate") | `Button` |
+| Read-only output (balance) | `Label` |
+| A table of journeys | `ItemList` / `Tree` |
+
+```gdscript
+extends Control
+
+func _ready() -> void:
+ # C633 — signal: runs when the user clicks the button
+ $CalculateButton.pressed.connect(_on_calculate_pressed)
+
+func _on_calculate_pressed() -> void:
+ var zone: int = int($ZoneSpinBox.value) # C633 — SpinBox: zone is a number
+ var fare: float = FARE_TABLE[zone]
+ # C633 — property: sets the label's text at runtime
+ $ResultLabel.text = "Fare: $%.2f" % fare
+```
+
+(The C627 sketch above used a `LineEdit` called `ZoneInput`. Zone is a number, so the *relevant* control is a `SpinBox` — making that upgrade is exactly the C627 → C633 step.)
+
+**Earns the tick:** controls chosen to fit the data (per the table above), at least one signal connected in code, at least one property changed at runtime. **Doesn't:** a `LineEdit` for everything, or a layout that never responds to the user.
+
+**Custom signals** count as strong C633 evidence — a signal is Godot's version of the glossary's *event* ("a special type of method that is called when an object's state changes"):
+
+```gdscript
+signal fare_calculated(amount: float) # C633 — custom signal
+
+func charge(fare: float) -> void:
+ balance -= fare
+ fare_calculated.emit(fare)
+```
+
+**In connect-go-dots** — every kind of C633 evidence in 25 lines of code:
+
+| Evidence | Where |
+|---|---|
+| Control fits the data | `TextureButton` — a clickable photo *is* a button whose face is the picture; `TextureRect` shows the chosen photo read-only; `GridContainer` lays out the 3-column grid |
+| Signal connected in code | `button.pressed.connect(_open.bind(button.texture_normal))` in `grid.gd` |
+| Signal connected in the editor | the Back button's `pressed` → `_on_back_pressed()` in `detail.tscn` |
+| Property set at runtime | `%Photo.texture = Shared.photo` in `detail.gd` |
+
+(`%Photo` / `%Photos` is scene-unique-name lookup — tick "Access as Unique Name" on the node.)
+
+**Also see:** `dodge-the-creeps` — `hud.gd` (Labels, Buttons, timers) and `player.gd` (`signal hit`).
+
+## Check Your Understanding
+
+1. C627 vs C633 — one sentence each.
+
+>| ### Answer
+>| C627: the program has a working GUI built from Control nodes. C633: each control is the *right* one for its data, wired with signals and runtime property changes.
+
+2. A yes/no setting (like concession) belongs on which control?
+
+>| ### Answer
+>| `CheckButton`.
+
+3. Name the three kinds of C633 evidence.
+
+>| ### Answer
+>| A relevant control chosen for the data, a signal connected, a property changed at runtime.
/dev/null .. sd/C06/Instructions and Operators.md
@@ 0,0 1,126 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Instructions and Operators — GDScript
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C611 | 1–2 | instructions |
+| C612 | 1–2 | arithmetic operators |
+| C623 | 3–4 | logical operators |
+| C624 | 3–4 | conditional operators |
+
+## C611 — Instructions
+
+**Definition.** A unit of code that can be executed by a compiler or interpreter.
+
+Label a short piece of code that *does something*: takes input, calculates, produces output.
+
+```gdscript
+trips_today += 1 # C611 — instruction: updates the trip counter
+```
+
+From a studied project:
+
+```gdscript
+# connect-go-dots — grid.gd
+Shared.photo = photo # C611 — instruction: stores the chosen photo
+```
+
+**Earns the tick:** any labelled statement that executes and has an effect. This is the floor of the ladder — every student should have it.
+
+## C612 — Arithmetic operators
+
+**Definition.** A symbol that performs basic mathematical operations such as addition, subtraction, multiplication and division.
+
+GDScript: `+` `-` `*` `/` `%` (remainder) and `**` (power).
+
+```gdscript
+# C612 — arithmetic operators
+var total: float = fare * trips + 0.50 # * multiply, + add
+var change: float = payment - total # - subtract
+var per_trip: float = total / trips # / divide
+var minutes_left: int = seconds % 60 # % remainder
+```
+
+**In tile-matching-game** (`game.gd`) — working out the board:
+
+```gdscript
+# tile-matching-game — game.gd
+var total_cards := rows * columns # C612 — * multiply
+if total_cards % 2 != 0: # C612 — % remainder: an odd board cannot hold pairs
+ return
+pairs_to_find = total_cards / 2 # C612 — / divide (int ÷ int stays int)
+```
+
+**Watch:** integer division truncates — `7 / 2` is `3`, but `7.0 / 2` is `3.5`. Being able to say why is C629 territory.
+
+## C623 — Logical operators
+
+**Definition.** A Boolean operator used to combine expressions, such as AND, OR.
+
+GDScript uses the words `and`, `or`, `not` (the symbols `&&`, `||`, `!` also work — prefer the words).
+
+```gdscript
+# C623 — logical operators
+if is_concession and zone <= 2: # and: both must be true
+ fare *= 0.5
+
+if not card_registered or balance < 0.0: # not, or
+ show_warning()
+```
+
+**In tile-matching-game** (`game.gd`):
+
+```gdscript
+# tile-matching-game — game.gd
+if is_busy or card.is_face_up or card.is_matched: # C623 — or: any reason to ignore the click
+ return
+
+if pairs_to_find > 0 and score >= pairs_to_find: # C623 — and: both needed to win
+ message_label.text = "All pairs found in %d turns!" % turns
+```
+
+**Earns the tick:** a condition that *combines* expressions. A bare `if balance >= fare:` is C624 only — no logical operator in sight.
+
+## C624 — Conditional operators
+
+**Definition.** A symbol used to compare two values within a condition: equals `==`, not equals `!=`, greater than `>`, less than `<`, greater than or equal `>=`, less than or equal `<=`. Used inside selection and iteration conditions to decide whether a branch runs or a loop continues.
+
+```gdscript
+# C624 — conditional operators
+if balance >= fare: # >= at least enough money
+ touch_on()
+elif balance == 0.0: # == exactly empty
+ show_topup_prompt()
+```
+
+**In tile-matching-game** (`game.gd`) — the heart of the game is one comparison:
+
+```gdscript
+# tile-matching-game — game.gd
+if first_card.pair_id == second_card.pair_id: # C624 — ==: the cards match
+ _handle_match()
+```
+
+**Not to be confused with** the ternary conditional *expression* (`0.5 if is_concession else 1.0` in GDScript) — that is shorthand for selection, not a comparison.
+
+**Watch:** `=` assigns, `==` compares. GDScript will refuse `if balance = 0.0:` — read the error, don't fight it.
+
+## Check Your Understanding
+
+1. In `if balance >= fare and is_concession:` — which two operator codes could you label, and on which symbols?
+
+>| ### Answer
+>| C624 on `>=` (conditional operator), C623 on `and` (logical operator).
+
+2. Why will `if balance = 0.0:` not run?
+
+>| ### Answer
+>| `=` assigns; comparing needs `==`. Godot reports a parse error.
+
+3. In `total_cards % 2 != 0` — what does `%` do, and which code is it?
+
+>| ### Answer
+>| `%` gives the remainder after division — C612 (arithmetic). The `!=` beside it is C624.
/dev/null .. sd/C06/Local and Global Variables.md
@@ 0,0 1,137 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# Local and Global Variables — GDScript
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C621 | 3–4 | local variables |
+| C622 | 3–4 | constants |
+| C628 | 3–4 | uses data types for local variables |
+| C631 | 5–6 | global variables |
+| C634 | 5–6 | uses appropriate data types for global variables |
+
+**Definition.** A *variable* stores and labels data to be referenced and manipulated in a program. Its **scope** is the part of the program that can see it.
+
+| | Where it is written | Who can see it |
+|---|---|---|
+| **Local (C621)** | Inside a function | Only that function |
+| **Global (C631)** | Outside every function, at script level | Every function in the script |
+
+**Quick check:** is the line indented inside a `func`? Local.
+
+## C621 — Local variables
+
+**Definition.** Variables defined inside a function that can only be accessed by that function.
+
+```gdscript
+func calculate_fare() -> void:
+ # C621 — local variable: only calculate_fare() can see it
+ var fare: float = 5.30
+ balance -= fare
+```
+
+Parameters and loop variables are local too — in `connect-go-dots/grid.gd`, the parameter `photo: Texture2D` and the loop variable `button` exist only inside their function.
+
+## C631 — Global variables
+
+**Definition.** Variables defined outside any function that can be accessed by all functions throughout the source code.
+
+At the script level:
+
+```gdscript
+extends Control
+
+# C631 — global variables: every func in this script can use them
+var balance: float = 20.00
+var is_concession: bool = false
+```
+
+Or using `class_name` with `static` for access from other scripts:
+
+```gdscript
+class_name GlobalVars
+
+static var g_var = 20 # C631 — global via class_name
+```
+
+An **autoload singleton** is the Godot-idiomatic project-wide global — if you use one, name it as your C631 evidence in validation.
+
+**In connect-go-dots** — the autoload in action (`shared.gd`, registered as `Shared`):
+
+```gdscript
+# connect-go-dots — shared.gd (autoload "Shared")
+extends Node
+
+## Handed from one screen to the next. Lives on root, so a scene change
+## cannot touch it.
+var photo: Texture2D # C631 — global: both screens use it
+```
+
+```gdscript
+Shared.photo = photo # C631: grid.gd — one screen writes it
+%Photo.texture = Shared.photo # C631: detail.gd — the other reads it
+```
+
+The `##` comment is model internal documentation: it says *why* the variable lives where it does.
+
+## C622 — Constants
+
+**Definition.** A fixed value that, once defined, cannot be altered during the execution of a program.
+
+```gdscript
+# C622 — constant: the daily cap never changes while the program runs
+const DAILY_CAP: float = 9.60
+```
+
+**Earns the tick:** `const` used for a value that genuinely never changes, named in CAPITALS. Showing Godot's error when you try to assign to it is a neat validation demo.
+
+## C628 and C634 — choosing the right data type
+
+C621/C631 is that the variable **exists**. C628/C634 is that its data type **suits the data** — C628 for locals, C634 for globals.
+
+```gdscript
+extends Control
+
+var trips_today: int = 0 # C634 — int: you cannot take half a trip
+var balance: float = 20.00 # C634 — float: money needs decimal places
+var is_concession: bool = false # C634 — bool: only two possible answers
+var card_id: String = "" # C634 — String: digits never used in a calculation
+
+func charge(zone: int) -> void:
+ var fare: float = FARE_TABLE[zone] # C628 — float: fares have cents
+ balance -= fare
+```
+
+From tile-matching-game (`deck.gd`):
+
+```gdscript
+# tile-matching-game — deck.gd
+var key: String = card["pair"] # C628 — String: the pair label from the CSV
+```
+
+**State the data type.** `var trips_today = 0` cannot earn C634 because no data type has been given for the marker to assess. Always write `: int`, `: float`, `: bool` or `: String`.
+
+`var trips_today := 0` is acceptable — GDScript works out the type for you — but name it in your comment so the marker can see it: `# C634 — int: you cannot take half a trip`.
+
+Types go beyond `int`/`float`/`bool`/`String`: in connect-go-dots the global is `var photo: Texture2D` — same standard, `# C634 — Texture2D: the value is an image`.
+
+The **why** in these comments doubles as your reasoning evidence (C629/C638) — see [Data Types](/sd/C06/Data%20Types).
+
+## Check Your Understanding
+
+1. `var speed := 5` at script level — which code does it earn as written, and what more would C634 need?
+
+>| ### Answer
+>| C631 (a global exists). C634 needs the type visible — write `: int`, or name it in the comment — plus the *why*.
+
+2. Are function parameters local or global?
+
+>| ### Answer
+>| Local (C621): they exist only inside their function.
+
+3. What three things make a C622 constant?
+
+>| ### Answer
+>| `const`, a CAPITALS name, and a value that genuinely never changes while the program runs.
/dev/null .. sd/C06/OOP Concepts.md
@@ 0,0 1,292 @@
+<!-- Generated from applied-computing-au vic/unit3-4/sat/C06-2026/C06-Reference-Godot — do not hand-edit; re-run the port. -->
+# OOP Concepts — GDScript
+
+
+**Skill codes on this page**
+
+| Code | Level | Skill |
+|---|---|---|
+| C643 | 7–8 | access modifiers |
+| C651 | 9–10 | classes |
+| C652 | 9–10 | objects |
+| C653 | 9–10 | abstraction |
+| C654 | 9–10 | encapsulation |
+| C655 | 9–10 | generalisation |
+| C656 | 9–10 | inheritance |
+
+**Definition.** *Object-oriented programming (OOP):* programming based on objects that contain data in the form of fields or attributes, and code in the form of methods.
+
+Level 9–10 asks for classes and objects **plus all relevant OOP principles** — one class on its own does not reach the top band.
+
+## C651 — Classes and C652 — Objects
+
+**Definitions.** *Class:* a program code template for creating objects. *Object:* any instantiated class that a program can inspect and/or change. *Instantiation:* the process by which an object is created from a class.
+
+```gdscript
+# MykiCard.gd
+class_name MykiCard # C651 — class: the template for every card
+extends RefCounted
+
+var _balance: float = 20.00
+
+func top_up(amount: float) -> void:
+ _balance += amount
+```
+
+```gdscript
+# C652 — objects: two cards from one template, separate balances
+var my_card: MykiCard = MykiCard.new()
+var your_card: MykiCard = MykiCard.new()
+my_card.top_up(10.0)
+```
+
+**Earns the tick:** C651 — a class *you wrote* (`class_name`, fields, methods). C652 — `.new()` creating an object your program then uses. Two objects holding different state is the cleanest demo.
+
+**In tile-matching-game:** `card.gd` opens with `class_name Card` — fields (`pair_id`, `is_face_up`) plus methods (`flip_up()`, `mark_matched()`) in one template (C651). The game then holds two of them:
+
+```gdscript
+# tile-matching-game — game.gd
+var first_card: Card = null # C652 — two objects from one class,
+var second_card: Card = null # each with its own state
+```
+
+(The board creates them with `card_scene.instantiate()` — instancing the card *scene* constructs a `Card` object, because the scene's root node runs `card.gd`.)
+
+**In club-ladder** — the direct `.new()` case:
+
+```gdscript
+# club-ladder — app.gd
+season.teams.append(Team.new(team_name)) # C652 — object created and used
+```
+
+`season.gd` builds them four arguments at a time from the XML — `Team.new(team_name, wins, draws, losses)` — and `Team._init` gives every parameter a default, so both calls work.
+
+## C653 — Abstraction
+
+**Definition.** An OOP principle that allows programmers to manage complexity by hiding implementation details and exposing only the essential features of an object.
+
+**How it works in GDScript:**
+
+- Base class defines structure meant for inheritance
+- Methods can have default implementations or error messages
+- Convention-based — not meant to be used directly
+- `assert(false)` is one way to indicate override needed
+- Focus on inheritance structure rather than enforcement
+
+```gdscript
+# C653 — abstraction: base class with common structure
+class_name Animal
+extends RefCounted
+
+var name: String
+
+func _init(p_name: String):
+ name = p_name
+
+func make_sound():
+ print("Some animal sound")
+
+func move():
+ print(name + " is moving")
+```
+
+Myki version:
+
+```gdscript
+# C653 — abstraction: callers use get_cost() and never see the fare rules
+class_name Journey
+extends RefCounted
+
+var fare: float
+
+func get_cost() -> float:
+ return fare
+```
+
+**Earns the tick:** a base class used through its simple interface while the details stay inside. "The HUD calls `get_cost()` and doesn't care how the cost is worked out" is the sentence to say.
+
+**In tile-matching-game:** `card.gd`'s own header comment makes the abstraction argument — a card "does NOT decide whether two cards match — that is the Game's job. The card only reports being clicked." The game calls `flip_up()` and `mark_matched()`; how a card draws itself stays hidden inside the card.
+
+## C654 — Encapsulation
+
+**Definition.** An OOP principle that involves bundling the data, and the methods that operate on that data, into a single unit or class.
+
+**How it works in GDScript:**
+
+- Single underscore `_` indicates private by convention only
+- No enforcement mechanism — purely documentation
+- All class members are technically public
+- Relies entirely on developer discipline
+- IDE may highlight convention violations
+
+```gdscript
+class_name BankAccount
+extends RefCounted
+
+var _balance: float = 0.0 # C654 — private by convention
+
+func get_balance() -> float:
+ return _balance
+
+func deposit(amount: float):
+ if amount > 0:
+ _balance += amount
+ print("Deposited $" + str(amount))
+ else:
+ print("Invalid amount")
+```
+
+Myki version:
+
+```gdscript
+class_name MykiCard
+extends RefCounted
+
+var _balance: float = 20.00 # C654 — private, cannot be changed directly
+
+func _is_valid(amount: float) -> bool: # C654 — private helper, used only inside this class
+ return amount > 0
+
+func top_up(amount: float) -> void: # C654 — the only door to _balance
+ if _is_valid(amount):
+ _balance += amount
+```
+
+**Earns the tick:** data behind `_`, changed only through methods that validate. In validation: show `top_up(-50)` being rejected.
+
+**In tile-matching-game:** `Card` bundles its state (`pair_id`, `is_face_up`, `is_matched`) with the methods that change it — outside code never *sets* those fields, it calls `flip_up()`, `flip_down()`, `mark_matched()`. (The game reads them directly; underscore-prefixing the fields and adding getters would push this to full-marks encapsulation.)
+
+### C643 — Access modifiers
+
+GDScript has no `private` / `public` keywords — the `_` prefix **is** the access modifier, applied by convention:
+
+```gdscript
+var _balance: float = 20.00 # C643 — "private": underscore convention
+func get_balance() -> float: # C643 — public getter is the only way in
+ return _balance
+```
+
+**Earns the tick:** the convention applied consistently *and named* — "the underscore marks it private by convention; other code must go through the getter."
+
+**In connect-go-dots:** `_open()` and `_on_back_pressed()` carry the underscore as internal helpers no other script should call. (`_ready()` also starts with `_`, but that is Godot's callback naming, not privacy.)
+
+**In tile-matching-game:** `Card` shows the split in one class — public `flip_up()` / `mark_matched()` for other scripts, private `_on_pressed()` for itself.
+
+## C655 — Generalisation
+
+**Definition.** The process of defining a general class (superclass) that encapsulates common attributes and behaviours of more specific classes (subclasses).
+
+**How it works in GDScript:**
+
+- `class_name` makes class globally accessible
+- `extends RefCounted` for automatic memory management
+- Constructor `_init` sets up shared data
+- Base class defines common interface for all subclasses
+
+```gdscript
+# C655 — generalisation: common functionality in base class
+class_name Vehicle
+extends RefCounted
+
+var brand: String
+var model: String
+var is_running: bool = false
+
+func _init(p_brand: String, p_model: String):
+ brand = p_brand
+ model = p_model
+
+func start_engine():
+ is_running = true
+ print(brand + " " + model + " started")
+
+func stop_engine():
+ is_running = false
+ print(brand + " stopped")
+```
+
+Myki version:
+
+```gdscript
+# C655 — generalisation: what every journey shares lives in the parent
+class_name Journey
+extends RefCounted
+
+var zone: int
+var fare: float
+
+func _init(p_zone: int, p_fare: float):
+ zone = p_zone
+ fare = p_fare
+
+func get_cost() -> float:
+ return fare
+```
+
+**Earns the tick:** shared fields and methods pulled *up* into one parent instead of repeated in each child — point at the duplication you avoided.
+
+## C656 — Inheritance
+
+**Definition.** A method of basing an object or class on another object or class, taking on its attributes and methods and potentially extending upon them.
+
+**How it works in GDScript:**
+
+- `extends` establishes parent-child relationship
+- `super()` calls parent constructor with parameters
+- Override by redefining method with same name
+- Single inheritance model (one parent)
+- Parent methods available unless explicitly overridden
+
+```gdscript
+# C656 — inheritance: Car is a Vehicle with extras
+class_name Car
+extends Vehicle
+
+var doors: int
+
+func _init(p_brand: String, p_model: String, p_doors: int):
+ super(p_brand, p_model)
+ doors = p_doors
+
+func honk():
+ print("Beep beep!")
+
+# C656 — override parent method
+func start_engine():
+ super.start_engine()
+ print("Car is ready to drive")
+```
+
+Myki version:
+
+```gdscript
+# C656 — inheritance: a ConcessionJourney is a Journey with one changed rule
+class_name ConcessionJourney
+extends Journey
+
+func get_cost() -> float: # override
+ return fare * 0.5
+```
+
+**Earns the tick:** `extends` *your own* class, `super` used, at least one method overridden — and both parent and child actually used by the running program.
+
+**Not enough:** every script in connect-go-dots has `extends Control` or `extends Node` — inheriting from an *engine* class. Necessary in Godot, but C656 wants `extends` on a class of your own.
+
+**Worth seeing anyway:** in tile-matching-game, `Card extends Button` shows what inheriting *buys* — the card never defines `pressed` or `disabled`, yet uses both, because they come from `Button`. That is inheritance working; it just is not *your* parent class, so on its own it does not earn C656.
+
+## Check Your Understanding
+
+1. Why does `extends Control` not earn C656?
+
+>| ### Answer
+>| It inherits from an *engine* class — the tick needs `extends` on a class you wrote.
+
+2. What is GDScript's access modifier, and which code is it?
+
+>| ### Answer
+>| The `_` underscore prefix, applied by convention — C643.
+
+3. List the minimum ingredients of full C656 evidence.
+
+>| ### Answer
+>| Your own parent class, `extends` on the child, `super` used, at least one override — and both classes used by the running program.
sd/VCE Software Development Hub.md ..
@@ 24,6 24,7 @@
- [C03 — Skills in Documenting a Software Requirements Specification](/sd/C03/C03-home)
- [C04 — Skills in Generating Design Ideas and Developing Evaluation Criteria](/sd/C04/C04-home)
- [C05 — Skills in Producing Detailed Designs](/sd/C05/C05-home)
+- [C06 — Skills in Using the Features of the Programming Language](/sd/C06/C06-home)
## Tools
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9