"""Rewrite the question texts of a gallery JSONL to the q3 wording. q3 = q2 wording (scripts/make_q2.py, kept unchanged so q2 artifacts stay reproducible) + loading overlay / spinner is NOT a modal (has_modal, screen instructions + criteria) + primary_button: loading overlay without actionable button -> none; destructive row inside a settings list is not the primary button. Gold is NOT touched here (see scripts/fix_settings_gold.py). usage: python scripts/make_q3.py in.jsonl out.jsonl """ import json, os, sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from make_q2 import INSTR as Q2_INSTR, SCREEN_CRITERIA as Q2_SCREEN_CRITERIA # Sentences appended to the q2 instructions (per language). INSTR_APPEND = { "screen": { "en": "A full-screen or inline loading overlay or spinner is not a modal (not a dialog or sheet).", "ja": "全画面またはインラインのローディングオーバーレイやスピナーはモーダル(ダイアログやシート)ではありません。", }, "has_modal": { "en": "A full-screen or inline loading overlay or spinner is NOT a modal: answer no for it.", "ja": "全画面またはインラインのローディングオーバーレイやスピナーはモーダルではありません。その場合は「いいえ」と答えてください。", }, "primary_button": { "en": "A loading overlay with no actionable button means none. A destructive row inside a settings list (e.g. Delete Account) is not the primary button.", "ja": "操作できるボタンのないローディングオーバーレイは「none」です。設定画面のリスト内にある破壊的な行(アカウント削除など)は主要ボタンではありません。", }, } # (en, ja) appended to the bilingual "en / ja" screen criteria. CRITERIA_APPEND = { "loading": ("A full-screen loading overlay or spinner is loading, not a modal or sheet.", "全画面のローディングオーバーレイやスピナーもこれ(モーダルやシートではない)"), "sheet": ("A loading overlay or spinner is not a sheet.", "ローディングオーバーレイやスピナーはシートではない"), } def q3_instr(qid, lang): base = Q2_INSTR[qid][lang] add = INSTR_APPEND.get(qid, {}).get(lang) if not add: return base return base + ("" if lang == "ja" else " ") + add def q3_criterion(key): base = Q2_SCREEN_CRITERIA[key] if key not in CRITERIA_APPEND: return base en, ja = base.rsplit(" / ", 1) add_en, add_ja = CRITERIA_APPEND[key] return f"{en}. {add_en} / {ja}。{add_ja}" def main(src, dst): n = 0 with open(src, encoding="utf-8") as f, open(dst, "w", encoding="utf-8", newline="\n") as out: for line in f: if not line.strip(): continue r = json.loads(line) lang = "ja" if r["meta"].get("lang") == "ja" else "en" for qid in Q2_INSTR: if qid in r["questions"]: r["questions"][qid]["instructions"] = q3_instr(qid, lang) crit = r["questions"]["screen"]["criteria"] for k in Q2_SCREEN_CRITERIA: if k in crit: crit[k] = q3_criterion(k) r["meta"]["question_version"] = "q3" out.write(json.dumps(r, ensure_ascii=False) + "\n") n += 1 print(f"{n} records -> {dst}") if __name__ == "__main__": if len(sys.argv) == 2 and sys.argv[1] == "--show": for q in INSTR_APPEND: for l in ("en", "ja"): print(f"[{q}/{l}] {q3_instr(q, l)}") for k in CRITERIA_APPEND: print(f"[criteria/{k}] {q3_criterion(k)}") else: main(sys.argv[1], sys.argv[2])