auto-<이름>에 쌓여 서로 덮어쓰지 않습니다.
같은 이름을 두 기기에서 쓰면 "다른 곳에서 수정됨"이 뜹니다.worlds.config.js로 저장·Publish.
이름은 i18n.js(world.{id}.name) 관리 — 월드 추가/삭제는 코드 작업.
트리에서 우클릭 → 월드 토글 또는 월드 위로 드래그로 pool에 추가.사과 개처럼 글자만), 대소문자는 무시.
편집 중인 본문은 저장 전이라도 검색된다.# queture: NN-NN-NN 주석을 병합한 학년-단원-깨처 색인.
흐린 행 = flavor 없는 깨처(저작 백로그), ∅n = 그룹 내 미저작 수,
✏️ = 비고에 # 코멘트(그룹 헤더엔 ✏️n 개수), ⏭/🕐/– = 카탈로그 상태,
∉ = 카탈로그 밖 id. flavor 클릭 = 에디터에서 열기 · 🎬 = 깨처 영상 ·
비고 클릭 = 그 자리에서 편집(⌘/Ctrl+Enter 저장, Esc 취소 —
docs/queture-catalog.md에 바로 반영). 다른 편집자의 비고는
패널 열기·탭 복귀 시 자동으로, ↻로는 즉시 다시 읽는다.ready.
Statements
x <- exprsample from expr into x
(a, b) <- exprtwo independent draws
(a < b) <- exprchain constraint: < ≤ > ≥ ≠
a[N<] <- exprarray of N; suffix < ≤ > ≥ ≠
x = exprassign (eager)
def f(a, b) = exprfunction (single expr; sees bindings at call site; hoisted)
where: condreject draw if false
draft: truepublish hold: game excludes this flavor + its subtree (sim preview still works; DRAFT checkbox edits this line)
favorite: trueeditorial 인기 tag: no game behavior — future favorites-only worlds / trial pools select on it (★FAV checkbox edits this line)
mode: equalanswer contract: cards are the stimulus, =/≠ buttons answer (correct = tap = iff values match). Inherits down the subtree; also mode: bigger to override an ancestor. MODE select edits this line
"tmpl" exproutput; pair: "t1" e1 | "t2" e2; || = sides shuffled 50:50 per draw
… hint "htmpl"per-side symbolic hint (💡 chips + wrong-answer banner); same template grammar. Bare hint = the display already is the value (chip skipped, banner reuses it)
strategy "tmpl"problem-level solving hint (통분해 봐 …); same template grammar. 💡 shows it FIRST (one chance), values second; wrong-answer banner tops with it. Game uses it only when ONE flavor made both cards (pair output / equal)
# commentto end of line; also after a statement. Kept in "…" strings
# QuetureURL: url대표 깨처 영상 URL(주석 메타데이터) — 트리의 leaf 옆 🎬 배지가 이 줄을 새 탭으로 연다. 형식 표준: docs/flavor-writing-guide.md
Sampler expressions
{a..b}uniform int; also {a..b step k}
{v1, v2, …}uniform pick; weighted: {v1:w1, v2:w2}. Strings too: op <- {"+", "-"}
pick(list)sampler over a realized list
Brackets: {} = unrealized sampler, [] = realized list. Scalar op sampler broadcasts.
Predef family — _x(k)
_n(k)k-digit uniform (10^(k−1)..10^k−1)
_n0(k)0..10^k−1 (k=0 ok → 0)
_n1(k)1..10^k−1
_n19(k)each digit 1..9 (no zero)
_n29(k)each digit 2..9
_n28(k)each digit 2..8
_ne(k)k-digit even
_no(k)k-digit odd
_n0e(k)even in 0..10^k−1
_n19e(k)no-zero + even
_n19o(k)no-zero + odd
_n19ee(k)every digit even {2,4,6,8}
_n19oo(k)every digit odd {1,3,5,7,9}
_n04(k)digits 0..4, lead 1..4 (carry-free)
_n01(k)digits 0/1, lead 1
_n00(k)d·10^i, one nonzero digit (3, 50, 200…)
_dr(k)k-digit repdigit (11, 22, 333…)
Predef fixed
_d00..9
_d11..9
_dd10..99
_dd00..99
_dd11..99
_dpprime digits {2,3,5,7}
_ddp2-digit primes
_b{0, 1}
_sign{−1, +1}
_neg1−9..−1
_neg_dd−99..−10
_10n{10, 100, 1k, 10k}
_pow2 _sq _cupowers of 2 / squares / cubes 1..9
_frac_s _frac_csimple / common unit fractions
_frac_genrandom proper fraction n/d
_dec1 _dec20.1..0.9 / 0.10..0.99
Expressions
^ (right) → unary − → * / % // → + − → == != < <= > >= → not → and → or → if c then a else b. Index: list[k]. Literals: true false (bindable via = or <-; {true, false} = coin flip).
Template — text
"{expr}" interpolates. Escape with \{ \}. Nested double quotes: \". Line break: <br> (cards render HTML). Sampler-typed value → rejection.
Template — math (KaTeX)
$…$ is a math block. Inside: single { } render as literal LaTeX braces; {{expr}} = interpolation (wrapped in {}). Literal $: \$. Example: "$\sqrt{{n}}$" n.
Env (read-only)
LEVEL (int ≥1, +1 every 5 correct), WORLD (1..6), LANG ("ko" | "en" — player's language). Locale-aware text: label = if LANG == "ko" then "평균" else "avg" then "{label}: {v}" v (inside a template, quotes need \").
STDLIB
Lists range(lo,hi[,step]) rep(v,k) rep_join(v,k,sep) join(sep,list) sum prod (곱, 빈 리스트→1: prod(digits(n))=자릿수 곱) len
Digits numcat(list) (digits→number: numcat([3,5])=35) digits(n) (number→digits: digits(325)=[3,2,5]) digit(n,i) (digit at place i, from the right: digit(3579,0)=9) ndigits(n) (digit count: ndigits(3579)=4) mask(n,i,ch) (digit at place i → ch, i=0 is ones, i may be a list of places: mask(3579,0,"?")="357?", mask(3597,[0,2],"?")="3?9?") maskall(n,i,ch,chAll) (inverse: place(s) i → ch, every other digit → chAll: maskall(3597,1,"?","■")="■■?■")
Sort·shuffle perm(list) (uniform random reorder, fresh per call: numcat(perm(digits(n)))) sample(list,k[,mode]) (k개 뽑기, 매 호출 새 난수·항상 리스트: 기본 "norep" 중복 없음 = 셔플의 앞 k개, k>len이면 reject; "rep" 중복 허용·k 제한 없음: numcat(sample(range(1,9),3))=서로 다른 세 자리, sample(range(1,6),4,"rep")=주사위 4번) sort(list[,dir]) (deterministic order, asc by default, "desc" 내림차순 — 숫자는 수치, 문자열은 사전순, 혼합은 reject: numcat(sort(digits(n),"desc"))=가장 큰 수 — asc 쌍둥이는 함정: numcat이 선두 0을 버려 numcat(sort(digits(105)))=15 ≠ 가장 작은 수, 0 자릿수 없을 때만)
Filter·query map(f,l1[,l2,…]) (f는 def/STDLIB 이름 — def가 괄호 없이 오는 유일한 자리; 원소별 적용, 리스트끼리 zip·스칼라 broadcast: def dbl(a) = a * 2 → map(dbl,[1,2,3])=[2,4,6], map(gcd,[4,6],[6,9])=[2,3]) cat(l1[,l2,…]) (리스트 연결 — 1단계만, 스칼라는 append: cat([1,2],[3,4])=[1,2,3,4], cat(d,7); 주의 a+b는 원소별 덧셈·[a,b]는 중첩) remove(list,v) (v와 같은 원소 제거, v는 값 또는 값 리스트: remove(digits(105),0)=[1,5]) keep(list,v) (반대 — v에 속하는 원소만 유지) uniq(list) (중복 제거, 첫 등장 순서: 서로 다른 자릿수 len(uniq(digits(n)))) rev(list) (뒤집은 복사본 — numcat(rev(digits(150)))=51, sort와 같은 선두 0 함정) count(list,v) (등장 횟수: count(digits(7770),7)=3) has(list,v) (포함 boolean — where 가드: where: not has(digits(n), 0))
Samplers pick(list) (list → uniform sampler) near(pivot,unit,k) (k closest multiples of unit, pivot excluded: near(24,10,2)={20,30}) union(a,b) inter(a,b) diff(a,b) (sampler set ops over {…}/{a..b}/pick/near/lists/scalars; uniform draw, empty result rejects: diff(near(n,10,4),n))
Arithmetic abs sign sqrt round floor ceil min max (쌍별 — 리스트 하나를 주면 spread: max(digits(n))=가장 큰 자릿수, 빈 리스트 reject) sq cube gcd
Transcendental exp log (base 10) ln sin cos tan asin acos atan pi() (trig in radians; non-finite result e.g. log(0) → rejection)
Display sup(n) sub(n) frac(n,d) fracHTML(n,d) lalign(s) ralign(s) (multi-line block: centered as a whole, lines left-/right-aligned) oprow(op,v) (row inside lalign/ralign: op flush left, v flush right — 세로셈 operator column; own line, no <br> around it: ralign(a + oprow("+", b) + "<hr>= " + masked))
Card visuals plot("fn(x)",xmin,xmax[,ymin,ymax]) (Desmos류 함수 그래프 SVG — x에 대한 QPL 식 문자열: plot("x*x - 2", -3, 3); 파라미터는 문자열 연결 plot("x*x + " + k, -3, 3); y범위 생략 시 자동) dots(n[,cols[,glyph]]) (개수 그리드 + 스태거 등장 애니메이션, 기본 5열·●: dots(12, 4, "🍎")) img(src,w,h) (이미지·움짤 — GIF/APNG/animated SVG, 고정 치수 8..800: img("assets/demo-star.svg", 110, 110); 에셋은 assets/에)
List broadcast
L op scalar, L op L (same length), -L apply element-wise (+ - * / // % ^). Unary fns map too: sq(range(1,n)) → squares. Length mismatch / comparison on a list rejects the draw.
Range bounds too: {1..[2,5,3]} ≡ [{1..2},{1..5},{1..3}] — one <- draws one list, slots independent. list..list zips (equal length); per-element empty range rejects.
Notes
Sampler op sampler → rejection (sample one first). _dec* may render like 0.7000…1 — build template from integer part.