<!-- Generated from applied-computing-au vic/unit3-4/sat/C07-2026/C07-Reference-Godot by port-reference-godot-to-wiki.py — do not hand-edit; re-run the port. --> # Validation Techniques — GDScript **Skill codes on this page** | Code | Level | Skill | |---|---|---| | C713 | 1–2 | identifies input data for validation | | C723 | 3–4 | existence checking | | C724 | 3–4 | type checking | | C725 | 3–4 | range checking | | C735 | 5–6 | two of the three checks | | C745 | 7–8 | all three checks | | C753 ✍️ | 9–10 | ALL input data, plus reasonableness and completeness | **Definition.** *Validation* checks the reasonableness of data inputs, while the program runs. It is not testing (testing happens to the finished program; validation happens to every input, every run). The three named checks: **existence** (was anything entered?), **type** (is it the right kind of value?), **range** (is it within acceptable limits?). **This ladder is not a checklist.** The individual checks are separate codes only at level 3–4. Above that, single codes stand for the *combination*: C735 = two checks working, C745 = all three, C753 = all inputs plus reasonableness and completeness. Consistency qualifiers decide the band: *some inconsistencies* (5–6) → *minor* (7–8) → *none* (9–10). **In the validation** Part B you add existence/type/range checks to the picked feature's real inputs, label them as you go, and **run a test to show a check actually fires** — a validation that never catches a bad value is scenery. ## C713 — Identify the inputs Level 1–2 is a written list of what needs validating: ```gdscript # C713 — inputs to validate in this feature: # team name — NameField (LineEdit), free text # zone — ZoneSpinBox (SpinBox), whole number # top-up — TopUpField (LineEdit), dollars and cents ``` **Earns the tick:** every user-facing input of the picked feature named. (Choosing constrained controls — a SpinBox can't receive letters — is good design, but the codes below want checks *in code*.) ## C723 — Existence check **Definition.** A test to see if a value has been entered as input or not. ```gdscript # club-ladder — app.gd func add_team(raw_name: String) -> void: var team_name := raw_name.strip_edges() if team_name == "": # C723 — existence: nothing entered message_label.text = "Type a team name first." return ``` Note the real-world details worth copying: `strip_edges()` first (spaces are not a name), and an error message that says **what to do**, not just "invalid". ## C724 — Type check **Definition.** A test to see if a value is of the specified data type or structure. GDScript's idioms — check *before* converting, or the conversion itself is the crash: ```gdscript # C724 — type: is the text actually a number? if not $TopUpField.text.is_valid_float(): $MessageLabel.text = "Enter an amount in dollars, like 10.50" return var amount := float($TopUpField.text) ``` `String.is_valid_int()` and `is_valid_float()` are the workhorses. The `is` keyword type-checks objects — real use in tile-matching-game: `if child is Card:` (`board.gd`). ## C725 — Range check **Definition.** Tests to see if a value is within a given range of acceptable values. ```gdscript # C725 — range: zones only run 1..3, amounts have a ceiling if zone < 1 or zone > MAX_ZONE: $MessageLabel.text = "Zone must be 1 to %d" % MAX_ZONE return if amount <= 0.0 or amount > MAX_TOP_UP: $MessageLabel.text = "Top-up must be between $0.01 and $%.2f" % MAX_TOP_UP return ``` The limits are **named constants** (`MAX_ZONE`, `MAX_TOP_UP`) — that's C7-1 working for C7-3. Clamping (`maxi(1, column_count)` in club-ladder's `board.gd`) is the accept-and-correct cousin of reject-and-message; for user input, prefer the message — silent correction hides the user's mistake from them. ## C735 and C745 — The checks working together One validated input, all three checks, in the order that cannot crash — existence, then type, then range: ```gdscript # C745 — full validation of the top-up amount (existence → type → range) func validate_top_up(raw: String) -> String: var text := raw.strip_edges() if text == "": # C723 — existence return "Enter an amount first." if not text.is_valid_float(): # C724 — type return "Enter a number, like 10.50" var amount := float(text) if amount <= 0.0 or amount > MAX_TOP_UP: # C725 — range return "Amount must be between $0.01 and $%.2f" % MAX_TOP_UP return "" # empty string = valid ``` C735 (5–6) is two of these working on real inputs; C745 (7–8) is all three, with at most *minor* inconsistencies. **Error messages are part of the standard** — "Must be between 8 and 72 in length" beats "Invalid input" because it tells the user how to fix it (that Discord message was the class's best-in-show in the Validation Detective activity). ## C753 — All inputs, plus reasonableness and completeness ✍️ Level 9–10 widens the lens from single fields to the **whole data set**: - **All relevant inputs** validated — not just the easy one. - **Completeness** — is anything missing? Real example: `deck.gd` skips half-empty CSV rows with `if row.size() < 2: continue` (tile-matching-game). - **Reasonableness** — can these values be true *together*? The model is club-ladder's cross-check: ```gdscript # club-ladder — app.gd ## In a competition where teams play each other, one team's win is always # C753 ✍️ ## another's loss — so total wins must equal total losses. Worth saying on ## screen rather than quietly showing figures that cannot be true. func totals_warning() -> String: if total_wins == total_losses: return "" return "Check your data: %d wins recorded, but %d losses." % [total_wins, total_losses] ``` **Earns the tick:** every input covered, a completeness check on incoming records, at least one reasonableness rule that crosses fields — and (✍️) the rule *written down*: work out what rules **your** data has to obey, and say so in a comment. **Then prove it fires.** End the validation task by entering a bad value and showing the message appear — the package script asks for exactly this test run. ## Check Your Understanding 1. Name the three validation checks and their level 3–4 codes. >| ### Answer >| Existence C723, type C724, range C725. 2. Why are C735 and C745 single codes rather than lists of checks? >| ### Answer >| Above level 3–4 the descriptor rewards the *combination* — two checks working (C735), then all three (C745) — with consistency qualifiers deciding the band. 3. What makes "Must be between 8 and 72 in length" a better error message than "Invalid input"? >| ### Answer >| It tells the user exactly how to fix the problem — specific beats generic. 4. Give an example of a reasonableness check (C753). >| ### Answer >| A cross-field rule — e.g. club-ladder's "total wins must equal total losses"; values that are individually fine but cannot be true together.
