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 | |
