@xom11/whiteboard 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.d.mts +259 -33
- package/dist/ai.d.ts +259 -33
- package/dist/ai.js +5424 -470
- package/dist/ai.js.map +1 -1
- package/dist/ai.mjs +4971 -351
- package/dist/ai.mjs.map +1 -1
- package/dist/catalog.json +5 -5
- package/dist/{chunk-V3YJ6JFL.mjs → chunk-44JY2AKC.mjs} +3 -3
- package/dist/{chunk-V3YJ6JFL.mjs.map → chunk-44JY2AKC.mjs.map} +1 -1
- package/dist/{chunk-GEC2D2EQ.mjs → chunk-BMYC2ILT.mjs} +4 -4
- package/dist/{chunk-GEC2D2EQ.mjs.map → chunk-BMYC2ILT.mjs.map} +1 -1
- package/dist/{chunk-PPKHCRRE.mjs → chunk-C76SOFXF.mjs} +3 -3
- package/dist/{chunk-PPKHCRRE.mjs.map → chunk-C76SOFXF.mjs.map} +1 -1
- package/dist/{chunk-IHUFOV7L.mjs → chunk-CH6SFONH.mjs} +15 -3
- package/dist/chunk-CH6SFONH.mjs.map +1 -0
- package/dist/{chunk-E6EDOPGT.mjs → chunk-DWIEVCGK.mjs} +254 -16
- package/dist/chunk-DWIEVCGK.mjs.map +1 -0
- package/dist/{chunk-SZDAS7LK.mjs → chunk-IE2GGHNF.mjs} +131 -81
- package/dist/chunk-IE2GGHNF.mjs.map +1 -0
- package/dist/{chunk-ZTQBUKLJ.mjs → chunk-JJ4FPCBE.mjs} +142 -22
- package/dist/chunk-JJ4FPCBE.mjs.map +1 -0
- package/dist/{chunk-QRUAEXLR.mjs → chunk-K5BS2H56.mjs} +5 -5
- package/dist/{chunk-QRUAEXLR.mjs.map → chunk-K5BS2H56.mjs.map} +1 -1
- package/dist/{chunk-BNBOIDO5.mjs → chunk-K7VJU7LQ.mjs} +3 -3
- package/dist/{chunk-BNBOIDO5.mjs.map → chunk-K7VJU7LQ.mjs.map} +1 -1
- package/dist/{chunk-H22OZYTW.mjs → chunk-KOXOC2FI.mjs} +48 -39
- package/dist/chunk-KOXOC2FI.mjs.map +1 -0
- package/dist/{chunk-CXHNVYMD.mjs → chunk-KWDBVLST.mjs} +5 -5
- package/dist/{chunk-CXHNVYMD.mjs.map → chunk-KWDBVLST.mjs.map} +1 -1
- package/dist/{chunk-OQIQNKPQ.mjs → chunk-LTLLQUMN.mjs} +4 -4
- package/dist/{chunk-OQIQNKPQ.mjs.map → chunk-LTLLQUMN.mjs.map} +1 -1
- package/dist/chunk-QK6OVDLC.mjs +103 -0
- package/dist/chunk-QK6OVDLC.mjs.map +1 -0
- package/dist/{chunk-QGNU34T7.mjs → chunk-QLQ4MJNO.mjs} +10 -4
- package/dist/chunk-QLQ4MJNO.mjs.map +1 -0
- package/dist/{chunk-BU5KLO3P.mjs → chunk-T3N4BSJV.mjs} +4 -4
- package/dist/{chunk-BU5KLO3P.mjs.map → chunk-T3N4BSJV.mjs.map} +1 -1
- package/dist/{chunk-5JM35CXV.mjs → chunk-TMRFSOM7.mjs} +4 -4
- package/dist/{chunk-5JM35CXV.mjs.map → chunk-TMRFSOM7.mjs.map} +1 -1
- package/dist/geometry-2d.d.mts +1 -1
- package/dist/geometry-2d.d.ts +1 -1
- package/dist/geometry-2d.js +841 -204
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +5 -5
- package/dist/geometry-3d.d.mts +1 -1
- package/dist/geometry-3d.d.ts +1 -1
- package/dist/geometry-3d.js +172 -22
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +4 -4
- package/dist/graph-2d.d.mts +1 -1
- package/dist/graph-2d.d.ts +1 -1
- package/dist/graph-2d.js +307 -100
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +7 -7
- package/dist/handleExtractProblem-BrDY9ifM.d.mts +58 -0
- package/dist/handleExtractProblem-BrDY9ifM.d.ts +58 -0
- package/dist/{host-HOSJHQ5H.mjs → host-4FIUNIDQ.mjs} +13 -12
- package/dist/host-4FIUNIDQ.mjs.map +1 -0
- package/dist/{host-2ISGVO7O.mjs → host-4ZB4XD4S.mjs} +9 -8
- package/dist/host-4ZB4XD4S.mjs.map +1 -0
- package/dist/{host-ZQCDAT6O.mjs → host-H2IGOKJU.mjs} +3 -3
- package/dist/{host-ZQCDAT6O.mjs.map → host-H2IGOKJU.mjs.map} +1 -1
- package/dist/{host-HKMZSCIT.mjs → host-KMWP7KBT.mjs} +286 -74
- package/dist/host-KMWP7KBT.mjs.map +1 -0
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +849 -206
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +22 -21
- package/dist/index.mjs.map +1 -1
- package/dist/latex.d.mts +1 -1
- package/dist/latex.d.ts +1 -1
- package/dist/latex.js +8 -2
- package/dist/latex.js.map +1 -1
- package/dist/latex.mjs +1 -1
- package/dist/render-NMS7OAV6.mjs +10 -0
- package/dist/{render-ZX2O2IK7.mjs.map → render-NMS7OAV6.mjs.map} +1 -1
- package/dist/serialize-PGHQZEPV.mjs +9 -0
- package/dist/{serialize-N4G6RFBB.mjs.map → serialize-PGHQZEPV.mjs.map} +1 -1
- package/dist/{types-C3FjpoUi.d.ts → types-tePd94vW.d.mts} +8 -0
- package/dist/{types-C3FjpoUi.d.mts → types-tePd94vW.d.ts} +8 -0
- package/package.json +2 -1
- package/dist/chunk-E6EDOPGT.mjs.map +0 -1
- package/dist/chunk-H22OZYTW.mjs.map +0 -1
- package/dist/chunk-IHUFOV7L.mjs.map +0 -1
- package/dist/chunk-QGNU34T7.mjs.map +0 -1
- package/dist/chunk-SZDAS7LK.mjs.map +0 -1
- package/dist/chunk-ZTQBUKLJ.mjs.map +0 -1
- package/dist/host-2ISGVO7O.mjs.map +0 -1
- package/dist/host-HKMZSCIT.mjs.map +0 -1
- package/dist/host-HOSJHQ5H.mjs.map +0 -1
- package/dist/render-ZX2O2IK7.mjs +0 -10
- package/dist/serialize-N4G6RFBB.mjs +0 -9
package/dist/ai.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stamps/geometry-2d/ai/deterministic/vocabulary.ts","../src/stamps/geometry-2d/ai/deterministic/coverage.ts","../src/stamps/geometry-2d/ai/rules/_shared.ts","../src/stamps/geometry-2d/ai/rules/triangle.ts","../src/stamps/geometry-2d/ai/rules/quad.ts","../src/stamps/geometry-2d/ai/rules/connect.ts","../src/stamps/geometry-2d/ai/rules/midpoint.ts","../src/stamps/geometry-2d/ai/rules/perpBisector.ts","../src/stamps/geometry-2d/ai/rules/cevian.ts","../src/stamps/geometry-2d/ai/rules/angleBisectorAngle.ts","../src/stamps/geometry-2d/ai/rules/centers.ts","../src/stamps/geometry-2d/ai/rules/perpFoot.ts","../src/stamps/geometry-2d/ai/rules/circleRadius.ts","../src/stamps/geometry-2d/ai/rules/circleTriangle.ts","../src/stamps/geometry-2d/ai/rules/tangentFromExt.ts","../src/stamps/geometry-2d/ai/rules/externalPoint.ts","../src/stamps/geometry-2d/ai/rules/arcMidpoint.ts","../src/stamps/geometry-2d/ai/rules/excenter.ts","../src/stamps/geometry-2d/ai/rules/parallelPerp.ts","../src/stamps/geometry-2d/ai/rules/reflection.ts","../src/stamps/geometry-2d/ai/rules/pointAtDistance.ts","../src/stamps/geometry-2d/ai/rules/eulerLine.ts","../src/stamps/geometry-2d/ai/rules/radicalAxis.ts","../src/stamps/geometry-2d/ai/rules/simson.ts","../src/stamps/geometry-2d/ai/rules/ninePoint.ts","../src/stamps/geometry-2d/ai/rules/diameterCirclePairwise.ts","../src/stamps/geometry-2d/ai/rules/angleBisectorFoot.ts","../src/stamps/geometry-2d/ai/rules/intersection.ts","../src/stamps/geometry-2d/ai/rules/chord.ts","../src/stamps/geometry-2d/ai/rules/incircleTangency.ts","../src/stamps/geometry-2d/ai/rules/altitudeDiameterCircles.ts","../src/stamps/geometry-2d/ai/rules/diameterCircleCutsSides.ts","../src/stamps/geometry-2d/ai/rules/registry.ts","../src/stamps/geometry-2d/ai/deterministic/runDeterministicIntents.ts","../src/stamps/geometry-2d/ai/deterministic/guards.ts","../src/stamps/geometry-2d/ai/normalizeIntent.ts","../src/stamps/geometry-2d/ai/resolveCircleNames.ts","../src/stamps/geometry-2d/ai/repairCircleIntersections.ts","../src/stamps/geometry-2d/dsl/transpile/errors.ts","../src/stamps/geometry-2d/dsl/transpile/refs.ts","../src/stamps/geometry-2d/ai/layout/disjointOffset.ts","../src/stamps/geometry-2d/ai/intent-builders/_types.ts","../src/stamps/geometry-2d/ai/intent-builders/shared.ts","../src/stamps/geometry-2d/ai/intent-builders/draw-shape.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/midpoint.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/perpFoot.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/centers.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/intersections.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/tangency.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/onSegment-free.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/angleBisectorFoot.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/externalAngleBisectorFoot.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/rightAngleViewing.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/arcMidpoint.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/reflect.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/pointAtDistance.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/externalToCircle.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/onCircle.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/index.ts","../src/stamps/geometry-2d/ai/intent-builders/connect.ts","../src/stamps/geometry-2d/ai/intent-builders/draw-circle.ts","../src/stamps/geometry-2d/ai/intent-builders/draw-line.ts","../src/stamps/geometry-2d/ai/intent-builders/mark-shape.ts","../src/stamps/geometry-2d/ai/intent-builders/registry.ts","../src/stamps/geometry-2d/ai/intentToDsl.ts","../src/stamps/geometry-2d/dsl/schema.ts","../src/stamps/geometry-2d/dsl/transpile/symbols.ts","../src/stamps/geometry-2d/dsl/transpile/cycles.ts","../src/stamps/geometry-2d/dsl/transpile/topology.ts","../src/stamps/geometry-2d/dsl/transpile/ids.ts","../src/stamps/geometry-2d/dsl/transpile.ts","../src/stamps/geometry-2d/ai/verify.ts","../src/stamps/geometry-2d/ai/deterministic/tryDeterministicFigure.ts","../src/stamps/geometry-2d/ai/deterministic/describeMiss.ts","../src/stamps/geometry-2d/ai/buildFigureIntent.ts","../src/stamps/geometry-2d/ai/handleGenerateFigure.ts","../src/stamps/geometry-2d/ai/envelope.ts","../src/stamps/geometry-2d/ai/intent.ts","../src/stamps/geometry-2d/ai/intentEnvelope.ts","../src/stamps/geometry-2d/ai/intentPrompt.ts","../src/stamps/geometry-2d/ai/handleGenerateFigureIntent.ts","../src/stamps/geometry-2d/ai/mergeIntents.ts"],"names":["others","PREFILTER","TRI","TRI_EN","TRI_G","TRI_EN_G","dm","CENTER","scanClause","from","circle","NAME_BEFORE","NAME_BEFORE_EN","opposite","z","PREFILTER_EN","parseNum","t","uniqueTriangle","CIRCLE_CENTER","LINE","CIRCLE_WORDS","CIRCLE_PAREN","resolveCircle","collect","addPoint","zodToJsonSchema"],"mappings":"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","file":"ai.mjs","sourcesContent":["// src/stamps/geometry-2d/ai/deterministic/vocabulary.ts\n//\n// Tập từ khóa \"geometry-relevant\" để confidence.ts đo coverage.\n// Format: lowercase, có dấu. countGeometryKeywords lowercase input rồi match.\n\nexport const GEOMETRY_KEYWORDS: readonly string[] = [\n // Base shapes\n 'tam giác', 'đường tròn', 'đương tròn', 'hình chữ nhật', 'hình vuông',\n 'hình bình hành', 'hình thoi', 'hình thang', 'tứ giác',\n // Triangle variants\n 'vuông tại', 'cân tại', 'đều',\n // Circle parts\n 'bán kính', 'tâm', 'đường kính', 'đương kính',\n // Segments / on-segment\n 'đoạn',\n // Derived points\n 'trung điểm', 'chân đường cao', 'chân đương cao', 'hình chiếu',\n 'trọng tâm', 'trực tâm', 'tâm nội tiếp', 'tâm ngoại tiếp',\n // Cevian names\n 'đường cao', 'đương cao', 'trung tuyến', 'phân giác', 'trung trực',\n // Special lines/circles\n 'tiếp tuyến', 'tiếp điểm', 'tiếp xúc',\n 'nội tiếp', 'ngoại tiếp',\n // Euler line (issue #47). Đánh dấu mọi clause \"Euler\" là geo-clause để\n // mention Euler chưa được claim (suy biến tam giác đều, hoặc đường tròn Euler\n // 9 điểm defer) → escalate fail-safe thay vì silent render-nothing.\n 'euler',\n // Trục đẳng phương (issue #47, construct 2). \"đẳng phương\" (≥10 ký tự, phân\n // biệt) đánh dấu clause là geo-clause: nếu radicalAxis rule miss (đồng tâm /\n // ≠2 đường tròn) → clause không phủ → escalate fail-safe (KHÔNG silent\n // render-nothing). Lowercase vì countGeometryKeywords lowercase input.\n 'đẳng phương',\n // Đường thẳng Simson (issue #47, construct 3). \"simson\" (danh từ riêng phân\n // biệt) đánh dấu clause là geo-clause: nếu simson rule miss (thiếu đường tròn\n // ngoại tiếp / >1 tam giác / P trùng đỉnh) → clause không phủ → escalate\n // fail-safe (KHÔNG silent render-nothing). Lowercase vì countGeometryKeywords\n // lowercase input.\n 'simson',\n // Đường tròn chín điểm / đường tròn Euler (issue #47, construct 4). \"chín điểm\"\n // đánh dấu clause là geo-clause: \"đường tròn Euler\" đã geo qua \"đường tròn\"/\n // \"euler\" sẵn, nhưng \"chín điểm\" (≥8 ký tự, phân biệt) phủ thêm cách diễn đạt\n // trần \"đường tròn chín điểm\" + làm fail-safe tường minh (nếu ninePoint rule\n // miss vì >1 tam giác → clause không phủ → escalate, KHÔNG silent render-nothing).\n // Lowercase vì countGeometryKeywords lowercase input.\n 'chín điểm',\n // Relations\n 'song song', 'vuông góc', 'giao điểm', 'cắt', 'đường thẳng', 'đương thẳng',\n // Ký hiệu (symbol-only phrasing tương đương từ chữ): \"⊥\" ≡ \"vuông góc\".\n // perpFoot rule đã nhận \"⊥\" ở tầng construct (PERP_DRAW), nhưng gate\n // hasGeometry trước đây CHỈ nhận chữ \"vuông góc\" → clause mà \"⊥\" là tín hiệu\n // hình học DUY NHẤT bị coi là văn xuôi (hasGeometry=false). Thêm \"⊥\" để 2\n // phrasing hành xử như nhau ở gate coverage (issue #46 nhóm A).\n '⊥',\n\n // === EN keywords (issue #46 group B) =======================================\n // Bộ từ khoá tiếng Anh để 1 clause TOÀN tiếng Anh được tính là geo-clause\n // (countGeometryKeywords > 0) → coverage gate không escalate sai dù rule EN đã\n // match. countGeometryKeywords lowercase input nên lưu lowercase ở đây.\n //\n // CHỈ thêm danh từ construct ĐA-KÝ-TỰ phân biệt, KHÔNG va chạm có hại như\n // substring của text tiếng Việt hay của nhau. KHÔNG thêm từ ngắn mơ hồ (\"on\",\n // \"at\", \"line\", \"point\", \"right\") vì dễ false-positive (\"point\" ⊂ \"appoint\",\n // \"at\" ⊂ \"tại\"…). Một danh từ construct / clause là đủ để đánh dấu geo.\n //\n // GOTCHA substring: \"centre\" ⊃ \"center\" KHÔNG xảy ra (khác chính tả); \"circle\"\n // KHÔNG ⊂ từ VN. \"radius\"/\"diameter\"/\"center\" là danh từ riêng cho circle.\n 'triangle',\n 'circle',\n 'square',\n 'rectangle',\n 'parallelogram',\n 'rhombus',\n 'trapezoid',\n 'trapezium',\n 'quadrilateral',\n 'midpoint',\n 'radius',\n 'diameter',\n 'center',\n 'centre',\n 'equilateral',\n 'isosceles',\n // Triangle centers (issue #46 group B). \"orthocenter\"/\"circumcenter\"/\n // \"incenter\" already contain \"center\" (already a keyword) — but list all four\n // explicitly for clarity + robustness. British -centre spellings included.\n 'centroid',\n 'orthocenter',\n 'orthocentre',\n 'circumcenter',\n 'circumcentre',\n 'incenter',\n 'incentre',\n // perpBisector + reflection EN (issue #46 group B). Hai danh từ này biến clause\n // \"perpendicular bisector …\" / \"reflection …\" tiếng Anh thành geo-clause để\n // coverage gate hoạt động: nếu rule EN match đủ thì clause được phủ; nếu clause\n // malformed (thiếu cặp đỉnh / thiếu trục) thì geo-clause không được phủ →\n // escalate (fail-safe), KHÔNG silent-incomplete. Đều ≥8 ký tự, phân biệt, không\n // substring của từ VN/EN nào hiện có (không va chạm).\n 'bisector',\n 'reflection',\n // tangentFromExt EN (issue #46 group B). Clause \"Draw the tangents from A to\n // (O)\" dùng ký hiệu \"(O)\" — KHÔNG có text keyword nào khác → coverage gate = 0\n // → escalate dù rule match. \"tangent\" (≥7 ký tự, phân biệt, KHÔNG substring của\n // từ VN/EN nào hiện có) đánh dấu clause là geo-clause. indexOf nên \"tangent\" tự\n // khớp trong \"tangents\"/\"tangent lines\" — KHÔNG cần thêm \"tangents\" riêng.\n 'tangent',\n // perpFoot EN (issue #46 group B). Clause \"Let H be the projection of A onto\n // BC\" / \"foot of the perpendicular from A to BC\" / \"Draw AH perpendicular to\n // BC\" → đánh dấu geo-clause để coverage gate fail-safe: nếu rule EN miss thì\n // geo-clause không phủ → escalate, KHÔNG silent-incomplete (triangle-only bỏ\n // điểm H). Cả hai ≥10 ký tự, phân biệt, không substring của từ VN/EN nào hiện\n // có. \"perpendicular bisector of BC\" đã có 'bisector' → 'perpendicular' chỉ\n // tăng count, không đổi hành vi.\n 'perpendicular',\n 'projection',\n // pointAtDistance EN (issue #46 group B). Clause \"On ray BA extended beyond A,\n // take D such that AD = AB\" / \"Extend AB beyond B to D ...\" / \"On the opposite\n // ray of ray BA, take D ...\" → mark geo-clause. \"extend\" (indexOf also matches\n // \"extended\"/\"extending\") + the phrase \"opposite ray\" (geometry-specific). If\n // the rule misses a malformed clause → geo-clause unclaimed → escalate\n // (fail-safe), NOT silent-drop of point D. No harmful substring collision with\n // any existing VN/EN keyword.\n 'extend',\n 'opposite ray',\n // cevian EN (issue #46 group B). Clause \"Draw the median AM\" / \"Draw the\n // altitude AH\" → mark geo-clause. Nếu rule không parse được clause median/\n // altitude bị lỗi → geo-clause không phủ → escalate (fail-safe), KHÔNG\n // silent-incomplete (triangle-only bỏ điểm chân). ('bisector' đã có ở trên.)\n // Cả hai đều là danh từ hình học riêng, không substring va chạm có hại.\n 'median',\n 'altitude',\n // connect EN (issue #46 nhóm B). VN \"đoạn\" LÀ keyword → \"segment\" parity để\n // \"Draw segment XY\" standalone là geo-clause: rule connect EN claim → render;\n // clause malformed (\"segment\" không cặp HOA) → geo unclaimed → escalate\n // (fail-safe). ≥7 ký tự, phân biệt, không substring va chạm. \"line\"/\"ray\"/\"draw\"/\n // \"join\"/\"connect\" CỐ Ý KHÔNG thêm (đối VN \"đường thẳng\"/\"tia\"/… cũng không phải\n // keyword → parity: render in-context, escalate standalone).\n 'segment',\n];\n\nexport function countGeometryKeywords(text: string): number {\n const lower = text.toLowerCase();\n let count = 0;\n for (const kw of GEOMETRY_KEYWORDS) {\n let from = 0;\n while (true) {\n const i = lower.indexOf(kw, from);\n if (i < 0) break;\n count++;\n from = i + kw.length;\n }\n }\n return count;\n}\n","// src/stamps/geometry-2d/ai/deterministic/coverage.ts\n//\n// Clause segmentation + coverage cho deterministic-first gate.\n// Track A chỉ \"tự tin\" dùng kết quả khi MỌI clause mang nội dung hình học\n// đều được ít nhất 1 rule match claim. Còn sót → escalate AI.\nimport { countGeometryKeywords } from './vocabulary';\n\nexport interface Clause {\n id: number;\n text: string;\n /** clause chứa ≥1 từ khoá hình học → tính vào mẫu số coverage. */\n hasGeometry: boolean;\n}\n\nexport interface CoverageReport {\n complete: boolean;\n coveredClauseIds: number[];\n uncovered: Clause[];\n ratio: number;\n}\n\ninterface MatchLike {\n clauseIds: number[];\n}\n\n/**\n * Tách đề thành clause theo dấu câu (. ; xuống dòng) và dấu phẩy đứng trước\n * từ dẫn (\"Gọi\", \"Vẽ\", \"Kẻ\"…). Clause thuần văn xuôi (không từ khoá hình học)\n * vẫn được giữ nhưng `hasGeometry=false` để không ép escalate.\n */\nexport function segmentClauses(problem: string): Clause[] {\n // Comma-split lookahead: tách clause ở dấu phẩy đứng TRƯỚC từ dẫn. VN dùng\n // (Gọi|Vẽ|Kẻ|Cho|Lấy|Dựng|trên|với). EN ADDITIVE (issue #46 group B): các từ\n // dẫn sub-clause viết HOA đầu câu (Let|Draw|Mark|Take|Construct|Join) — \"Triangle\n // ABC, let M be the midpoint of BC\" tách thành 2 clause. Thuần additive: không\n // đổi segmentation VN (alternation rời nhau, không trùng từ).\n return problem\n .split(\n /[.;\\n]+|,\\s*(?=(?:Gọi|Vẽ|Kẻ|Cho|Lấy|Dựng|trên|với|Let|Draw|Mark|Take|Construct|Join)\\b)/u,\n )\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n .map((text, id) => ({ id, text, hasGeometry: countGeometryKeywords(text) > 0 }));\n}\n\nexport function computeCoverage(\n clauses: readonly Clause[],\n matches: readonly MatchLike[],\n): CoverageReport {\n const claimed = new Set<number>();\n for (const m of matches) for (const id of m.clauseIds) claimed.add(id);\n\n const geoClauses = clauses.filter((c) => c.hasGeometry);\n const uncovered = geoClauses.filter((c) => !claimed.has(c.id));\n const coveredClauseIds = geoClauses\n .filter((c) => claimed.has(c.id))\n .map((c) => c.id);\n\n return {\n complete: uncovered.length === 0 && geoClauses.length > 0,\n coveredClauseIds,\n uncovered,\n ratio: geoClauses.length === 0 ? 0 : coveredClauseIds.length / geoClauses.length,\n };\n}\n","// src/stamps/geometry-2d/ai/rules/_shared.ts\n//\n// Helper dùng chung cho rule module: intent factory (cast IntentT tập trung 1 chỗ)\n// + trích tên điểm từ lời dẫn tiếng Việt. Rule module KHÔNG tự cast `as any`.\nimport type { IntentT } from '../intent';\n\n// --- Intent factories (cast tập trung) ---------------------------------------\n// variant/shape/kind là string runtime; zod validate lại ở builder/transpile,\n// nên cast qua unknown an toàn trong phạm vi NLU.\n\nexport function drawShape(\n shape: string,\n labels: string[],\n variant = 'any',\n explicitCoords?: Record<string, readonly [number, number]>,\n): IntentT {\n return {\n op: 'draw-shape',\n shape,\n labels,\n variant,\n ...(explicitCoords ? { explicitCoords } : {}),\n } as unknown as IntentT;\n}\n\nexport function addPoint(name: string, constraint: Record<string, unknown>): IntentT {\n return { op: 'add-point', name, constraint } as unknown as IntentT;\n}\n\nexport function connect(from: string, to: string, style = 'segment'): IntentT {\n return { op: 'connect', from, to, style } as unknown as IntentT;\n}\n\nexport function drawCircle(\n name: string,\n spec: string,\n extra: Record<string, unknown> = {},\n): IntentT {\n return { op: 'draw-circle', name, spec, ...extra } as unknown as IntentT;\n}\n\nexport function drawLine(\n name: string,\n kind: string,\n extra: Record<string, unknown> = {},\n): IntentT {\n return { op: 'draw-line', name, kind, ...extra } as unknown as IntentT;\n}\n\n/** Đa giác con (triangle|quadrilateral) nối các ĐIỂM ĐÃ CÓ — không tạo coord mới. */\nexport function markShape(shape: string, labels: string[]): IntentT {\n return { op: 'mark-shape', shape, labels } as unknown as IntentT;\n}\n\n// --- Point-name extraction ----------------------------------------------------\n\nconst INTRO_NAME =\n /(?:Gọi|Lấy|Dựng|Vẽ|Kẻ|Đặt|Xác định)\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)\\b/u;\nconst NAME_LA = /\\b([A-Z])(?:['′]?)\\s+là\\b/u;\n\n/**\n * Trích tên điểm được giới thiệu trong clause:\n * \"Gọi M là trung điểm BC\" → \"M\"\n * \"Lấy điểm D trên cạnh AB\" → \"D\"\n * \"H là trực tâm\" → \"H\"\n * Trả undefined nếu không tìm thấy (caller tự quyết fallback / bỏ qua).\n */\nexport function extractPointName(clauseText: string): string | undefined {\n const intro = INTRO_NAME.exec(clauseText);\n if (intro) return intro[1];\n const la = NAME_LA.exec(clauseText);\n if (la) return la[1];\n return undefined;\n}\n\n/** Tách \"BC\" → [\"B\",\"C\"]; \"AB\" → [\"A\",\"B\"]. Trả [] nếu không phải cặp đỉnh. */\nexport function pairFromToken(token: string): string[] {\n const m = /^([A-Z])([A-Z])$/u.exec(token.trim());\n return m ? [m[1], m[2]] : [];\n}\n\n// --- Side / segment prefix ----------------------------------------------------\n// Tiền tố \"cạnh\"/\"đoạn\" tuỳ chọn TRƯỚC cặp đỉnh, cho phép bổ ngữ \"huyền\"/\"thẳng\"\n// chen giữa: \"cạnh BC\", \"cạnh huyền BC\", \"đoạn AC\", \"đoạn thẳng AC\". Fail-safe:\n// \"cạnh thẳng\"/\"đoạn huyền\" (sai cặp) KHÔNG khớp vì bổ ngữ bị buộc đúng loại.\n// Là FRAGMENT regex (string, không cờ) để nhúng vào pattern lớn hơn — bổ ngữ là\n// optional nên prefix vẫn khớp dạng trần \"cạnh BC\".\nexport const SIDE_PREFIX = '(?:cạnh(?:\\\\s+huyền)?\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?';\n\n/** \"đường\" và typo \"đương\" (thiếu dấu huyền). */\nexport const DUONG_KW = '[Đđ]ư[ờơ]ng';\n\n/** \"đường tròn\" và typo \"đương tròn\". */\nexport const CIRCLE_KW = DUONG_KW + '\\\\s*tròn';\n\n/**\n * Kiểm tra tên có phải là nhãn điểm (tâm) hay không.\n * Thỏa mãn: 1 chữ HOA + tuỳ chọn dấu phẩy/số (vd: O, O', O1).\n */\nexport function isCenterName(name: string): boolean {\n return /^[A-Z]['′]?\\d*$/u.test(name);\n}\n","// src/stamps/geometry-2d/ai/rules/triangle.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { drawShape, addPoint, drawCircle, markShape } from './_shared';\n\n// MULTI-MATCH: 1 clause có thể chứa NHIỀU tam giác (\"tam giác ABC và tam giác\n// ABD vuông tại A\", \"tam giác đều DEF nội tiếp tam giác ABC\"). Bắt MỌI tam giác\n// (cờ 'g'), variant bind từ TEXT WINDOW giữa tam giác này và tam giác KẾ — KHÔNG\n// vơ chữ \"đều\"/\"vuông tại X\" của tam giác khác.\n//\n// leadMod = từ bổ nghĩa ĐỨNG TRƯỚC bộ 3 đỉnh (\"tam giác đều DEF\", \"tam giác\n// vuông ABC\", \"tam giác cân ABC\"). leadMod \"đều\" → equilateral ngay; \"vuông\"/\n// \"cân\" leadMod (không có \"tại X\") không đủ thông tin chọn đỉnh → để window xử lý.\nconst TRI_G = /tam giác\\s+(?:(đều|vuông|cân)\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\nconst RIGHT_AT = /vuông\\s+tại\\s+([A-Z])(?![A-Za-z])/u;\nconst ISO_AT = /cân\\s+tại\\s+([A-Z])(?![A-Za-z])/u;\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Dùng lookaround \\p{L} để chặn match giữa từ dài hơn.\nconst EQUILATERAL = /(?<!\\p{L})đều(?!\\p{L})/u;\n\n// === EN patterns (issue #46 group B) ========================================\n// MULTI-MATCH như VN: cờ 'g'. leadMod ĐỨNG TRƯỚC \"triangle\" (mirror \"tam giác đều\n// DEF\"): \"equilateral triangle ABC\", \"right triangle ABC\", \"isosceles triangle\n// ABC\". First-letter case flexibility ([Tt], [Ee]…) — KHÔNG cờ 'i' (sẽ phá [A-Z]\n// nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]).\nconst TRI_EN_G =\n /(?:([Ee]quilateral|[Rr]ight-angled|[Rr]ight|[Ii]sosceles)\\s+)?[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n// Window modifiers (đứng SAU nhãn): \"right angle at A\" / \"right-angled at A\".\nconst RIGHT_AT_EN = /[Rr]ight(?:\\s+angle|-angled)\\s+at\\s+([A-Z])(?![A-Za-z])/u;\n// \"with apex A\" / \"apex at A\" / \"apex A\". CHỈ nhận khi ngữ cảnh cân (isosceles).\nconst APEX_AT_EN = /apex\\s+(?:at\\s+)?([A-Z])(?![A-Za-z])/u;\n// \"... is equilateral\" / \"equilateral triangle …\" trong window riêng tam giác này.\nconst EQUILATERAL_EN = /(?<![A-Za-z])[Ee]quilateral(?![A-Za-z])/u;\nconst ISOSCELES_EN = /(?<![A-Za-z])[Ii]sosceles(?![A-Za-z])/u;\n\n/** Chuẩn hoá leadMod EN về token canonical: 'equilateral'|'right'|'isosceles'. */\nfunction normLeadEn(lead: string | undefined): string | undefined {\n if (!lead) return undefined;\n const l = lead.toLowerCase();\n if (l === 'equilateral') return 'equilateral';\n if (l === 'right' || l === 'right-angled') return 'right';\n if (l === 'isosceles') return 'isosceles';\n return undefined;\n}\n\ninterface TriHit {\n labels: string[];\n /** leadMod đứng ngay trước bộ 3 đỉnh, hoặc undefined. */\n lead?: string;\n /** ngôn ngữ của hit — quyết định dùng window VN hay EN khi suy variant. */\n lang: 'vi' | 'en';\n /** offset bắt đầu match (để sắp xếp + tính window theo thứ tự text). */\n start: number;\n /** vị trí ngay sau match (đầu window). */\n end: number;\n}\n\n/**\n * Suy variant cho 1 tam giác từ: leadMod (\"tam giác đều DEF\") + WINDOW text\n * (đoạn từ ngay sau bộ 3 đỉnh tới đầu tam giác kế / hết clause). \"vuông tại X\" /\n * \"cân tại X\" CHỈ áp nếu X ∈ labels của tam giác NÀY (tránh bind nhầm sang tam\n * giác khác cùng clause). Quy ước enum (xem TriangleVariantZ): cân tại A ⇒\n * isoceles-BC (đáy CYCLIC: apex A→BC, B→CA, C→AB); vuông tại A ⇒ right-at-A.\n */\n// Variant enum là POSITIONAL theo INDEX đỉnh đặc biệt trong labels (builder\n// triangleCanonical: isoceles-BC ⇒ apex = vertex[0], right-at-A ⇒ vertex[0]\n// vuông). KHÔNG dùng chữ-cái-nhãn: tam giác [A,C,D] \"cân tại A\" (apex idx 0) →\n// isoceles-BC (positional), KHÔNG phải \"isoceles-CD\". Với nhãn ABC chuẩn,\n// positional trùng label nên tương thích ngược.\nconst RIGHT_BY_IDX = ['right-at-A', 'right-at-B', 'right-at-C'];\nconst ISO_BY_IDX = ['isoceles-BC', 'isoceles-CA', 'isoceles-AB'];\n\n// === Thales: tam giác VUÔNG nội tiếp đường tròn → đường kính + glider ===========\n// Vuông tại A nội tiếp (O) ⟺ BC là ĐƯỜNG KÍNH (góc nội tiếp chắn nửa đường tròn).\n// Dựng RÀNG BUỘC (kéo vẫn vuông): 2 đầu mút đường kính free + tâm O = trung điểm +\n// đường tròn centerThrough (bán kính theo đầu mút) + apex là glider onCircle.\n// → góc vuông tại apex luôn đúng; AB<AC chọn bằng vị trí đầu mút cạnh ngắn (bên trái).\n//\n// CHỈ kích hoạt khi tam giác VUÔNG + có ngữ cảnh \"nội tiếp đường tròn/(O)\" SAU nhãn\n// (window). \"đường tròn nội tiếp tam giác\" (incircle) đứng TRƯỚC nhãn → KHÔNG ở\n// trong window → không kích hoạt (đúng: incircle không liên quan góc vuông).\nconst THALES_R = 4;\nconst THALES_THETA = 2.3; // ~131° (góc phần tư II) → apex gần đầu mút TRÁI = cạnh ngắn\n\n// \"nội tiếp (trong)? (đường tròn (O)/tâm O)? | (O)\" — circumcircle tam giác inscribed.\nconst TRI_INSCRIBED =\n /nội\\s*tiếp\\s+(?:trong\\s+)?(?:đường\\s*tròn\\s*(?:\\(\\s*([A-Z])\\s*\\)|tâm\\s+([A-Z]))?|\\(\\s*([A-Z])\\s*\\))/u;\n// Bất đẳng thức cạnh \"AB < AC\" / \"AC > AB\" (2 cạnh chia sẻ đỉnh vuông).\nconst INEQ = /([A-Z])([A-Z])\\s*([<>])\\s*([A-Z])([A-Z])/u;\n\n/** Tên đường tròn ngoại tiếp từ window; undefined nếu không có \"nội tiếp …\". */\nfunction inscribedCircleName(window: string): string | undefined {\n const m = TRI_INSCRIBED.exec(window);\n if (!m) return undefined;\n return m[1] ?? m[2] ?? m[3] ?? ''; // '' → caller default 'O'\n}\n\n/** Đầu mút (≠ apex) của cạnh NGẮN hơn theo \"AB < AC\"; default others[0]. */\nfunction shorterLegEnd(window: string, apex: string, others: string[]): string {\n const m = INEQ.exec(window);\n if (m) {\n const op = m[3];\n const o1 = m[1] === apex ? m[2] : m[2] === apex ? m[1] : undefined; // cạnh 1 (≠apex)\n const o2 = m[4] === apex ? m[5] : m[5] === apex ? m[4] : undefined; // cạnh 2 (≠apex)\n if (o1 && o2 && others.includes(o1) && others.includes(o2)) {\n return op === '<' ? o1 : o2; // '<' → cạnh 1 ngắn; '>' → cạnh 2 ngắn\n }\n }\n return others[0];\n}\n\n/**\n * Dựng Thales cho tam giác vuông (apex tại index `apexIdx`) nội tiếp đường tròn\n * `circleNameRaw`. Trả null nếu tên tâm đụng nhãn đỉnh (fail-safe → drawShape).\n */\nfunction thalesIntents(\n labels: string[],\n apexIdx: number,\n circleNameRaw: string,\n window: string,\n): IntentT[] | null {\n const apex = labels[apexIdx];\n const others = labels.filter((_, i) => i !== apexIdx); // 2 đầu mút đường kính\n const cn = circleNameRaw || 'O';\n if (labels.includes(cn)) return null; // tên tâm trùng đỉnh → bỏ Thales (an toàn)\n const shortEnd = shorterLegEnd(window, apex, others);\n const longEnd = others[0] === shortEnd ? others[1] : others[0];\n return [\n addPoint(shortEnd, { kind: 'free', at: [-THALES_R, 0] }), // cạnh ngắn: đầu mút TRÁI\n addPoint(longEnd, { kind: 'free', at: [THALES_R, 0] }),\n addPoint(cn, { kind: 'midpoint', of: shortEnd + longEnd }), // tâm O = trung điểm đường kính\n drawCircle(cn, 'centerThrough', { center: cn, through: shortEnd }),\n addPoint(apex, { kind: 'onCircle', circle: cn, theta: THALES_THETA }), // apex glider (gần TRÁI)\n markShape('triangle', labels),\n ];\n}\n\nfunction variantFor(hit: TriHit, window: string): string {\n return hit.lang === 'en' ? variantForEn(hit, window) : variantForVi(hit, window);\n}\n\nfunction variantForVi(hit: TriHit, window: string): string {\n const { labels, lead } = hit;\n // \"tam giác đều DEF\" hoặc chữ \"đều\" trong window riêng của tam giác này.\n if (lead === 'đều' || EQUILATERAL.test(window)) return 'equilateral';\n\n const ra = RIGHT_AT.exec(window);\n if (ra) {\n const i = labels.indexOf(ra[1]);\n if (i >= 0) return RIGHT_BY_IDX[i];\n }\n\n const iso = ISO_AT.exec(window);\n if (iso) {\n const i = labels.indexOf(iso[1]);\n if (i >= 0) return ISO_BY_IDX[i];\n }\n\n return 'any';\n}\n\n/**\n * EN variant — mirror VN POSITIONAL semantics. leadMod canonical ('equilateral'/\n * 'right'/'isosceles') + WINDOW riêng tam giác này. \"right triangle ABC\" KHÔNG có\n * \"right angle at X\" → 'any' (đủ thông tin loại nhưng không biết đỉnh, fail-safe\n * như VN \"tam giác vuông ABC\"). \"isosceles\" không \"apex X\" → 'any'. apex/right-at\n * CHỈ áp nếu đỉnh ∈ labels (tránh bind nhầm / đỉnh ngoài tam giác).\n */\nfunction variantForEn(hit: TriHit, window: string): string {\n const { labels, lead } = hit;\n if (lead === 'equilateral' || EQUILATERAL_EN.test(window)) return 'equilateral';\n\n // \"right angle at A\" / \"right-angled at A\" → positional. CHỈ trong window\n // (không vơ modifier của tam giác kế).\n const ra = RIGHT_AT_EN.exec(window);\n if (ra) {\n const i = labels.indexOf(ra[1]);\n if (i >= 0) return RIGHT_BY_IDX[i];\n }\n\n // Apex CHỈ có nghĩa trong ngữ cảnh cân: leadMod 'isosceles' HOẶC từ \"isosceles\"\n // trong window. \"with apex A\" → isoceles theo INDEX của A trong labels.\n const isoCtx = lead === 'isosceles' || ISOSCELES_EN.test(window);\n if (isoCtx) {\n const ap = APEX_AT_EN.exec(window);\n if (ap) {\n const i = labels.indexOf(ap[1]);\n if (i >= 0) return ISO_BY_IDX[i];\n }\n }\n\n return 'any';\n}\n\n/**\n * \"tam giác ABC\" / \"triangle ABC\" → draw-shape triangle. NHIỀU tam giác / clause\n * → emit-all (mỗi tam giác 1 intent), variant bind theo cú pháp gần (leadMod +\n * window) để KHÔNG mis-render (vd không gán \"đều\"/\"equilateral\" của DEF cho ABC).\n *\n * EN ADDITIVE (issue #46 group B): quét THÊM TRI_EN_G. Hit VN+EN gom chung, sắp\n * theo vị trí TEXT; window mỗi hit = từ sau nhãn tới START của hit KẾ (modifier\n * tiền-vị của tam giác kế KHÔNG lọt vào window hit hiện tại). VN behavior giữ\n * nguyên: với chỉ-VN, start hit kế = vị trí \"tam giác\" kế ≡ logic indexOf cũ.\n */\nexport const triangleRule: LanguageRule = {\n id: 'triangle',\n priority: 100,\n languages: ['vi', 'en'],\n patterns: [TRI_G, TRI_EN_G],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const hits: TriHit[] = [];\n\n TRI_G.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(c.text)) !== null) {\n hits.push({\n lead: m[1],\n lang: 'vi',\n labels: [m[2], m[3], m[4]],\n start: m.index,\n end: m.index + m[0].length,\n });\n }\n\n TRI_EN_G.lastIndex = 0;\n while ((m = TRI_EN_G.exec(c.text)) !== null) {\n hits.push({\n lead: normLeadEn(m[1]),\n lang: 'en',\n labels: [m[2], m[3], m[4]],\n start: m.index,\n end: m.index + m[0].length,\n });\n }\n\n if (hits.length === 0) continue;\n\n // Sắp theo vị trí TEXT để window mỗi hit kết thúc ở START hit kế (gồm cả\n // modifier tiền-vị của hit kế) → không leak modifier giữa các tam giác.\n hits.sort((a, b) => a.start - b.start);\n\n const intents = hits.flatMap((hit, idx) => {\n const next = hits[idx + 1];\n const windowEnd = next ? next.start : c.text.length;\n const window = c.text.slice(hit.end, windowEnd);\n const variant = variantFor(hit, window);\n // Thales: tam giác VUÔNG + nội tiếp đường tròn (window) → dựng ràng buộc\n // (đường kính + apex glider) thay draw-shape free (free chỉ \"may mắn\" vuông,\n // kéo là vỡ + không thoả AB<AC). circle3 của circleTriangle bị idempotent\n // loại (cùng tên → centerThrough của triangle prio 100 thắng).\n const rightIdx = RIGHT_BY_IDX.indexOf(variant);\n if (rightIdx >= 0) {\n const circleName = inscribedCircleName(window);\n if (circleName !== undefined) {\n const thales = thalesIntents(hit.labels, rightIdx, circleName, window);\n if (thales) return thales;\n }\n }\n return [drawShape('triangle', hit.labels, variant)];\n });\n\n out.push({ ruleId: 'triangle', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/quad.ts\n//\n// Tứ giác / đa giác 4 đỉnh: hình vuông, chữ nhật, bình hành, thoi, thang\n// (cân/vuông/thường), tứ giác chung. Mỗi loại trích 4 ký tự HOA liền sau tên\n// hình → draw-shape với shape + variant tương ứng.\nimport type { LanguageRule, RuleContext, RuleMatch } from './_types';\nimport { drawShape, drawCircle, addPoint, markShape } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Dùng lookaround \\p{L} (cờ 'u') ở prefilter để chặn biên từ.\n// 4 đỉnh = ĐÚNG 4 ký tự HOA liền nhau (vd \"ABCD\") neo ngay sau tên hình; neo\n// biên cuối (?![A-Z]) để 5+ đỉnh (\"ABCDE\") KHÔNG match → escalate qua guard.\nconst QUAD = '([A-Z])([A-Z])([A-Z])([A-Z])(?![A-Z])';\n\n// Mỗi entry: regex tên hình (đã neo trước 4 đỉnh) → shape + variant.\n// CỜ 'g' để matchAll quét MỌI khai báo hình trong cùng một clause (vd \"hình\n// bình hành ABCD và hình chữ nhật EFGH\" → 2 shape, theo thứ tự TEXT).\n// Thứ tự QUAN TRỌNG: loại cụ thể (hình thang cân/vuông) phải đứng TRƯỚC loại\n// chung (hình thang), và mọi \"hình ...\" phải đứng trước \"tứ giác\" chung — vì\n// engine consume vùng text đã match nên loại cụ thể giành quyền trước.\ninterface QuadKind {\n name: RegExp;\n shape: string;\n variant: string;\n}\n\nconst KINDS: QuadKind[] = [\n // hình thang cân / vuông (modifier TRƯỚC đỉnh) — phải match trước thang chung\n {\n name: new RegExp('hình\\\\s+thang\\\\s+cân\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'isoceles',\n },\n {\n name: new RegExp('hình\\\\s+thang\\\\s+vuông\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'right',\n },\n // hình thang chung — sau đó dò modifier 'vuông'/'cân' đứng SAU đỉnh\n // (\"hình thang ABCD vuông tại A\" → right; \"...cân\" → isoceles).\n {\n name: new RegExp('hình\\\\s+thang\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'general',\n },\n {\n name: new RegExp('hình\\\\s+vuông\\\\s+' + QUAD, 'gu'),\n shape: 'square',\n variant: 'standard',\n },\n {\n name: new RegExp('hình\\\\s+chữ\\\\s+nhật\\\\s+' + QUAD, 'gu'),\n shape: 'rectangle',\n variant: 'wide',\n },\n {\n name: new RegExp('hình\\\\s+bình\\\\s+hành\\\\s+' + QUAD, 'gu'),\n shape: 'parallelogram',\n variant: 'standard',\n },\n {\n name: new RegExp('hình\\\\s+thoi\\\\s+' + QUAD, 'gu'),\n shape: 'rhombus',\n variant: 'standard',\n },\n {\n name: new RegExp('tứ\\\\s+giác(?:\\\\s+lồi)?\\\\s+' + QUAD, 'gu'),\n shape: 'quadrilateral',\n variant: 'any',\n },\n\n // === EN names (issue #46 group B) — same shape/variant mapping as VN ========\n // First-letter case flex ([Ss]quare…) — KHÔNG cờ 'i' (sẽ phá [A-Z] nhãn QUAD).\n // Modifier EN đứng TRƯỚC tên (\"isosceles trapezoid ABCD\") → entry riêng cho\n // isosceles/right trapezoid, đặt TRƯỚC trapezoid chung để giành quyền (overlaps).\n // KHÔNG có post-positional modifier EN trong slice này (chỉ pre-positional).\n {\n name: new RegExp('[Ii]sosceles\\\\s+(?:[Tt]rapezoid|[Tt]rapezium)\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'isoceles',\n },\n {\n name: new RegExp('[Rr]ight\\\\s+(?:[Tt]rapezoid|[Tt]rapezium)\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'right',\n },\n {\n name: new RegExp('(?:[Tt]rapezoid|[Tt]rapezium)\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'general',\n },\n {\n name: new RegExp('[Ss]quare\\\\s+' + QUAD, 'gu'),\n shape: 'square',\n variant: 'standard',\n },\n {\n name: new RegExp('[Rr]ectangle\\\\s+' + QUAD, 'gu'),\n shape: 'rectangle',\n variant: 'wide',\n },\n {\n name: new RegExp('[Pp]arallelogram\\\\s+' + QUAD, 'gu'),\n shape: 'parallelogram',\n variant: 'standard',\n },\n {\n name: new RegExp('[Rr]hombus\\\\s+' + QUAD, 'gu'),\n shape: 'rhombus',\n variant: 'standard',\n },\n {\n name: new RegExp('[Qq]uadrilateral\\\\s+' + QUAD, 'gu'),\n shape: 'quadrilateral',\n variant: 'any',\n },\n];\n\n// Prefilter toàn đề: bất kỳ tên hình 4 đỉnh nào (VN + EN).\nconst PREFILTER =\n /hình\\s+(?:vuông|chữ\\s+nhật|bình\\s+hành|thoi|thang)|tứ\\s+giác|[Ss]quare|[Rr]ectangle|[Pp]arallelogram|[Rr]hombus|[Tt]rapezoid|[Tt]rapezium|[Qq]uadrilateral/u;\n\n// \"hình thang ABCD vuông tại A\" / \"...cân ...\" — modifier đứng SAU đỉnh, ngay\n// sau cụm 4 đỉnh (cho phép xen khoảng trắng). Cờ 'u' bắt buộc cho ký tự Việt.\nconst RIGHT_AFTER = /vuông(?!\\p{L})/u;\nconst ISO_AFTER = /(?<!\\p{L})cân(?!\\p{L})/u;\n// Biên cắt tail: KHÔNG cho modifier \"vuông\"/\"cân\" của hình SAU (\"…và hình vuông\n// EFGH\") bị gán nhầm cho hình thang đứng trước → dừng tail ở khai báo hình kế.\nconst NEXT_SHAPE = /hình\\s|tứ\\s+giác/u;\n\ninterface Hit {\n index: number;\n shape: string;\n variant: string;\n labels: string[];\n /** offset ngay sau cụm 4 đỉnh, để dò modifier hậu vị cho hình thang chung. */\n afterEnd: number;\n}\n\n/**\n * Quét MỌI khai báo hình trong một clause. Mỗi vị trí ký tự chỉ thuộc một kind\n * (kind cụ thể giành trước nhờ thứ tự KINDS). Trả về danh sách hit đã sắp theo\n * vị trí TEXT để emit đúng thứ tự xuất hiện trong đề.\n */\nfunction scanClause(text: string): Hit[] {\n const claimed: Hit[] = [];\n const taken: Array<[number, number]> = []; // vùng [start,end) đã thuộc kind trước\n\n const overlaps = (start: number, end: number) =>\n taken.some(([s, e]) => start < e && end > s);\n\n for (const k of KINDS) {\n k.name.lastIndex = 0;\n for (const m of text.matchAll(k.name)) {\n const start = m.index ?? 0;\n const end = start + m[0].length;\n if (overlaps(start, end)) continue; // đã bị kind cụ thể hơn chiếm\n taken.push([start, end]);\n\n let variant = k.variant;\n // Hình thang chung: dò modifier hậu vị ngay sau 4 đỉnh (\"ABCD vuông tại A\").\n // Cắt tail tại khai báo hình kế tiếp để không nuốt modifier của hình sau.\n if (k.shape === 'trapezoid' && k.variant === 'general') {\n let tail = text.slice(end, end + 24);\n const next = NEXT_SHAPE.exec(tail);\n if (next) tail = tail.slice(0, next.index);\n if (RIGHT_AFTER.test(tail)) variant = 'right';\n else if (ISO_AFTER.test(tail)) variant = 'isoceles';\n }\n claimed.push({\n index: start,\n shape: k.shape,\n variant,\n labels: [m[1], m[2], m[3], m[4]],\n afterEnd: end,\n });\n }\n }\n\n claimed.sort((a, b) => a.index - b.index);\n return claimed;\n}\n\n// --- Tứ giác nội tiếp đường tròn (cyclic quadrilateral) — issue #46 nhóm C/B --\n//\n// \"Cho tứ giác ABCD nội tiếp đường tròn (O)\" hiện chỉ vẽ tứ giác, BỎ đường tròn\n// (render coverage-complete nhưng thiếu hình). Bổ sung đường tròn ngoại tiếp đi\n// qua đúng 4 đỉnh — đặt 4 đỉnh ĐỒNG VIÊN để circle3 thực sự đi qua cả 4.\n//\n// EN (nhóm B Tier 2, fix silent-incomplete): detectCyclic nay nhận thêm các dạng\n// tiếng Anh — Pattern A \"(is/are) inscribed in (a/the) circle (O)\", Pattern B\n// \"circle (O) circumscribes/(is) circumscribed (about/around) ...\". Trước đây đề\n// EN render quad-ONLY (rớt circle âm thầm); nay parity VN (quad concyclic +\n// through3). TRIANGLE_DECL cũng nhận \"Triangle ABC\" để fail-safe ownedByOthers\n// chặn silent-wrong khi tứ giác EN chia đỉnh với tam giác EN.\n//\n// KIẾN TRÚC single-emitter: quadRule LÀ emitter DUY NHẤT của hình tứ giác. Khi\n// phát hiện ngữ cảnh nội tiếp, CHÍNH rule này emit (circle + 4 glider + polygon)\n// — KHÔNG dùng draw-shape (vốn tạo đỉnh FREE) cho nhánh nội tiếp.\n//\n// FIX 2026-06-09 (bug \"đỉnh D không trên đường tròn, kéo đường tròn D không theo\"):\n// trước đây nhánh nội tiếp emit draw-shape (4 đỉnh FREE ở toạ độ đồng viên TĨNH) +\n// circle3 qua 3 đỉnh → đỉnh thứ 4 chỉ TÌNH CỜ nằm trên circle, KHÔNG ràng buộc →\n// kéo 1 trong 3 đỉnh kia (định nghĩa lại circle3) thì đỉnh 4 ở lại, rời đường tròn.\n// NAY: đường tròn centerRadius (tâm O hiện) + 4 đỉnh là glider `onCircle` (theta cố\n// định) → TẤT CẢ ràng buộc trên đường tròn; kéo tâm O cả 4 di chuyển theo, luôn\n// đồng viên. polygon nối 4 đỉnh qua mark-shape (không tạo coord mới).\n//\n// 4 đỉnh trên đường tròn bán kính 5 (đồng viên), góc theta cố định cho layout lồi\n// A→B→C→D (chiều kim đồng hồ), bảo toàn bố cục cũ.\nconst CYCLIC_QUAD_COORDS: readonly [number, number][] = [\n [-3, 4],\n [4, 3],\n [3, -4],\n [-4, -3],\n];\n// Bán kính + góc theta dẫn xuất TỪ toạ độ trên (đồng bộ layout): glider đặt tại\n// (cos θ, sin θ)·r quanh tâm → giữ đúng vị trí lồi như bản free cũ.\nconst CYCLIC_RADIUS = Math.hypot(CYCLIC_QUAD_COORDS[0][0], CYCLIC_QUAD_COORDS[0][1]);\nconst CYCLIC_QUAD_THETAS: readonly number[] = CYCLIC_QUAD_COORDS.map(([x, y]) =>\n Math.atan2(y, x),\n);\n\n// Tên tâm tuỳ chọn: \"(O)\" hoặc \"tâm O\" (mượn idiom của circleTriangle).\nconst CENTER = '(?:\\\\(\\\\s*([A-Z])\\\\s*\\\\)|tâm\\\\s+([A-Z]))?';\n\n// Pattern A — tứ giác nội tiếp đường tròn: \"ABCD nội tiếp (trong) đường tròn\n// (O)/tâm O\". Neo ^ vào phần text NGAY SAU 4 đỉnh (hit.afterEnd). Center group 1|2.\nconst QUAD_INSCRIBED_IN_CIRCLE = new RegExp(\n '^[\\\\s,]*(?:nội\\\\s*tiếp\\\\s+(?:trong\\\\s+)?(?:một\\\\s+)?đường\\\\s*tròn|(?:is\\\\s+|are\\\\s+)?inscribed\\\\s+in\\\\s+(?:a\\\\s+|the\\\\s+)?circle)\\\\s*' +\n CENTER,\n 'iu',\n);\n\n// Pattern B — đường tròn ngoại tiếp tứ giác: \"đường tròn (O)/tâm O ngoại tiếp\"\n// đứng NGAY TRƯỚC \"tứ giác ABCD\". Neo $ vào phần text TRƯỚC hit.index. Center 1|2.\nconst CIRCLE_CIRCUMSCRIBES_QUAD = new RegExp(\n '(?:đường\\\\s*tròn|circle)\\\\s*' +\n CENTER +\n '\\\\s*(?:ngoại\\\\s*tiếp|(?:is\\\\s+|are\\\\s+)?circumscrib(?:es|ed)(?:\\\\s+(?:about|around))?)\\\\s+$',\n 'iu',\n);\n\n// Khai báo tam giác bất kỳ trong đề — 3 đỉnh HOA của nó \"thuộc\" tam giác (không\n// được dời sang toạ độ đồng viên của tứ giác). Cờ 'g' để quét mọi khai báo.\nconst TRIANGLE_DECL = /(?:tam\\s*giác|[Tt]riangle)\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n/**\n * Tập ký tự đỉnh \"thuộc về hình khác\" trong TOÀN đề: mọi đỉnh tam giác + đỉnh\n * của mọi tứ giác hit KHÁC (chuỗi nhãn khác hit hiện tại). Nếu 4 đỉnh của tứ\n * giác này giao tập đó → KHÔNG áp dụng đồng viên (đặt chúng theo CYCLIC_QUAD\n * sẽ phá toạ độ đã có của hình kia → silent-wrong).\n */\nfunction ownedByOthers(ctx: RuleContext, selfLabels: string[]): Set<string> {\n const owned = new Set<string>();\n TRIANGLE_DECL.lastIndex = 0;\n for (const m of ctx.problem.matchAll(TRIANGLE_DECL)) {\n owned.add(m[1]);\n owned.add(m[2]);\n owned.add(m[3]);\n }\n const selfKey = selfLabels.join('');\n for (const c of ctx.clauses) {\n for (const h of scanClause(c.text)) {\n if (h.labels.join('') === selfKey) continue; // chính tứ giác này\n for (const lbl of h.labels) owned.add(lbl);\n }\n }\n return owned;\n}\n\n/**\n * Phát hiện ngữ cảnh nội tiếp cho 1 hit tứ giác chung trong clause `text`.\n * Trả tên tâm (hoặc '') nếu khớp Pattern A/B; undefined nếu không nội tiếp.\n */\nfunction detectCyclic(text: string, hit: Hit): string | undefined {\n // Pattern A: phần text NGAY SAU 4 đỉnh.\n const a = QUAD_INSCRIBED_IN_CIRCLE.exec(text.slice(hit.afterEnd));\n if (a) return a[1] ?? a[2] ?? '';\n // Pattern B: phần text TRƯỚC \"tứ giác\" (hit.index = đầu \"tứ giác\").\n const b = CIRCLE_CIRCUMSCRIBES_QUAD.exec(text.slice(0, hit.index));\n if (b) return b[1] ?? b[2] ?? '';\n return undefined;\n}\n\n/**\n * Tứ giác / đa giác 4 đỉnh → draw-shape. Duyệt từng clause, quét EMIT-ALL mọi\n * khai báo hình (theo thứ tự text). KHÔNG trích được ĐÚNG 4 đỉnh HOA liền (vd\n * \"ABCDE\" 5 đỉnh) → bỏ qua khai báo đó (escalate AI qua guard).\n *\n * Tứ giác CHUNG (shape 'quadrilateral') có ngữ cảnh nội tiếp đường tròn → emit\n * THÊM draw-circle (through3) + đặt 4 đỉnh đồng viên qua explicitCoords. Hình\n * có tên (vuông/chữ nhật/...) NGOÀI phạm vi increment này (giữ hành vi cũ).\n *\n * GIỚI HẠN ĐÃ BIẾT (defer, không sửa): nếu CÙNG nhãn tứ giác được khai báo ở\n * HAI clause (vd \"Cho tứ giác ABCD. Đường tròn ngoại tiếp tứ giác ABCD\") — một\n * plain + một cyclic — cả hai draw-shape sống sót qua JSON dedup (explicitCoords\n * khác nhau) → polygon trùng \"ABCD2\" chồng lên nhau. Hiếm gặp + lành tính\n * (polygon trùng khít, không sai hình học). Test/probe để 1-clause để né.\n */\nexport const quadRule: LanguageRule = {\n id: 'quad',\n priority: 100,\n languages: ['vi', 'en'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n for (const hit of scanClause(c.text)) {\n let intents = [drawShape(hit.shape, hit.labels, hit.variant)];\n // Chỉ tứ giác CHUNG: thử phát hiện đường tròn ngoại tiếp.\n if (hit.shape === 'quadrilateral') {\n const center = detectCyclic(c.text, hit);\n if (center !== undefined) {\n // Fail-safe: đỉnh dùng chung với hình khác → giữ quad-only.\n const owned = ownedByOthers(ctx, hit.labels);\n const shared = hit.labels.some((lbl) => owned.has(lbl));\n if (!shared) {\n const centerName = center || 'O';\n // Đường tròn centerRadius (tâm `centerName`) — resolveCircleNames sẽ\n // inject point tâm + rename circle khi name trùng center (\"(O)\"=tâm O).\n // 4 đỉnh = glider onCircle (theta cố định, layout lồi) → CONSTRAINED.\n // polygon nối 4 đỉnh qua mark-shape (đỉnh đã có, không tạo coord mới).\n // Thứ tự: circle TRƯỚC (glider ref nó), rồi 4 glider, rồi polygon.\n intents = [\n drawCircle(centerName, 'centerRadius', {\n center: centerName,\n radius: CYCLIC_RADIUS,\n }),\n ...hit.labels.map((lbl, i) =>\n addPoint(lbl, { kind: 'onCircle', circle: centerName, theta: CYCLIC_QUAD_THETAS[i] }),\n ),\n markShape(hit.shape, hit.labels),\n ];\n }\n }\n }\n out.push({\n ruleId: 'quad',\n clauseIds: [c.id],\n intents,\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/connect.ts\n//\n// Construct 'connect': vẽ đoạn / đường thẳng / tia giữa 2 đỉnh có tên.\n// BẢO THỦ (priority thấp 40): chỉ claim clause khi có TỪ KHOÁ vẽ rõ ràng\n// (đoạn | cạnh | nối | kẻ | đường thẳng | tia) đi kèm cặp 2 ký tự HOA.\n// KHÔNG khớp \"tam giác ABC\" (3 ký tự liền) hay tên đường 1 ký tự (\"đường d\").\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { connect } from './_shared';\nimport type { IntentT } from '../intent';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Dùng lookaround \\p{L}; cờ 'u' bắt buộc cho mọi regex Việt.\n// Cặp đỉnh = 2 ký tự HOA liền; (?![A-Z]) chặn \"ABC\" (tam giác) khỏi bị bắt.\n\n// LƯU Ý case: KHÔNG dùng cờ 'i' (nó khiến [A-Z] khớp chữ thường → \"đoạn THẳng\"\n// bắt \"th\" làm cặp T,H rác, vỡ pipeline). Nhưng vẫn cần khớp keyword HOA đầu câu\n// (\"Kẻ\", \"Nối\", \"Đoạn\") → case-insensitive CHỈ ở ký tự đầu keyword bằng [Xx].\n// Vertices LUÔN strict [A-Z].\n// \"đường thẳng AB\" → line. \"đường thẳng\" phải đứng trước cặp.\nconst LINE_KW = /[Đđ]ường\\s*thẳng\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"tia AB\" → ray. Không bắt \"tia phân giác\", \"tia đối\" (theo sau là chữ thường).\nconst RAY_KW = /(?<!\\p{L})[Tt]ia\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"tia đối của tia XY\": cụm tia ĐỐI — match \"tia XY\" bên trong KHÔNG được emit ray\n// naive X→Y vì điểm mới nằm trên tia NGƯỢC hướng (gốc X, đi xa Y). Vẽ ray X→Y\n// sẽ minh hoạ SAI hướng (tia gốc thay vì tia đối). pointAtDistance đã dựng điểm\n// mới đúng trên tia đối; connect suppress để tránh ray double/sai hướng.\n// Kiểm tra text NGAY TRƯỚC vị trí match \"tia\": kết thúc bằng \"đối của \" (≥0 space).\nconst TIA_DOI_BEFORE = /tia\\s*đối\\s+của\\s+$/u;\n// \"nối A với/và B\" → segment. Tên 1 ký tự, không phải cặp.\nconst NOI_KW = /(?<!\\p{L})[Nn]ối\\s+([A-Z])\\s+(?:với|và)\\s+([A-Z])(?![A-Za-z])/gu;\n// \"đoạn (thẳng) AB\" | \"cạnh AB\" | \"kẻ AB\" → segment.\nconst SEG_KW =\n /(?<!\\p{L})(?:[Đđ]oạn(?:\\s*thẳng)?|[Cc]ạnh|[Kk]ẻ)\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n\n// ============ EN connect forms (issue #46 nhóm B) ============================\n// connect.ts vốn VN-only. Mirror các form VN sang EN, GIỮ NGUYÊN parity ở gate\n// vocab: VN \"đoạn\" LÀ keyword → EN \"segment\" cũng vào vocab (standalone render).\n// VN \"đường thẳng\"/\"tia\"/\"nối\"/\"kẻ\" KHÔNG phải keyword → EN \"line\"/\"ray\"/\"connect\"/\n// \"join\"/\"draw\" cũng KHÔNG vào vocab → chỉ render IN-CONTEXT (vd có tam giác), đề\n// standalone → escalate (geoClauses=0). Đối xứng VN/EN tuyệt đối + tôn trọng\n// do-not-add list (\"line\" đã bị cấm trong vocabulary.ts).\n//\n// runDeterministicIntents dedup intent theo JSON.stringify CROSS-RULE → \"Draw AH\n// perpendicular to BC\" khớp CẢ perpFoot (emit connect(A,H,'segment')) lẫn DRAW_PAIR_EN\n// (cũng connect(A,H,'segment')) → IDENTICAL → deduped, vô hại.\n\n// \"segment XY\" → segment (đối VN \"đoạn\"). Group 1,2 = cặp HOA.\nconst SEG_NOUN_EN = /(?<![A-Za-z])[Ss]egment\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"line XY\" → line (đối VN \"đường thẳng\").\nconst LINE_NOUN_EN = /(?<![A-Za-z])[Ll]ine\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// Guard cho segment/line noun: BỎ match nếu cặp thuộc clause của rule prio cao\n// hơn đã SỞ HỮU cặp: perpBisector (\"(perpendicular) bisector (segment|line) PAIR\")\n// / perpFoot (\"perpendicular to (line|segment) PAIR\") / pointAtDistance (\"Extend(ed)\n// segment|line XY beyond …\"). 3 rule đó emit cặp đúng style HOẶC dựng điểm phái sinh;\n// connect KHÔNG được double-emit segment/line trần — đặc biệt với pointAtDistance:\n// clause malformed (thiếu distance / sai hướng) → pointAtDistance KHÔNG emit → clause\n// cần ESCALATE; connect claim sẽ MASK escalate đó (silent-incomplete, bỏ điểm mới).\n// Case flex [Bb]/[Pp]/[Ee] (BẮT BUỘC: HOA đầu clause không được slip — bài học batch16).\nconst NOUN_OWNED_BEFORE_EN = /(?:[Bb]isector|[Pp]erpendicular\\s+to|[Ee]xtend(?:ed)?)\\s+$/u;\n// \"ray XY\" → ray (đối VN \"tia\"). 2 guard:\n// (a) preceding \"opposite ray of ray XY\" (OPPOSITE_RAY_BEFORE_EN): điểm mới nằm trên\n// tia ĐỐI → vẽ ray X→Y SAI hướng (EN mirror VN TIA_DOI_BEFORE, batch9 8ee33af).\n// (b) trailing \"(?!\\s*,?\\s*extended)\": \"ray XY extended beyond Z\" là construct CỦA\n// pointAtDistance (RAY_EXTENDED_EN). connect KHÔNG claim — nếu malformed (thiếu\n// distance / Z≠Y sai hướng) pointAtDistance escalate fail-safe; connect claim sẽ\n// MASK (silent-incomplete bỏ điểm D). Well-formed thì pointAtDistance đã lo điểm\n// D — connect đứng ngoài để giữ EN-cũ (batch15) byte-identical.\n// \"Draw ray AB\" trần (không \"extended\"/không \"opposite ray of\") → vẫn vẽ ray A→B.\nconst RAY_NOUN_EN = /(?<![A-Za-z])[Rr]ay\\s+([A-Z])([A-Z])(?![A-Za-z])(?!\\s*,?\\s*extended)/gu;\nconst OPPOSITE_RAY_BEFORE_EN = /opposite\\s+ray\\s+of\\s+$/u;\n// \"Connect/Join XY\" → segment (đối VN \"nối\", form cặp HOA).\nconst JOIN_PAIR_EN = /(?<![A-Za-z])(?:[Cc]onnect|[Jj]oin)\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"Connect/Join X and/to/with Y\" → segment (tên 1 ký tự, mirror VN NOI_KW).\nconst JOIN_AND_EN =\n /(?<![A-Za-z])(?:[Cc]onnect|[Jj]oin)\\s+([A-Z])\\s+(?:and|to|with)\\s+([A-Z])(?![A-Za-z])/gu;\n// \"Draw XY\" trần → segment (đối VN \"kẻ\"). perpFoot draw-form \"Draw AH perpendicular\n// to BC\" cũng khớp nhưng emit connect(A,H,'segment') IDENTICAL → deduped.\n// perpBisector/cevian/tangent draw-form có \"the\"/\"two\"/chữ thường sau \"Draw\" →\n// KHÔNG cặp HOA → KHÔNG match ở đây.\nconst DRAW_PAIR_EN = /(?<![A-Za-z])[Dd]raw\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n\nfunction collect(\n re: RegExp,\n text: string,\n style: string,\n used: Set<string>,\n out: IntentT[],\n // Guard tuỳ chọn: bỏ qua match nếu text NGAY TRƯỚC vị trí match khớp regex này\n // (vd \"tia đối của \" trước \"tia XY\" → không emit ray naive sai hướng).\n skipIfPrecededBy?: RegExp,\n): void {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n if (skipIfPrecededBy && skipIfPrecededBy.test(text.slice(0, m.index))) {\n continue;\n }\n const a = m[1].toUpperCase();\n const b = m[2].toUpperCase();\n // Dedup theo cặp đỉnh trong cùng clause: vẽ trùng AB nhiều lần vô nghĩa,\n // và tránh 2 từ khoá khác nhau cùng claim 1 cặp (vd \"đoạn AB\" + \"kẻ AB\").\n const key = `${a}${b}`;\n if (used.has(key)) continue;\n used.add(key);\n out.push(connect(a, b, style));\n }\n}\n\n/**\n * Mỗi clause khớp ≥1 từ khoá vẽ → push 1 RuleMatch (gom mọi cặp tìm được).\n * Nhiều cặp trong cùng clause ⇒ nhiều intent, cùng clauseId.\n * Priority 40: thấp để rule chuyên biệt (trung trực, phân giác…) claim trước.\n */\nexport const connectRule: LanguageRule = {\n id: 'connect',\n priority: 40,\n languages: ['vi', 'en'],\n patterns: [\n LINE_KW, RAY_KW, NOI_KW, SEG_KW,\n SEG_NOUN_EN, LINE_NOUN_EN, RAY_NOUN_EN, JOIN_PAIR_EN, JOIN_AND_EN, DRAW_PAIR_EN,\n ],\n match(ctx) {\n const result: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents: IntentT[] = [];\n // Dùng span-key để 1 vị trí không bị 2 từ khoá double-count, nhưng cho\n // phép nhiều cặp khác vị trí trong cùng clause.\n const used = new Set<string>();\n // Thứ tự quan trọng: \"đường thẳng AB\" phải claim trước SEG (chứa \"thẳng\"\n // KHÔNG match SEG vì SEG yêu cầu \"đoạn thẳng\"/\"cạnh\"/\"kẻ\", không \"đường\").\n collect(LINE_KW, c.text, 'line', used, intents);\n // RAY: suppress ray naive khi nằm trong cụm \"tia đối của tia XY\" (hướng tia\n // gốc X→Y sai so với điểm mới trên tia đối). pointAtDistance lo điểm mới.\n collect(RAY_KW, c.text, 'ray', used, intents, TIA_DOI_BEFORE);\n collect(NOI_KW, c.text, 'segment', used, intents);\n collect(SEG_KW, c.text, 'segment', used, intents);\n // EN forms (issue #46 nhóm B). `used` dedup cặp đã claim bởi form VN trong\n // cùng clause (clause trộn ngôn ngữ hiếm, nhưng an toàn). Thứ tự: noun trước,\n // verb sau; DRAW cuối (trần nhất).\n collect(SEG_NOUN_EN, c.text, 'segment', used, intents, NOUN_OWNED_BEFORE_EN);\n collect(LINE_NOUN_EN, c.text, 'line', used, intents, NOUN_OWNED_BEFORE_EN);\n collect(RAY_NOUN_EN, c.text, 'ray', used, intents, OPPOSITE_RAY_BEFORE_EN);\n collect(JOIN_PAIR_EN, c.text, 'segment', used, intents);\n collect(JOIN_AND_EN, c.text, 'segment', used, intents);\n collect(DRAW_PAIR_EN, c.text, 'segment', used, intents);\n if (intents.length > 0) {\n result.push({ ruleId: 'connect', clauseIds: [c.id], intents });\n }\n }\n return result;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/midpoint.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, pairFromToken, SIDE_PREFIX } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\n\n// Prefilter toàn đề. \"trung điểm\" KHÔNG khớp \"trung trực\" (an toàn, rule khác lo).\nconst MIDPOINT = /trung\\s*điểm/u;\n\n// Dạng A (GLOBAL): tên điểm ĐỨNG TRƯỚC \"(là) trung điểm (của (cạnh|đoạn)) <PAIR>\".\n// \"Gọi M là trung điểm BC\" | \"M là trung điểm của BC\" | \"M trung điểm cạnh BC\"\n// | \"M là trung điểm cạnh huyền BC\" | \"trung điểm đoạn thẳng AC\"\n// Tên = ký tự HOA NGAY TRƯỚC cụm trung điểm (cục bộ quanh match, KHÔNG quét intro).\nconst NAME_BEFORE_G = new RegExp(\n `([A-Z])(?:['′]?)\\\\s+(?:là\\\\s+|=\\\\s+)?trung\\\\s*điểm\\\\s+(?:của\\\\s+)?${SIDE_PREFIX}([A-Z])([A-Z])(?!\\\\p{L})`,\n 'gu',\n);\n\n// Dạng B (GLOBAL): tên điểm ĐỨNG SAU \"trung điểm <NAME> của (cạnh|đoạn) <PAIR>\".\n// \"trung điểm I của (cạnh huyền) AB\" | \"trung điểm I của đoạn thẳng BC\"\nconst NAME_AFTER_G = new RegExp(\n `trung\\\\s*điểm\\\\s+([A-Z])(?:['′]?)\\\\s+của\\\\s+${SIDE_PREFIX}([A-Z])([A-Z])(?!\\\\p{L})`,\n 'gu',\n);\n\n// Distributive \"lần lượt\": \"M, N (, P) lần lượt là trung điểm AB, AC (, BC)\" →\n// zip 1-1: M=mid(AB), N=mid(AC), P=mid(BC). group1 = blob tên (≥2, phẩy),\n// group2 = blob cặp đỉnh (≥2, phẩy). Số tên PHẢI bằng số cặp (else bỏ qua,\n// escalate — không đoán lệch). SIDE_PREFIX cho \"(các) cạnh/đoạn\" trước blob cặp.\nconst DISTRIB = new RegExp(\n `((?:[A-Z](?:['′]?)\\\\s*,\\\\s*)+[A-Z](?:['′]?))\\\\s+lần\\\\s*lượt\\\\s+(?:là\\\\s+)?(?:điểm\\\\s+)?trung\\\\s*điểm\\\\s+(?:của\\\\s+)?(?:các\\\\s+)?${SIDE_PREFIX}((?:[A-Z][A-Z]\\\\s*,\\\\s*)*(?:[A-Z][A-Z]\\\\s*,\\\\s*)?[A-Z][A-Z](?:\\\\s*và\\\\s*[A-Z][A-Z])?)`,\n 'u',\n);\n\n// Tách 1 token tên trong blob distributive → \"M\" / \"M'\" (prime normalize ′→').\nfunction nameToken(raw: string): string | undefined {\n const m = /^([A-Z])(['′]?)/u.exec(raw.trim());\n if (!m) return undefined;\n return m[2] ? `${m[1]}'` : m[1];\n}\n\n// === EN patterns (issue #46 group B) ========================================\n// Prefilter EN: \"midpoint\" (first-letter case flex [Mm], KHÔNG cờ 'i' — phá [A-Z]).\nconst MIDPOINT_EN = /[Mm]idpoint/u;\n// EN side/segment prefix tuỳ chọn TRƯỚC cặp đỉnh: \"segment BC\", \"side BC\".\nconst SIDE_PREFIX_EN = '(?:segment\\\\s+|side\\\\s+)?';\n\n// EN dạng A (GLOBAL): tên ĐỨNG TRƯỚC. \"M is the midpoint of BC\" | \"let M be the\n// midpoint of segment BC\". Tên = HOA NGAY TRƯỚC \"is/be the midpoint\" (cục bộ).\n// (?![A-Za-z]) neo cuối cặp đỉnh (chặn \"BCD\" 3 chữ → escalate-safe).\nconst NAME_BEFORE_EN_G = new RegExp(\n `([A-Z])(?:['′]?)\\\\s+(?:is|be)\\\\s+the\\\\s+midpoint\\\\s+of\\\\s+${SIDE_PREFIX_EN}([A-Z])([A-Z])(?![A-Za-z])`,\n 'gu',\n);\n\n// EN dạng B (GLOBAL): tên ĐỨNG SAU. \"midpoint M of BC\" | \"midpoint I of segment AB\".\nconst NAME_AFTER_EN_G = new RegExp(\n `[Mm]idpoint\\\\s+([A-Z])(?:['′]?)\\\\s+of\\\\s+${SIDE_PREFIX_EN}([A-Z])([A-Z])(?![A-Za-z])`,\n 'gu',\n);\n\n/**\n * \"Gọi M là trung điểm BC\" → add-point M {kind:'midpoint', of:'BC'}.\n *\n * GLOBAL: emit MỌI cụm \"trung điểm <PAIR>\" trong clause (vd \"M là trung điểm BC\n * và N là trung điểm AC\" → 2 add-point). Tên điểm bind THEO TỪNG MATCH cục bộ:\n * - dạng A: ký tự HOA NGAY TRƯỚC \"(là) trung điểm\" — KHÔNG quét lời dẫn\n * toàn clause (tránh \"Lấy điểm D, gọi M là trung điểm BC\" gán nhầm 'D').\n * - dạng B: ký tự HOA NGAY SAU \"trung điểm\" (\"trung điểm I của AB\").\n * Match nào không có tên cục bộ HOẶC cặp đỉnh không hợp lệ → BỎ QUA match đó\n * (escalate AI), không bịa tên.\n */\nexport const midpointRule: LanguageRule = {\n id: 'midpoint',\n priority: 50,\n languages: ['vi', 'en'],\n patterns: [MIDPOINT, MIDPOINT_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const hasVi = MIDPOINT.test(c.text);\n const hasEn = MIDPOINT_EN.test(c.text);\n if (!hasVi && !hasEn) continue;\n\n const emit = (name: string, pairToken: string, clauseId: number) => {\n const pair = pairFromToken(pairToken);\n if (!name || pair.length !== 2) return;\n out.push({\n ruleId: 'midpoint',\n clauseIds: [clauseId],\n intents: [addPoint(name, { kind: 'midpoint', of: pair.join('') })],\n });\n };\n\n if (hasVi) {\n // Distributive \"lần lượt\" ưu tiên: \"M, N lần lượt là trung điểm AB, AC\"\n // → M=mid(AB), N=mid(AC). Số tên = số cặp mới emit (else bỏ qua → escalate).\n const dm = DISTRIB.exec(c.text);\n if (dm) {\n const names = dm[1]\n .split(',')\n .map((s) => nameToken(s))\n .filter((x): x is string => !!x);\n const pairs = dm[2]\n .split(/\\s*,\\s*|\\s+và\\s+/u)\n .map((s) => s.trim())\n .filter(Boolean);\n if (names.length >= 2 && names.length === pairs.length) {\n for (let i = 0; i < names.length; i++) emit(names[i], pairs[i], c.id);\n continue; // clause đã xử lý bằng distributive — skip dạng A/B + EN\n }\n }\n\n // Theo dõi vị trí cụm \"trung điểm\" đã được dạng A claim, để dạng B không\n // nhân đôi cùng một occurrence.\n const consumed = new Set<number>();\n\n // Dạng A — tên đứng trước. Vị trí cụm \"trung điểm\" = chỉ số bắt đầu match\n // (gần đúng: match bắt đầu ở ký tự tên, \"trung điểm\" theo ngay sau).\n NAME_BEFORE_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_BEFORE_G)) {\n const tdIdx = c.text.indexOf('trung', m.index ?? 0);\n if (tdIdx >= 0) consumed.add(tdIdx);\n emit(m[1], m[2] + m[3], c.id);\n }\n\n // Dạng B — tên đứng sau \"trung điểm\". Bỏ qua occurrence đã được dạng A claim.\n NAME_AFTER_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_AFTER_G)) {\n const tdIdx = m.index ?? 0;\n if (consumed.has(tdIdx)) continue;\n emit(m[1], m[2] + m[3], c.id);\n }\n }\n\n // --- EN (issue #46 group B) — dạng A (name before) + B (name after) -----\n // EN dạng A khớp \"X is/be the midpoint of …\"; dạng B khớp \"midpoint X of …\".\n // 2 dạng không chồng (A cần \"is/be the\", B cần HOA ngay sau \"midpoint\") nên\n // KHÔNG cần consumed-set như VN.\n if (hasEn) {\n NAME_BEFORE_EN_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_BEFORE_EN_G)) {\n emit(m[1], m[2] + m[3], c.id);\n }\n NAME_AFTER_EN_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_AFTER_EN_G)) {\n emit(m[1], m[2] + m[3], c.id);\n }\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpBisector.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, pairFromToken } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Dùng lookaround \\p{L} (cờ 'u') thay cho \\b.\n//\n// \"(đường) trung trực (của) (đoạn|đoạn thẳng|cạnh) <PAIR>\"\n// \"đường trung trực của BC\" → connect('B','C','perpBisector')\n// \"trung trực AB\" → connect('A','B','perpBisector')\n// \"d là đường trung trực BC\" → connect('B','C','perpBisector') (tên 'd' bỏ qua;\n// connect không nhận name)\n//\n// Cụm nối giữa \"trung trực\" và cặp đỉnh: optional \"của\", \"đoạn\", \"đoạn thẳng\",\n// \"cạnh\" (lặp tự do). Cặp đỉnh = 2 ký tự HOA liền.\n// Cờ 'g' để bắt MỌI cụm \"trung trực <PAIR>\" trong 1 clause (vd \"trung trực BC\n// và trung trực CA\" → emit cả 2). Reset lastIndex trước mỗi clause.\nconst PERP_BISECTOR =\n /(?<!\\p{L})trung\\s*trực\\s+(?:(?:của|đoạn|đoạn\\s+thẳng|cạnh)\\s+)*([A-Z][A-Z])(?!\\p{L})/gu;\n\n// \"(đường) trung trực (của) PAIR1 cắt [đường thẳng|đoạn|cạnh|tia]? PAIR2 tại D\":\n// đường trung trực CỦA PAIR1 (line dựng) ∩ đường PAIR2 = điểm D.\n// \"Đường trung trực của BC cắt AB tại D\" → perpBisector(B,C) + D=giao(pb_BC, AB)\n// group1 = PAIR1 (đoạn lấy trung trực); group2 = PAIR2 (đường bị cắt); group3 = D.\n//\n// perpBisector là LINE dựng (không phải đoạn) nên KHÔNG dùng intersection rule\n// generic (vốn chỉ nhận cặp đỉnh): rule này tự đặt perpBisector + intersection ref\n// TÊN shape mà connect builder sinh ('pb_<PAIR1>', deterministic + dedup JSON nên\n// duy nhất). PAIR1/PAIR2 chia sẻ đỉnh là BÌNH THƯỜNG (pb là đường khác đoạn PAIR2).\nconst PERP_BIS_CUT =\n /(?<!\\p{L})[Tt]rung\\s*trực\\s+(?:(?:của|đoạn|đoạn\\s+thẳng|cạnh)\\s+)*([A-Z][A-Z])(?!\\p{L})\\s+cắt\\s+(?:đường\\s*thẳng\\s+|đoạn(?:\\s+thẳng)?\\s+|cạnh\\s+|tia\\s+)?([A-Z][A-Z])(?!\\p{L})\\s+tại\\s+([A-Z])(?!\\p{L})/gu;\n\n/** prefilter nhanh trên toàn đề. */\nconst PREFILTER = /trung\\s*trực/u;\n\n// === EN (issue #46 group B) ===\n// \"(the)? perpendicular bisector (of|the|segment|line|side)* PAIR\" → connect(P1,P2,'perpBisector').\n// First-letter flex [Pp] (KHÔNG cờ 'i'). Global để bắt nhiều cụm/clause như VN.\nconst PERP_BISECTOR_EN =\n /[Pp]erpendicular\\s+bisector\\s+(?:(?:of|the|segment|line|side)\\s+)*([A-Z][A-Z])(?!\\p{L})/gu;\nconst PERP_BISECTOR_EN_PRE = /[Pp]erpendicular\\s+bisector/u;\n\n/**\n * \"(đường) trung trực của <PAIR>\" → connect(P1, P2, 'perpBisector').\n *\n * GLOBAL: 1 clause có thể chứa nhiều cụm trung trực (\"trung trực BC và trung\n * trực CA\") → emit connect cho MỖI cặp. Lấy cặp đỉnh ngay sau mỗi \"trung trực\"\n * (bỏ qua \"của/đoạn/cạnh\" xen giữa). Cụm không trích được cặp đỉnh hợp lệ →\n * bỏ qua cụm đó (escalate AI, an toàn hơn đoán sai). Tên đường (vd \"d là …\")\n * không cần — connect không nhận name.\n */\nexport const perpBisectorRule: LanguageRule = {\n id: 'perpBisector',\n priority: 70,\n languages: ['vi', 'en'],\n patterns: [PREFILTER, PERP_BISECTOR_EN_PRE],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n PERP_BISECTOR.lastIndex = 0; // regex 'g' có state — reset mỗi clause\n for (const m of c.text.matchAll(PERP_BISECTOR)) {\n const pair = pairFromToken(m[1]);\n if (pair.length !== 2) continue; // không trích được cặp đỉnh → bỏ cụm\n out.push({\n ruleId: 'perpBisector',\n clauseIds: [c.id],\n intents: [connect(pair[0], pair[1], 'perpBisector')],\n });\n }\n\n // \"trung trực PAIR1 cắt PAIR2 tại D\" → perpBisector(PAIR1) + giao điểm D.\n // Emit connect(perpBisector) NGAY TRƯỚC intersection (cùng match) để shape\n // 'pb_<PAIR1>' tồn tại khi transpile resolve ref của intersection (connect\n // trùng với loop plain ở trên sẽ bị dedup JSON → an toàn).\n PERP_BIS_CUT.lastIndex = 0;\n for (const m of c.text.matchAll(PERP_BIS_CUT)) {\n const pb = pairFromToken(m[1]);\n const line = pairFromToken(m[2]);\n const d = m[3];\n if (pb.length !== 2 || line.length !== 2) continue;\n // Giao điểm phải là điểm MỚI: D không trùng đỉnh nào của 2 cặp.\n if (new Set([pb[0], pb[1], line[0], line[1]]).has(d)) continue;\n const pbName = `pb_${pb[0]}${pb[1]}`; // khớp connect builder uniqueShapeName('pb_BC')\n out.push({\n ruleId: 'perpBisector',\n clauseIds: [c.id],\n intents: [\n connect(pb[0], pb[1], 'perpBisector'),\n addPoint(d, { kind: 'intersection', of: [pbName, m[2]] }),\n ],\n });\n }\n\n // --- EN (issue #46 group B) — mirror VN: global, emit-all, escalate-safe ---\n PERP_BISECTOR_EN.lastIndex = 0;\n for (const m of c.text.matchAll(PERP_BISECTOR_EN)) {\n const pair = pairFromToken(m[1]);\n if (pair.length !== 2) continue;\n out.push({\n ruleId: 'perpBisector',\n clauseIds: [c.id],\n intents: [connect(pair[0], pair[1], 'perpBisector')],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/cevian.ts\n//\n// Cevian (đường đồng quy từ đỉnh): đường cao / trung tuyến / phân giác.\n// Phrasing thực tế: tên cevian dạng VF = đỉnh + chân (vd \"đường cao AH\",\n// \"AM là trung tuyến\", \"vẽ phân giác AD\"). Cần triangle context (ctx.problem)\n// để suy ra cạnh đối diện đỉnh = 2 đỉnh còn lại.\n//\n// Mỗi cevian khớp → RuleMatch với 2 intent cùng clauseId:\n// - add-point (chân: perpFoot / midpoint / angleBisectorFoot)\n// - connect (đoạn cevian visible VF, style segment)\n//\n// Nguyên tắc fail-safe:\n// - 1 clause có thể chứa NHIỀU cevian (cùng/khác loại): dùng matchAll (cờ /g)\n// để emit ĐỦ, không chỉ match đầu tiên.\n// - foot trùng đỉnh tam giác (\"đường cao AB\" → foot=B) → SKIP (đừng tạo\n// add-point sẽ bị builder hạ về 'free' → fidelity guard escalate).\n// - 2 cevian KHÁC nhau cùng đặt 1 tên chân (vd \"đường cao AH\" + \"trung tuyến\n// BH\" — cùng tên H nhưng ràng buộc mâu thuẫn) → SKIP tất cả cevian mang tên\n// chân đó (không claim → coverage escalate). Thà escalate còn hơn dựng SAI.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect } from './_shared';\n\n// Tam giác từ toàn đề (cần để suy cạnh đối diện). LƯU Ý: \\b không khớp quanh\n// ký tự Việt → dùng class trực tiếp, có cờ 'u'.\nconst TRI = /tam\\s*giác(?:\\s+(?:vuông|cân|đều|nhọn|tù))?\\s+([A-Z])([A-Z])([A-Z])/u;\n\n// === EN (issue #46 group B) =================================================\n// Tam giác tiếng Anh: \"triangle ABC\" (first-letter case flex [Tt], KHÔNG cờ 'i'\n// — sẽ phá [A-Z] nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]). Adjective\n// \"right/isosceles/…\" chỉ đứng TRƯỚC \"triangle\" nên vẫn khớp (vd \"right triangle\n// ABC\"). Đề VN không chứa \"triangle\" và đề EN không chứa \"tam giác\" → VN\n// byte-identical.\nconst TRI_EN = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\n\n// Cevian type → patterns. Mỗi pattern capture đỉnh (g1) + chân (g2): 2 ký tự\n// HOA liền (vd \"AH\"). (?![A-Z]) chặn match nhầm vào cụm 3 ký tự (vd \"ABC\").\n// TẤT CẢ pattern dùng cờ /g để matchAll bắt MỌI cevian trong 1 clause.\ntype CevianType = 'altitude' | 'median' | 'bisector' | 'externalBisector';\n\n// LƯU Ý case: KHÔNG dùng cờ 'i' (làm [A-Z] khớp chữ thường → bắt rác). Nhưng\n// keyword có thể HOA ở đầu câu (\"Đường cao AH\", \"Trung tuyến AM\", \"Phân giác AD\")\n// → ký tự đầu keyword + verb dùng [Xx]; vertices LUÔN strict [A-Z].\nconst CEVIAN_PATTERNS: ReadonlyArray<{ type: CevianType; patterns: readonly RegExp[] }> = [\n {\n type: 'altitude',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Hh]ạ|[Dd]ựng)\\s+[Đđ]ường\\s*cao\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /[Đđ]ường\\s*cao\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?đường\\s*cao/gu,\n // EN (issue #46 group B). g1=apex g2=foot, nhãn strict [A-Z], NO cờ 'i'.\n // First-letter flex [Aa] (HOA đầu câu \"Altitude AH\"); KHÔNG cờ 'i' (phá nhãn).\n // forward \"altitude AH\" (lời dẫn \"Draw the \" phía trước bỏ qua). \"foot of\n // the altitude from A to BC\" KHÔNG khớp: sau \"altitude\" là \"from\" (chữ\n // thường), không cặp HOA → perpFoot.ts sở hữu.\n /[Aa]ltitude\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n // reverse \"AH is/be the altitude\". (?![A-Za-z]) chặn \"altitudes\"/nối chữ.\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:is|be)\\s+(?:the\\s+)?altitude(?![A-Za-z])/gu,\n ],\n },\n {\n type: 'median',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+[Tt]rung\\s*tuyến\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /[Tt]rung\\s*tuyến\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?trung\\s*tuyến/gu,\n // EN (issue #46 group B). g1=apex g2=foot. First-letter flex [Mm].\n /[Mm]edian\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:is|be)\\s+(?:the\\s+)?median(?![A-Za-z])/gu,\n ],\n },\n {\n // \"phân giác (trong) AD\": từ \"trong\" (phân giác TRONG = internal bisector,\n // loại thường) tuỳ chọn chen giữa \"phân giác\" và cặp đỉnh. \"phân giác NGOÀI\"\n // (external bisector) CHƯA hỗ trợ: forward tự reject (sau \"phân giác\" là chữ\n // thường \"ngoài\", không HOA pair); suffix cần (?!\\s+ngoài) để KHÔNG nhận nhầm\n // \"AD là phân giác ngoài\" thành internal → escalate (fail-safe).\n type: 'bisector',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+(?:[Đđ]ường\\s*|[Tt]ia\\s+)?phân\\s*giác(?:\\s+trong)?\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?:[Đđ]ường\\s*phân\\s*giác|[Tt]ia\\s+phân\\s*giác|[Pp]hân\\s*giác)(?:\\s+trong)?\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?(?:đường\\s*|tia\\s+)?phân\\s*giác(?:\\s+trong)?(?!\\s+ngoài)/gu,\n // EN (issue #46 group B) — internal bisector ONLY. g1=apex g2=foot.\n // forward \"(angle)? bisector AD\". 3 negative lookbehind:\n // (?<![Pp]erpendicular\\s) — \"perpendicular bisector AD\" thuộc perpBisector.ts\n // (EN regex của nó CŨNG khớp cặp HOA) → tránh double-emit.\n // (?<![Ee]xternal\\s)/(?<![Ee]xterior\\s) — external bisector EN DEFER → KHÔNG\n // nhận nhầm thành internal (silent-wrong).\n // Dạng \"of angle\"/\"angle bisector of\" (angleBisectorAngle.ts) tự loại: cần\n // cặp HOA NGAY sau \"bisector\", \"of\" chen vào sẽ phá khớp. First-letter flex\n // [Bb] (HOA đầu câu) — lookbehind PHẢI first-letter flex [Pp]/[Ee] để chặn cả\n // \"Perpendicular\"/\"External\" HOA đầu clause (else double-emit silent-wrong).\n /(?<![Pp]erpendicular\\s)(?<![Ee]xternal\\s)(?<![Ee]xterior\\s)(?:[Aa]ngle\\s+)?[Bb]isector\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n // reverse \"AD is/be the (angle)? bisector\". (?!\\s+of) chặn \"is the bisector\n // of …\" (thuộc angleBisectorAngle). \"the perpendicular/external bisector\"\n // tự loại: từ chen giữa \"the\" và \"bisector\" phá (?:angle\\s+)?bisector.\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:is|be)\\s+(?:the\\s+)?(?:angle\\s+)?bisector(?!\\s+of)(?![A-Za-z])/gu,\n ],\n },\n {\n // \"phân giác NGOÀI AD\" (external bisector, Issue #46 nhóm A). Nhánh RIÊNG,\n // BẮT BUỘC có từ \"ngoài\" sau \"phân giác\" (forward) hoặc trước/sau cặp đỉnh\n // (suffix). Phân giác ngoài ⊥ phân giác trong tại đỉnh → builder dựng qua\n // angleBisector(trong) + perpendicular. KHÔNG đụng pattern 'bisector' nội bộ\n // (vốn đã reject \"ngoài\" qua chữ thường forward + (?!\\s+ngoài) suffix).\n type: 'externalBisector',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+(?:[Đđ]ường\\s*|[Tt]ia\\s+)?phân\\s*giác\\s+ngoài\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?:[Đđ]ường\\s*phân\\s*giác|[Tt]ia\\s+phân\\s*giác|[Pp]hân\\s*giác)\\s+ngoài\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?(?:đường\\s*|tia\\s+)?phân\\s*giác\\s+ngoài/gu,\n ],\n },\n];\n\n// Prefilter: bất kỳ từ khoá cevian nào trên toàn đề (hoa đầu câu → [Đđ]/[Tt]/[Pp]).\n// EN (issue #46 group B): runRules prefilter theo `patterns` (BỎ QUA field\n// `languages`) → đề EN thuần cần EN prefilter thì match() mới chạy. Đây là cờ\n// boolean .test() thuần (KHÔNG capture nhãn) nên cờ 'i' AN TOÀN.\nconst PREFILTER = [\n /[Đđ]ường\\s*cao/u,\n /[Tt]rung\\s*tuyến/u,\n /[Pp]hân\\s*giác/u,\n /median/i,\n /altitude/i,\n /bisector/i,\n];\n\n/** Cạnh đối diện đỉnh V trong tam giác = 2 đỉnh còn lại, join token (vd \"BC\"). */\nfunction opposite(tri: readonly string[], vertex: string): string | undefined {\n const rest = tri.filter((v) => v !== vertex);\n return rest.length === 2 ? rest[0] + rest[1] : undefined;\n}\n\ninterface Cevian {\n clauseId: number;\n type: CevianType;\n apex: string;\n foot: string;\n opp: string;\n}\n\n/**\n * \"đường cao AH\" / \"trung tuyến AM\" / \"phân giác AD\" → add-point(chân) +\n * connect(VF). apex PHẢI là đỉnh tam giác (else bỏ qua: tránh match nhầm\n * cặp như \"BD cắt\"). Không có tam giác hoặc apex ngoài tam giác → escalate.\n */\nexport const cevianRule: LanguageRule = {\n id: 'cevian',\n priority: 60,\n languages: ['vi', 'en'],\n patterns: PREFILTER,\n match(ctx) {\n // Tam giác gate: VN trước, EN fallback (mirror angleBisectorAngle). Đề VN\n // không chứa \"triangle\", đề EN không chứa \"tam giác\" → VN byte-identical.\n const triMatch = TRI.exec(ctx.problem);\n const triMatchEN = TRI_EN.exec(ctx.problem);\n const tri = triMatch\n ? [triMatch[1], triMatch[2], triMatch[3]]\n : triMatchEN\n ? [triMatchEN[1], triMatchEN[2], triMatchEN[3]]\n : null;\n if (!tri) return []; // không có tam giác → escalate\n\n // ── Pass 1: gom MỌI cevian hợp lệ (apex là đỉnh, foot không trùng đỉnh) ──\n // Dedup theo (apex,foot,type) — KHÔNG dedup chỉ theo tên chân: 2 cevian\n // khác nhau cùng tên chân là XUNG ĐỘT (xử ở pass 2), không phải trùng lặp.\n const candidates: Cevian[] = [];\n const seen = new Set<string>(); // \"apex|foot|type\"\n\n for (const c of ctx.clauses) {\n for (const cp of CEVIAN_PATTERNS) {\n for (const re of cp.patterns) {\n re.lastIndex = 0;\n for (const m of c.text.matchAll(re)) {\n const apex = m[1];\n const foot = m[2];\n // apex phải là đỉnh tam giác; else có thể là cặp cạnh ngẫu nhiên.\n if (!tri.includes(apex)) continue;\n // foot trùng đỉnh tam giác (\"đường cao AB\" → foot=B) → SKIP sớm:\n // builder sẽ hạ điểm về 'free' → fidelity guard escalate; bỏ ở đây\n // cho sạch (không claim → coverage escalate trực tiếp).\n if (tri.includes(foot)) continue;\n const opp = opposite(tri, apex);\n if (!opp) continue; // apex không suy ra được cạnh đối diện → bỏ qua\n\n const key = `${apex}|${foot}|${cp.type}`;\n if (seen.has(key)) continue;\n seen.add(key);\n candidates.push({ clauseId: c.id, type: cp.type, apex, foot, opp });\n }\n }\n }\n }\n\n // ── Pass 2: phát hiện XUNG ĐỘT tên chân ──\n // Nếu 1 tên chân được ≥2 cevian khác nhau đặt (vd \"đường cao AH\" +\n // \"trung tuyến BH\" cùng tên H, ràng buộc mâu thuẫn) → bỏ TẤT cevian mang\n // tên đó. Không claim → escalate (thà escalate còn hơn dựng SAI ngữ nghĩa).\n const footCount = new Map<string, number>();\n for (const cv of candidates) footCount.set(cv.foot, (footCount.get(cv.foot) ?? 0) + 1);\n\n const out: RuleMatch[] = [];\n for (const cv of candidates) {\n if ((footCount.get(cv.foot) ?? 0) > 1) continue; // tên chân xung đột → skip\n\n let pointIntent;\n if (cv.type === 'altitude') {\n pointIntent = addPoint(cv.foot, { kind: 'perpFoot', from: cv.apex, onLine: cv.opp });\n } else if (cv.type === 'median') {\n pointIntent = addPoint(cv.foot, { kind: 'midpoint', of: cv.opp });\n } else if (cv.type === 'externalBisector') {\n pointIntent = addPoint(cv.foot, {\n kind: 'externalAngleBisectorFoot',\n from: cv.apex,\n onLine: cv.opp,\n });\n } else {\n pointIntent = addPoint(cv.foot, {\n kind: 'angleBisectorFoot',\n from: cv.apex,\n onLine: cv.opp,\n });\n }\n\n out.push({\n ruleId: 'cevian',\n clauseIds: [cv.clauseId],\n intents: [pointIntent, connect(cv.apex, cv.foot, 'segment')],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/angleBisectorAngle.ts\n//\n// Phân giác theo GÓC (3-point angle, KHÔNG đặt tên chân) — Issue #46 nhóm A.\n//\n// Phrasing đề thi RẤT phổ biến: \"Vẽ tia phân giác của góc BAC\", \"phân giác góc\n// BAC\", \"đường phân giác của góc A\"… → vẽ phân giác TRONG của góc, VISIBLE,\n// KHÔNG có tên chân (khác hẳn cevian \"phân giác AD\" foot-named).\n//\n// Emit 1 intent draw-line/angleBisector (VISIBLE), KHÔNG add-point foot, KHÔNG\n// connect. vertex = đỉnh góc:\n// - \"góc XYZ\" (3 ký tự HOA): vertex = chữ GIỮA (Y), p1=X, p2=Z.\n// - \"góc A\" (1 ký tự, trong tam giác): vertex=A, p1/p2 = 2 đỉnh còn lại\n// (suy như cevian opposite). Không có tam giác để suy 2 tia → escalate.\n//\n// Discriminator: PHẢI có \"góc\" + (cụm 3 HOA HOẶC 1 HOA là đỉnh tam giác). KHÔNG\n// đụng cevian \"phân giác AD\"/\"phân giác ngoài AD\" (2 ký tự foot-named): cevian\n// pattern yêu cầu cặp HOA NGAY sau \"phân giác\", nhưng ở đây sau \"phân giác\" là\n// \"góc\" (chữ thường) → cevian không khớp → KHÔNG double-emit.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { drawLine } from './_shared';\n\n// Tam giác từ toàn đề (cần để suy 2 cạnh cho \"góc A\"). \\b không khớp quanh ký\n// tự Việt → dùng class trực tiếp, cờ 'u'.\nconst TRI = /tam\\s*giác(?:\\s+(?:vuông|cân|đều|nhọn|tù))?\\s+([A-Z])([A-Z])([A-Z])/u;\n\n// === EN (issue #46 group B) =================================================\n// Tam giác tiếng Anh: \"triangle ABC\" (first-letter case flex [Tt], KHÔNG cờ 'i'\n// — sẽ phá [A-Z] nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]). Không cần\n// 'g' (chỉ cần tam giác đầu tiên để fallback suy 2 cạnh, như TRI VN).\nconst TRI_EN = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\n\n// Prefilter: VN cần \"phân giác\" + \"góc\"; EN cần \"angle bisector\" (Form B) hoặc\n// \"bisector of (the)? angle/∠\" (Form A). `.some` → ANY khớp là trigger match().\n// \"languages\" là metadata thuần (runRules prefilter theo `patterns`, BỎ QUA nó).\nconst PREFILTER = [\n /[Pp]hân\\s*giác/u,\n /góc/u,\n /[Aa]ngle\\s+bisector/u, // Form B EN\n /[Bb]isector\\s+of\\s+(?:the\\s+)?(?:[Aa]ngle|∠)/u, // Form A EN\n];\n\n// \"phân giác … góc XYZ\" (3 ký tự HOA liền). (?![A-Z]) chặn cụm 4+ ký tự.\n// Cho phép cụm dẫn \"(đường|tia) phân giác (của)? góc\" — bổ ngữ optional.\nconst ANGLE3 =\n /phân\\s*giác\\s+(?:(?:của|cho)\\s+)?góc\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/giu;\n// \"phân giác … góc A\" (1 ký tự HOA, không theo sau bởi HOA khác → không phải 3-point).\nconst ANGLE1 =\n /phân\\s*giác\\s+(?:(?:của|cho)\\s+)?góc\\s+([A-Z])(?![A-Z])/giu;\n\n// \"chân (của)? (đường|tia)? \" NGAY TRƯỚC \"phân giác\" → cụm \"CHÂN phân giác\" là\n// FOOT (điểm), thuộc angleBisectorFoot.ts. angleBisectorAngle né để KHÔNG vẽ tia\n// phân giác trùng (foot builder đã tự dựng tia bên trong) → tránh double-emit.\nconst CHAN_BEFORE = /chân\\s+(?:của\\s+)?(?:đường\\s*|tia\\s+)?$/u;\n\n// === EN regex (issue #46 group B) ===========================================\n// First-letter flex [Bb]/[Aa] (KHÔNG cờ 'i' — sẽ phá [A-Z] nhãn). Nhãn HOA\n// strict, neo (?![A-Z]). Cờ 'g' để emit-all + matchAll. Yêu cầu chữ\n// \"angle\"/∠ → KHÔNG khớp \"perpendicular bisector of BC\" (không có \"angle\").\n//\n// Form A: \"(the)? bisector of (the)? (angle|∠) XYZ\" — bổ ngữ \"the\" optional.\n// \"Draw the bisector of angle BAC.\" → {p1:B, vertex:A, p2:C}\n// Form B: \"(the)? angle bisector of XYZ\" — \"of\" sau \"bisector\", KHÔNG \"angle/∠\".\n// \"The angle bisector of MNP.\" → {M,N,P}\nconst ANGLE3_EN_A =\n /[Bb]isector\\s+of\\s+(?:the\\s+)?(?:[Aa]ngle|∠)\\s*([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\nconst ANGLE3_EN_B =\n /[Aa]ngle\\s+bisector\\s+of\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n// 1-letter \"angle A\" (Form A only — Form B \"angle bisector of A\" hiếm/mơ hồ,\n// defer). Cần tam giác EN để suy 2 cạnh.\nconst ANGLE1_EN_A =\n /[Bb]isector\\s+of\\s+(?:the\\s+)?(?:[Aa]ngle|∠)\\s*([A-Z])(?![A-Z])/gu;\n\n/** 2 đỉnh còn lại của tam giác (≠ vertex), giữ thứ tự xuất hiện trong tri. */\nfunction others(tri: readonly string[], vertex: string): string[] {\n return tri.filter((v) => v !== vertex);\n}\n\ninterface Hit {\n clauseId: number;\n p1: string;\n vertex: string;\n p2: string;\n}\n\n/**\n * \"phân giác (của) góc XYZ/A\" → draw-line/angleBisector VISIBLE (1 intent,\n * không foot, không connect). vertex = chữ giữa (3-point) hoặc đỉnh tam giác\n * (1-letter, suy 2 cạnh từ tam giác). Mơ hồ / không suy được 2 tia → escalate.\n */\nexport const angleBisectorAngleRule: LanguageRule = {\n id: 'angleBisectorAngle',\n // Cao hơn cevian (60) — chạy trước; tuy nhiên 2 rule không tranh chấp vì\n // discriminator \"góc\" loại cevian khỏi cụm này.\n priority: 62,\n languages: ['vi', 'en'],\n patterns: PREFILTER,\n match(ctx) {\n // Tam giác fallback (suy 2 cạnh cho \"góc A\"/\"angle A\"): VN trước, EN sau.\n // Đề VN không chứa \"triangle\" và đề EN không chứa \"tam giác\" → KHÔNG đụng\n // nhau (VN byte-identical).\n const triMatch = TRI.exec(ctx.problem);\n const triMatchEN = TRI_EN.exec(ctx.problem);\n const tri = triMatch\n ? [triMatch[1], triMatch[2], triMatch[3]]\n : triMatchEN\n ? [triMatchEN[1], triMatchEN[2], triMatchEN[3]]\n : null;\n\n const hits: Hit[] = [];\n const seen = new Set<string>(); // \"p1|vertex|p2\" dedup\n\n for (const c of ctx.clauses) {\n // ── 3-point \"góc XYZ\": vertex = chữ giữa, không cần tam giác ──\n ANGLE3.lastIndex = 0;\n for (const m of c.text.matchAll(ANGLE3)) {\n if (CHAN_BEFORE.test(c.text.slice(0, m.index))) continue; // \"chân … phân giác\" = foot\n const [p1, vertex, p2] = [m[1], m[2], m[3]];\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n\n // ── 1-letter \"góc A\": cần tam giác để suy 2 cạnh ──\n // Dùng pattern ANGLE1 nhưng BỎ QUA những match đã bị ANGLE3 nuốt (cùng vị\n // trí bắt đầu): so vị trí của vertex 1-letter với các 3-point đã thấy.\n ANGLE1.lastIndex = 0;\n for (const m of c.text.matchAll(ANGLE1)) {\n if (CHAN_BEFORE.test(c.text.slice(0, m.index))) continue; // \"chân … phân giác\" = foot\n const vertex = m[1];\n if (!tri) continue; // không tam giác → escalate\n if (!tri.includes(vertex)) continue; // đỉnh ngoài tam giác → bỏ qua\n const rest = others(tri, vertex);\n if (rest.length !== 2) continue; // không suy được 2 tia → bỏ qua\n const [p1, p2] = rest;\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n\n // ── EN 3-point: Form A \"(bisector of) angle XYZ\" + Form B \"angle bisector\n // of XYZ\". vertex = chữ giữa, không cần tam giác. seen dedup chung VN.\n for (const re of [ANGLE3_EN_A, ANGLE3_EN_B]) {\n re.lastIndex = 0;\n for (const m of c.text.matchAll(re)) {\n const [p1, vertex, p2] = [m[1], m[2], m[3]];\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n }\n\n // ── EN 1-letter \"angle A\" (Form A): cần tam giác EN/VN để suy 2 cạnh.\n ANGLE1_EN_A.lastIndex = 0;\n for (const m of c.text.matchAll(ANGLE1_EN_A)) {\n const vertex = m[1];\n if (!tri) continue; // không tam giác → escalate\n if (!tri.includes(vertex)) continue; // đỉnh ngoài tam giác → bỏ qua\n const rest = others(tri, vertex);\n if (rest.length !== 2) continue; // không suy được 2 tia → bỏ qua\n const [p1, p2] = rest;\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n }\n\n return hits.map<RuleMatch>((h) => ({\n ruleId: 'angleBisectorAngle',\n clauseIds: [h.clauseId],\n intents: [\n drawLine(`bis${h.p1}${h.vertex}${h.p2}`, 'angleBisector', {\n p1: h.p1,\n vertex: h.vertex,\n p2: h.p2,\n }) as IntentT,\n ],\n }));\n },\n};\n","// src/stamps/geometry-2d/ai/rules/centers.ts\n//\n// Tâm tam giác: trọng tâm (centroid), trực tâm (orthocenter), tâm đường tròn\n// ngoại tiếp (circumcenter), tâm đường tròn nội tiếp (incenter).\n//\n// Mọi kind này cần bộ 3 đỉnh of=[A,B,C]. Bind theo tam giác NÊU TRONG CÙNG\n// CLAUSE với cụm từ khoá (vd \"trọng tâm tam giác DEF\" → of=[D,E,F]) — KHÔNG lấy\n// tam giác đầu đề. Chỉ fallback tam giác toàn đề khi clause không nêu tam giác\n// nào VÀ đề có ĐÚNG 1 tam giác. Nhập nhằng (clause không nêu, đề >1 tam giác)\n// → bỏ qua (escalate). Không có tam giác nào → bỏ qua (escalate).\n// Tên điểm phải trích được (HOA ngay sau cụm từ khoá, hoặc \"X là <từ khoá>\");\n// nếu không → bỏ qua, KHÔNG bịa tên.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// Tam giác (global): quét mọi tam giác nêu trong một đoạn text.\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\n// === EN (issue #46 group B) =================================================\n// Tam giác tiếng Anh: \"triangle ABC\" (first-letter case flex [Tt], KHÔNG cờ 'i'\n// — sẽ phá [A-Z] nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]). ADDITIVE:\n// quét THÊM cùng TRI_G; merge theo vị trí TEXT để VN behavior giữ nguyên.\nconst TRI_EN_G = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n// Từ khoá tâm. \\b không khớp quanh ký tự Việt nên dùng lookaround \\p{L}.\n// \"trọng tâm\" — chặn nhầm với \"trung tâm\" bằng cách yêu cầu đúng \"trọng\".\nconst CENTROID_KW = /(?<!\\p{L})trọng\\s*tâm(?!\\p{L})/u;\n// \"trực tâm\" — chặn nhầm với \"trung trực\" (kết thúc bằng \"trực\", không phải \"trực tâm\").\nconst ORTHO_KW = /(?<!\\p{L})trực\\s*tâm(?!\\p{L})/u;\n// \"ngoại tiếp\" → circumcenter.\nconst CIRCUM_KW = /(?<!\\p{L})ngoại\\s*tiếp(?!\\p{L})/u;\n// \"nội tiếp\" → incenter (chỉ khi nói về TÂM, không phải \"tam giác nội tiếp đường tròn\").\nconst INSCRIBE_KW = /(?<!\\p{L})nội\\s*tiếp(?!\\p{L})/u;\n// Tên tâm đứng trước \"tâm\" qua \"là\": \"O là tâm\", \"Gọi O là tâm (đường tròn)…\".\nconst NAME_BEFORE_TAM = /(?<!\\p{L})([A-Z])\\s+là\\s+tâm(?!\\p{L})/u;\n\n// === EN keyword (issue #46 group B) =========================================\n// Từ khoá tâm tiếng Anh. First-letter case flex ([Cc], [Oo]…) — KHÔNG cờ 'i'\n// (sẽ phá [A-Z] nhãn). British spelling -centre cũng nhận. Neo (?![A-Za-z]) để\n// không khớp giữa từ dài hơn. centroid → centroid; orthocenter/-centre →\n// orthocenter; circumcenter/-centre → circumcenter; incenter/-centre → incenter.\nconst CENTROID_KW_EN = /(?<![A-Za-z])[Cc]entroid(?![A-Za-z])/u;\nconst ORTHO_KW_EN = /(?<![A-Za-z])[Oo]rthocent(?:er|re)(?![A-Za-z])/u;\nconst CIRCUM_KW_EN = /(?<![A-Za-z])[Cc]ircumcent(?:er|re)(?![A-Za-z])/u;\nconst INCENTER_KW_EN = /(?<![A-Za-z])[Ii]ncent(?:er|re)(?![A-Za-z])/u;\n\n// Tên điểm đứng NGAY SAU cụm từ khoá: \"trọng tâm G\", \"tâm (đường tròn) ngoại tiếp O\".\nfunction nameAfter(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const rest = text.slice(m.index + m[0].length);\n // bỏ qua các từ chêm phổ biến (\"của\", \"là\", \"tam giác\", \"đường tròn\", dấu câu)\n const after = /^[\\s,:của là]*?(?:tam\\s*giác\\s+)?([A-Z])(?!\\p{L})/u.exec(rest);\n return after ? after[1] : undefined;\n}\n\n// Tên điểm đứng TRƯỚC cụm từ khoá: \"G là trọng tâm\", \"H là trực tâm\".\nfunction nameBefore(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const before = text.slice(0, m.index);\n // \"...<HOA> (là)? \" ngay trước từ khoá\n const mm = /(?<!\\p{L})([A-Z])\\s+(?:là\\s+)?$/u.exec(before);\n return mm ? mm[1] : undefined;\n}\n\nfunction resolveName(text: string, kw: RegExp): string | undefined {\n return nameBefore(text, kw) ?? nameAfter(text, kw);\n}\n\n// Tâm đường tròn ngoại/nội tiếp: tên đứng trước \"tâm\" (qua \"là\") — vd \"Gọi O là\n// tâm đường tròn ngoại tiếp\" — hoặc sau cụm từ khoá — vd \"ngoại tiếp O\".\nfunction resolveCenterName(text: string, kw: RegExp): string | undefined {\n const before = NAME_BEFORE_TAM.exec(text);\n if (before) return before[1];\n return nameAfter(text, kw);\n}\n\n// --- EN name resolution (issue #46 group B) ---------------------------------\n// Tên điểm đứng TRƯỚC cụm từ khoá EN qua \"is/be the\": \"G is the centroid\",\n// \"Let H be the orthocenter\". Tên = ký tự HOA NGAY TRƯỚC \"is/be the <kw>\"\n// (cục bộ, KHÔNG quét lời dẫn toàn clause). KHÔNG cờ 'i' (giữ [A-Z]).\nfunction nameBeforeEn(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const before = text.slice(0, m.index);\n // \"...<HOA> (is|be) the \" ngay trước từ khoá.\n const mm = /(?<![A-Za-z])([A-Z])\\s+(?:is|be)\\s+the\\s+$/u.exec(before);\n return mm ? mm[1] : undefined;\n}\n\n// Tên điểm đứng NGAY SAU cụm từ khoá EN: \"centroid G\", \"orthocenter H\".\n// Bỏ qua từ chêm \"of\"/\"the\" KHÔNG được phép ở đây — nếu sau từ khoá là \"of …\"\n// (vd \"centroid of triangle ABC\") thì KHÔNG có tên điểm → undefined (fail-safe,\n// KHÔNG bịa tên).\nfunction nameAfterEn(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const rest = text.slice(m.index + m[0].length);\n const after = /^\\s+([A-Z])(?![A-Za-z])/u.exec(rest);\n return after ? after[1] : undefined;\n}\n\nfunction resolveNameEn(text: string, kw: RegExp): string | undefined {\n return nameBeforeEn(text, kw) ?? nameAfterEn(text, kw);\n}\n\n/** Một tam giác phát hiện trong text: bộ 3 đỉnh + offset bắt đầu match. */\ninterface TriHit {\n tri: string[];\n index: number;\n}\n\n/**\n * Tập tam giác (bộ 3 đỉnh + vị trí) nêu trong một đoạn text, gồm CẢ VN\n * (\"tam giác ABC\") VÀ EN (\"triangle ABC\"), sắp theo vị trí TEXT. ADDITIVE:\n * với đề thuần VN, chỉ TRI_G khớp ⇒ kết quả identical với hành vi cũ.\n */\nfunction triangleHits(text: string): TriHit[] {\n const hits: TriHit[] = [];\n TRI_G.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(text)) !== null) {\n hits.push({ tri: [m[1], m[2], m[3]], index: m.index });\n }\n TRI_EN_G.lastIndex = 0;\n while ((m = TRI_EN_G.exec(text)) !== null) {\n hits.push({ tri: [m[1], m[2], m[3]], index: m.index });\n }\n hits.sort((a, b) => a.index - b.index);\n return hits;\n}\n\n/**\n * Tập tam giác (mỗi tam giác = bộ 3 đỉnh) nêu trong một đoạn text. Trùng (cùng\n * 3 chữ liền) được giữ theo lượt xuất hiện; caller dedup nếu cần.\n */\nfunction trianglesIn(text: string): string[][] {\n return triangleHits(text).map((h) => h.tri);\n}\n\n/**\n * Tam giác để bind 'of' cho 1 clause:\n * 1. Ưu tiên tam giác nêu NGAY TRONG clause (gần cụm từ khoá nhất theo index).\n * 2. Nếu clause không nêu tam giác nào → fallback tam giác toàn đề CHỈ KHI đề\n * có duy nhất 1 tam giác (theo bộ đỉnh, dedup). Nhiều tam giác → undefined\n * (nhập nhằng, escalate). Không có tam giác → undefined.\n */\nfunction resolveTriangle(\n clauseText: string,\n kwIndex: number,\n uniqueProblemTri: string[] | undefined,\n): string[] | undefined {\n const inClause = triangleHits(clauseText);\n if (inClause.length > 0) {\n // chọn tam giác gần cụm từ khoá nhất (ưu tiên đứng SAU; nếu không có thì lấy\n // tam giác gần nhất bất kể phía). Gồm cả tam giác VN lẫn EN trong clause.\n let best: { tri: string[]; dist: number } | undefined;\n for (const h of inClause) {\n const idx = h.index;\n // khoảng cách: ưu tiên tam giác đứng sau từ khoá (idx >= kwIndex).\n const after = idx >= kwIndex;\n const dist = Math.abs(idx - kwIndex) + (after ? 0 : 1_000);\n if (!best || dist < best.dist) best = { tri: h.tri, dist };\n }\n return best?.tri;\n }\n return uniqueProblemTri;\n}\n\n/**\n * Tâm tam giác → add-point với of=[A,B,C]. Một clause có thể nêu nhiều tâm\n * (vd \"trọng tâm G và trực tâm H\"); emit từng intent, cùng claim clause.\n */\nexport const centersRule: LanguageRule = {\n id: 'centers',\n priority: 70,\n languages: ['vi', 'en'],\n patterns: [\n CENTROID_KW,\n ORTHO_KW,\n CIRCUM_KW,\n INSCRIBE_KW,\n CENTROID_KW_EN,\n ORTHO_KW_EN,\n CIRCUM_KW_EN,\n INCENTER_KW_EN,\n ],\n match(ctx) {\n // Tam giác duy nhất toàn đề (dedup theo bộ đỉnh) — dùng làm fallback khi\n // clause KHÔNG tự nêu tam giác. Nhiều tam giác khác nhau → undefined (nhập\n // nhằng → escalate). Không có → undefined (không dựng được → escalate).\n const allTri = trianglesIn(ctx.problem);\n const distinct = new Set(allTri.map((t) => t.join('')));\n const uniqueProblemTri = distinct.size === 1 ? allTri[0] : undefined;\n\n // helper: bind 'of' cho 1 cụm từ khoá tại vị trí kwIndex trong clause.\n const ofFor = (text: string, kw: RegExp): string[] | undefined => {\n const m = kw.exec(text);\n const kwIndex = m ? m.index : 0;\n return resolveTriangle(text, kwIndex, uniqueProblemTri);\n };\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents = [];\n\n if (CENTROID_KW.test(c.text)) {\n const name = resolveName(c.text, CENTROID_KW);\n const of = ofFor(c.text, CENTROID_KW);\n if (name && of) intents.push(addPoint(name, { kind: 'centroid', of }));\n }\n if (ORTHO_KW.test(c.text)) {\n const name = resolveName(c.text, ORTHO_KW);\n const of = ofFor(c.text, ORTHO_KW);\n if (name && of) intents.push(addPoint(name, { kind: 'orthocenter', of }));\n }\n // circumcenter: \"ngoại tiếp\". incenter: \"nội tiếp\" nhưng KHÔNG khi clause\n // cũng có \"ngoại tiếp\" (cùng cụm gây nhập nhằng) — ưu tiên ngoại tiếp.\n if (CIRCUM_KW.test(c.text)) {\n const name = resolveCenterName(c.text, CIRCUM_KW);\n const of = ofFor(c.text, CIRCUM_KW);\n if (name && of) intents.push(addPoint(name, { kind: 'circumcenter', of }));\n } else if (INSCRIBE_KW.test(c.text)) {\n const name = resolveCenterName(c.text, INSCRIBE_KW);\n const of = ofFor(c.text, INSCRIBE_KW);\n if (name && of) intents.push(addPoint(name, { kind: 'incenter', of }));\n }\n\n // --- EN (issue #46 group B) — mirror VN semantics, mỗi từ khoá độc lập --\n // Các danh từ tâm EN là chính tả riêng biệt (centroid/orthocenter/\n // circumcenter/incenter) nên KHÔNG nhập nhằng lẫn nhau như \"ngoại/nội\n // tiếp\" VN — xử lý từng cái độc lập. Tên + of giải qua helper EN; thiếu\n // tên HOẶC of không bind được → bỏ qua (escalate, KHÔNG bịa).\n if (CENTROID_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, CENTROID_KW_EN);\n const of = ofFor(c.text, CENTROID_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'centroid', of }));\n }\n if (ORTHO_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, ORTHO_KW_EN);\n const of = ofFor(c.text, ORTHO_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'orthocenter', of }));\n }\n if (CIRCUM_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, CIRCUM_KW_EN);\n const of = ofFor(c.text, CIRCUM_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'circumcenter', of }));\n }\n if (INCENTER_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, INCENTER_KW_EN);\n const of = ofFor(c.text, INCENTER_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'incenter', of }));\n }\n\n if (intents.length > 0) {\n out.push({ ruleId: 'centers', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpFoot.ts\n//\n// Hình chiếu vuông góc / chân đường vuông góc (đường cao):\n// \"Gọi H là hình chiếu (vuông góc) của A trên/lên/xuống (đường thẳng|cạnh)? BC\"\n// \"Gọi H là chân đường vuông góc (hạ|kẻ) từ A (đến|xuống) BC\"\n// \"H, K lần lượt là hình chiếu của B trên AC và của C trên AB\" → 2 foot\n// → addPoint('H', { kind:'perpFoot', from:'A', onLine:'BC' })\n//\n// onLine giữ nguyên token sau giới từ (pair 'BC' hoặc tên đường 1 ký tự 'd').\n//\n// Tên foot bind CỤC BỘ (ký tự HOA + \"là\" NGAY TRƯỚC cụm \"hình chiếu\"/\"chân đường\"),\n// KHÔNG lấy lời dẫn đầu clause — tránh gán nhầm cho \"Gọi N là điểm bất kỳ, H là …\".\n// Match GLOBAL để dựng đủ nhiều foot trong cùng clause.\n//\n// SKIP (để pipeline escalate AI thay vì đoán sai):\n// - không trích được tên foot cục bộ;\n// - modifier \"trung điểm (của)? hình chiếu …\" — đổi nghĩa, foot không còn là điểm cần dựng.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, DUONG_KW } from './_shared';\n\n// LƯU Ý: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt. Mọi\n// regex chứa ký tự Việt dùng cờ 'u' + tránh \\b.\n\n// Prefilter toàn đề: \"hình chiếu\" / \"chân đường (cao|vuông góc)\" / ký hiệu ⊥ /\n// \"vuông góc\" (cho dạng \"Kẻ AH ⊥ BC tại H\"). \"vuông góc\" rộng nhưng match() chỉ\n// emit khi pattern khớp thật → an toàn.\nconst PREFILTER = new RegExp(\n 'hình\\\\s*chiếu|chân\\\\s+(?:của\\\\s+)?' +\n DUONG_KW +\n '\\\\s+(?:cao|vuông\\\\s*góc)|⊥|vuông\\\\s*góc',\n 'u',\n);\n// EN prefilter (issue #46 group B). runRules prefilter theo `patterns` (BỎ QUA\n// field `languages`) → BẮT BUỘC có 1 EN regex thì match() mới chạy cho đề EN\n// thuần. Rộng nhưng match() chỉ emit khi core khớp thật → an toàn.\nconst PREFILTER_EN = /projection|perpendicular|foot\\s+of/i;\n\n// onLine token: tên đường 1 ký tự HOA HOẶC cặp đỉnh 2 ký tự HOA (vd 'BC'). Chấp\n// nhận tiền tố \"đường thẳng\" / \"cạnh\" / \"đoạn\" trước token.\nconst LINE = '(?:' + DUONG_KW + '\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])';\nconst PREP = '(?:trên|lên|xuống|đến|tới)';\n\n// \"hình chiếu (vuông góc)? (của)? X PREP [cạnh|đường thẳng] LINE\"\nconst PROJ_CORE = `hình\\\\s*chiếu\\\\s+(?:vuông\\\\s*góc\\\\s+)?(?:của\\\\s+)?([A-Z])\\\\s+${PREP}\\\\s+${LINE}`;\n// \"chân đường (vuông góc|cao) (hạ|kẻ|vẽ|dựng)? (từ)? X PREP LINE\"\nconst FOOT_CORE = `chân\\\\s+(?:của\\\\s+)?${DUONG_KW}\\\\s+(?:vuông\\\\s*góc|cao)\\\\s*(?:hạ\\\\s+|kẻ\\\\s+|vẽ\\\\s+|dựng\\\\s+)?(?:từ\\\\s+)?([A-Z])\\\\s+${PREP}\\\\s+${LINE}`;\n\n// Phân phối \"X, Y lần lượt là <core của FROM1 ... LINE1> và (của|từ)? FROM2 PREP LINE2\".\n// groups: 1=name1 2=name2 | PROJ: 3=from1 4=line1 | FOOT: 5=from1 6=line1 | tail: 7=from2 8=line2\nconst LANLUOT = new RegExp(\n `([A-Z])(?:[′'])?\\\\s*,\\\\s*([A-Z])(?:[′'])?\\\\s+lần\\\\s+lượt\\\\s+là\\\\s+(?:${PROJ_CORE}|${FOOT_CORE})\\\\s+và\\\\s+(?:của\\\\s+|từ\\\\s+)?([A-Z])\\\\s+${PREP}\\\\s+${LINE}`,\n 'gu',\n);\n\n// Một foot đơn (projection hoặc chân đường).\n// groups: PROJ 1=from 2=line | FOOT 3=from 4=line\nconst SINGLE = new RegExp(`(?:${PROJ_CORE})|(?:${FOOT_CORE})`, 'gu');\n\n// Distributive SHARED-FROM: \"X, Y, Z lần lượt là hình chiếu (vuông góc)? của D\n// trên BC, CA, AB\" → zip tên↔cạnh, MỘT `from` (D) chung. KHÁC LANLUOT (2 chân,\n// mỗi chân from riêng, nối \"và\"): ở đây 1 from + DANH SÁCH cạnh ngăn phẩy (≥2).\n// Số tên PHẢI bằng số cạnh (else bỏ → escalate, không đoán lệch).\n// groups: 1=names blob (≥2, phẩy) | 2=from | 3=lines blob (≥2, phẩy)\nconst NAMES_BLOB = \"((?:[A-Z](?:['′]?)\\\\s*,\\\\s*)+[A-Z](?:['′]?))\";\nconst LINES_BLOB = '((?:[A-Z]{1,2}\\\\s*,\\\\s*)+[A-Z]{1,2})(?!\\\\p{L})';\nconst DISTRIB_PROJ = new RegExp(\n NAMES_BLOB +\n '\\\\s+lần\\\\s*lượt\\\\s+(?:là\\\\s+)?hình\\\\s*chiếu\\\\s+(?:vuông\\\\s*góc\\\\s+)?(?:của\\\\s+)?([A-Z])(?!\\\\p{L})' +\n '\\\\s+(?:trên|lên|xuống|đến)\\\\s+(?:các\\\\s+)?' +\n LINES_BLOB,\n 'gu',\n);\nconst DISTRIB_FOOT = new RegExp(\n NAMES_BLOB +\n '\\\\s+lần\\\\s*lượt\\\\s+(?:là\\\\s+)?chân\\\\s+(?:của\\\\s+)?đường\\\\s+(?:vuông\\\\s*góc|cao)\\\\s*(?:hạ\\\\s+|kẻ\\\\s+|vẽ\\\\s+|dựng\\\\s+)?(?:từ\\\\s+)?([A-Z])(?!\\\\p{L})' +\n '\\\\s+(?:đến|xuống|trên|tới)\\\\s+(?:các\\\\s+)?' +\n LINES_BLOB,\n 'gu',\n);\n\n/** Tách blob tên distributive \"X, Y, Z\" → ['X','Y','Z'] (chuẩn hoá prime ′→'). */\nfunction splitNames(blob: string): string[] {\n return blob\n .split(',')\n .map((s) => {\n const mm = /^([A-Z])(['′]?)/u.exec(s.trim());\n return mm ? (mm[2] ? `${mm[1]}'` : mm[1]) : '';\n })\n .filter(Boolean);\n}\n\n// \"Kẻ/Vẽ/Dựng XY (⊥|vuông góc với?) [cạnh|đường thẳng]? LINE (tại Z)?\"\n// \"Kẻ AH ⊥ BC tại H\" | \"Vẽ AH vuông góc với BC\" | \"Dựng AH vuông góc cạnh BC\"\n// Tên foot = chữ thứ 2 của cặp XY (g2); from = g1; onLine = g3. \"tại Z\" (g4) nếu\n// có PHẢI trùng foot (else xung đột → skip). connect.ts (SEG_KW \"Kẻ AH\") đã lo\n// đoạn AH → rule này CHỈ emit add-point, KHÔNG connect (tránh double).\n// groups: 1=from 2=foot 3=onLine 4=tại-point(optional)\nconst PERP_DRAW = new RegExp(\n `(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+(?:⊥|vuông\\\\s*góc(?:\\\\s+với)?)\\\\s+(?:với\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])(?:\\\\s+tại\\\\s+([A-Z]))?`,\n 'gu',\n);\n\n// modifier \"trung điểm (của)?\" NGAY TRƯỚC cụm → đổi nghĩa, không dựng foot.\nconst MID_BEFORE = /trung\\s+điểm(?:\\s+của)?\\s*$/u;\n// Tên foot cục bộ: ký tự HOA + \"là\" NGAY TRƯỚC cụm (vd \"Gọi H là \", \"… , H là \").\nconst NAME_BEFORE = /([A-Z])(?:[′'])?\\s+là\\s+$/u;\n\n// === EN (issue #46 group B) ==================================================\n// Additive — KHÔNG đụng building block VN ở trên. Nhãn STRICT [A-Z] (KHÔNG cờ\n// 'i' — sẽ nuốt chữ thường); first-letter flex của verb bằng [Dd]/[Cc].\n//\n// onLine token EN: tiền tố \"line \"/\"side \"/\"segment \" optional + 1-2 ký tự HOA,\n// neo (?![A-Z]) để chặn cụm 3+ ký tự.\nconst LINE_EN = '(?:line\\\\s+|side\\\\s+|segment\\\\s+)?([A-Z]{1,2})(?![A-Z])';\n\n// Form A — \"(orthogonal)? projection of X (onto|on|to) LINE\"\n// groups: 1=from 2=line\nconst PROJ_CORE_EN = `(?:orthogonal\\\\s+)?projection\\\\s+of\\\\s+([A-Z])\\\\s+(?:onto|on|to)\\\\s+${LINE_EN}`;\n// Form B — \"foot of (the)? (perpendicular|altitude) from X (to|onto|on) LINE\"\n// groups: 1=from 2=line\nconst FOOT_CORE_EN = `foot\\\\s+of\\\\s+(?:the\\\\s+)?(?:perpendicular|altitude)\\\\s+from\\\\s+([A-Z])\\\\s+(?:to|onto|on)\\\\s+${LINE_EN}`;\n\n// Single EN core (projection HOẶC foot-of). Ghép 2 group block → group dịch:\n// PROJ: 1=from 2=line | FOOT: 3=from 4=line → đọc bằng m[1]??m[3], m[2]??m[4].\nconst SINGLE_EN = new RegExp(`(?:${PROJ_CORE_EN})|(?:${FOOT_CORE_EN})`, 'gu');\n\n// Form C draw — \"Draw|Construct|Drop XY perpendicular to (line|side|segment)? LINE (at Z)?\"\n// \"Draw AH perpendicular to BC at H\" | \"Construct AH perpendicular to BC\"\n// foot = chữ thứ 2 cặp XY (g2); from = g1; onLine = g3; at = g4 (optional).\n// \"Draw the perpendicular bisector …\" KHÔNG khớp: sau \"Draw\" là \"the\" (chữ\n// thường) chứ không phải cặp HOA → perpBisector territory, không double-emit.\n// groups: 1=from 2=foot 3=onLine 4=at(optional)\nconst PERP_DRAW_EN = new RegExp(\n `(?:[Dd]raw|[Cc]onstruct|[Dd]rop)\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+perpendicular\\\\s+to\\\\s+(?:line\\\\s+|side\\\\s+|segment\\\\s+)?([A-Z]{1,2})(?![A-Z])(?:\\\\s+at\\\\s+([A-Z]))?`,\n 'gu',\n);\n\n// Tên foot ĐỨNG TRƯỚC core qua \"Let X be the …\" / \"X is the …\".\n// \"Let H be the projection …\" | \"K is the orthogonal projection …\"\nconst NAME_BEFORE_EN = /([A-Z])(?:[′'])?\\s+(?:be|is)\\s+(?:the\\s+)?$/u;\n\ninterface Foot {\n name: string;\n from: string;\n onLine: string;\n /** Emit thêm connect(from, foot) — đoạn vuông góc từ điểm tới chân. Dùng cho:\n * Form C (EN draw \"Draw AH ⊥ BC\") + distributive VN \"X,Y,Z hình chiếu của D…\"\n * (thể hiện hình chiếu DX/DY/DZ). Foot đơn VN KHÔNG set → byte-identical. */\n withSegment?: boolean;\n}\n\n/** Parse mọi foot trong 1 clause. Trả [] nếu không bind được tên / bị skip. */\nfunction parseFeet(text: string): Foot[] {\n const out: Foot[] = [];\n const consumed: Array<[number, number]> = [];\n\n // 0) Distributive SHARED-FROM: \"X, Y, Z lần lượt là hình chiếu/chân vuông góc\n // của D trên BC, CA, AB\" → zip tên↔cạnh (from D chung). Span đã khớp →\n // consumed để SINGLE không xử lại. Zip lệch (số tên ≠ số cạnh) → bỏ.\n for (const re of [DISTRIB_PROJ, DISTRIB_FOOT]) {\n re.lastIndex = 0;\n for (const dm of text.matchAll(re)) {\n const names = splitNames(dm[1]);\n const from = dm[2];\n const lines = dm[3].split(',').map((s) => s.trim()).filter(Boolean);\n if (names.length < 2 || names.length !== lines.length) continue; // zip lệch → escalate\n // withSegment: vẽ kèm đoạn vuông góc from→foot (DX/DY/DZ) để THỂ HIỆN hình\n // chiếu (render perpFoot chỉ tạo điểm chân, không tự vẽ đường rớt vuông góc).\n names.forEach((name, i) => out.push({ name, from, onLine: lines[i], withSegment: true }));\n consumed.push([dm.index ?? 0, (dm.index ?? 0) + dm[0].length]);\n }\n }\n\n // 1) \"X, Y lần lượt là … và …\" → 2 foot (name bind sẵn trong cú pháp).\n LANLUOT.lastIndex = 0;\n let lm: RegExpExecArray | null;\n while ((lm = LANLUOT.exec(text)) !== null) {\n if (MID_BEFORE.test(text.slice(0, lm.index))) continue; // \"trung điểm của …\" → skip\n const from1 = lm[3] ?? lm[5];\n const line1 = lm[4] ?? lm[6];\n out.push({ name: lm[1], from: from1, onLine: line1 });\n out.push({ name: lm[2], from: lm[7], onLine: lm[8] });\n consumed.push([lm.index, lm.index + lm[0].length]);\n }\n\n // 2) foot đơn — bind tên CỤC BỘ. Bỏ qua nếu nằm trong span \"lần lượt\" đã xử lý.\n SINGLE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = SINGLE.exec(text)) !== null) {\n const start = m.index;\n if (consumed.some(([a, b]) => start >= a && start < b)) continue;\n const before = text.slice(0, start);\n if (MID_BEFORE.test(before)) continue; // \"trung điểm của hình chiếu …\" → đổi nghĩa\n const nm = NAME_BEFORE.exec(before);\n if (!nm) continue; // không có tên cục bộ → escalate AI\n out.push({ name: nm[1], from: m[1] ?? m[3], onLine: m[2] ?? m[4] });\n }\n\n // 3) \"Kẻ XY ⊥ LINE (tại Z)\" — tên foot lấy từ cặp XY (không cần \"X là\").\n PERP_DRAW.lastIndex = 0;\n let pm: RegExpExecArray | null;\n while ((pm = PERP_DRAW.exec(text)) !== null) {\n const from = pm[1];\n const foot = pm[2];\n const onLine = pm[3];\n const at = pm[4]; // \"tại Z\" (optional)\n if (at && at !== foot) continue; // \"tại K\" ≠ chân H → xung đột → escalate\n if (onLine.includes(foot)) continue; // chân trùng đỉnh của đường → degenerate\n out.push({ name: foot, from, onLine });\n }\n\n // 4) EN projection / foot-of — tên bind ĐỨNG TRƯỚC qua \"Let X be the …\"/\"X is\n // the …\". Không có tên-trước → escalate (fail-safe). \"trung điểm\" KHÔNG\n // áp dụng EN; MID_BEFORE giữ nguyên VN, ở đây không cần.\n SINGLE_EN.lastIndex = 0;\n let em: RegExpExecArray | null;\n while ((em = SINGLE_EN.exec(text)) !== null) {\n const before = text.slice(0, em.index);\n const nm = NAME_BEFORE_EN.exec(before);\n if (!nm) continue; // không có \"X be/is the\" → escalate AI\n const from = em[1] ?? em[3];\n const onLine = em[2] ?? em[4];\n out.push({ name: nm[1], from, onLine });\n }\n\n // 5) EN draw form \"Draw XY perpendicular to LINE (at Z)\" — foot = chữ 2 cặp XY.\n // connect.ts VN-only → tự emit connect(from, foot) để vẽ đoạn (parity VN).\n PERP_DRAW_EN.lastIndex = 0;\n let dm: RegExpExecArray | null;\n while ((dm = PERP_DRAW_EN.exec(text)) !== null) {\n const from = dm[1];\n const foot = dm[2];\n const onLine = dm[3];\n const at = dm[4]; // \"at Z\" (optional)\n if (at && at !== foot) continue; // \"at K\" ≠ chân H → xung đột → escalate\n if (onLine.includes(foot)) continue; // chân trùng đỉnh đường → degenerate\n out.push({ name: foot, from, onLine, withSegment: true });\n }\n return out;\n}\n\n/**\n * Mỗi clause → 0..n add-point perpFoot. Tên foot bind cục bộ theo cú pháp gần,\n * match global để dựng đủ (vd \"H, K lần lượt …\" = 2 foot).\n */\nexport const perpFootRule: LanguageRule = {\n id: 'perpFoot',\n priority: 65,\n languages: ['vi', 'en'],\n patterns: [PREFILTER, PREFILTER_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const feet = parseFeet(c.text);\n if (feet.length === 0) continue;\n // Foot add-point TRƯỚC; với EN draw form (withSegment) push THÊM connect\n // NGAY SAU add-point của foot đó (H phải tồn tại trước khi connect tham\n // chiếu). VN feet không set withSegment → byte-identical.\n const intents = feet.flatMap((f) => {\n const add = addPoint(f.name, { kind: 'perpFoot', from: f.from, onLine: f.onLine });\n return f.withSegment ? [add, connect(f.from, f.name, 'segment')] : [add];\n });\n out.push({ ruleId: 'perpFoot', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleRadius.ts\n//\n// Đường tròn theo TÂM: bán kính số / bán kính ký hiệu CHỮ / \"đi qua <điểm>\".\n// - \"đường tròn (tâm) O bán kính 3\" → centerRadius {center:'O', radius:3}\n// - \"(O; 3)\" / \"(O, 3)\" → centerRadius {center:'O', radius:3}\n// - \"(O; R)\" / \"(I; r)\" / \"bán kính R\" → centerRadius bán kính CANONICAL\n// (issue #46 nhóm A — xem dưới)\n// - \"đường tròn tâm O đi qua A\" → centerThrough {center:'O', through:'A'}\n//\n// CHỈ emit khi có bán kính SỐ, bán kính ký hiệu CHỮ (R/r), hoặc \"đi qua <điểm>\".\n// \"(O)\" trơ (không số/chữ/\"đi qua\") → bỏ qua (chỉ tham chiếu; rule khác/AI xử lý).\n//\n// BÁN KÍNH KÝ HIỆU CHỮ (issue #46): \"Cho đường tròn (O; R)\" cực phổ biến ở đề thi.\n// R là KÝ HIỆU (giá trị thực không cho) → vẽ với bán kính CANONICAL dương để minh\n// hoạ (fail-safe: không sai ngữ nghĩa — đường tròn tâm O bán kính tuỳ ý). CHỈ nhận\n// đúng [Rr] đứng riêng: hệ số \"2R\" (defer Cụm C) và chữ khác \"(A; B)\" → bỏ qua.\n//\n// GOTCHA segmentation: segmentClauses() tách trên '.' ';' ',' nên ký hiệu gọn\n// \"(O; 3)\" / \"(O, 2.5)\" BỊ cắt ngang clause (\"(O\" và \"3)\" thành 2 clause). Vì\n// vậy nhánh PAREN quét trên TOÀN đề (ctx.problem) rồi gán match cho clause chứa\n// fragment \"(<tâm>\". Nhánh WORDS / THROUGH segment nguyên vẹn → quét per-clause.\n//\n// GOTCHA \\b: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { Clause } from '../deterministic/coverage';\nimport { drawCircle, CIRCLE_KW } from './_shared';\n\n// \"đường tròn tâm O bán kính 3\" / \"(O) bán kính 3\" / \"O bán kính 3\".\n// Tâm 1 ký tự HOA; \"tâm\" optional; có thể bọc trong ngoặc \"(O)\".\n// Hỗ trợ PAREN tên chữ (alpha, omega...).\n//\n// GLOBAL (/gu) vì 1 clause có thể nêu NHIỀU đường tròn (\"tâm I bán kính 2 và\n// tâm O bán kính 5\" không có dấu câu tách → cùng clause). matchAll quét hết.\n//\n// Gap tâm→\"bán kính\" dùng tempered quantifier `(?:(?!đường|và\\s)[^A-Z])*?` để\n// KHÔNG nhảy qua một \"đường tròn\" khác hay liên từ \"và \" (ranh giới giữa 2 hình).\n// Nếu nhảy qua được, \"tâm O và … tâm I bán kính 5\" sẽ bind nhầm 5 vào O. Chặn ở\n// đây ⇒ match bắt đầu từ O thất bại, regex tự dời tới \"tâm I bán kính 5\" (đúng),\n// còn \"tâm O\" trơ (không số) không bị nuốt → không claim → escalate phần đó.\nconst CENTER_RADIUS_WORDS_G = new RegExp(\n CIRCLE_KW +\n '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?:\\\\s*\\\\))?(?:(?!đường|và\\\\s)[^A-Z])*?bán\\\\s*kính\\\\s+(\\\\d+(?:[.,]\\\\d+)?)',\n 'gu',\n);\n\n// \"đường tròn tâm O đi qua A\" / \"(O) đi qua A\" / \"O đi qua A\".\n// GLOBAL: nhiều \"đường tròn … đi qua …\" trong 1 clause.\nconst CENTER_THROUGH_G = new RegExp(\n CIRCLE_KW + '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?:\\\\s*\\\\))?\\\\s+đi\\\\s+qua\\\\s+([A-Z])',\n 'gu',\n);\n\n// Phần \"đi qua B và C\" (≥2 điểm surface): chưa hỗ trợ (DSL centerThrough 1 điểm).\n// Phát hiện để SKIP match đó → điểm thứ 2 (C) thiếu trong DSL → named-entity\n// guard escalate AI (an toàn) thay vì render thiếu C.\nconst THROUGH_MULTI = /đi\\s+qua\\s+[A-Z]\\s*(?:và|,)\\s*[A-Z]/u;\n\n// Ký hiệu gọn \"(O; 3)\" / \"(O, 3)\" — quét toàn đề (global) vì có thể nhiều.\nconst CENTER_RADIUS_PAREN_G = /\\(\\s*([A-Z])\\s*[;,]\\s*(\\d+(?:[.,]\\d+)?)\\s*\\)/gu;\n\n/**\n * Bán kính CANONICAL (board units) khi đề cho bán kính KÝ HIỆU CHỮ (\"(O; R)\",\n * \"bán kính R\"). Giá trị thực là ký hiệu → vẽ minh hoạ; khớp scale với bán kính\n * số mặc định nhỏ (vd \"(O; 3)\"). circleCR yêu cầu radius > 0.\n */\nexport const SYMBOLIC_RADIUS = 3;\n\n// Ký hiệu gọn bán kính CHỮ \"(O; R)\" / \"(I; r)\" — quét toàn đề. Bán kính CHỈ [Rr]\n// đứng RIÊNG (theo sau là ')'): \"2R\" (hệ số, defer) và chữ khác \"(A; B)\" KHÔNG\n// khớp → escalate (fail-safe). Center 1 ký tự HOA như nhánh số.\nconst CENTER_RADIUS_LETTER_PAREN_G = /\\(\\s*([A-Z])\\s*[;,]\\s*[Rr]\\s*\\)/gu;\n\n// \"đường tròn tâm O bán kính R\" — words, bán kính CHỮ. Mirror tempered của\n// CENTER_RADIUS_WORDS_G; (?![A-Za-z]) chặn \"Ra\"/\"Rồi\"… và phần số (\"2R\") để\n// nhánh số lo. GLOBAL: nhiều đường tròn / clause.\n// \"đường tròn tâm O bán kính R\" — words, bán kính CHỮ. Mirror tempered của\n// CENTER_RADIUS_WORDS_G; (?![A-Za-z]) chặn \"Ra\"/hệ số \"2R\" (nhánh số lo phần \"2\", nhưng \"radius 2R\"\n// hiếm; vẫn fail-safe vì \\d không có sau \"radius\" khi viết \"radius R\").\nconst CENTER_RADIUS_LETTER_WORDS_G = new RegExp(\n CIRCLE_KW +\n '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?:\\\\s*\\\\))?(?:(?!đường|và\\\\s)[^A-Z])*?bán\\\\s*kính\\\\s+[Rr](?![A-Za-z])',\n 'gu',\n);\n\n// === EN words patterns (issue #46 group B) ==================================\n// Tiền tố tâm EN dùng chung cho cả 3 dạng (radius số / radius CHỮ / passing\n// through). Chấp nhận: \"circle with center O\", \"circle centered at O\", \"circle\n// of center O\" + chính tả Anh-Anh \"centre\". cent(?:er|re) + (?:ed)? + (?:at|of)?\n// First-letter case flex [Cc] — KHÔNG cờ 'i' (sẽ phá [A-Z] tâm/điểm).\n//\n// Gap tâm→keyword: tempered `(?:(?![Cc]ircle)[^A-Z])*?` — KHÔNG nhảy qua \"circle\"\n// khác (ranh giới giữa 2 đường tròn) và KHÔNG nuốt chữ HOA (tâm/điểm kế). Lazy →\n// dừng ở \"radius\"/\"passing\" gần nhất. GLOBAL: nhiều đường tròn / clause.\nconst CIRCLE_CENTER_EN =\n '[Cc]ircle\\\\s+(?:with\\\\s+|of\\\\s+)?cent(?:er|re)(?:ed)?\\\\s+(?:at\\\\s+|of\\\\s+)?([A-Z])(?![A-Za-z])';\nconst EN_GAP = '(?:(?![Cc]ircle)[^A-Z])*?';\n\n// \"circle with center O and radius 3\" / \"circle centered at O with radius 3\" /\n// \"circle of center O radius 3\" → centerRadius số.\nconst CIRCLE_CR_EN_G = new RegExp(\n CIRCLE_CENTER_EN + EN_GAP + 'radius\\\\s+(\\\\d+(?:[.,]\\\\d+)?)',\n 'gu',\n);\n\n// \"circle with center O and radius R\" (bán kính CHỮ ký hiệu) → canonical.\n// (?![A-Za-z]) chặn \"Ra\"/hệ số \"2R\" (nhánh số lo phần \"2\", nhưng \"radius 2R\"\n// hiếm; vẫn fail-safe vì \\d không có sau \"radius\" khi viết \"radius R\").\nconst CIRCLE_CR_LETTER_EN_G = new RegExp(\n CIRCLE_CENTER_EN + EN_GAP + 'radius\\\\s+[Rr](?![A-Za-z])',\n 'gu',\n);\n\n// \"circle with center O passing through A\" / \"circle centered at O passing\n// through A\" → centerThrough. Điểm = 1 ký tự HOA neo (?![A-Za-z]).\nconst CIRCLE_THROUGH_EN_G = new RegExp(\n CIRCLE_CENTER_EN + EN_GAP + 'passing\\\\s+through\\\\s+([A-Z])(?![A-Za-z])',\n 'gu',\n);\n\n// Prefilter EN (NON-global để không vướng lastIndex ở .some(test)).\nconst EN_PREFILTER = new RegExp(CIRCLE_CENTER_EN, 'u');\n\n/** \"3\" / \"3.5\" / \"3,5\" → number. NaN nếu không parse được. */\nfunction parseNum(raw: string): number {\n return Number(raw.replace(',', '.'));\n}\n\n/**\n * Circle này là đường tròn NGOẠI/NỘI TIẾP tam giác? (\"tam giác ABC nội tiếp\n * đường tròn (O; 3)\") → circleTriangle sở hữu (through3/inscribedIn theo 3 đỉnh);\n * circleRadius KHÔNG emit thêm 1 đường tròn rời (sẽ chồng + không nhất quán).\n * Bán kính chỉ là chú thích — circumcircle xác định bởi 3 đỉnh, bỏ radius là OK.\n */\nfunction isInscribedCircumscribed(problem: string, center: string): boolean {\n // Quan hệ \"nội/ngoại tiếp\" (VN) + \"inscribed/circumscribes/circumscribed\" (EN,\n // issue #46 group B). EN mirror chống silent-WRONG: \"Triangle ABC inscribed in\n // circle (O; 3)\" — circleTriangle EN sở hữu through3 (qua 3 đỉnh) → circleRadius\n // KHÔNG emit centerRadius rời quanh O.\n const REL = '(?:(?:nội|ngoại)\\\\s*tiếp|[Ii]nscribed|[Cc]ircumscrib(?:es|ed))';\n // Chiều 1 — quan hệ ĐỨNG TRƯỚC circle: \"(tam giác) nội/ngoại tiếp … (O\".\n // Gap [^.]{0,30}? đủ nuốt \"in circle \" trước \"(O\" (EN).\n const after = new RegExp(\n `${REL}[^.]{0,30}?(?:đường\\\\s*tròn\\\\s*|[Cc]ircle\\\\s*)?\\\\(?\\\\s*${center}(?![A-Z])`,\n 'u',\n );\n // Chiều 2 — circle ĐỨNG TRƯỚC quan hệ: ký hiệu \"(O; R) … ngoại/nội tiếp\".\n // circleTriangle sở hữu circumcircle/incircle (qua 3 đỉnh) → circleRadius bỏ\n // để tránh DOUBLE-circle quanh O. [^()]* không vượt ngoặc khác; [^.]{0,30}?\n // không nhảy câu (giữ proximity, tránh false-positive với circle rời khác).\n const before = new RegExp(\n `\\\\(\\\\s*${center}\\\\s*[;,][^()]*\\\\)[^.]{0,30}?${REL}`,\n 'u',\n );\n return after.test(problem) || before.test(problem);\n}\n\n/** Clause chứa fragment \"(<center>\" (ký hiệu gọn bị segmentation cắt vào đây). */\nfunction findParenClauseId(\n clauses: readonly Clause[],\n center: string,\n): number | undefined {\n const frag = new RegExp(`\\\\(\\\\s*${center}(?![A-Z])`, 'u');\n for (const c of clauses) if (frag.test(c.text)) return c.id;\n return undefined;\n}\n\nexport const circleRadiusRule: LanguageRule = {\n id: 'circleRadius',\n priority: 75,\n languages: ['vi', 'en'],\n patterns: [\n CENTER_RADIUS_WORDS_G,\n CENTER_THROUGH_G,\n /\\(\\s*[A-Z]\\s*[;,]\\s*\\d/u,\n /\\(\\s*[A-Z]\\s*[;,]\\s*[Rr]\\s*\\)/u, // ký hiệu bán kính CHỮ \"(O; R)\"\n /bán\\s*kính\\s+[Rr](?![A-Za-z])/u, // words bán kính CHỮ \"bán kính R\"\n EN_PREFILTER, // EN \"circle with center O …\" (issue #46 group B)\n ],\n match(ctx) {\n const out: RuleMatch[] = [];\n\n // --- Per-clause: dạng \"bán kính <số>\" + \"đi qua <điểm>\" (segment nguyên) ---\n for (const c of ctx.clauses) {\n // 1) \"đi qua <điểm>\" (centerThrough). GLOBAL: nhiều đường tròn / clause.\n // \"đi qua B và C\" (≥2 điểm) → SKIP toàn bộ centerThrough clause này:\n // chưa hỗ trợ multi-surface-point, để guard escalate (không render thiếu).\n const throughMulti = THROUGH_MULTI.test(c.text);\n if (!throughMulti) {\n CENTER_THROUGH_G.lastIndex = 0;\n let ct: RegExpExecArray | null;\n while ((ct = CENTER_THROUGH_G.exec(c.text)) !== null) {\n const center = ct[1];\n const through = ct[2];\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerThrough', { center, through })],\n });\n }\n }\n\n // 2) \"bán kính <số>\". GLOBAL: \"tâm I bán kính 2 và tâm O bán kính 5\" emit\n // 2 intent. Gap tempered (xem CENTER_RADIUS_WORDS_G) ⇒ không bind nhầm.\n // radius CHỮ (\"R\") → \\d không match → bỏ qua → escalate.\n CENTER_RADIUS_WORDS_G.lastIndex = 0;\n let crw: RegExpExecArray | null;\n while ((crw = CENTER_RADIUS_WORDS_G.exec(c.text)) !== null) {\n const center = crw[1];\n const radius = parseNum(crw[2]);\n if (!Number.isFinite(radius) || radius <= 0) continue;\n if (isInscribedCircumscribed(ctx.problem, center)) continue; // circleTriangle sở hữu\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius })],\n });\n }\n\n // 3) \"bán kính R/r\" (bán kính CHỮ ký hiệu) → centerRadius bán kính canonical.\n // Clause có \"nội/ngoại tiếp\" → mơ hồ (circleTriangle/escalate sở hữu) → bỏ\n // (clause-local, không ảnh hưởng nhánh số ở clause khác).\n if (!/(?:nội|ngoại)\\s*tiếp/u.test(c.text)) {\n CENTER_RADIUS_LETTER_WORDS_G.lastIndex = 0;\n let clw: RegExpExecArray | null;\n while ((clw = CENTER_RADIUS_LETTER_WORDS_G.exec(c.text)) !== null) {\n const center = clw[1];\n if (isInscribedCircumscribed(ctx.problem, center)) continue;\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n }\n\n // --- EN words (issue #46 group B) ---------------------------------------\n // Fail-safe: clause có \"inscribed\"/\"circumscribed\" → circle phụ thuộc\n // tam giác/hình (circleTriangle EN OUT OF SCOPE) → KHÔNG emit lone circle.\n if (!/[Ii]nscribed|[Cc]ircumscribed/u.test(c.text)) {\n // 1) passing through → centerThrough.\n CIRCLE_THROUGH_EN_G.lastIndex = 0;\n let ent: RegExpExecArray | null;\n while ((ent = CIRCLE_THROUGH_EN_G.exec(c.text)) !== null) {\n const center = ent[1];\n const through = ent[2];\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerThrough', { center, through })],\n });\n }\n\n // 2) radius <số> → centerRadius.\n CIRCLE_CR_EN_G.lastIndex = 0;\n let ecr: RegExpExecArray | null;\n while ((ecr = CIRCLE_CR_EN_G.exec(c.text)) !== null) {\n const center = ecr[1];\n const radius = parseNum(ecr[2]);\n if (!Number.isFinite(radius) || radius <= 0) continue;\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius })],\n });\n }\n\n // 3) radius R/r (ký hiệu CHỮ) → centerRadius canonical.\n CIRCLE_CR_LETTER_EN_G.lastIndex = 0;\n let ecl: RegExpExecArray | null;\n while ((ecl = CIRCLE_CR_LETTER_EN_G.exec(c.text)) !== null) {\n const center = ecl[1];\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n }\n }\n\n // --- Toàn đề: ký hiệu gọn \"(O; 3)\" / \"(O, 3)\" (bị segmentation cắt) -------\n CENTER_RADIUS_PAREN_G.lastIndex = 0;\n let pm: RegExpExecArray | null;\n while ((pm = CENTER_RADIUS_PAREN_G.exec(ctx.problem)) !== null) {\n const center = pm[1];\n const radius = parseNum(pm[2]);\n if (!Number.isFinite(radius) || radius <= 0) continue;\n if (isInscribedCircumscribed(ctx.problem, center)) continue; // circleTriangle sở hữu\n const clauseId = findParenClauseId(ctx.clauses, center);\n out.push({\n ruleId: 'circleRadius',\n clauseIds: clauseId === undefined ? [] : [clauseId],\n intents: [drawCircle(center, 'centerRadius', { center, radius })],\n });\n }\n\n // --- Toàn đề: ký hiệu bán kính CHỮ \"(O; R)\" / \"(I; r)\" (segmenter cắt ';') ---\n // Bán kính ký hiệu → bán kính canonical. Guard 2 chiều bỏ qua khi đường tròn\n // nội/ngoại tiếp tam giác (circleTriangle sở hữu).\n CENTER_RADIUS_LETTER_PAREN_G.lastIndex = 0;\n let lpm: RegExpExecArray | null;\n while ((lpm = CENTER_RADIUS_LETTER_PAREN_G.exec(ctx.problem)) !== null) {\n const center = lpm[1];\n if (isInscribedCircumscribed(ctx.problem, center)) continue; // circleTriangle sở hữu\n const clauseId = findParenClauseId(ctx.clauses, center);\n out.push({\n ruleId: 'circleRadius',\n clauseIds: clauseId === undefined ? [] : [clauseId],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleTriangle.ts\n//\n// Đường tròn nội/ngoại tiếp tam giác:\n// \"đường tròn ngoại tiếp tam giác ABC\" → circumcircle → drawCircle through3\n// \"đường tròn nội tiếp tam giác ABC\" → incircle → drawCircle inscribedIn\n//\n// LƯU Ý disambiguate \"nội tiếp\" có 2 nghĩa ngược nhau tuỳ ngữ cảnh:\n// - \"ĐƯỜNG TRÒN nội tiếp tam giác\" → incircle (inscribedIn)\n// - \"TAM GIÁC nội tiếp đường tròn\" → circumcircle (through3) — tam giác nội\n// tiếp tức đường tròn NGOẠI tiếp tam giác.\n// \"ngoại tiếp\" (đường tròn ngoại tiếp tam giác) luôn là circumcircle.\n//\n// QUAN TRỌNG (chống mis-render):\n// - \"đường tròn ngoại/nội tiếp\" PHẢI theo sau bởi \"tam giác <XYZ>\" (token \"tam\n// giác\" bắt buộc). Nếu theo sau là \"tứ giác\"/\"hình ...\" (vd \"đường tròn\n// ngoại tiếp tứ giác BCEF\") → CHƯA hỗ trợ → KHÔNG claim để escalate AI, KHÔNG\n// được vơ tam giác đầu đề (mis-render circle qua 3 đỉnh khác).\n// - Bind tam giác từ cụm ngay SAU từ khoá trong clause (không phải tam giác\n// đầu tiên trong đề). Nhiều cấu trúc / clause → emit-all (matchAll cờ 'g').\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawCircle, CIRCLE_KW } from './_shared';\n\n// \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Dùng lookaround \\p{L} + cờ 'u'.\nconst HAS_INSCRIBE = /(?<!\\p{L})(?:nội|ngoại)\\s*tiếp(?!\\p{L})/iu;\n\n// Tên tâm tuỳ chọn xen giữa \"đường tròn\" và \"ngoại/nội tiếp\": \"(O)\" hoặc \"tâm O\".\n// (?:...)? để có thể vắng. Cờ 'i' an toàn ở cụm từ khoá; ([A-Z]) vẫn HOA-only.\n// PAREN hỗ trợ cả tên chữ (alpha, omega, (O)...).\nconst CENTER = '(?:\\\\(\\\\s*([^\\\\s;,).:]+)\\\\s*\\\\)|tâm\\\\s+([A-Z]))?';\n\n// \"đường tròn [ (O)/tâm O ] ngoại tiếp tam giác XYZ\" → circumcircle (through3).\n// Token \"tam giác\" + 3 đỉnh HOA BẮT BUỘC ngay sau \"ngoại tiếp\". Cờ 'g' để bắt\n// MỌI cấu trúc trong clause; 'i' để hoa đầu câu (\"Đường\"/\"Ngoại\"/\"Tam\") cũng\n// khớp — nhưng group đỉnh ([A-Z]) KHÔNG dùng 'i' (regex 'i' không tác động lên\n// lớp ký tự đã chỉ định HOA → vẫn chỉ khớp HOA, tránh nuốt chữ thường).\nconst CIRCUM_TRI = new RegExp(\n CIRCLE_KW + '\\\\s*' +\n CENTER +\n '\\\\s*ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\n\n// \"đường tròn [ (I)/tâm I ] nội tiếp tam giác XYZ\" → incircle (inscribedIn).\nconst INCIRCLE_TRI = new RegExp(\n CIRCLE_KW + '\\\\s*' +\n CENTER +\n '\\\\s*nội\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\n\n// \"tam giác XYZ nội tiếp (trong) đường tròn [ (O)/tâm O ]\" → circumcircle.\n// Tam giác đứng TRƯỚC, đường tròn đứng SAU. Center (nếu có) đứng sau \"đường tròn\".\nconst TRI_INSCRIBED_IN_CIRCLE = new RegExp(\n 'tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?nội\\\\s*tiếp\\\\s+(?:trong\\\\s+)?' +\n CIRCLE_KW +\n '\\\\s*' +\n CENTER,\n 'giu',\n);\n\n// \"tam giác XYZ ngoại tiếp đường tròn [ (I)/tâm I ]\" → incircle (inscribedIn).\n// Tam giác NGOẠI tiếp (circumscribes) đường tròn = đường tròn NỘI tiếp tam giác.\n// \"đường tròn\" BẮT BUỘC NGAY sau \"ngoại tiếp\" (KHÔNG optional) để phân biệt với\n// \"đường tròn ngoại tiếp tam giác\" (circumcircle — đường tròn đứng TRƯỚC, \"ngoại\n// tiếp\" theo sau bởi \"tam giác\"). [^.]{0,40}? không vượt dấu '.' (không nhảy câu).\nconst TRI_CIRCUMSCRIBES_CIRCLE = new RegExp(\n 'tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?ngoại\\\\s*tiếp\\\\s+' +\n CIRCLE_KW +\n '\\\\s*' +\n CENTER,\n 'giu',\n);\n\n// Dạng TẮT: \"(O)\"/\"(I)\" NGAY sau \"nội/ngoại tiếp\" — KHÔNG có chữ \"đường tròn\"\n// (vd \"tam giác ABC nội tiếp (O)\"). Phổ biến ở đề olympiad; thiếu nhánh này thì\n// circumcircle O không được tạo → arcMidpoint tham chiếu O fail (transpile).\n// Paren BẮT BUỘC (1 ký tự HOA trong ngoặc) để KHÔNG over-match \"nội tiếp\" trần.\n// Phân biệt với TRI_INSCRIBED_IN_CIRCLE/TRI_CIRCUMSCRIBES_CIRCLE: ở đó sau \"tiếp\"\n// là \"đường tròn\" → 2 nhánh không chồng (dedup theo spec:tri vẫn an toàn nếu có).\nconst TRI_INSCRIBED_IN_PAREN = new RegExp(\n 'tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?nội\\\\s*tiếp\\\\s+(?:trong\\\\s+)?\\\\(\\\\s*([A-Z])\\\\s*\\\\)',\n 'giu',\n);\nconst TRI_CIRCUMSCRIBES_PAREN = new RegExp(\n 'tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?ngoại\\\\s*tiếp\\\\s+\\\\(\\\\s*([A-Z])\\\\s*\\\\)',\n 'giu',\n);\n\n// --- Ký hiệu ngoặc \"(O; R)\" quét TOÀN ĐỀ (segmenter cắt ';') ------------------\n// \"(đường tròn)? (O; R) ngoại/nội tiếp tam giác XYZ\" — circle ĐỨNG TRƯỚC. R là\n// CHỮ (bán kính ký hiệu) nên circleRadius bỏ qua (cần \\d). Guard\n// (?![^)]*[A-Z]\\s*[;,]) chặn paren méo nhiều dấu chấm phẩy \"(A; B; C)\".\nconst PAREN_CENTER =\n '(?:' + CIRCLE_KW + '\\\\s*)?\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)\\\\s*';\nconst CIRCUM_TRI_PAREN = new RegExp(\n PAREN_CENTER + 'ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\nconst INCIRCLE_TRI_PAREN = new RegExp(\n PAREN_CENTER + 'nội\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\n\n// === EN patterns (issue #46 group B) ========================================\n// Semantics đối xứng VN. Phân biệt through3 (circumcircle) vs inscribedIn\n// (incircle) bằng SUBJECT (triangle/circle) + verb:\n// - triangle inscribed in circle → through3 (circle ngoại tiếp tam giác)\n// - triangle circumscribes/circumscribed about circle → inscribedIn (incircle)\n// - circle inscribed in triangle → inscribedIn (incircle)\n// - circle circumscribes/circumscribed about triangle → through3 (circumcircle)\n//\n// KHÔNG cờ 'i' (sẽ nuốt chữ thường vào group nhãn/center [A-Z]). First-letter\n// flex bằng [Tt]riangle / [Cc]ircle / [Ii]nscribed / [Cc]ircumscrib. Group\n// nhãn/center [A-Z] STRICT. Gap token = [^.]{0,N}? (non-greedy, không vượt '.').\n//\n// Center EN sau \"circle\": \"(O)\" (paren) hoặc bare \"O\" (neo (?![A-Za-z])).\nconst EN_CIRCLE_CENTER = '[Cc]ircle\\\\s+(?:\\\\(\\\\s*([A-Z])\\\\s*\\\\)|([A-Z])(?![A-Za-z]))';\nconst EN_TRI = '[Tt]riangle\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])';\n\n// SUBJECT=triangle + \"inscribed in\" circle → through3 (circumcircle).\n// \"triangle ABC (is)? inscribed in (the)? circle (O)\".\nconst EN_TRI_INSCRIBED_IN_CIRCLE = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n EN_CIRCLE_CENTER,\n 'gu',\n);\n\n// SUBJECT=triangle + \"circumscribes / circumscribed about|around\" circle → inscribedIn.\nconst EN_TRI_CIRCUMSCRIBES_CIRCLE = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n EN_CIRCLE_CENTER,\n 'gu',\n);\n\n// SUBJECT=circle + \"inscribed in\" triangle → inscribedIn (incircle).\nconst EN_CIRCLE_INSCRIBED_IN_TRI = new RegExp(\n EN_CIRCLE_CENTER +\n '[^.]{0,12}?[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// SUBJECT=circle + \"circumscribes / circumscribed about|around\" triangle → through3.\nconst EN_CIRCLE_CIRCUMSCRIBES_TRI = new RegExp(\n EN_CIRCLE_CENTER +\n '[^.]{0,12}?[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// --- EN paren whole-problem (segmenter cắt ';' trong \"(O; R)\") ----------------\n// Mirror VN PAREN: center \"(O\" bị cắt khỏi \"R)\". circle ĐỨNG TRƯỚC hoặc SAU.\n// Center = \"(\" + 1 ký tự HOA + \";\"/\",\" (KHÔNG đóng ngoặc cùng clause vì bị cắt).\n// Guard (?![^)]*[A-Z]\\s*[;,]) chặn paren méo nhiều dấu chấm phẩy.\nconst EN_PAREN_CIRCLE =\n '[Cc]ircle\\\\s+\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)\\\\s*';\n\n// \"triangle XYZ inscribed in circle (O; R)\" → through3.\nconst EN_TRI_INSCRIBED_PAREN = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n '[Cc]ircle\\\\s+\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)',\n 'gu',\n);\n\n// \"circle (O; R) circumscribes triangle XYZ\" → through3.\nconst EN_PAREN_CIRCLE_CIRCUMSCRIBES_TRI = new RegExp(\n EN_PAREN_CIRCLE +\n '[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// \"circle (I; r) inscribed in triangle XYZ\" → inscribedIn.\nconst EN_PAREN_CIRCLE_INSCRIBED_TRI = new RegExp(\n EN_PAREN_CIRCLE +\n '[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// \"triangle XYZ circumscribes circle (I; r)\" → inscribedIn.\nconst EN_TRI_CIRCUMSCRIBES_PAREN = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n '[Cc]ircle\\\\s+\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)',\n 'gu',\n);\n\n// Prefilter EN (NON-global cho .test). Chỉ \"inscribed\"/\"circumscrib\" mới quan tâm.\nconst HAS_INSCRIBE_EN = /[Ii]nscribed|[Cc]ircumscrib/u;\n\ninterface CircHit {\n index: number;\n spec: 'through3' | 'inscribedIn';\n tri: [string, string, string];\n /** tên tâm; '' nếu không khai báo (default 'O' khi emit). */\n center: string;\n}\n\nfunction pushAll(\n text: string,\n re: RegExp,\n spec: 'through3' | 'inscribedIn',\n // index của 3 group đỉnh trong match; center luôn group 1+2.\n triStart: number,\n out: CircHit[],\n): void {\n re.lastIndex = 0;\n for (const m of text.matchAll(re)) {\n const center = m[1] ?? m[2] ?? '';\n out.push({\n index: m.index ?? 0,\n spec,\n tri: [m[triStart], m[triStart + 1], m[triStart + 2]],\n center,\n });\n }\n}\n\n/**\n * Quét MỌI cấu trúc \"(đường tròn) ngoại/nội tiếp tam giác XYZ\" trong 1 clause.\n * Vùng text [start,end) đã thuộc 1 cấu trúc thì cấu trúc khác bỏ qua (tránh\n * trùng — \"tam giác XYZ nội tiếp đường tròn\" KHÔNG bị INCIRCLE_TRI quét lại).\n */\nfunction scanClause(text: string): CircHit[] {\n const hits: CircHit[] = [];\n // CIRCUM_TRI / INCIRCLE_TRI: center là group 1|2, đỉnh là group 3,4,5.\n pushAll(text, CIRCUM_TRI, 'through3', 3, hits);\n pushAll(text, INCIRCLE_TRI, 'inscribedIn', 3, hits);\n // TRI_INSCRIBED_IN_CIRCLE: đỉnh là group 1,2,3, center là group 4|5.\n TRI_INSCRIBED_IN_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(TRI_INSCRIBED_IN_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'through3',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n // TRI_CIRCUMSCRIBES_CIRCLE: tam giác ngoại tiếp đường tròn → incircle (inscribedIn).\n TRI_CIRCUMSCRIBES_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(TRI_CIRCUMSCRIBES_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'inscribedIn',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n // Dạng tắt \"(O)\"/\"(I)\" không kèm \"đường tròn\": center là group 4.\n TRI_INSCRIBED_IN_PAREN.lastIndex = 0;\n for (const m of text.matchAll(TRI_INSCRIBED_IN_PAREN)) {\n hits.push({ index: m.index ?? 0, spec: 'through3', tri: [m[1], m[2], m[3]], center: m[4] ?? '' });\n }\n TRI_CIRCUMSCRIBES_PAREN.lastIndex = 0;\n for (const m of text.matchAll(TRI_CIRCUMSCRIBES_PAREN)) {\n hits.push({ index: m.index ?? 0, spec: 'inscribedIn', tri: [m[1], m[2], m[3]], center: m[4] ?? '' });\n }\n\n // --- EN (issue #46 group B) ---------------------------------------------\n // SUBJECT=triangle (group 1,2,3) → center group 4|5.\n EN_TRI_INSCRIBED_IN_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(EN_TRI_INSCRIBED_IN_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'through3',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n EN_TRI_CIRCUMSCRIBES_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(EN_TRI_CIRCUMSCRIBES_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'inscribedIn',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n // SUBJECT=circle (center group 1|2) → triangle group 3,4,5.\n EN_CIRCLE_INSCRIBED_IN_TRI.lastIndex = 0;\n for (const m of text.matchAll(EN_CIRCLE_INSCRIBED_IN_TRI)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'inscribedIn',\n tri: [m[3], m[4], m[5]],\n center: m[1] ?? m[2] ?? '',\n });\n }\n EN_CIRCLE_CIRCUMSCRIBES_TRI.lastIndex = 0;\n for (const m of text.matchAll(EN_CIRCLE_CIRCUMSCRIBES_TRI)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'through3',\n tri: [m[3], m[4], m[5]],\n center: m[1] ?? m[2] ?? '',\n });\n }\n\n // Khử trùng: 2 hit cùng 3 đỉnh + cùng spec → giữ 1 (vd câu vừa khớp\n // CIRCUM_TRI lẫn TRI_INSCRIBED_IN_CIRCLE hiếm khi xảy ra, nhưng an toàn).\n const seen = new Set<string>();\n const dedup: CircHit[] = [];\n hits.sort((a, b) => a.index - b.index);\n for (const h of hits) {\n const key = `${h.spec}:${h.tri.join('')}`;\n if (seen.has(key)) continue;\n seen.add(key);\n dedup.push(h);\n }\n return dedup;\n}\n\ninterface ParenHit {\n spec: 'through3' | 'inscribedIn';\n tri: [string, string, string];\n center: string;\n /** text khớp trên TOÀN đề (để gán clauseId qua substring-inclusion). */\n matchedText: string;\n}\n\n/**\n * Quét TOÀN đề cho ký hiệu ngoặc \"(O; R) ngoại/nội tiếp tam giác XYZ\" — dạng bị\n * segmenter cắt ngang ';' nên per-clause không bắt được. circle ĐỨNG TRƯỚC.\n */\nfunction scanProblemParen(problem: string): ParenHit[] {\n const out: ParenHit[] = [];\n const push = (re: RegExp, spec: 'through3' | 'inscribedIn') => {\n re.lastIndex = 0;\n for (const m of problem.matchAll(re)) {\n out.push({\n spec,\n tri: [m[2], m[3], m[4]],\n center: m[1] ?? '',\n matchedText: m[0],\n });\n }\n };\n push(CIRCUM_TRI_PAREN, 'through3');\n push(INCIRCLE_TRI_PAREN, 'inscribedIn');\n\n // --- EN (issue #46 group B): center group khác vị trí tuỳ SUBJECT ----------\n // SUBJECT=triangle (group 1,2,3) → center group 4.\n const pushTriFirst = (re: RegExp, spec: 'through3' | 'inscribedIn') => {\n re.lastIndex = 0;\n for (const m of problem.matchAll(re)) {\n out.push({ spec, tri: [m[1], m[2], m[3]], center: m[4] ?? '', matchedText: m[0] });\n }\n };\n pushTriFirst(EN_TRI_INSCRIBED_PAREN, 'through3');\n pushTriFirst(EN_TRI_CIRCUMSCRIBES_PAREN, 'inscribedIn');\n // SUBJECT=circle (center group 1) → triangle group 2,3,4.\n push(EN_PAREN_CIRCLE_CIRCUMSCRIBES_TRI, 'through3');\n push(EN_PAREN_CIRCLE_INSCRIBED_TRI, 'inscribedIn');\n return out;\n}\n\nfunction intentFor(spec: 'through3' | 'inscribedIn', tri: string[], center: string) {\n const name = center || 'O';\n return spec === 'inscribedIn'\n ? drawCircle(name, 'inscribedIn', { triangle: tri })\n : drawCircle(name, 'through3', { points: tri });\n}\n\n/**\n * Mỗi clause: quét emit-all các \"(đường tròn) nội/ngoại tiếp tam giác XYZ\".\n * - circumcircle (through3): \"đường tròn ngoại tiếp tam giác ABC\",\n * \"tam giác ABC nội tiếp đường tròn (O)\".\n * - incircle (inscribedIn): \"đường tròn nội tiếp tam giác ABC\",\n * \"tam giác ABC ngoại tiếp đường tròn (I)\".\n * Cộng nhánh TOÀN đề cho ký hiệu \"(O; R) ngoại/nội tiếp tam giác\" (bị cắt ';').\n * \"ngoại/nội tiếp\" mà KHÔNG có \"tam giác XYZ\" ngay sau (vd \"tứ giác\", \"hình\n * ...\", hoặc \"nội tiếp\" trần) → KHÔNG claim → escalate AI.\n */\nexport const circleTriangleRule: LanguageRule = {\n id: 'circleTriangle',\n priority: 72,\n languages: ['vi', 'en'],\n patterns: [HAS_INSCRIBE, HAS_INSCRIBE_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n const emitted = new Set<string>(); // \"spec:tri\" — dedup cross per-clause/paren.\n\n // 1) Per-clause (VN giữ nguyên hành vi cũ; EN thêm qua HAS_INSCRIBE_EN).\n for (const c of ctx.clauses) {\n if (!HAS_INSCRIBE.test(c.text) && !HAS_INSCRIBE_EN.test(c.text)) continue;\n const hits = scanClause(c.text);\n if (hits.length === 0) continue; // có \"ngoại/nội tiếp\" nhưng không tam giác\n for (const h of hits) emitted.add(`${h.spec}:${h.tri.join('')}`);\n out.push({\n ruleId: 'circleTriangle',\n clauseIds: [c.id],\n intents: hits.map((h) => intentFor(h.spec, h.tri, h.center)),\n });\n }\n\n // 2) Toàn đề: ký hiệu \"(O; R)\" (segmenter cắt ';'). Bỏ qua nếu (spec:tri) đã\n // emit ở per-clause. clauseId = mọi clause là substring của đoạn khớp\n // (đoạn này trải qua nhiều clause do bị cắt) → coverage tính phủ cả 2.\n for (const h of scanProblemParen(ctx.problem)) {\n const key = `${h.spec}:${h.tri.join('')}`;\n if (emitted.has(key)) continue;\n emitted.add(key);\n const clauseIds = ctx.clauses\n .filter((c) => h.matchedText.includes(c.text))\n .map((c) => c.id);\n out.push({\n ruleId: 'circleTriangle',\n clauseIds,\n intents: [intentFor(h.spec, h.tri, h.center)],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentFromExt.ts\n//\n// Tiếp tuyến TỪ điểm NGOÀI đường tròn (2 nhánh):\n// \"Kẻ hai tiếp tuyến từ A đến (O)\" → drawLine(t, tangentFromExt, {from:'A', circle:'O', which:'both'})\n// \"Vẽ tiếp tuyến từ điểm A tới đường tròn O\" → drawLine(t, tangentFromExt, {from:'A', circle:'O', which:'both'})\n// \"Từ A vẽ tiếp tuyến với (O)\" → drawLine(t, tangentFromExt, {from:'A', circle:'O', which:'both'})\n//\n// Phân biệt với tangentAt (\"tiếp tuyến TẠI A của (O)\") — chỗ đó dùng \"tại\",\n// còn ở đây là \"từ <điểm ngoài>\". Rule này CHỈ match \"từ\"/\"Từ ... vẽ tiếp tuyến\".\n//\n// GOTCHA: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\n// from / circle là 1 ký tự HOA; name của line default 't' (LabelZ cho phép).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawLine, addPoint } from './_shared';\n\n// Prefilter toàn đề: phải có \"tiếp tuyến\".\nconst HAS_TANGENT = /tiếp\\s*tuyến/u;\n\n// Target đường tròn: PHẢI có dấu hiệu đường tròn — \"(X)\" hoặc \"đường tròn X\".\n// KHÔNG nhận chữ HOA TRẦN (vd \"tiếp tuyến từ A đến BC\": \"BC\" là đoạn thẳng, không\n// phải đường tròn → không claim, escalate). Hai alternative → 2 capture nhóm,\n// caller lấy nhóm nào khớp.\nconst CIRCLE_TARGET = String.raw`(?:đường\\s*tròn\\s*([A-Z])(?:['′]?)|\\(\\s*([A-Z])(?:['′]?)\\s*\\))`;\n\n// \"(kẻ|vẽ) (hai)? tiếp tuyến từ (điểm)? A (đến|tới|với) <đường tròn>\"\n// - động từ kẻ/vẽ BẮT BUỘC: chặn ngữ cảnh TÍNH/giả thiết (\"Độ dài tiếp tuyến\n// từ A đến (O) bằng 5\" → không có kẻ/vẽ → không match, escalate).\n// - \"hai\"/\"một\" optional (1 hay 2 nhánh vẫn coi là tiếp tuyến từ điểm ngoài).\n// - from = 1 ký tự HOA sau \"từ (điểm)?\".\n// - giới từ đến/tới/với nối qua đường tròn (bắt buộc có dấu hiệu — CIRCLE_TARGET).\nconst FROM_FORM = new RegExp(\n String.raw`(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:một\\s+|hai\\s+)?tiếp\\s*tuyến\\s+từ\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)\\s+(?:đến|tới|với)\\s+` +\n CIRCLE_TARGET,\n 'u',\n);\n\n// Biến thể đảo: \"Từ (điểm)? A ... (kẻ|vẽ) (hai)? tiếp tuyến (đến|tới|với) <đường tròn>\".\n// - kẻ|vẽ vẫn bắt buộc (đã có sẵn trong cú pháp đảo).\nconst TU_FORM = new RegExp(\n String.raw`(?<!\\p{L})[Tt]ừ\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)(?!\\p{L})[^.]{0,40}?(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:một\\s+|hai\\s+)?tiếp\\s*tuyến\\s+(?:đến|tới|với)\\s+` +\n CIRCLE_TARGET,\n 'u',\n);\n\n// === EN patterns (issue #46 group B) ========================================\n// Target đường tròn EN: \"(X)\" (language-agnostic, giống VN) HOẶC \"circle X\" /\n// \"circle (X)\". KHÔNG nhận chữ HOA TRẦN (\"from A to BC\": BC là đoạn → không\n// claim → escalate). Hai alternative → 2 capture nhóm (caller lấy nhóm nào khớp).\n// - nhóm 1: ([A-Z]) sau \"circle\" (có thể bọc \"(...)\").\n// - nhóm 2: ([A-Z]) trong \"(...)\" trần (không từ \"circle\").\n// First-letter flex [Cc]; KHÔNG cờ 'i' (giữ [A-Z] strict cho nhãn).\nconst CIRCLE_TARGET_EN = String.raw`(?:[Cc]ircle\\s*\\(?\\s*([A-Z])(?:['′]?)\\s*\\)?|\\(\\s*([A-Z])(?:['′]?)\\s*\\))`;\n\n// \"(Draw|Construct) (the|two)? tangent(s)? (lines)? from (the)? A to (the)? <circle>\"\n// - động từ Draw/Construct BẮT BUỘC: chặn ngữ cảnh TÍNH (\"The length of the\n// tangent from A to (O) is 5\" → không có Draw/Construct → không match,\n// escalate). Mirror ràng buộc verb của FROM_FORM (VN).\n// - giới từ \"from <A> to <circle>\" BẮT BUỘC: phân biệt với tangentAt\n// (\"tangent ... at A\" → không có \"from ... to\" → không match ở đây).\n// - from = 1 ký tự HOA sau \"from (the)?\".\n// - circle bắt buộc có dấu hiệu (CIRCLE_TARGET_EN — \"(X)\" hoặc \"circle X\").\n// GROUP INDEX: from = nhóm 1; circle = nhóm 2 (\"circle X\") HOẶC nhóm 3 (\"(X)\").\nconst FROM_FORM_EN = new RegExp(\n String.raw`(?:[Dd]raw|[Cc]onstruct)\\s+(?:the\\s+|two\\s+|the\\s+two\\s+)?tangents?(?:\\s+lines?)?\\s+from\\s+(?:the\\s+)?([A-Z])(?:['′]?)\\s+to\\s+(?:the\\s+)?` +\n CIRCLE_TARGET_EN,\n 'u',\n);\n\n// Biến thể đảo EN: \"From (the)? A, ... (draw|construct) (the|two)? tangent(s)?\n// (lines)? to (the)? <circle>\".\n// - verb draw/construct vẫn bắt buộc (nằm sau \"From A\").\n// - \"from A ... to <circle>\" vẫn đầy đủ (from ở đầu, to trước circle).\n// GROUP INDEX: from = nhóm 1; circle = nhóm 2 (\"circle X\") HOẶC nhóm 3 (\"(X)\").\nconst FROM_INV_EN = new RegExp(\n String.raw`(?<![A-Za-z])[Ff]rom\\s+(?:the\\s+)?([A-Z])(?:['′]?)(?![A-Za-z])[^.]{0,40}?(?:[Dd]raw|[Cc]onstruct)\\s+(?:the\\s+|two\\s+|the\\s+two\\s+)?tangents?(?:\\s+lines?)?\\s+to\\s+(?:the\\s+)?` +\n CIRCLE_TARGET_EN,\n 'u',\n);\n\n// === NAMED tangent points (issue #46) =======================================\n// \"Vẽ hai tiếp tuyến AB, AC từ A đến (O)\" — B, C LÀ tiếp điểm (named). Khác với\n// nhánh UNNAMED ở trên (regex unnamed FAIL vì \"AB, AC\" chen giữa \"tiếp tuyến\" và\n// \"từ\"). Hai regex dưới bắt 2 đoạn tiếp tuyến + đường tròn trong 1 match.\n// GROUP INDEX (cả VN & EN): m[1]=chữ đầu đoạn 1 (điểm ngoài x1),\n// m[2]=tiếp điểm 1 (B), m[3]=chữ đầu đoạn 2 (x2), m[4]=tiếp điểm 2 (C),\n// m[5]/m[6] = circle (qua CIRCLE_TARGET / CIRCLE_TARGET_EN).\nconst NAMED_FROM_VN = new RegExp(\n String.raw`(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:một\\s+|hai\\s+)?tiếp\\s*tuyến\\s+([A-Z])([A-Z])\\s*(?:,|và)\\s*([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?(?:đến|tới|với)\\s+` +\n CIRCLE_TARGET,\n 'u',\n);\nconst NAMED_FROM_EN = new RegExp(\n String.raw`(?:[Dd]raw|[Cc]onstruct)\\s+(?:the\\s+|two\\s+|the\\s+two\\s+)?tangents?(?:\\s+lines?)?\\s+([A-Z])([A-Z])\\s*(?:,|and)\\s*([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?to\\s+(?:the\\s+)?` +\n CIRCLE_TARGET_EN,\n 'u',\n);\n\nexport const tangentFromExtRule: LanguageRule = {\n id: 'tangentFromExt',\n priority: 65,\n languages: ['vi', 'en'],\n // EN prefilter \"tangent\" để runRules (prefilter qua patterns[], bỏ qua\n // languages) chạy match() cho đề EN thuần (không có \"tiếp tuyến\").\n patterns: [HAS_TANGENT, /[Tt]angent/u],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // === NAMED tangent points (issue #46): \"tiếp tuyến AB, AC ... (O)\" → dựng\n // tiếp điểm B,C (tangentPointExt) cộng với 2 tiếp tuyến. from = chữ cái đầu\n // CHUNG của 2 đoạn (điểm ngoài); tiếp điểm = chữ cái thứ 2 mỗi đoạn.\n const named = NAMED_FROM_VN.exec(c.text) ?? NAMED_FROM_EN.exec(c.text);\n if (named) {\n const from = named[1];\n const tpB = named[2];\n const x2 = named[3];\n const tpC = named[4];\n const circle = named[5] ?? named[6];\n // Hợp lệ: cùng điểm ngoài (m1===m3), 2 tiếp điểm phân biệt & khác điểm ngoài.\n if (\n circle && from === x2 &&\n tpB !== from && tpC !== from && tpB !== tpC\n ) {\n out.push({\n ruleId: 'tangentFromExt',\n clauseIds: [c.id],\n intents: [\n drawLine('t', 'tangentFromExt', { from, circle, which: 'both' }),\n addPoint(tpB, { kind: 'tangentPoint', from, circle, which: 0 }),\n addPoint(tpC, { kind: 'tangentPoint', from, circle, which: 1 }),\n ],\n });\n continue; // clause handled — skip unnamed path\n }\n // not valid named form → fall through to unnamed logic (will likely escalate)\n }\n // VN trước (FROM_FORM / TU_FORM), giữ nguyên hành vi cũ; EN sau (FROM_FORM_EN\n // / FROM_INV_EN). circle bắt qua 1 trong các alternative capture group.\n const m =\n FROM_FORM.exec(c.text) ??\n TU_FORM.exec(c.text) ??\n FROM_FORM_EN.exec(c.text) ??\n FROM_INV_EN.exec(c.text);\n if (!m) continue;\n const from = m[1];\n // circle bắt qua 1 trong 2 alternative:\n // VN: \"đường tròn X\" = m[2], \"(X)\" = m[3].\n // EN: \"circle X\" = m[2], \"(X)\" = m[3] (cùng index — cả 2 dạng đều có\n // circle ở nhóm 2/3 vì from luôn là nhóm 1, CIRCLE_TARGET(_EN) có 2\n // alternative nhóm 2 & 3).\n const circle = m[2] ?? m[3];\n // Không xác định được from hoặc circle → bỏ qua (escalate AI).\n if (!from || !circle) continue;\n out.push({\n ruleId: 'tangentFromExt',\n clauseIds: [c.id],\n intents: [\n drawLine('t', 'tangentFromExt', { from, circle, which: 'both' }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/externalPoint.ts\n//\n// Điểm nằm NGOÀI đường tròn (free external point):\n// \"Lấy điểm A nằm ngoài đường tròn (O)\" → addPoint(A, {externalToCircle, circle:'O'})\n// \"Lấy điểm A ở ngoài (O)\" → addPoint(A, {externalToCircle, circle:'O'})\n// \"Gọi A là điểm nằm ngoài (O)\" → addPoint(A, {externalToCircle, circle:'O'})\n// \"Take a point A outside the circle (O).\" (EN) → addPoint(A, {externalToCircle, circle:'O'})\n//\n// Mục đích: UNBLOCK tangentFromExt render END-TO-END. tangentFromExt emit\n// drawLine(from:'A', circle:'O') nhưng KHÔNG rule nào dựng điểm A ngoài circle\n// → transpile UNKNOWN_REF A → escalate. Rule này dựng A (qua builder\n// externalToCircle, đọc tâm+bán kính từ build state, đặt A free ngoài circle).\n//\n// PRIORITY 68: sau circleRadius (75) / circleTriangle (72) để circle build\n// TRƯỚC, trước tangentFromExt (65) để A build TRƯỚC tangent. Build order:\n// circle → A → tangent (đúng phụ thuộc).\n//\n// GOTCHA \\b: ký tự Việt \"ngoài\" → KHÔNG dùng \\b. Cờ 'u' cho mọi regex.\n// `[^.A-Z]` giữa name và \"ngoài\"/\"outside\" chặn nhảy qua nhãn HOA khác / dấu chấm.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// VN: \"(Lấy|Gọi) (điểm)? A ... ngoài (đường tròn (X) | (X))\".\n// - from = nhóm 1 (1 ký tự HOA).\n// - circle = nhóm 2 (\"đường tròn X\") HOẶC nhóm 3 (\"(X)\").\n// - [^.A-Z]{0,14}? cho \"nằm\"/\"ở\" chen giữa, chặn dấu chấm / nhãn HOA khác.\nconst VN_FORM = new RegExp(\n String.raw`(?:[Ll]ấy|[Gg]ọi)\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)[^.A-Z]{0,14}?ngoài\\s+(?:đường\\s*tròn\\s*\\(?\\s*([A-Z])\\s*\\)?|\\(\\s*([A-Z])\\s*\\))`,\n 'u',\n);\n\n// EN: \"(Take|Let|Mark|Choose|Pick) (a)? (point)? A ... outside (the)? (circle (X) | (X))\".\n// - from = nhóm 1; circle = nhóm 2 (\"circle X\") HOẶC nhóm 3 (\"(X)\").\n// - [^.A-Z]{0,24}? cho \"be a point\"/\"nằm\" chen giữa, chặn dấu chấm / nhãn HOA.\nconst EN_FORM = new RegExp(\n String.raw`(?:[Tt]ake|[Ll]et|[Mm]ark|[Cc]hoose|[Pp]ick)\\s+(?:a\\s+)?(?:point\\s+)?([A-Z])(?:['′]?)[^.A-Z]{0,24}?outside\\s+(?:the\\s+)?(?:[Cc]ircle\\s*\\(?\\s*([A-Z])\\s*\\)?|\\(\\s*([A-Z])\\s*\\))`,\n 'u',\n);\n\nexport const externalPointRule: LanguageRule = {\n id: 'externalPoint',\n priority: 68,\n languages: ['vi', 'en'],\n // Prefilter toàn đề (runRules prefilter qua patterns[], BỎ QUA languages):\n // cần bắt cả VN (\"ngoài\") lẫn EN (\"outside\"). match() mới có regex chặt.\n patterns: [/ngoài/u, /[Oo]utside/u],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = VN_FORM.exec(c.text) ?? EN_FORM.exec(c.text);\n if (!m) continue;\n const from = m[1];\n const circle = m[2] ?? m[3];\n if (!from || !circle) continue; // escalate-safe\n out.push({\n ruleId: 'externalPoint',\n clauseIds: [c.id],\n intents: [addPoint(from, { kind: 'externalToCircle', circle })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/arcMidpoint.ts\n//\n// Điểm chính giữa cung: \"Gọi M là điểm chính giữa cung BC (không chứa A)\".\n// → add-point M {kind:'arcMidpoint', circle:'O', a:'B', b:'C', notContaining:'A'}\n//\n// circle lấy từ toàn đề (\"(O)\" / \"đường tròn (tâm) O\"); KHÔNG có circle → bỏ qua\n// (escalate AI — không thể dựng cung mà không biết đường tròn).\n//\n// notContaining (PHẢI là đỉnh thứ 3, ∉ {a,b}):\n// - \"không chứa X\" → X (chỉ nhận nếu X ∉ {a,b}; X∈{a,b} vô nghĩa → bỏ qua)\n// - không nêu nhưng có tam giác → đỉnh thứ 3 (đỉnh tam giác không thuộc cặp cung)\n// - cả hai đều không suy được → bỏ qua (escalate)\n//\n// CHỈ xử lý cú pháp \"cung (nhỏ)? <PAIR> không chứa <Z>\" (containment ÂM, cung nhỏ).\n// Vượt scope → bỏ qua (escalate, an toàn — đừng mis-render):\n// - \"cung lớn <PAIR>\" → cung lớn, ngữ nghĩa cung đối → defer\n// - \"chứa X\" (containment DƯƠNG, không có \"không\" đứng trước) → defer\n//\n// Tên điểm qua extractPointName / ký tự HOA trước \"(là) điểm chính giữa\"; không\n// trích được tên → bỏ qua (đừng bịa tên).\n//\n// EN (issue #46 group B): hỗ trợ thêm các dạng tiếng Anh tương đương —\n// \"Let M be the midpoint of arc BC not containing A\"\n// \"M is the midpoint of the (minor) arc BC\" (suy notContaining từ \"Triangle ABC\")\n// \"major arc\" → defer (mirror \"cung lớn\"); \"containing X\" dương → defer.\n// Tên điểm EN qua \"X is/be the midpoint of … arc\" (extractPointName là VN-only).\n// Collision midpoint EN (rule prio 50): KHÔNG xảy ra — midpoint EN cần\n// \"midpoint of (segment|side)? [A-Z][A-Z]\", nhưng sau \"of\" ở đây là \"arc\" (chữ\n// thường) → [A-Z] fail → midpoint không grab \"BC\".\n//\n// GOTCHA \\b: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawCircle, extractPointName, pairFromToken } from './_shared';\n\n// Prefilter toàn đề: \"chính giữa cung\" hoặc \"trung điểm cung\".\nconst ARC_MID = /(?:chính\\s+giữa|trung\\s*điểm)\\s+(?:của\\s+)?cung/u;\n\n// Cụm cung + cặp đỉnh: \"điểm chính giữa cung (nhỏ|lớn) BC\".\n// \"nhỏ|lớn\" optional; \"của\" optional. Cặp đỉnh = 2 ký tự HOA liền.\nconst ARC_PAIR =\n /(?:chính\\s+giữa|trung\\s*điểm)\\s+(?:của\\s+)?cung\\s+(?:nhỏ\\s+|lớn\\s+)?([A-Z])([A-Z])/u;\n\n// Tên điểm đứng TRƯỚC cụm: \"M (là) (điểm) (chính giữa|trung điểm) cung\".\nconst NAME_BEFORE =\n /([A-Z])(?:['′]?)\\s+(?:là\\s+)?(?:điểm\\s+)?(?:chính\\s+giữa|trung\\s*điểm)\\s+(?:của\\s+)?cung/u;\n\n// \"không chứa X\" → X.\nconst NOT_CONTAINING = /không\\s+chứa\\s+([A-Z])/u;\n\n// Tam giác trong toàn đề → 3 đỉnh (dùng suy notContaining khi đề không nêu).\nconst TRI = /tam giác\\s+([A-Z])([A-Z])([A-Z])/u;\n\n// Tên đường tròn trong toàn đề: \"đường tròn (tâm) O\" / \"(O)\".\n// - \"đường tròn tâm O\" / \"đường tròn O\" → O\n// - \"(O)\" đứng riêng (1 ký tự HOA trong ngoặc, không phải cặp đỉnh / số)\nconst CIRCLE_WORDS = /đường\\s*tròn\\s*(?:\\(\\s*)?(?:tâm\\s+)?([A-Z])(?![A-Z])/u;\nconst CIRCLE_PAREN = /\\(\\s*([A-Z])\\s*\\)/u;\n\n// === EN patterns (issue #46 group B) =========================================\n// First-letter case-flex [Mm]/[Tt]; KHÔNG cờ 'i' (phá nhãn [A-Z]). Nhãn STRICT\n// [A-Z] + neo (?![A-Za-z]) cuối cặp đỉnh (chặn \"BCD\" 3 chữ → escalate-safe).\n// Prefilter EN: \"midpoint of (the)? (minor|major)? arc\".\nconst ARC_MID_EN = /[Mm]idpoint\\s+of\\s+(?:the\\s+)?(?:minor\\s+|major\\s+)?arc/u;\n// Cụm cung + cặp đỉnh EN.\nconst ARC_PAIR_EN =\n /[Mm]idpoint\\s+of\\s+(?:the\\s+)?(?:minor\\s+|major\\s+)?arc\\s+([A-Z])([A-Z])(?![A-Za-z])/u;\n// Tên đứng TRƯỚC: \"M is/be the midpoint of arc\". (EN không có lời dẫn VN; extractPointName VN-only.)\nconst NAME_BEFORE_EN =\n /([A-Z])(?:['′]?)\\s+(?:is|be)\\s+the\\s+midpoint\\s+of\\s+(?:the\\s+)?(?:minor\\s+|major\\s+)?arc/u;\n// \"not containing (the)? (point|vertex)? X\".\nconst NOT_CONTAINING_EN = /not\\s+containing\\s+(?:the\\s+)?(?:point\\s+|vertex\\s+)?([A-Z])(?![A-Za-z])/u;\n// Tam giác EN (suy notContaining khi không nêu \"not containing\").\nconst TRI_EN = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Za-z])/u;\n// Scope guard: \"major arc\" → defer (mirror VN \"cung lớn\").\nconst MAJOR_ARC_EN = /major\\s+arc/u;\n\n/** Tên đường tròn từ toàn đề; undefined nếu không tìm thấy. */\nfunction resolveCircle(problem: string): string | undefined {\n const w = CIRCLE_WORDS.exec(problem);\n if (w) return w[1];\n const p = CIRCLE_PAREN.exec(problem);\n if (p) return p[1];\n return undefined;\n}\n\n/**\n * Tên cho circumcircle NGẦM (khi đề không nêu \"(O)\"): ưu tiên 'O' (quy ước), né\n * nếu đã là token HOA đứng riêng trong đề (vd điểm O); else 'O1'/'O2'/'W'.\n */\nfunction synthCircleName(problem: string): string {\n for (const cand of ['O', 'O1', 'O2', 'W']) {\n if (!new RegExp(`(?<!\\\\p{L})${cand}(?![\\\\p{L}\\\\d])`, 'u').test(problem)) return cand;\n }\n return 'O'; // fallback (resolveCircleNameCollisions sẽ dedup nếu cần)\n}\n\n/**\n * \"Gọi M là điểm chính giữa cung nhỏ BC không chứa A\" → add-point M\n * {kind:'arcMidpoint', circle, a:'B', b:'C', notContaining:'A'}.\n *\n * Một clause khớp khi: trích được tên điểm, cặp đỉnh cung, đường tròn, và\n * notContaining (nêu \"không chứa X\" hoặc suy từ đỉnh thứ 3 của tam giác). Thiếu\n * bất kỳ thành phần nào → bỏ qua clause (escalate AI thay vì đoán sai).\n */\nexport const arcMidpointRule: LanguageRule = {\n id: 'arcMidpoint',\n priority: 60,\n languages: ['vi', 'en'],\n patterns: [ARC_MID, ARC_MID_EN],\n match(ctx) {\n const explicitCircle = resolveCircle(ctx.problem);\n const tri = TRI.exec(ctx.problem);\n const triEnM0 = TRI_EN.exec(ctx.problem);\n // Tam giác để suy circumcircle NGẦM khi đề KHÔNG nêu \"(O)\" (VN ưu tiên, EN fallback).\n const circumTri: string[] | null = tri\n ? [tri[1], tri[2], tri[3]]\n : triEnM0\n ? [triEnM0[1], triEnM0[2], triEnM0[3]]\n : null;\n // \"(O)\" tường minh thắng; else circumcircle ngầm của tam giác (tên synth).\n const circle = explicitCircle ?? (circumTri ? synthCircleName(ctx.problem) : undefined);\n if (!circle) return []; // không circle tường minh + không tam giác → escalate\n const usesCircum = !explicitCircle;\n\n const out: RuleMatch[] = [];\n // Khi dùng circumcircle ngầm, prepend drawCircle(through3) vào arcMidpoint ĐẦU\n // TIÊN dùng nó → circle emit TRƯỚC điểm (transpile resolve ref theo thứ tự).\n let circumEmitted = false;\n const withCircum = (ap: IntentT): IntentT[] => {\n if (usesCircum && !circumEmitted && circumTri) {\n circumEmitted = true;\n return [drawCircle(circle, 'through3', { points: circumTri }), ap];\n }\n return [ap];\n };\n // Circumcircle ngầm chỉ hợp lệ khi 2 đầu mút cung LÀ đỉnh tam giác.\n const arcOnCircum = (a: string, b: string): boolean =>\n !usesCircum || (!!circumTri && circumTri.includes(a) && circumTri.includes(b));\n\n for (const c of ctx.clauses) {\n if (!ARC_MID.test(c.text)) continue;\n\n // Vượt scope (chỉ xử lý \"cung (nhỏ) PAIR không chứa Z\"):\n // - \"cung lớn\" → cung đối, defer → escalate\n // - \"chứa X\" containment DƯƠNG (không có \"không\" trước) → defer → escalate\n if (/cung\\s+lớn/u.test(c.text)) continue;\n if (/chứa/u.test(c.text) && !/không\\s+chứa/u.test(c.text)) continue;\n\n const pairM = ARC_PAIR.exec(c.text);\n if (!pairM) continue;\n const pair = pairFromToken(pairM[1] + pairM[2]);\n if (pair.length !== 2) continue;\n const [a, b] = pair;\n if (!arcOnCircum(a, b)) continue; // circumcircle ngầm: cung phải là 2 đỉnh tam giác\n\n // Tên điểm: lời dẫn \"Gọi/Lấy X là …\" ưu tiên, fallback HOA trước cụm.\n const before = NAME_BEFORE.exec(c.text);\n const name = extractPointName(c.text) ?? (before ? before[1] : undefined);\n if (!name) continue; // không trích được tên → bỏ qua\n\n // notContaining: \"không chứa X\" hoặc đỉnh thứ 3 của tam giác.\n let notContaining: string | undefined;\n const nc = NOT_CONTAINING.exec(c.text);\n if (nc) {\n notContaining = nc[1];\n // notContaining = endpoint của cung (a/b) → vô nghĩa hình học → escalate.\n if (notContaining === a || notContaining === b) continue;\n } else if (tri) {\n const verts = [tri[1], tri[2], tri[3]];\n notContaining = verts.find((v) => v !== a && v !== b);\n }\n if (!notContaining) continue; // không suy được → bỏ qua\n\n out.push({\n ruleId: 'arcMidpoint',\n clauseIds: [c.id],\n intents: withCircum(addPoint(name, { kind: 'arcMidpoint', circle, a, b, notContaining })),\n });\n }\n\n // --- EN (issue #46 group B) ---------------------------------------------------\n // Tam giác EN để suy notContaining (đỉnh thứ 3) khi đề không nêu \"not containing\".\n const triEnVerts = triEnM0 ? [triEnM0[1], triEnM0[2], triEnM0[3]] : undefined;\n\n for (const c of ctx.clauses) {\n if (!ARC_MID_EN.test(c.text)) continue;\n // Vượt scope (mirror VN): \"major arc\" → cung đối, defer → escalate.\n if (MAJOR_ARC_EN.test(c.text)) continue;\n // \"containing X\" DƯƠNG (không có \"not\" trước) → defer → escalate.\n if (/containing/u.test(c.text) && !/not\\s+containing/u.test(c.text)) continue;\n\n const pairM = ARC_PAIR_EN.exec(c.text);\n if (!pairM) continue;\n const pair = pairFromToken(pairM[1] + pairM[2]);\n if (pair.length !== 2) continue;\n const [a, b] = pair;\n if (!arcOnCircum(a, b)) continue; // circumcircle ngầm: cung phải là 2 đỉnh tam giác\n\n // Tên điểm: \"M is/be the midpoint of arc\" (HOA trước). Không có → bỏ qua.\n const before = NAME_BEFORE_EN.exec(c.text);\n const name = before ? before[1] : undefined;\n if (!name) continue;\n\n // notContaining: \"not containing X\" tường minh, hoặc đỉnh thứ 3 của tam giác EN.\n let notContaining: string | undefined;\n const nc = NOT_CONTAINING_EN.exec(c.text);\n if (nc) {\n notContaining = nc[1];\n if (notContaining === a || notContaining === b) continue; // endpoint cung → vô nghĩa\n } else if (triEnVerts) {\n notContaining = triEnVerts.find((v) => v !== a && v !== b);\n }\n if (!notContaining) continue;\n\n out.push({\n ruleId: 'arcMidpoint',\n clauseIds: [c.id],\n intents: withCircum(addPoint(name, { kind: 'arcMidpoint', circle, a, b, notContaining })),\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/excenter.ts\n//\n// Tâm đường tròn bàng tiếp (excenter): \"J là tâm bàng tiếp góc A\".\n// → add-point J {kind:'excenter', of:['A','B','C'], opposite:'A'}\n//\n// excenter cần BỘ 3 đỉnh tam giác (of) + ĐỈNH ĐỐI DIỆN (opposite — góc mà đường\n// tròn bàng tiếp ứng với). DSL/intent/render đã support; rule này chỉ lo NLU.\n//\n// Tam giác: nêu trong clause → lấy; else tam giác DUY NHẤT toàn đề; nhập nhằng /\n// không có → bỏ qua (escalate). Đỉnh đối PHẢI thuộc tam giác (else escalate).\n//\n// Tên tâm: ký tự HOA đứng TRƯỚC \"(là) tâm (đường tròn)? bàng tiếp\" (cục bộ, KHÔNG\n// quét lời dẫn toàn clause). Không trích được tên → bỏ qua (đừng bịa).\n//\n// KHÔNG dùng extractPointName (_shared) ở đây: NAME_LA của nó dùng `là\\b` (ASCII\n// \\b sau 'à' không khớp) nên không bắt được \"X là …\". Rule tự neo qua NAME_BEFORE.\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt. Regex chứa ký\n// tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\n//\n// Chỉ dựng ĐIỂM tâm (excenter). \"Vẽ đường tròn bàng tiếp\" (excircle) chưa có\n// intent path → clause không đặt tên tâm sẽ KHÔNG match → escalate (an toàn).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// Prefilter toàn đề.\nconst EXCENTER_KW = /bàng\\s*tiếp/u;\n\n// Tam giác (1 lần) trong 1 đoạn text.\nconst TRI = /tam\\s*giác\\s+([A-Z])([A-Z])([A-Z])/u;\nconst TRI_G = /tam\\s*giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\n// Đỉnh đối diện: \"bàng tiếp (trong)? (góc|đỉnh|ứng với (đỉnh)?|đối diện (đỉnh)?) X\".\nconst OPPOSITE =\n /bàng\\s*tiếp\\s+(?:trong\\s+)?(?:góc|đỉnh|ứng\\s+với(?:\\s+đỉnh)?|đối\\s+diện(?:\\s+đỉnh)?)\\s+([A-Z])(?!\\p{L})/u;\n\n// Tên tâm đứng TRƯỚC: \"J (là)? tâm (của)? (đường tròn)? bàng tiếp\".\nconst NAME_BEFORE =\n /([A-Z])(?:['′]?)\\s+(?:là\\s+)?(?:tâm\\s+)?(?:(?:của\\s+)?đường\\s*tròn\\s+)?bàng\\s*tiếp/u;\n\n/**\n * of=[A,B,C] cho 1 clause: ưu tiên tam giác nêu trong clause; else tam giác DUY\n * NHẤT toàn đề (dedup theo bộ đỉnh). Nhiều tam giác khác nhau / không có →\n * undefined (escalate).\n */\nfunction resolveTriangleOf(clauseText: string, problem: string): string[] | undefined {\n const inClause = TRI.exec(clauseText);\n if (inClause) return [inClause[1], inClause[2], inClause[3]];\n TRI_G.lastIndex = 0;\n const all: string[] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) all.push(m[1] + m[2] + m[3]);\n const distinct = new Set(all);\n if (distinct.size === 1) {\n const t = all[0];\n return [t[0], t[1], t[2]];\n }\n return undefined;\n}\n\n/**\n * \"J là tâm bàng tiếp góc A\" → add-point J {kind:'excenter', of:[A,B,C], opposite:'A'}.\n * Thiếu đỉnh đối / tam giác / tên → bỏ qua clause (escalate AI thay vì đoán sai).\n */\nexport const excenterRule: LanguageRule = {\n id: 'excenter',\n priority: 60,\n languages: ['vi'],\n patterns: [EXCENTER_KW],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!EXCENTER_KW.test(c.text)) continue;\n\n const oppM = OPPOSITE.exec(c.text);\n if (!oppM) continue; // không xác định đỉnh đối → escalate\n const opposite = oppM[1];\n\n const of = resolveTriangleOf(c.text, ctx.problem);\n if (!of) continue; // không có/nhập nhằng tam giác → escalate\n if (!of.includes(opposite)) continue; // đỉnh đối phải thuộc tam giác\n\n const nameM = NAME_BEFORE.exec(c.text);\n const name = nameM ? nameM[1] : undefined;\n if (!name) continue; // không trích được tên → bỏ qua (đừng bịa)\n\n out.push({\n ruleId: 'excenter',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'excenter', of, opposite })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/parallelPerp.ts\n//\n// Đường thẳng QUA 1 điểm, song song / vuông góc với 1 đường (cặp đỉnh):\n// \"Qua A kẻ đường thẳng song song với BC\" → draw-line parallelThrough A→BC\n// \"Từ A vẽ đường thẳng vuông góc với BC\" → draw-line perpThrough A→BC\n//\n// Phân biệt với perpFoot (\"Kẻ AH vuông góc BC\" → chân H): rule này BẮT BUỘC mở\n// đầu \"Qua/Từ <P>\" (P = điểm đường thẳng đi qua, KHÔNG sinh chân). perpFoot\n// không có tiền tố \"Qua/Từ\" nên 2 rule không chồng.\n//\n// Tên line không nêu trong đề → synthesize (\"parA\"/\"prpA\"); guard chỉ track điểm\n// HOA nên line name không bị đòi. Nếu đề có \"cắt … tại N\" (giao điểm) → phần đó\n// KHÔNG được claim → coverage/guard escalate (an toàn) thay vì dựng thiếu N.\n//\n// GOTCHA \\b: dùng (?!\\p{L}) + cờ 'u' quanh ký tự Việt.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawLine } from './_shared';\n\n// \"Qua/Từ <P> [kẻ/vẽ/dựng đường thẳng (d)] song song|vuông góc [với] [cạnh|đoạn] <PAIR>\".\n// group1 = through point; group2 = kind keyword; group3+4 = cặp đỉnh đường tham chiếu.\n// [^.]{0,24}? bắc cầu cụm \"kẻ đường thẳng (d) \" nhưng KHÔNG vượt dấu '.'.\nconst RE = new RegExp(\n '(?:Qua|qua|Từ|từ)\\\\s+(?:điểm\\\\s+)?([A-Z])(?:[\\'′]?)(?!\\\\p{L})' +\n '[^.]{0,24}?(song\\\\s*song|vuông\\\\s*góc)\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?' +\n '([A-Z])([A-Z])(?!\\\\p{L})',\n 'gu',\n);\n\n// Prefilter toàn đề (NON-global cho .test).\nconst PREFILTER =\n /(?:Qua|qua|Từ|từ)\\s+(?:điểm\\s+)?[A-Z][^.]{0,24}?(?:song\\s*song|vuông\\s*góc)/u;\n\nexport const parallelPerpRule: LanguageRule = {\n id: 'parallelPerp',\n priority: 58,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const through = m[1];\n const isParallel = /song/.test(m[2]);\n const to = m[3] + m[4];\n // Song song với đường CHỨA chính điểm qua → trùng đường đó (degenerate) → bỏ.\n if (isParallel && to.includes(through)) continue;\n const kind = isParallel ? 'parallelThrough' : 'perpThrough';\n const name = (isParallel ? 'par' : 'prp') + through;\n out.push({\n ruleId: 'parallelPerp',\n clauseIds: [c.id],\n intents: [drawLine(name, kind, { through, to })],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/reflection.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, extractPointName } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + tránh \\b.\n\n// Prefilter toàn đề: \"đối xứng\" (cho phép viết liền \"đốixứng\" hiếm gặp → giữ \\s*).\nconst REFLECT = /đối\\s*xứng/u;\n\n// Dạng A: tên điểm ĐỨNG TRƯỚC.\n// \"D đối xứng (với) H qua BC\"\n// \"D là (điểm) đối xứng (của|với) H qua (đường thẳng|cạnh|trục) <Z>\"\n// Z bắt mở (chữ cái + dấu phẩy/′), phân loại điểm/đường ở dưới.\nconst NAME_BEFORE =\n /([A-Z])(?:['′]?)\\s+(?:là\\s+)?(?:điểm\\s+)?đối\\s*xứng\\s+(?:của\\s+|với\\s+)?([A-Z])(?:['′]?)\\s+qua\\s+(?:đường\\s*thẳng\\s+|cạnh\\s+|đoạn\\s+|trục\\s+|trung\\s*điểm\\s+|điểm\\s+)?([A-Za-z][A-Za-z′']?)/u;\n\n// Dạng B: KHÔNG có tên dẫn trước \"đối xứng\" (lấy tên từ lời dẫn \"Gọi/Lấy …\").\n// \"Gọi D là điểm đối xứng của H qua BC\"\n// \"Lấy điểm đối xứng của H qua M\"\nconst NAME_AFTER =\n /(?:điểm\\s+)?đối\\s*xứng\\s+(?:của\\s+|với\\s+)?([A-Z])(?:['′]?)\\s+qua\\s+(?:đường\\s*thẳng\\s+|cạnh\\s+|đoạn\\s+|trục\\s+|trung\\s*điểm\\s+|điểm\\s+)?([A-Za-z][A-Za-z′']?)/u;\n\n// === EN (issue #46 group B) ===\n// \"<Name> is/be the reflection of <Of> (over|across|in|about|through) (the)? (line|point|segment)? <Z>\"\n// Name đứng TRƯỚC (qua \"is\"/\"be the\" — gồm \"Let D be the reflection...\"). KHÔNG cờ 'i'.\n// (?<![A-Za-z]) đảm bảo Name là nhãn đơn. Z phân loại bằng classifyThrough (reuse).\nconst REFLECT_EN =\n /(?<![A-Za-z])([A-Z])(?:['′]?)\\s+(?:is|be)\\s+the\\s+reflection\\s+of\\s+([A-Z])(?:['′]?)\\s+(?:over|across|in|about|through)\\s+(?:the\\s+)?(?:line\\s+|point\\s+|segment\\s+)?([A-Za-z][A-Za-z′']?)/u;\nconst REFLECT_EN_PRE = /[Rr]eflection/u;\n\n// Phân loại token Z (đã strip dấu phẩy/′):\n// \"M\" → điểm (1 ký tự HOA) → reflectPoint\n// \"BC\" → đường (cặp 2 ký tự HOA) → reflectLine\n// \"d\" → đường (tên đường, chữ thường) → reflectLine\nfunction classifyThrough(raw: string): { kind: 'point' | 'line'; value: string } | undefined {\n const z = raw.replace(/['′]/gu, '').trim();\n if (/^[A-Z]$/u.test(z)) return { kind: 'point', value: z };\n if (/^[A-Z][A-Z]$/u.test(z)) return { kind: 'line', value: z };\n // tên đường thẳng chữ thường (d, d1, a, xy…) → đường\n if (/^[a-z][A-Za-z0-9]*$/u.test(z)) return { kind: 'line', value: z };\n return undefined;\n}\n\n/**\n * Đối xứng (Cụm A reflection):\n * \"D đối xứng H qua BC\" → reflectLine (qua ĐƯỜNG: cặp đỉnh BC / tên đường d)\n * \"Q đối xứng P qua M\" → reflectPoint (qua ĐIỂM: 1 ký tự HOA)\n * \"D là điểm đối xứng của H qua đường thẳng d\" → reflectLine (through='d')\n *\n * name (điểm ảnh) = ký tự HOA đứng trước \"đối xứng\" (dạng A) hoặc lời dẫn\n * \"Gọi/Lấy …\" (dạng B). of = điểm gốc (X). through = Z, phân loại bằng\n * classifyThrough. Không trích đủ name / of / through hợp lệ → BỎ QUA clause\n * (đừng bịa tên) để pipeline escalate AI.\n */\nexport const reflectionRule: LanguageRule = {\n id: 'reflection',\n priority: 55,\n languages: ['vi', 'en'],\n patterns: [REFLECT, REFLECT_EN_PRE],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!REFLECT.test(c.text) && !REFLECT_EN_PRE.test(c.text)) continue;\n\n let name: string | undefined;\n let of: string | undefined;\n let throughRaw: string | undefined;\n\n const before = NAME_BEFORE.exec(c.text);\n if (before) {\n name = before[1];\n of = before[2];\n throughRaw = before[3];\n } else {\n const after = NAME_AFTER.exec(c.text);\n if (after) {\n // Không có tên đứng trước → lấy từ lời dẫn (\"Gọi D là …\").\n name = extractPointName(c.text);\n of = after[1];\n throughRaw = after[2];\n } else {\n // --- EN (issue #46 group B) — chỉ chạy khi cả 2 dạng VN fail. ---\n const en = REFLECT_EN.exec(c.text);\n if (en) {\n name = en[1];\n of = en[2];\n throughRaw = en[3];\n }\n }\n }\n\n if (!name || !of || !throughRaw) continue;\n\n const through = classifyThrough(throughRaw);\n if (!through) continue;\n\n const constraint =\n through.kind === 'point'\n ? { kind: 'reflectPoint', of, through: through.value }\n : { kind: 'reflectLine', of, through: through.value };\n\n out.push({\n ruleId: 'reflection',\n clauseIds: [c.id],\n intents: [addPoint(name, constraint)],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/pointAtDistance.ts\n//\n// Constraint METRIC: điểm trên tia kéo dài, cách mốc một khoảng cho trước.\n// C = through + d · unit(through − from) (xem spec 2026-06-06-point-at-distance)\n//\n// Phrasing phủ:\n// - \"trên tia đối của tia BA, lấy (điểm)? C sao cho BC = R\"\n// tia đối của tia BA = tia từ B ngược hướng A ⇒ hướng A→B kéo dài.\n// ⇒ from = A, through = B, điểm mới C nằm NGOÀI B.\n// - \"kéo dài AB (về phía B) lấy C sao cho BC = R\"\n// ⇒ from = A, through = B.\n// - EN (issue #46 group B):\n// \"On ray XY extended beyond Y, take D such that YD = …\" ⇒ from=X, through=Y.\n// \"Extend XY beyond Y to D such that YD = …\" ⇒ from=X, through=Y.\n// \"On the opposite ray of ray XY, take D such that XD …\" ⇒ from=Y, through=X.\n//\n// Hướng suy từ thứ tự token (from→through), KHÔNG cần field thừa. Điểm mốc đo\n// khoảng cách (through) trùng đỉnh đầu của cụm \"YZ = ...\" (Y = through, Z = tên\n// điểm mới). Ta dùng chính cặp này để chốt hướng + nguồn distance.\n//\n// distance (3 nguồn — discriminated union):\n// \"= R\" / \"= bán kính\" / \"= bán kính (O)\" → {kind:'circleRadius', circle}\n// \"= AB\" / \"= MN\" (2 ký tự HOA) → {kind:'segmentLength', p1, p2}\n// \"= 3\" / \"= 2,5\" / \"= 2 cm\" → {kind:'literal', value}\n//\n// GOTCHA \\b: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt.\n// Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// LƯU Ý: KHÔNG dùng cờ 'i' — nó làm [A-Z] khớp cả chữ thường, hỏng việc trích\n// tên điểm (đỉnh là CHỮ HOA). Clause có thể bắt đầu bằng chữ HOA (\"Kéo dài…\",\n// \"Trên tia đối…\") nên chữ cái đầu từ-khoá tiếng Việt dùng alternation [Kk]/[Tt].\n// --- Prefilter (toàn đề) ------------------------------------------------------\nconst KEYWORD = /(?:[Kk]éo\\s*dài|tia\\s*đối)/u;\n\n// --- Trigger trên clause ------------------------------------------------------\n// \"trên tia đối của tia BA\" → cặp [B, A] (B = gốc tia, A = hướng cũ). Hướng kéo\n// dài là tia đối ⇒ from = A, through = B.\nconst TIA_DOI =\n /tia\\s*đối\\s+của\\s+tia\\s+([A-Z])([A-Z])(?![A-Z])/u;\n// \"kéo dài AB\" → cặp [A, B]. Mặc định lấy điểm về phía B (đỉnh cuối) ⇒ from = A,\n// through = B. (\"về phía A\" hiếm + cần re-map; defer → bỏ qua để escalate.)\nconst KEO_DAI =\n /[Kk]éo\\s*dài\\s+(?:(?:đoạn|cạnh|tia)\\s+)?([A-Z])([A-Z])(?![A-Z])/u;\n\n// \"lấy (điểm)? C sao cho\" / \"lấy C\" / \"lấy C′\" → tên điểm mới (CAPTURE prime).\n// Issue #46 nhóm A: prime (' U+0027 / ′ U+2032) là PHẦN của tên — giữ lại để\n// \"C′\" ≠ đỉnh \"C\" (tránh addPoint dedup drop → escalate). Group 2 = prime char.\nconst TAKE_POINT =\n /lấy\\s+(?:điểm\\s+)?([A-Z])(['′]?)(?![A-Z])/u;\n\n// Normalize prime về 1 dạng: ′ (U+2032) → ' (U+0027). NameZ/serialize NAME_REGEX\n// cho phép ' nhưng KHÔNG cho phép ′ → chuẩn hoá để name \"C'\" chảy qua DSL/render\n// (label) không cần đổi schema. Trả về tên đầy đủ (chữ + prime đã normalize).\nfunction normalizePointName(letter: string, prime: string): string {\n return prime ? `${letter}'` : letter;\n}\n\n// \"về phía X\": hướng kéo dài. Mặc định through = đỉnh cuối cụm. Nếu \"về phía X\"\n// mà X KHÁC through (vd \"kéo dài AB về phía A\") → hướng đảo, rule không xử lý\n// đúng (defer) → skip để escalate.\nconst VE_PHIA = /về\\s+phía\\s+([A-Z])(?![A-Za-z])/u;\n\n// === EN (issue #46 group B) ==================================================\n// Additive — KHÔNG đụng building block VN ở trên. Nhãn STRICT [A-Z] (KHÔNG cờ\n// 'i' — sẽ nuốt chữ thường); first-letter flex của verb bằng [Ee]/[Tt]/[Mm]/…\n//\n// EN prefilter (runRules tests `patterns` against whole problem, IGNORING the\n// `languages` field — so an EN regex is REQUIRED here for EN-only problems to\n// reach match()). Broad but match() validates precisely → safe.\nconst PREFILTER_EN = /beyond|opposite\\s+ray/i;\n\n// \"ray XY extended beyond Z\" → ray X→Y extended past Z. from=X, through=Y;\n// require Z===Y (you extend past the FAR endpoint). Comma before \"extended\" ok.\nconst RAY_EXTENDED_EN =\n /ray\\s+([A-Z])([A-Z])(?![A-Z])\\s*,?\\s*extended\\s+beyond\\s+([A-Z])(?![A-Z])/u;\n// \"extend(ed)? (segment|line|side)? XY beyond Z\" (no \"ray\"). from=X, through=Y;\n// require Z===Y.\nconst EXTEND_SEG_EN =\n /[Ee]xtend(?:ed)?\\s+(?:segment\\s+|line\\s+|side\\s+)?([A-Z])([A-Z])(?![A-Z])\\s+beyond\\s+([A-Z])(?![A-Z])/u;\n// \"opposite ray of ray XY\" → mirror VN tia đối: from=Y(2nd), through=X(1st).\nconst OPPOSITE_RAY_EN =\n /opposite\\s+ray\\s+of\\s+ray\\s+([A-Z])([A-Z])(?![A-Z])/u;\n\n// New-point name (EN). \"take/mark/choose/pick D\" or \"to D\" (phrasing \"extend AB\n// beyond B TO D\"). Lookbehind (?<![A-Za-z]) stops \"to\" matching inside words\n// (into, photo). NO `i` flag — capture is [A-Z]; first-letter flex per verb.\n// group 1 = letter, group 2 = prime (mirror VN TAKE_POINT).\nconst TAKE_POINT_EN =\n /(?<![A-Za-z])(?:[Tt]ake|[Mm]ark|[Cc]hoose|[Pp]ick|to)\\s+(?:a\\s+|the\\s+)?(?:point\\s+)?([A-Z])(['′]?)(?![A-Z])/u;\n\n// Cụm chốt mốc + khoảng cách: \"BC = R\" / \"BC = AB\" / \"BC = 3\" / \"BC = 2,5 cm\".\n// Đỉnh đầu (m[1]) = mốc đo (through); đỉnh sau (m[2]) = điểm mới (Z); m[3] = prime\n// của điểm mới (CAPTURE — phải khớp tên điểm mới ở TAKE_POINT). Issue #46 nhóm A:\n// điểm mới có thể mang dấu phẩy/prime (\"BC′ = R\"); giữ prime để chốt mốc đúng.\n// Phần sau dấu \"=\" (m[4]) gom thô để parse riêng (radius / segment / số). KHÔNG\n// kết thúc trên ',' — dấu phẩy có thể là phân tách thập phân (\"2,5\"); clause đã\n// được segmentClauses tách trên dấu chấm/'; nên gom tới hết clause là an toàn.\nconst DIST_CLAUSE =\n /(?:sao\\s+cho\\s+)?([A-Z])([A-Z])(['′]?)(?![A-Z])\\s*=\\s*(.+?)\\s*(?:[.;]|$)/u;\n\n// --- Distance parsing ---------------------------------------------------------\nconst RADIUS_WORD = /(?<!\\p{L})(?:R|bán\\s*kính)(?!\\p{L})/u;\nconst CIRCLE_OF_RADIUS = /bán\\s*kính\\s*(?:\\(\\s*)?([A-Z])\\s*\\)?/u;\nconst SEGMENT_PAIR = /^\\s*([A-Z])([A-Z])(?![A-Z])\\s*$/u;\nconst NUMBER = /(\\d+(?:[.,]\\d+)?)/u;\n\n// Tâm đường tròn trong đề: \"(O;\" / \"(O)\" / \"đường tròn tâm O\" → tên circle.\nconst CIRCLE_NAME_PAREN = /\\(\\s*([A-Z])\\s*[;,)]/u;\nconst CIRCLE_NAME_WORDS = /đường\\s*tròn\\s*(?:tâm\\s+)?([A-Z])(?![A-Z])/u;\n\nfunction parseNum(raw: string): number {\n return Number(raw.replace(',', '.'));\n}\n\n/** Tên circle để gắn radius. Suy từ đề (ctx.problem); mặc định 'O'. */\nfunction resolveCircleName(problem: string): string {\n const w = CIRCLE_NAME_WORDS.exec(problem);\n if (w) return w[1];\n const p = CIRCLE_NAME_PAREN.exec(problem);\n if (p) return p[1];\n return 'O';\n}\n\ntype DistanceBase =\n | { kind: 'circleRadius'; circle: string }\n | { kind: 'segmentLength'; p1: string; p2: string }\n | { kind: 'literal'; value: number };\n\ntype Distance = DistanceBase & { scale?: number; offset?: number };\n\n// --- Hệ số/bội/offset (Issue #46 nhóm C) -------------------------------------\n// Tách \"<scale>·base ± offset\". scale = số đứng TRƯỚC base (qua dấu nhân ·/./×/*\n// hoặc dán liền \"2AB\"/\"2R\" hoặc cách \"2 AB\"). offset = \"± số\" đứng SAU base.\n// \"2R\" → scale 2, base R\n// \"2·AB\" → scale 2, base AB\n// \"R + 1\" → base R, offset +1\n// \"2R + 1\" → scale 2, base R, offset +1\n// base có thể là R/bán kính, cặp đỉnh (AB), hoặc số literal.\n//\n// Hệ số đứng trước base: \"2\", \"2·\", \"2.\", \"2×\", \"2*\", \"2 \" (số rồi base).\nconst COEF_PREFIX = /^(\\d+(?:[.,]\\d+)?)\\s*[·.×*]?\\s*(?=[A-Z]|bán)/u;\n// Offset đứng cuối: \"± số\" (chỉ số literal, không nhân thêm đại lượng).\nconst OFFSET_SUFFIX = /([+-])\\s*(\\d+(?:[.,]\\d+)?)\\s*$/u;\n// Dấu nhân CHỈ giữa 2 đại lượng (vd \"R·AB\", \"AB·MN\"): tích 2 đại lượng → mơ hồ.\n// Phát hiện: có dấu nhân mà 2 BÊN đều KHÔNG phải số → reject.\nconst MUL_TWO_QUANTITIES = /[A-Z](?:\\s*['′])?\\s*[·×*]\\s*[A-Z]/u;\n\n/** Parse phần sau dấu \"=\" → DistanceSpec hoặc undefined (không nhận dạng được). */\nfunction parseDistance(raw: string, problem: string): Distance | undefined {\n let text = raw.trim();\n\n // 0. TỪ CHỐI ngay các biểu thức KHÔNG xử lý được:\n if (/\\//u.test(text)) return undefined; // chia: \"AB/2\", \"1/2 AB\" → defer\n if (/\\blần\\b/u.test(text)) return undefined; // \"2 lần bán kính\" → defer\n if (MUL_TWO_QUANTITIES.test(text)) return undefined; // tích 2 đại lượng \"R·AB\"\n // '-' đứng đầu (giá trị âm trực tiếp \"-3\") → defer. ('-' offset xử lý ở dưới.)\n if (/^-/u.test(text)) return undefined;\n\n // 1. Tách offset \"± số\" ở cuối (literal). Không nhân thêm đại lượng.\n let offset: number | undefined;\n const off = OFFSET_SUFFIX.exec(text);\n if (off) {\n const sign = off[1] === '-' ? -1 : 1;\n offset = sign * parseNum(off[2]);\n text = text.slice(0, off.index).trim();\n }\n // Sau khi bóc offset, KHÔNG còn được phép có toán tử +/- (vd \"1 + 2 + R\" lạ).\n if (/[+]/u.test(text)) return undefined;\n if (/-\\s*\\d/u.test(text)) return undefined;\n\n // 2. Tách hệ số (scale) đứng trước base. Chỉ nhận khi PHÍA SAU là base\n // (đỉnh HOA / \"bán\"). \"3\" đơn lẻ KHÔNG khớp (→ literal value).\n let scale: number | undefined;\n const coef = COEF_PREFIX.exec(text);\n if (coef) {\n scale = parseNum(coef[1]);\n if (!(Number.isFinite(scale) && scale > 0)) return undefined;\n text = text.slice(coef[0].length).trim();\n }\n\n // Còn sót dấu nhân lẻ (vd \"·R\" do tách lỗi) → mơ hồ.\n if (/[·×*]/u.test(text)) return undefined;\n\n const withCoef = (base: DistanceBase): Distance => {\n const d: Distance = { ...base };\n if (scale !== undefined) d.scale = scale;\n if (offset !== undefined) d.offset = offset;\n return d;\n };\n\n // 3. base = bán kính: \"R\" / \"bán kính\" / \"bán kính (O)\".\n if (RADIUS_WORD.test(text)) {\n const co = CIRCLE_OF_RADIUS.exec(text);\n const circle = co ? co[1] : resolveCircleName(problem);\n return withCoef({ kind: 'circleRadius', circle });\n }\n // 4. base = đoạn = 2 ký tự HOA liền (\"AB\", \"MN\").\n const seg = SEGMENT_PAIR.exec(text);\n if (seg) return withCoef({ kind: 'segmentLength', p1: seg[1], p2: seg[2] });\n // 5. base = số literal (board units). \"2 cm\" → 2 (cm-mapping defer).\n // Lưu ý: nếu đã tách scale thì KHÔNG còn base số (scale·số vô nghĩa) → defer.\n if (scale === undefined) {\n const num = NUMBER.exec(text);\n if (num) {\n const value = parseNum(num[1]);\n if (Number.isFinite(value) && value > 0) return withCoef({ kind: 'literal', value });\n }\n }\n return undefined;\n}\n\n/**\n * \"kéo dài AB lấy C sao cho BC = R\" / \"trên tia đối của tia BA, lấy C sao cho\n * BC = R\" → add-point C kind:pointAtDistance. Hướng (from→through) suy từ token\n * cặp + mốc đo (đỉnh đầu cụm \"YZ = …\"). Không parse đủ (thiếu tên điểm mới /\n * distance không nhận dạng / mốc không khớp) → bỏ qua để escalate AI.\n *\n * EN (issue #46 group B) — mirror VN, chỉ chạy khi VN không xác định được hướng:\n * \"ray XY extended beyond Y, take D such that YD = …\" → from=X, through=Y\n * \"extend XY beyond Y to D such that YD = …\" → from=X, through=Y\n * \"opposite ray of ray XY, take D such that XD = …\" → from=Y, through=X\n */\nexport const pointAtDistanceRule: LanguageRule = {\n id: 'pointAtDistance',\n priority: 55,\n languages: ['vi', 'en'],\n patterns: [KEYWORD, PREFILTER_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n let from: string | undefined;\n let through: string | undefined;\n let name: string | undefined;\n let isEn = false;\n\n // --- Hướng VN (from → through) ---\n const doi = TIA_DOI.exec(c.text);\n if (doi) {\n // tia đối của tia BA: B = gốc, A = hướng cũ ⇒ kéo dài về B ⇒ from=A, through=B.\n from = doi[2];\n through = doi[1];\n } else {\n const kd = KEO_DAI.exec(c.text);\n if (kd) {\n // kéo dài AB (về phía B mặc định) ⇒ from=A, through=B.\n from = kd[1];\n through = kd[2];\n }\n }\n\n if (from && through) {\n // VN name (GIỮ prime, normalize ′→').\n const take = TAKE_POINT.exec(c.text);\n name = take ? normalizePointName(take[1], take[2]) : undefined;\n } else {\n // --- EN direction (additive; chỉ khi VN không xác định được hướng) ---\n const opp = OPPOSITE_RAY_EN.exec(c.text);\n const ray = RAY_EXTENDED_EN.exec(c.text);\n const ext = EXTEND_SEG_EN.exec(c.text);\n if (opp) {\n // opposite ray of ray XY → mirror VN tia đối: from=Y, through=X.\n from = opp[2];\n through = opp[1];\n } else if (ray && ray[3] === ray[2]) {\n // ray XY extended beyond Z (Z must = Y): from=X, through=Y.\n from = ray[1];\n through = ray[2];\n } else if (ext && ext[3] === ext[2]) {\n // extend XY beyond Z (Z must = Y): from=X, through=Y.\n from = ext[1];\n through = ext[2];\n }\n if (from && through) {\n isEn = true;\n const takeEn = TAKE_POINT_EN.exec(c.text);\n name = takeEn ? normalizePointName(takeEn[1], takeEn[2]) : undefined;\n }\n }\n\n if (!from || !through || !name) continue;\n\n // VE_PHIA: chỉ VN (EN không có \"về phía\"). Giữ outcome VN byte-identical.\n if (!isEn) {\n const vp = VE_PHIA.exec(c.text);\n if (vp && vp[1] !== through) continue;\n }\n\n // --- Mốc đo + khoảng cách (\"YZ = …\") — language-agnostic (DIST_CLAUSE) ---\n const dc = DIST_CLAUSE.exec(c.text);\n if (!dc) continue;\n const anchor = dc[1]; // Y = mốc đo (phải trùng through; đỉnh đơn)\n const newPt = normalizePointName(dc[2], dc[3]); // Z = điểm mới (phải trùng name)\n // Mốc đo phải là through; đỉnh sau là điểm mới ta vừa lấy (so theo tên đã\n // normalize ⇒ \"BC′\" khớp điểm \"C'\", \"BD′\" KHÔNG khớp điểm \"C'\").\n if (anchor !== through || newPt !== name) continue;\n\n const distance = parseDistance(dc[4], ctx.problem);\n if (!distance) continue;\n\n out.push({\n ruleId: 'pointAtDistance',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'pointAtDistance', from, through, distance })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/eulerLine.ts\n//\n// Đường thẳng Euler (issue #47, construct 1): đường thẳng đi qua 3 tâm tam giác\n// THẲNG HÀNG — trọng tâm G, trực tâm H, tâm đường tròn ngoại tiếp O. KHÔNG phải\n// kind DSL riêng — compose từ 3 tâm (centroid/orthocenter/circumcenter, đã có)\n// + kind tổng quát `lineThrough([G,H,O])`.\n//\n// Fail-safe (escalate, KHÔNG dựng sai):\n// - \"đường tròn Euler\" (đường tròn 9 điểm) → KHÔNG khớp (regex chỉ nhận\n// \"đường (thẳng) Euler\", không có \"tròn\").\n// - Tam giác đều (\"đều\") → G≡H≡O suy biến, đường Euler không xác định → bỏ qua.\n// - Không có tam giác / >1 tam giác (nhập nhằng) → bỏ qua.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\n// \"đường thẳng Euler\" / \"đường Euler\" — \"thẳng\" optional. KHÔNG khớp \"đường tròn\n// Euler\" (vì \"tròn\" KHÔNG phải nhánh optional \"thẳng\"). \\p{L} lookaround vì \\b\n// không khớp quanh ký tự Việt.\nconst EULER_LINE_KW = /(?<!\\p{L})đường\\s+(?:thẳng\\s+)?[Ee]uler(?!\\p{L})/u;\n\n// Tam giác (global): quét mọi tam giác nêu trong đề.\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\n// Tam giác đều → 3 tâm trùng → đường Euler suy biến.\nconst EQUILATERAL_KW = /(?<!\\p{L})đều(?!\\p{L})/u;\n\n/** Bộ 3 đỉnh duy nhất toàn đề; undefined nếu 0 hoặc >1 tam giác phân biệt. */\nfunction uniqueTriangle(problem: string): [string, string, string] | undefined {\n TRI_G.lastIndex = 0;\n const tris: string[][] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) {\n tris.push([m[1], m[2], m[3]]);\n }\n const distinct = new Set(tris.map((t) => t.join('')));\n if (distinct.size !== 1) return undefined;\n const t = tris[0];\n return [t[0], t[1], t[2]];\n}\n\nexport const eulerLineRule: LanguageRule = {\n id: 'eulerLine',\n priority: 68,\n languages: ['vi'],\n patterns: [EULER_LINE_KW],\n match(ctx) {\n // Suy biến tam giác đều → escalate (G≡H≡O → đường Euler không xác định).\n if (EQUILATERAL_KW.test(ctx.problem)) return [];\n\n const tri = uniqueTriangle(ctx.problem);\n if (!tri) return []; // 0 hoặc >1 tam giác → nhập nhằng → escalate.\n const [A, B, C] = tri;\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!EULER_LINE_KW.test(c.text)) continue;\n out.push({\n ruleId: 'eulerLine',\n clauseIds: [c.id],\n intents: [\n addPoint('G', { kind: 'centroid', of: [A, B, C] }),\n addPoint('H', { kind: 'orthocenter', of: [A, B, C] }),\n addPoint('O', { kind: 'circumcenter', of: [A, B, C] }),\n drawLine('euler' + A + B + C, 'lineThrough', { points: ['G', 'H', 'O'] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/radicalAxis.ts\n//\n// Trục đẳng phương 2 đường tròn (issue #47, construct 2): đường ⊥ đường nối tâm\n// O₁O₂, mọi điểm trên nó có lũy thừa (power) bằng nhau với 2 đường tròn. KHÔNG\n// phải kind point — compose từ kind tổng quát `radicalAxis(circle1, circle2)`\n// (tham chiếu 2 CIRCLE đã được circleRadius dựng theo center letter).\n//\n// Fail-safe (escalate, KHÔNG dựng sai):\n// - Đồng tâm \"(O;3) và (O;5)\" → {O} (1 center phân biệt) → bỏ qua (suy biến,\n// trục không xác định).\n// - 0 hoặc 1 đường tròn có bán kính → không đủ 2 → bỏ qua.\n// - >2 đường tròn → nhập nhằng (cặp nào?) → bỏ qua.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawLine } from './_shared';\n\n// \"trục đẳng phương\" / \"đẳng phương\" — \"trục\" optional. \\p{L} lookaround vì \\b\n// không khớp quanh ký tự Việt.\nconst RADICAL_KW = /(?<!\\p{L})(?:trục\\s+)?đẳng\\s*phương(?!\\p{L})/u;\n\n// Đường tròn CÓ BÁN KÍNH (số hoặc ký hiệu R/r) — khớp những gì circleRadius\n// dựng qua centerRadius. \"(O; 3)\" / \"(I, 2.5)\" / \"(O; R)\". Global: nhiều đường\n// tròn / đề. Group 1 = center letter.\nconst CIRCLE_R_G = /\\(\\s*([A-Z])\\s*[;,]\\s*(?:\\d|[Rr])/gu;\n\n/** Các center letter phân biệt của đường tròn-có-bán-kính nêu trong đề. */\nfunction circleCentersWithRadius(problem: string): string[] {\n CIRCLE_R_G.lastIndex = 0;\n const centers = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = CIRCLE_R_G.exec(problem)) !== null) {\n centers.add(m[1]);\n }\n return [...centers];\n}\n\nexport const radicalAxisRule: LanguageRule = {\n id: 'radicalAxis',\n priority: 66,\n languages: ['vi'],\n patterns: [RADICAL_KW],\n match(ctx) {\n const centers = circleCentersWithRadius(ctx.problem);\n // Cần ĐÚNG 2 đường tròn phân biệt. Đồng tâm → 1 center → escalate. >2 → mơ hồ.\n if (centers.length !== 2) return [];\n const [c1, c2] = centers;\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!RADICAL_KW.test(c.text)) continue;\n out.push({\n ruleId: 'radicalAxis',\n clauseIds: [c.id],\n intents: [drawLine('rad' + c1 + c2, 'radicalAxis', { circle1: c1, circle2: c2 })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/simson.ts\n//\n// Đường thẳng Simson (issue #47, construct 3): P trên đường tròn ngoại tiếp tam\n// giác ABC → 3 chân vuông góc hạ từ P xuống 3 cạnh (BC, CA, AB) THẲNG HÀNG\n// (định lý Simson). KHÔNG kind DSL riêng — compose:\n// - P = onCircle (glider trên đường tròn ngoại tiếp, theta cố định 0.7).\n// - 3 chân = perpFoot (chiếu trực giao xuống đường vô hạn BC/CA/AB).\n// - đường Simson = lineThrough([chân1, chân2, chân3]).\n//\n// Fail-safe (escalate, KHÔNG dựng sai):\n// - Không có đường tròn ngoại tiếp khai báo → KHÔNG đặt được P → bỏ qua.\n// - 0 hoặc >1 tam giác phân biệt (nhập nhằng) → bỏ qua.\n// - P trùng đỉnh (Simson của A) → 3 chân suy biến → bỏ qua.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\n// \"Simson\" — danh từ riêng. \\b không khớp quanh ký tự ASCII letter ổn, nhưng\n// dùng lookaround [A-Za-z] để chắc chắn không khớp trong từ khác.\nconst SIMSON_KW = /(?<![A-Za-z])[Ss]imson(?![A-Za-z])/u;\n\n// Tam giác (global): quét mọi tam giác nêu trong đề.\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\n// Tên tâm đường tròn ngoại tiếp: \"(O)\" — dạng ngoặc 1 chữ HOA.\nconst CIRCLE_CENTER = /\\(\\s*([A-Z])\\s*\\)/u;\n\n// P của Simson: \"Simson của (điểm) P\".\nconst SIMSON_OF = /[Ss]imson\\s+của\\s+(?:điểm\\s+)?([A-Z])(?![A-Za-z])/u;\n\n/** Bộ 3 đỉnh duy nhất toàn đề; undefined nếu 0 hoặc >1 tam giác phân biệt. */\nfunction uniqueTriangle(problem: string): [string, string, string] | undefined {\n TRI_G.lastIndex = 0;\n const tris: string[][] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) {\n tris.push([m[1], m[2], m[3]]);\n }\n const distinct = new Set(tris.map((t) => t.join('')));\n if (distinct.size !== 1) return undefined;\n const t = tris[0];\n return [t[0], t[1], t[2]];\n}\n\nexport const simsonRule: LanguageRule = {\n id: 'simson',\n priority: 64,\n languages: ['vi'],\n patterns: [SIMSON_KW],\n match(ctx) {\n const tri = uniqueTriangle(ctx.problem);\n if (!tri) return []; // 0 hoặc >1 tam giác → nhập nhằng → escalate.\n const [A, B, C] = tri;\n\n // Đường tròn ngoại tiếp PHẢI được khai báo (vd \"(O)\") — circleTriangle dựng\n // circle tên theo chữ trong \"(O)\". Thiếu → KHÔNG đặt được P → escalate.\n const cm = CIRCLE_CENTER.exec(ctx.problem);\n if (!cm) return [];\n const O = cm[1];\n\n // P của Simson.\n const pm = SIMSON_OF.exec(ctx.problem);\n if (!pm) return []; // không xác định được P → escalate.\n const P = pm[1];\n\n // Suy biến: P là 1 đỉnh tam giác → 3 chân trùng → đường Simson suy biến.\n if (P === A || P === B || P === C) return [];\n\n const f1 = 'S' + A + B + C + '1';\n const f2 = 'S' + A + B + C + '2';\n const f3 = 'S' + A + B + C + '3';\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!SIMSON_KW.test(c.text)) continue;\n out.push({\n ruleId: 'simson',\n clauseIds: [c.id],\n intents: [\n addPoint(P, { kind: 'onCircle', circle: O, theta: 0.7 }),\n addPoint(f1, { kind: 'perpFoot', from: P, onLine: B + C }),\n addPoint(f2, { kind: 'perpFoot', from: P, onLine: C + A }),\n addPoint(f3, { kind: 'perpFoot', from: P, onLine: A + B }),\n drawLine('simson' + P, 'lineThrough', { points: [f1, f2, f3] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/ninePoint.ts\n//\n// Đường tròn chín điểm / đường tròn Euler (issue #47, construct 4): đường tròn qua\n// 3 trung điểm cạnh (= cũng qua 3 chân đường cao + 3 trung điểm đỉnh-trực tâm;\n// bán kính R/2). Dựng = circle3 qua 3 TRUNG ĐIỂM CẠNH — TRÁNH radius-scaling.\n// Compose midpoint×3 + circle3, KHÔNG kind DSL mới.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle } from './_shared';\n\n// \"đường tròn chín điểm\" / \"đường tròn Euler\" / \"chín điểm\". KHÔNG khớp \"đường\n// thẳng Euler\" (yêu cầu \"tròn\" trước Euler — đó là đường thẳng Euler, construct 1).\nconst NINE_KW = /(?<!\\p{L})(?:đường\\s*tròn\\s+Euler|(?:đường\\s*tròn\\s+)?chín\\s*điểm)(?!\\p{L})/u;\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\nfunction uniqueTriangle(problem: string): [string, string, string] | undefined {\n TRI_G.lastIndex = 0;\n const tris: string[][] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) tris.push([m[1], m[2], m[3]]);\n const distinct = new Set(tris.map((t) => t.join('')));\n if (distinct.size !== 1) return undefined;\n const t = tris[0];\n return [t[0], t[1], t[2]];\n}\n\nexport const ninePointRule: LanguageRule = {\n id: 'ninePoint',\n priority: 63,\n languages: ['vi'],\n patterns: [NINE_KW],\n match(ctx) {\n const tri = uniqueTriangle(ctx.problem);\n if (!tri) return []; // 0 hoặc >1 tam giác → escalate.\n const [A, B, C] = tri;\n const mAB = 'M' + A + B, mBC = 'M' + B + C, mCA = 'M' + C + A;\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!NINE_KW.test(c.text)) continue;\n out.push({\n ruleId: 'ninePoint',\n clauseIds: [c.id],\n intents: [\n addPoint(mAB, { kind: 'midpoint', of: A + B }),\n addPoint(mBC, { kind: 'midpoint', of: B + C }),\n addPoint(mCA, { kind: 'midpoint', of: C + A }),\n drawCircle('N9', 'through3', { points: [mAB, mBC, mCA] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/diameterCirclePairwise.ts\n//\n// Đề \"đường tròn đường kính đôi một cắt nhau lần thứ hai\" (whole-problem construct):\n//\n// Cho đường tròn (O) và ba dây cung AB, AC, AD bất kì. Các đường tròn đường\n// kính AB, AC, AD đôi một cắt nhau lần thứ hai tại M, N, P.\n//\n// Bản chất: (đ.kính AX)∩(đ.kính AY) lần 2 = chân vuông góc hạ từ A xuống XY\n// (∠ nhìn AX,AY = 90°). M,N,P = 3 chân Simson của A với ΔBCD. Đề gốc chỉ là\n// GIẢ THIẾT → hình tối giản: (O)+O, A/B/C/D, dây AX, 3 đường tròn đường kính,\n// M/N/P (giao điểm thứ hai, loại điểm chung A).\n//\n// Fail-safe (escalate, KHÔNG dựng sai): thiếu tâm \"(O)\"; <2 đường kính chung\n// apex; đầu mút/kết quả trùng; số tên kết quả ≠ số đường kính.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, drawCircle, DUONG_KW } from './_shared';\n\n// Tâm đường tròn: \"(O)\" — ngoặc 1 chữ HOA.\nconst CIRCLE_CENTER = /\\(\\s*([A-Z])\\s*\\)/u;\n// Prefilter: phải có \"đường kính\" + dấu hiệu \"đôi một\"/\"cắt nhau\".\nconst KW_DIAMETER = new RegExp(DUONG_KW + '\\\\s*kính', 'u');\nconst KW_PAIRWISE = /đôi một|cắt nhau/u;\n\n// Góc đặt điểm (radian) — apex trên cao, các đầu mút còn lại rải cung dưới ở\n// vị trí TỔNG QUÁT (tránh suy biến chân vuông góc trùng nhau).\nconst APEX_THETA = 2.0;\nconst OTHER_THETAS = [5.5, 4.0, 0.6, 3.3, 1.1, 5.0] as const;\n\ninterface Parsed {\n center: string;\n apex: string;\n others: string[];\n results: string[];\n}\n\nfunction parse(problem: string): Parsed | undefined {\n const cm = CIRCLE_CENTER.exec(problem);\n if (!cm) return undefined;\n const center = cm[1];\n\n // Vùng sau \"đường kính\" tới khi gặp \"đôi một\"/\"cắt nhau\" (cùng câu).\n const dm = new RegExp(DUONG_KW + '\\\\s*kính\\\\s+([^.;\\n]*)', 'u').exec(problem);\n if (!dm) return undefined;\n let region = dm[1];\n const cut = region.search(/đôi một|cắt nhau/u);\n if (cut >= 0) region = region.slice(0, cut);\n const pairs = region.match(/[A-Z][A-Z]/g) ?? [];\n if (pairs.length < 2) return undefined;\n\n // apex = chữ xuất hiện trong MỌI cặp.\n const counts = new Map<string, number>();\n for (const pr of pairs) {\n counts.set(pr[0], (counts.get(pr[0]) ?? 0) + 1);\n counts.set(pr[1], (counts.get(pr[1]) ?? 0) + 1);\n }\n const apexEntries = [...counts].filter(([, n]) => n === pairs.length);\n if (apexEntries.length !== 1) return undefined; // 0 → không chung; >1 → nhập nhằng\n const apex = apexEntries[0][0];\n const others = pairs.map((pr) => (pr[0] === apex ? pr[1] : pr[0]));\n if (new Set(others).size !== others.length) return undefined; // đầu mút trùng\n if (others.includes(apex)) return undefined;\n\n // Tên kết quả sau \"tại\": các chữ HOA đơn lẻ (M, N, P, ...).\n const rm = /\\btại\\s+([A-Z][^.;\\n]*)/u.exec(problem);\n if (!rm) return undefined;\n const results = rm[1].match(/\\b[A-Z]\\b/g) ?? [];\n // \"đôi một cắt nhau\" của n đường kính chung apex = TẤT CẢ C(n,2) cặp → C(n,2)\n // giao điểm. Số tên kết quả phải khớp đúng (n=3 → 3; n=4 → 6; ...).\n const numPairs = (others.length * (others.length - 1)) / 2;\n if (results.length !== numPairs) return undefined;\n if (new Set(results).size !== results.length) return undefined;\n\n return { center, apex, others, results };\n}\n\nexport const diameterCirclePairwiseRule: LanguageRule = {\n id: 'diameter-circle-pairwise',\n priority: 66,\n languages: ['vi'],\n patterns: [KW_DIAMETER],\n match(ctx) {\n if (!KW_PAIRWISE.test(ctx.problem)) return [];\n const p = parse(ctx.problem);\n if (!p) return [];\n const { center, apex, others, results } = p;\n\n const circOf = (other: string) => `k${apex}${other}`;\n const oCircle = `k${center}`; // tên entity đường tròn (O) (khác điểm tâm O)\n\n // Tất cả cặp (i<j) theo thứ tự từ điển — \"đôi một\" = mọi cặp đường kính.\n const allPairs: Array<[number, number]> = [];\n for (let i = 0; i < others.length; i++)\n for (let j = i + 1; j < others.length; j++) allPairs.push([i, j]);\n\n const intents = [\n // (O): tâm `center` (free) + bán kính cố định.\n drawCircle(oCircle, 'centerRadius', { center, radius: 4 }),\n // apex + các đầu mút = glider trên (O), vị trí tổng quát.\n addPoint(apex, { kind: 'onCircle', circle: oCircle, theta: APEX_THETA }),\n ...others.map((o, i) =>\n addPoint(o, { kind: 'onCircle', circle: oCircle, theta: OTHER_THETAS[i % OTHER_THETAS.length] }),\n ),\n // Dây cung apex–đầu mút.\n ...others.map((o) => connect(apex, o, 'segment')),\n // Đường tròn đường kính apex–đầu mút.\n ...others.map((o) => drawCircle(circOf(o), 'diameter', { endpoints: [apex, o] })),\n // Giao điểm thứ hai của TỪNG cặp đường tròn đường kính, loại điểm chung apex.\n ...results.map((r, k) =>\n addPoint(r, {\n kind: 'circleSecondIntersection',\n c1: circOf(others[allPairs[k][0]]),\n c2: circOf(others[allPairs[k][1]]),\n exclude: apex,\n }),\n ),\n ];\n\n const out: RuleMatch[] = [{\n ruleId: 'diameter-circle-pairwise',\n // Whole-problem construct: claim mọi clause để coverage gate đầy đủ.\n clauseIds: ctx.clauses.map((c) => c.id),\n intents,\n }];\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/angleBisectorFoot.ts\n//\n// Chân đường phân giác (trong/ngoài) hạ từ một đỉnh xuống cạnh đối:\n// \"D là chân đường phân giác từ A\" → onLine = cạnh đối A (suy từ tam giác)\n// \"D là chân đường phân giác trong kẻ từ A đến BC\" → onLine = BC (nêu rõ)\n// \"D là chân phân giác góc A\" → onLine = cạnh đối A\n// \"D là chân đường phân giác ngoài từ A\" → externalAngleBisectorFoot\n// → add-point D {kind:'angleBisectorFoot', from:'A', onLine:'BC'} (builder dựng\n// tia phân giác ∠(onLine[0])-from-(onLine[1]) ∩ đoạn onLine).\n//\n// Phân biệt (KHÔNG chồng rule khác):\n// - cevian (\"phân giác AD\" — đỉnh+chân dạng cặp HOA NGAY sau \"phân giác\"): rule\n// này BẮT BUỘC chữ \"chân\" mở đầu cụm → cevian không khớp.\n// - perpFoot (\"chân đường vuông góc / cao\"): keyword khác (\"vuông góc\"/\"cao\").\n// - angleBisectorAngle (\"phân giác góc A\" — vẽ tia VISIBLE, không foot): rule\n// đó tự né khi có \"chân\" đứng trước (guard CHAN_BEFORE bên angleBisectorAngle).\n//\n// Cần TAM GIÁC để suy cạnh đối khi đề KHÔNG nêu cạnh (\"đến BC\"); nêu rõ thì dùng\n// luôn. Tên chân (HOA) bind cục bộ qua \"X là\" NGAY TRƯỚC cụm. Thiếu tên / không\n// suy được cạnh đối → bỏ qua clause (escalate AI thay vì đoán sai).\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt (\"đ\",\"ề\",\"ạ\"…).\n// Regex chứa ký tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// Tam giác toàn đề (suy cạnh đối). Bổ ngữ \"vuông|cân|đều|nhọn|tù\" optional.\nconst TRI = /tam\\s*giác(?:\\s+(?:vuông|cân|đều|nhọn|tù))?\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\n\n// onLine token: tên đường 1 ký tự HOA HOẶC cặp đỉnh 2 ký tự HOA. Tiền tố tuỳ chọn.\nconst LINE = '(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])';\n// Giới từ dẫn tới cạnh đáy.\nconst PREP_TO = '(?:đến|tới|xuống|trên|ra)';\n// Đỉnh: \"từ (đỉnh)? X\" | \"của góc X\" | \"góc X\" | \"tại (đỉnh)? X\" | \"đỉnh X\".\nconst VERTEX =\n '(?:từ\\\\s+(?:đỉnh\\\\s+)?|của\\\\s+góc\\\\s+|góc\\\\s+|tại\\\\s+(?:đỉnh\\\\s+)?|đỉnh\\\\s+)([A-Z])(?![A-Z])';\n\n// \"chân (của)? (đường|tia)? phân giác (trong|ngoài)? (hạ|kẻ|vẽ|dựng)? VERTEX (PREP_TO LINE)?\".\n// group1 = trong|ngoài (optional); group2 = vertex; group3 = onLine (optional).\nconst CORE = new RegExp(\n 'chân\\\\s+(?:của\\\\s+)?(?:đường\\\\s*|tia\\\\s+)?phân\\\\s*giác\\\\s+(?:(trong|ngoài)\\\\s+)?' +\n '(?:(?:hạ|kẻ|vẽ|dựng)\\\\s+)?' +\n VERTEX +\n `(?:\\\\s+${PREP_TO}\\\\s+${LINE})?`,\n 'gu',\n);\n\n// Tên chân đứng TRƯỚC: \"X là \" NGAY TRƯỚC cụm \"chân … phân giác\".\nconst NAME_BEFORE = /([A-Z])(?:['′]?)\\s+là\\s+$/u;\n\n// Prefilter toàn đề.\nconst PREFILTER = /chân\\s+(?:của\\s+)?(?:đường\\s*|tia\\s+)?phân\\s*giác/u;\n\n/** Cạnh đối diện đỉnh V trong tam giác = 2 đỉnh còn lại, join token (vd \"BC\"). */\nfunction opposite(tri: readonly string[], vertex: string): string | undefined {\n const rest = tri.filter((v) => v !== vertex);\n return rest.length === 2 ? rest[0] + rest[1] : undefined;\n}\n\n/**\n * Mỗi clause → 0..n add-point angleBisectorFoot / externalAngleBisectorFoot.\n * onLine ưu tiên cạnh nêu rõ (\"đến BC\"); else suy cạnh đối từ tam giác. Tên chân\n * bind cục bộ. Thiếu tên / không suy được cạnh → bỏ qua (escalate).\n */\nexport const angleBisectorFootRule: LanguageRule = {\n id: 'angleBisectorFoot',\n priority: 63,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const triM = TRI.exec(ctx.problem);\n const tri = triM ? [triM[1], triM[2], triM[3]] : null;\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n CORE.lastIndex = 0;\n for (const m of c.text.matchAll(CORE)) {\n const external = m[1] === 'ngoài';\n const vertex = m[2];\n let onLine: string | undefined = m[3]; // cạnh nêu rõ (optional)\n if (!onLine) {\n if (!tri || !tri.includes(vertex)) continue; // không suy được cạnh đối → escalate\n onLine = opposite(tri, vertex);\n }\n if (!onLine) continue; // không có cạnh (nêu rõ/suy ra) → escalate\n // Tên chân: \"X là\" NGAY TRƯỚC cụm; không có → escalate (đừng bịa).\n const nm = NAME_BEFORE.exec(c.text.slice(0, m.index));\n if (!nm) continue;\n const name = nm[1];\n if (onLine.includes(name)) continue; // chân trùng đầu mút cạnh đáy → degenerate\n const kind = external ? 'externalAngleBisectorFoot' : 'angleBisectorFoot';\n out.push({\n ruleId: 'angleBisectorFoot',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind, from: vertex, onLine })],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/intersection.ts\n//\n// Giao điểm GENERIC của 2 đường thẳng/đoạn cho bởi CẶP ĐỈNH (2 ký tự HOA):\n// \"D là giao điểm của AB và CE\" → tên TRƯỚC (\"X là …\")\n// \"AM cắt CN tại K\" → tên SAU (\"… tại D\")\n// \"AC và BD cắt nhau tại O\" → tên SAU, dạng \"cắt nhau\"\n// → add-point D {kind:'intersection', of:['AB','CE']} (builder ensure 2 segment\n// rồi lấy giao). Mỗi ref = 1 đường qua 2 điểm đã có; thiếu điểm → transpile-fail\n// → escalate (fail-safe).\n//\n// CHỈ nhận ref CẶP ĐỈNH \"AB\" (2 ký tự HOA). KHÔNG nhận:\n// - giao 2 ĐƯỜNG TRÒN \"(O) và (O')\" → kind circleIntersection (rule khác/defer);\n// ref \"(O)\" có ngoặc nên [A-Z]{2} không khớp → tự loại.\n// - line∩circle \"AB cắt (O) tại M\" → secondIntersection (defer); \"(O)\" không\n// phải cặp đỉnh → tự loại.\n// - \"đôi một cắt nhau\" (diameterCirclePairwise) → \"đôi một\" chen giữa cặp đỉnh\n// và \"cắt nhau\" phá khớp dạng C; dạng dùng dấu phẩy (không \"và\") cũng không khớp.\n//\n// Guard degenerate (fail-safe — thà escalate còn hơn dựng điểm vô nghĩa):\n// - 4 đầu mút phải PHÂN BIỆT: chia sẻ đỉnh → 2 đường gặp tại đỉnh chung (không\n// phải điểm mới) → bỏ qua.\n// - tên điểm cần dựng KHÔNG được nằm trong ref (định nghĩa vòng) → bỏ qua.\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt. Regex chứa ký\n// tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, DUONG_KW } from './_shared';\n\n// Ref = cặp đỉnh \"AB\" (đúng 2 ký tự HOA, cho phép khoảng trắng ở giữa \"A B\", neo (?![A-Z]) chặn cụm 3+).\n// Tiền tố \"đường thẳng|đoạn|tia|cạnh\" optional.\nconst REF =\n '(?:' +\n DUONG_KW +\n '\\\\s*thẳng\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+|tia\\\\s+|cạnh\\\\s+)?([A-Z]\\\\s*[A-Z])(?![A-Z])';\nconst CONN = '(?:và|với)';\n\n// A: \"giao điểm (của)? REF1 (và|với) REF2\" — tên đứng TRƯỚC qua \"X là\".\nconst GIAO_DIEM = new RegExp(`giao\\\\s*điểm\\\\s+(?:của\\\\s+)?${REF}\\\\s*${CONN}\\\\s*${REF}`, 'gu');\n// B: \"REF1 cắt REF2 tại D\" — tên SAU.\nconst CAT_TAI = new RegExp(`${REF}\\\\s+cắt\\\\s+${REF}\\\\s+tại\\\\s+([A-Z])(?![A-Z])`, 'gu');\n// C: \"REF1 (và|với) REF2 (cắt|giao) nhau tại D\" — tên SAU. REF2 NGAY trước \"cắt\n// nhau\" → \"đôi một\" (diameterCirclePairwise) chen vào sẽ phá khớp.\nconst CAT_NHAU = new RegExp(\n `${REF}\\\\s*${CONN}\\\\s*${REF}\\\\s+(?:cắt|giao)\\\\s+nhau\\\\s+tại\\\\s+([A-Z])(?![A-Z])`,\n 'gu',\n);\n// D: \"E, F lần lượt là giao điểm của AB và CD, của AD và BC\" → zip 2 tên với 2 cặp.\nconst DISTRIB_TWO = new RegExp(\n `([A-Z])\\\\s*,\\\\s*([A-Z])\\\\s+lần\\\\s*lượt\\\\s+là\\\\s+giao\\\\s*điểm\\\\s+của\\\\s+${REF}\\\\s*${CONN}\\\\s*${REF}\\\\s*,\\\\s*của\\\\s+${REF}\\\\s*${CONN}\\\\s*${REF}`,\n 'gu',\n);\n\n// Tên điểm đứng TRƯỚC (pattern A): \"X là \" NGAY TRƯỚC \"giao điểm\".\nconst NAME_BEFORE = /([A-Z])(?:['′]?)\\s+là\\s+$/u;\n\n// Prefilter toàn đề.\nconst PREFILTER = /giao\\s*điểm|cắt|giao\\s+nhau/u;\n\n/**\n * Build intent intersection nếu hợp lệ: 4 đầu mút phân biệt (không chia sẻ đỉnh)\n * + tên không nằm trong ref. Ngược lại trả null (escalate).\n */\nfunction makeIntent(name: string, ref1: string, ref2: string): IntentT | null {\n ref1 = ref1.replace(/\\s+/g, '');\n ref2 = ref2.replace(/\\s+/g, '');\n const ends = [ref1[0], ref1[1], ref2[0], ref2[1]];\n if (new Set(ends).size !== 4) return null; // chia sẻ đỉnh / ref trùng → degenerate\n if (ends.includes(name)) return null; // ref chứa chính điểm cần dựng → vô nghĩa\n return addPoint(name, { kind: 'intersection', of: [ref1, ref2] });\n}\n\nexport const intersectionRule: LanguageRule = {\n id: 'intersection',\n // THẤP HƠN mọi rule tạo điểm (midpoint=50 thấp nhất, perpFoot/cevian/center…\n // đều ≥50): intentsToDsl xử lý intent THEO THỨ TỰ priority DESC (không topo-sort)\n // → các điểm đầu mút (vd M,N trung điểm trong \"AM cắt CN tại K\") phải được dựng\n // TRƯỚC khi intersection tham chiếu chúng. Đặt 45 (>connect 40) để chạy sau cùng.\n priority: 45,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const seen = new Set<string>(); // tên đã claim trong clause (tránh trùng tên)\n const emit = (name: string, ref1: string, ref2: string) => {\n if (seen.has(name)) return;\n const intent = makeIntent(name, ref1, ref2);\n if (!intent) return;\n seen.add(name);\n out.push({ ruleId: 'intersection', clauseIds: [c.id], intents: [intent] });\n };\n\n DISTRIB_TWO.lastIndex = 0;\n for (const m of c.text.matchAll(DISTRIB_TWO)) {\n emit(m[1], m[3], m[4]);\n emit(m[2], m[5], m[6]);\n }\n\n // A: tên TRƯỚC — \"X là giao điểm của REF1 và REF2\".\n GIAO_DIEM.lastIndex = 0;\n for (const m of c.text.matchAll(GIAO_DIEM)) {\n const nm = NAME_BEFORE.exec(c.text.slice(0, m.index));\n if (nm) emit(nm[1], m[1], m[2]);\n }\n // B: \"REF1 cắt REF2 tại D\".\n CAT_TAI.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_TAI)) emit(m[3], m[1], m[2]);\n // C: \"REF1 và REF2 cắt nhau tại D\".\n CAT_NHAU.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_NHAU)) emit(m[3], m[1], m[2]);\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/chord.ts\n//\n// Dây cung của đường tròn (chord):\n// \"Cho đường tròn (O), dây AB\" → circle O + A,B ∈ (O) + đoạn AB\n// \"đường tròn tâm O. Dây cung MN\" → circle O + M,N ∈ (O) + đoạn MN\n// \"AB là dây của (O)\" → reverse\n// → drawCircle(O, centerRadius default) + onCircle A,B + connect A-B (dây).\n//\n// \"(O)\" KHÔNG có bán kính (circleRadius cố ý BỎ QUA \"(O)\" trơ). Dây cần MỘT đường\n// tròn để minh hoạ → emit circleCR tâm O bán kính CANONICAL (SYMBOLIC_RADIUS), y\n// như cách xử lý \"(O; R)\" ký hiệu. 2 đầu mút dây là glider onCircle (theta phân\n// biệt) → nằm ĐÚNG trên đường tròn; đoạn nối = dây.\n//\n// Nếu đường tròn O đã được rule khác (circleRadius) dựng với bán kính cụ thể →\n// addShape idempotent theo TÊN + circleRadius priority cao hơn ⇒ định nghĩa cụ\n// thể THẮNG, circle ở đây bị bỏ (không chồng). onCircle/connect vẫn dùng O đó.\n//\n// Circle emit TRƯỚC (RuleMatch đầu) để onCircle tham chiếu O đã tồn tại (transpile\n// xử lý theo thứ tự). Claim cả clause khai báo đường tròn để coverage không sót.\n//\n// Thiếu đường tròn / đầu mút dây trùng tâm / cặp trùng → bỏ qua (escalate).\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt. Regex chứa ký\n// tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { Clause } from '../deterministic/coverage';\nimport { addPoint, connect, drawCircle, CIRCLE_KW } from './_shared';\nimport { SYMBOLIC_RADIUS } from './circleRadius';\n\n// Tên đường tròn toàn đề: \"đường tròn (tâm) O\" / \"(O)\".\n// Hỗ trợ cả tên chữ (alpha, omega...).\nconst CIRCLE_WORDS = new RegExp(CIRCLE_KW + '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?![A-Z])', 'u');\nconst CIRCLE_PAREN = /\\(\\s*([^\\\\s;,).:]+)\\s*\\)/u;\n\n// \"dây (cung)? AB\" (forward) / \"AB là (một)? dây (cung)?\" (reverse). Cặp đỉnh 2\n// ký tự HOA liền, neo (?![A-Z]) chặn cụm 3+.\n// [Dd]ây: \"Dây\" HOA đầu câu (sau dấu '.') cũng khớp; nhãn cặp đỉnh vẫn STRICT HOA.\nconst CHORD_FWD = /[Dd]ây\\s+(?:cung\\s+)?([A-Z])([A-Z])(?![A-Z])/gu;\nconst CHORD_REV = /([A-Z])([A-Z])(?![A-Z])\\s+là\\s+(?:một\\s+)?dây(?:\\s+cung)?(?!\\p{L})/gu;\n\n// Glider angle cho 2 đầu mút dây (radian) — phân biệt để A≠B, dây trải phần trên.\nconst THETA_A = 2.3;\nconst THETA_B = 0.7;\n\n// Prefilter toàn đề (\"Dây\" HOA đầu câu cũng khớp).\nconst PREFILTER = /[Dd]ây/u;\n\n/** Clause id chứa khai báo đường tròn (CIRCLE_WORDS hoặc \"(O)\"). */\nfunction findCircleClauseId(clauses: readonly Clause[], circle: string): number | undefined {\n const frag = new RegExp(CIRCLE_KW + `|\\\\(\\\\s*${circle}\\\\s*\\\\)`, 'u');\n for (const c of clauses) if (frag.test(c.text)) return c.id;\n return undefined;\n}\n\n/**\n * Resolve tên đường tròn từ toàn đề; undefined nếu không có.\n */\nfunction resolveCircle(problem: string): string | undefined {\n const w = CIRCLE_WORDS.exec(problem);\n if (w) return w[1];\n const p = CIRCLE_PAREN.exec(problem);\n if (p) return p[1];\n return undefined;\n}\n\nexport const chordRule: LanguageRule = {\n id: 'chord',\n // Dưới circleRadius (75) — nếu circle O có bán kính cụ thể, định nghĩa đó thắng.\n priority: 52,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = resolveCircle(ctx.problem);\n if (!circle) return []; // không có đường tròn → escalate\n\n // Gom các dây hợp lệ.\n interface Chord {\n clauseId: number;\n a: string;\n b: string;\n }\n const chords: Chord[] = [];\n const seen = new Set<string>(); // \"a|b\" (chuẩn hoá thứ tự) tránh trùng\n for (const c of ctx.clauses) {\n const collect = (re: RegExp) => {\n re.lastIndex = 0;\n for (const m of c.text.matchAll(re)) {\n const a = m[1];\n const b = m[2];\n if (a === b) continue; // cặp trùng → degenerate\n if (a === circle || b === circle) continue; // đầu mút trùng tâm → degenerate\n const key = [a, b].sort().join('|');\n if (seen.has(key)) continue;\n seen.add(key);\n chords.push({ clauseId: c.id, a, b });\n }\n };\n collect(CHORD_FWD);\n collect(CHORD_REV);\n }\n if (chords.length === 0) return []; // không trích được dây → escalate\n\n const out: RuleMatch[] = [];\n // 1) Đường tròn (centerRadius default) — TRƯỚC, claim clause khai báo đường\n // tròn để coverage không sót clause \"Cho đường tròn (O)\".\n const circleClauseId = findCircleClauseId(ctx.clauses, circle);\n out.push({\n ruleId: 'chord',\n clauseIds: circleClauseId === undefined ? [] : [circleClauseId],\n intents: [drawCircle(circle, 'centerRadius', { center: circle, radius: SYMBOLIC_RADIUS })],\n });\n // 2) Mỗi dây: A,B glider onCircle (theta phân biệt) + đoạn nối.\n for (const ch of chords) {\n out.push({\n ruleId: 'chord',\n clauseIds: [ch.clauseId],\n intents: [\n addPoint(ch.a, { kind: 'onCircle', circle, theta: THETA_A }),\n addPoint(ch.b, { kind: 'onCircle', circle, theta: THETA_B }),\n connect(ch.a, ch.b, 'segment'),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/incircleTangency.ts\n//\n// Tiếp điểm của đường tròn nội tiếp với các cạnh tam giác:\n// \"Đường tròn (I) nội tiếp tam giác ABC tiếp xúc với các cạnh BC, CA, AB\n// tại các điểm D, E, G\"\n// → D/E/G = tangencyPoint(circle I, onLine BC/CA/AB).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\nimport type { IntentT } from '../intent';\nimport type { Clause } from '../deterministic/coverage';\n\nconst PREFILTER = /tiếp\\s*xúc/u;\n\nconst INCIRCLE_IN_CLAUSE = /đường\\s*tròn\\s*(?:\\(\\s*([A-Z])\\s*\\)|tâm\\s+([A-Z]))?\\s*nội\\s*tiếp\\s+tam\\s*giác\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/iu;\n\nconst SIDE_POINT_LIST = /tiếp\\s*xúc\\s+(?:với\\s+)?(?:các\\s+)?(?:cạnh|đoạn)\\s+([A-Z]{2}(?:\\s*,\\s*[A-Z]{2})*)\\s+(?:lần\\s*lượt\\s+)?tại\\s+(?:các\\s+)?(?:điểm\\s+)?([A-Z](?:\\s*,\\s*[A-Z])*)(?![A-Za-z])/iu;\n\nfunction splitCsv(blob: string): string[] {\n return blob\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\nfunction normalizeSpaces(text: string): string {\n return text.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction logicalChunks(problem: string, clauses: readonly Clause[]): Array<{ text: string; clauseIds: number[] }> {\n return problem\n .split(/[.;]+/u)\n .map((text) => normalizeSpaces(text))\n .filter(Boolean)\n .map((text) => ({\n text,\n clauseIds: clauses\n .filter((c) => text.includes(normalizeSpaces(c.text)))\n .map((c) => c.id),\n }));\n}\n\nfunction parseIncircleName(text: string): string | undefined {\n const m = INCIRCLE_IN_CLAUSE.exec(text);\n if (!m) return undefined;\n return m[1] ?? m[2] ?? 'O';\n}\n\nfunction parseTangencies(text: string, circle: string): IntentT[] {\n const m = SIDE_POINT_LIST.exec(text);\n if (!m) return [];\n\n const sides = splitCsv(m[1]);\n const names = splitCsv(m[2]);\n if (sides.length === 0 || sides.length !== names.length) return [];\n\n return names.map((name, i) => (\n addPoint(name, { kind: 'tangencyPoint', circle, onLine: sides[i] })\n ));\n}\n\nexport const incircleTangencyRule: LanguageRule = {\n id: 'incircleTangency',\n priority: 71,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const chunk of logicalChunks(ctx.problem, ctx.clauses)) {\n const circle = parseIncircleName(chunk.text);\n if (!circle) continue;\n\n const intents = parseTangencies(chunk.text, circle);\n if (intents.length === 0) continue;\n\n out.push({ ruleId: 'incircleTangency', clauseIds: chunk.clauseIds, intents });\n }\n return out;\n },\n};\n","import type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, drawCircle, drawShape, CIRCLE_KW, DUONG_KW } from './_shared';\n\nconst TRI = /tam\\s*giác(?:[^A-Z.;\\n]*)\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\nconst ALTITUDES = /các\\s+đường\\s*cao\\s+([A-Z])([A-Z])\\s*,\\s*([A-Z])([A-Z])(?![A-Z])/u;\nconst DIAMETER_INTERSECTION = new RegExp(\n CIRCLE_KW +\n '\\\\s+' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])\\\\s+và\\\\s+' +\n CIRCLE_KW +\n '\\\\s+' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])[^.;\\n]*?tại\\\\s+các\\\\s+điểm\\\\s+([A-Z])\\\\s*,\\\\s*([A-Z])(?![A-Z])',\n 'u',\n);\nconst SEGMENT_CIRCLE = new RegExp(\n '[Đđ]oạn\\\\s+thẳng\\\\s+([A-Z])([A-Z])\\\\s+cắt\\\\s+' +\n CIRCLE_KW +\n '\\\\s+' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])\\\\s+tại\\\\s+điểm\\\\s+([A-Z])(?![A-Z])',\n 'gu',\n);\nconst LINE_LINE =\n /[Cc]ác\\s+đường\\s+thẳng\\s+([A-Z])([A-Z])\\s+và\\s+([A-Z])([A-Z])\\s+cắt\\s+nhau\\s+tại\\s+([A-Z])(?![A-Z])/u;\n\nfunction opposite(triangle: readonly string[], apex: string): string | undefined {\n const rest = triangle.filter((v) => v !== apex);\n return rest.length === 2 ? rest[0] + rest[1] : undefined;\n}\n\nexport const altitudeDiameterCirclesRule: LanguageRule = {\n id: 'altitude-diameter-circles',\n priority: 67,\n languages: ['vi'],\n patterns: [new RegExp(DUONG_KW + '\\\\s*cao', 'u'), new RegExp(DUONG_KW + '\\\\s*kính', 'u')],\n match(ctx) {\n const tri = TRI.exec(ctx.problem);\n const alts = ALTITUDES.exec(ctx.problem);\n const circles = DIAMETER_INTERSECTION.exec(ctx.problem);\n if (!tri || !alts || !circles) return [];\n\n const triangle = [tri[1], tri[2], tri[3]] as const;\n const altPairs = [\n [alts[1], alts[2]],\n [alts[3], alts[4]],\n ] as const;\n\n const altitudeIntents = [];\n for (const [apex, foot] of altPairs) {\n if (!triangle.includes(apex) || triangle.includes(foot)) return [];\n const opp = opposite(triangle, apex);\n if (!opp) return [];\n altitudeIntents.push(\n addPoint(foot, { kind: 'perpFoot', from: apex, onLine: opp }),\n connect(apex, foot, 'segment'),\n );\n }\n\n const dia1 = circles[1] + circles[2];\n const dia2 = circles[3] + circles[4];\n const known = new Set(altPairs.map(([a, f]) => `${a}${f}`));\n if (!known.has(dia1) || !known.has(dia2) || dia1 === dia2) return [];\n\n const c1 = `k${dia1}`;\n const c2 = `k${dia2}`;\n const x = circles[5];\n const y = circles[6];\n if (x === y) return [];\n\n const segCircles = [...ctx.problem.matchAll(SEGMENT_CIRCLE)];\n const extraPointIntents = [];\n for (const m of segCircles) {\n const line = `${m[1]}${m[2]}`;\n const dia = `${m[3]}${m[4]}`;\n const point = m[5];\n if (line === dia || point === line[0] || point === line[1]) return [];\n const circle = dia === dia1 ? c1 : dia === dia2 ? c2 : undefined;\n if (!circle) return [];\n extraPointIntents.push(\n addPoint(point, { kind: 'intersection', of: [line, circle], branch: 0 }),\n );\n }\n\n const lineLine = LINE_LINE.exec(ctx.problem);\n if (lineLine) {\n extraPointIntents.push(\n addPoint(lineLine[5], {\n kind: 'intersection',\n of: [`${lineLine[1]}${lineLine[2]}`, `${lineLine[3]}${lineLine[4]}`],\n }),\n );\n }\n\n const intents = [\n drawShape('triangle', [...triangle], 'any'),\n ...altitudeIntents,\n drawCircle(c1, 'diameter', { endpoints: [dia1[0], dia1[1]] }),\n drawCircle(c2, 'diameter', { endpoints: [dia2[0], dia2[1]] }),\n addPoint(x, { kind: 'circleIntersection', c1, c2, which: 0 }),\n addPoint(y, { kind: 'circleIntersection', c1, c2, which: 1 }),\n ...extraPointIntents,\n ];\n\n const out: RuleMatch[] = [{\n ruleId: 'altitude-diameter-circles',\n clauseIds: ctx.clauses.map((c) => c.id),\n intents,\n }];\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/diameterCircleCutsSides.ts\n//\n// \"Đường tròn đường kính BC cắt AB, AC tại M và N\" — đường tròn đường kính một\n// cạnh cắt hai cạnh kề tại các điểm phái sinh (phân phối 1-1):\n//\n// Cho tam giác ABC nhọn, đường tròn đường kính BC cắt AB, AC tại M và N.\n//\n// Bản chất: đường tròn đường kính PQ đi qua P, Q. Cạnh AB (chứa B ∈ đường kính)\n// cắt đường tròn tại B và một điểm thứ hai M (= chân đường cao hạ từ C, ∠BMC=90°\n// Thales). Vì luôn biết điểm chung (đỉnh dùng chung giữa cạnh và đường kính), ta\n// dựng M bằng `secondIntersection` (JSXGraph otherintersection loại điểm chung) —\n// robust hơn `intersection`+branch (không phụ thuộc thứ tự index JSXGraph).\n//\n// Phân phối: \"cắt L1, L2 tại X, Y\" → zip L1↔X, L2↔Y (kèm biến thể \"lần lượt\",\n// nối \"và\", tiền tố \"cạnh\"/\"các cạnh\"). Đường tròn KHÔNG tự dựng tam giác (triangle\n// rule lo) — chỉ emit đường tròn + các giao điểm.\n//\n// Fail-safe (escalate, thà thiếu hơn dựng sai):\n// - số cạnh ≠ số điểm → bỏ qua.\n// - cạnh không chia sẻ ĐÚNG 1 đỉnh với đường kính (0 → không biết điểm chung;\n// 2 → cạnh trùng đường kính, suy biến) → bỏ qua.\n// - tên điểm trùng đỉnh cạnh/đường kính (định nghĩa vòng) → bỏ qua.\n//\n// GOTCHA \\b: \\b của JS theo ASCII. Vùng tên điểm (\"M và N\", \"M, N\") các chữ HOA\n// luôn cách bởi dấu cách/phẩy nên \\b[A-Z]\\b an toàn; vẫn dùng cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawCircle, CIRCLE_KW, DUONG_KW } from './_shared';\n\n// Anchor \"đường tròn đường kính PQ cắt <cạnh…> (lần lượt)? tại <điểm…>\".\n// lineRegion lazy tới \"tại\" đầu tiên; pointRegion tới hết clause (không . ; \\n).\nconst PATTERN = new RegExp(\n CIRCLE_KW +\n '\\\\s+' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+cắt\\\\s+([^.;\\\\n]*?)\\\\s+(?:lần\\\\s*lượt\\\\s+)?tại\\\\s+([^.;\\n]*)',\n 'u',\n);\n\nconst PREFILTER = new RegExp(DUONG_KW + '\\\\s*kính', 'u');\n\n/** Đỉnh chung DUY NHẤT giữa cạnh \"AB\" và đường kính \"BC\" (vd \"B\"). */\nfunction sharedVertex(line: string, dia: string): string | undefined {\n const shared = [line[0], line[1]].filter((ch) => dia.includes(ch));\n return shared.length === 1 ? shared[0] : undefined;\n}\n\nexport const diameterCircleCutsSidesRule: LanguageRule = {\n // THẤP HƠN triangle (100): cần A,B,C dựng trước khi secondIntersection tham\n // chiếu cạnh/đỉnh. Đặt 66 (cùng họ diameterCirclePairwise) — đủ thấp so với 100.\n id: 'diameter-circle-cuts-sides',\n priority: 66,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = PATTERN.exec(c.text);\n if (!m) continue;\n\n const d0 = m[1];\n const d1 = m[2];\n const dia = d0 + d1; // \"BC\"\n const lines = m[3].match(/[A-Z][A-Z](?![A-Z])/gu) ?? [];\n const points = m[4].match(/\\b[A-Z]\\b/gu) ?? [];\n\n // Phân phối 1-1: cần ≥1 cạnh và số cạnh == số điểm.\n if (lines.length === 0 || lines.length !== points.length) continue;\n\n const circle = `k${dia}`;\n const intents: IntentT[] = [\n drawCircle(circle, 'diameter', { endpoints: [d0, d1] }),\n ];\n\n let ok = true;\n const seen = new Set<string>();\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const pt = points[i];\n const other = sharedVertex(line, dia);\n // Cần đúng 1 đỉnh chung (điểm đã biết trên cả cạnh lẫn đường tròn).\n if (!other) { ok = false; break; }\n // Tên điểm phải MỚI, không trùng đỉnh cạnh/đường kính.\n if (line.includes(pt) || dia.includes(pt) || seen.has(pt)) { ok = false; break; }\n seen.add(pt);\n intents.push(addPoint(pt, { kind: 'secondIntersection', line, circle, other }));\n }\n if (!ok) continue;\n\n out.push({ ruleId: 'diameter-circle-cuts-sides', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/registry.ts\n//\n// Đăng ký rule + engine chạy theo priority. Thêm construct mới = import module\n// + thêm vào ALL_RULES (không sửa engine).\nimport type { LanguageRule, RuleContext, RuleMatch } from './_types';\nimport { triangleRule } from './triangle';\nimport { quadRule } from './quad';\nimport { connectRule } from './connect';\nimport { midpointRule } from './midpoint';\nimport { perpBisectorRule } from './perpBisector';\nimport { cevianRule } from './cevian';\nimport { angleBisectorAngleRule } from './angleBisectorAngle';\nimport { centersRule } from './centers';\nimport { perpFootRule } from './perpFoot';\nimport { circleRadiusRule } from './circleRadius';\nimport { circleTriangleRule } from './circleTriangle';\nimport { tangentFromExtRule } from './tangentFromExt';\nimport { externalPointRule } from './externalPoint';\nimport { arcMidpointRule } from './arcMidpoint';\nimport { excenterRule } from './excenter';\nimport { parallelPerpRule } from './parallelPerp';\nimport { reflectionRule } from './reflection';\nimport { pointAtDistanceRule } from './pointAtDistance';\nimport { eulerLineRule } from './eulerLine';\nimport { radicalAxisRule } from './radicalAxis';\nimport { simsonRule } from './simson';\nimport { ninePointRule } from './ninePoint';\nimport { diameterCirclePairwiseRule } from './diameterCirclePairwise';\nimport { angleBisectorFootRule } from './angleBisectorFoot';\nimport { intersectionRule } from './intersection';\nimport { chordRule } from './chord';\nimport { incircleTangencyRule } from './incircleTangency';\nimport { altitudeDiameterCirclesRule } from './altitudeDiameterCircles';\nimport { diameterCircleCutsSidesRule } from './diameterCircleCutsSides';\n\nconst RULES: readonly LanguageRule[] = [\n triangleRule,\n quadRule,\n connectRule,\n midpointRule,\n perpBisectorRule,\n cevianRule,\n angleBisectorAngleRule,\n centersRule,\n perpFootRule,\n circleRadiusRule,\n circleTriangleRule,\n tangentFromExtRule,\n externalPointRule,\n arcMidpointRule,\n excenterRule,\n parallelPerpRule,\n reflectionRule,\n pointAtDistanceRule,\n eulerLineRule,\n radicalAxisRule,\n simsonRule,\n ninePointRule,\n diameterCirclePairwiseRule,\n angleBisectorFootRule,\n intersectionRule,\n chordRule,\n incircleTangencyRule,\n altitudeDiameterCirclesRule,\n diameterCircleCutsSidesRule,\n];\n\n/** Sắp xếp priority giảm dần (cao chạy trước) — tính 1 lần ở module load. */\nexport const ALL_RULES: readonly LanguageRule[] = [...RULES].sort(\n (a, b) => b.priority - a.priority,\n);\n\nexport function runRules(ctx: RuleContext): RuleMatch[] {\n const matches: RuleMatch[] = [];\n for (const rule of ALL_RULES) {\n if (!rule.patterns.some((p) => p.test(ctx.problem))) continue;\n matches.push(...rule.match(ctx));\n }\n return matches;\n}\n","// src/stamps/geometry-2d/ai/deterministic/runDeterministicIntents.ts\n//\n// Track A orchestrator: rule engine → IntentT[] + coverage gate.\n// Chỉ lo NLU; gate transpile/verify do router (buildFigureIntent) áp dụng sau.\nimport type { IntentT } from '../intent';\nimport { segmentClauses, computeCoverage, type Clause, type CoverageReport } from './coverage';\nimport { runRules } from '../rules/registry';\n\nexport type DetIntentResult =\n | { ok: true; intents: IntentT[]; coverage: CoverageReport }\n | {\n ok: false;\n reason: 'incomplete-coverage' | 'no-match';\n coverage: CoverageReport;\n };\n\ninterface Collected {\n /** Intent từ MỌI clause có rule claim, deduped theo JSON. */\n intents: IntentT[];\n coverage: CoverageReport;\n matchCount: number;\n}\n\n// Segment → rules → coverage → dedup. Dùng chung cho gate đầy đủ\n// (runDeterministicIntents) lẫn partial (tryPartialDeterministic).\n// Dedupe intent y hệt nhau: nhiều rule cùng tham chiếu 1 hình (vd \"tam giác ABC\"\n// xuất hiện ở nhiều clause → triangle rule emit lặp; centers/cevian cũng cần nó).\nfunction collectDeterministic(problem: string): Collected {\n const clauses = segmentClauses(problem);\n const matches = runRules({ problem, clauses });\n const coverage = computeCoverage(clauses, matches);\n\n const seen = new Set<string>();\n const intents = matches\n .flatMap((m) => m.intents)\n .filter((i) => {\n const key = JSON.stringify(i);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n return { intents, coverage, matchCount: matches.length };\n}\n\nexport function runDeterministicIntents(problem: string): DetIntentResult {\n const { intents, coverage, matchCount } = collectDeterministic(problem);\n\n if (matchCount === 0) return { ok: false, reason: 'no-match', coverage };\n if (!coverage.complete) return { ok: false, reason: 'incomplete-coverage', coverage };\n return { ok: true, intents, coverage };\n}\n\nexport interface PartialDeterministicResult {\n /** Intent deterministic từ các clause đã được rule claim (deduped). */\n detIntents: IntentT[];\n /** Clause geo CHƯA được phủ — phần LLM cần bù (hybrid Phase 2). */\n uncovered: Clause[];\n coverage: CoverageReport;\n /**\n * true khi deterministic phủ MỘT PHẦN: có rule match + ≥1 intent NHƯNG coverage\n * CHƯA đầy đủ. Đây là điều kiện kích hoạt hybrid (Phase 2 gọi LLM bù `uncovered`\n * rồi mergeIntents). false khi: complete (Track A lo đủ) hoặc no-match/0 intent\n * (full LLM Track B).\n */\n hasPartial: boolean;\n}\n\n/**\n * Deterministic-only (KHÔNG LLM): thu intent phần đã phủ + clause còn thiếu, kể\n * cả khi coverage incomplete. Nền cho hybrid partial-coverage — Phase 2 sẽ gọi\n * LLM bù `uncovered` rồi `mergeIntents(detIntents, llmIntents)`.\n */\nexport function tryPartialDeterministic(problem: string): PartialDeterministicResult {\n const { intents, coverage, matchCount } = collectDeterministic(problem);\n return {\n detIntents: intents,\n uncovered: coverage.uncovered,\n coverage,\n hasPartial: matchCount > 0 && !coverage.complete && intents.length > 0,\n };\n}\n","// src/stamps/geometry-2d/ai/deterministic/guards.ts\n//\n// Hai guard fail-safe cho deterministic-first: nếu DSL dựng được KHÔNG trung thành\n// với đề, router escalate AI thay vì render hình sai/thiếu. Bổ sung cho coverage\n// clause-level (vốn coarse, dễ bỏ lọt khi 1 clause chứa nhiều construct).\nimport type { DslInputT } from '../../dsl/schema';\nimport type { IntentT } from '../intent';\n\n// ── Guard 1: named-entity present ────────────────────────────────────────────\n// Mọi đỉnh/điểm được ĐẶT TÊN hay KHAI BÁO trong đề phải tồn tại trong DSL.\n// KHÔNG dùng \\b (ASCII) quanh ký tự Việt.\n\n// Tên điểm dẫn nhập 1 ký tự HOA: \"Gọi M\", \"lấy điểm D\", \"cắt … tại D\", \"N là …\",\n// \"H, K lần lượt\", \"và P là\".\n// Issue #46 nhóm A: prime (' U+0027 / ′ U+2032) là PHẦN của tên (\"D′\" ≠ \"D\").\n// Group prime đứng ngay sau chữ cái — collect bằng letter + normalize(prime) để\n// expected-name khớp DSL (rule pointAtDistance giữ prime → DSL có \"D'\").\nconst NAMED_INTRO = /(?:Gọi|gọi|Lấy|lấy|Dựng|dựng|Đặt|đặt|tại|điểm|và)\\s+(?:điểm\\s+)?([A-Z])(['′]?)(?![A-Za-z])/gu;\n// LƯU Ý: KHÔNG dùng `là\\b` — `\\b` của JS theo ASCII, mà 'à' (U+00E0) là\n// non-word-char ASCII → `\\b` sau 'là' KHÔNG khớp khi theo sau là space/dấu câu\n// → pattern chết, bỏ sót mọi \"X là <construct>\" (bug silent-incomplete). Dùng\n// lookahead non-letter Unicode (?!\\p{L}) để neo cuối \"là\".\nconst NAMED_LA = /([A-Z])(['′]?)(?![A-Za-z])\\s+là(?!\\p{L})/gu;\nconst NAMED_LANLUOT = /([A-Z])(['′]?)(?![A-Za-z])\\s*,\\s*([A-Z])(['′]?)(?![A-Za-z])\\s+lần lượt/gu;\n\n// Ghép chữ cái + prime đã normalize (′→') thành tên đầy đủ. Đồng bộ với\n// rules/pointAtDistance.ts normalizePointName — giữ naming layer nhất quán.\nfunction joinPrime(letter: string | undefined, prime: string | undefined): string | undefined {\n if (!letter) return undefined;\n return prime ? `${letter}'` : letter;\n}\n\n// Đỉnh của hình khai báo: \"tam giác ABC\", \"tứ giác ABCD\", \"hình vuông/… ABCD\".\n// Bắt cụm 3-4 ký tự HOA LIỀN ngay sau tên hình (mỗi đỉnh phải có trong DSL).\nconst SHAPE_TRI = /tam giác\\s+([A-Z]{3})(?![A-Z])/gu;\nconst SHAPE_QUAD = /(?:tứ giác|hình\\s+(?:vuông|chữ nhật|bình hành|thoi|thang))\\s+([A-Z]{4})(?![A-Z])/gu;\n\nexport interface NamedEntityReport {\n ok: boolean;\n missing: string[];\n}\n\nfunction collectExpectedNames(problem: string): Set<string> {\n const names = new Set<string>();\n // Mỗi entry [letterGroup, primeGroup]: tên = letter + normalize(prime).\n const add = (re: RegExp, groups: [number, number][]) => {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(problem)) !== null) {\n for (const [lg, pg] of groups) {\n const name = joinPrime(m[lg], m[pg]);\n if (name) names.add(name);\n }\n }\n };\n add(NAMED_INTRO, [[1, 2]]);\n add(NAMED_LA, [[1, 2]]);\n add(NAMED_LANLUOT, [[1, 2], [3, 4]]);\n // Đỉnh hình: tách cụm 3/4 ký tự thành từng đỉnh.\n for (const re of [SHAPE_TRI, SHAPE_QUAD]) {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(problem)) !== null) {\n for (const ch of m[1]) names.add(ch);\n }\n }\n return names;\n}\n\nexport function allNamedEntitiesPresent(problem: string, dsl: DslInputT): NamedEntityReport {\n const present = new Set<string>();\n for (const p of dsl.points) present.add(p.name);\n for (const s of dsl.shapes) present.add(s.name);\n\n const missing: string[] = [];\n for (const name of collectExpectedNames(problem)) {\n if (!present.has(name)) missing.push(name);\n }\n return { ok: missing.length === 0, missing };\n}\n\n// ── Guard 2: intent → DSL fidelity ───────────────────────────────────────────\n// Mỗi add-point intent dựng điểm phái sinh (không phải 'free') PHẢI hiện diện\n// trong DSL đúng dạng. Builder idempotent DROP add-point khi tên trùng đỉnh sẵn\n// có (vd \"đường cao AB\" → foot B trùng vertex B) → điểm để 'free' → guard bắt.\n\nexport interface FidelityReport {\n ok: boolean;\n dropped: string[];\n}\n\nexport function verifyIntentFidelity(intents: readonly IntentT[], dsl: DslInputT): FidelityReport {\n const byName = new Map<string, { kind: string }>();\n for (const p of dsl.points) byName.set(p.name, p as unknown as { kind: string });\n\n const dropped: string[] = [];\n for (const intent of intents) {\n if (intent.op !== 'add-point') continue;\n const kind = (intent as { constraint?: { kind?: string } }).constraint?.kind;\n // free point không phải construct phái sinh → skip fidelity.\n // externalToCircle CỐ TÌNH dựng FREE point ngoài circle (như fixture canonical\n // tangent-from-external-named.ts): builder đặt A kind 'free' tại coord ngoài\n // circle, KHÔNG phải điểm phái sinh đặc thù bị drop. Nếu builder fail-safe skip\n // (circle thiếu / tâm không free) → A missing → guard allNamedEntitiesPresent\n // bắt (named-missing). Vì vậy bỏ externalToCircle khỏi fidelity check.\n if (!kind || kind === 'free' || kind === 'externalToCircle') continue;\n const name = (intent as { name: string }).name;\n const pt = byName.get(name);\n // Thiếu hẳn, hoặc bị builder hạ về 'free' (đã bị drop bởi vertex trùng tên).\n if (!pt || pt.kind === 'free') dropped.push(name);\n }\n return { ok: dropped.length === 0, dropped };\n}\n","// src/stamps/geometry-2d/ai/normalizeIntent.ts\n//\n// Post-LLM variant normalizer cho Intent pipeline.\n//\n// Mục đích: fix 2 nhóm bias quan sát được trong eval gemma3:12b:\n// 1. LLM emit isoceles variant SAI position (vd \"cân tại A\" → 'isoceles-AB'\n// thay vì 'isoceles-BC') vì naming rule canonical không trực giác.\n// 2. LLM follow prompt \"rectangle: wide | tall\" → emit 'wide' trong khi\n// eval + đa số sản phẩm muốn 'standard' (rendering identical với 'wide').\n//\n// Pure function, không mutate input.\n\nimport type { IntentT, DrawShapeIntentT, DrawLineIntentT } from './intent';\n\nconst CAN_TAI_RE = /c[aâ]n\\s+t[aạ]i\\s+([A-Z])/i;\nconst ISOCELES_AT_RE = /isoceles\\s+(?:at|with\\s+apex)\\s+([A-Z])/i;\nconst TALL_RECT_RE = /(cao|hẹp|thin|tall|portrait)/i;\n\n/**\n * Apply variant normalization. Returns new array; input unmodified.\n *\n * Rules áp dụng (chỉ override khi MATCH chắc; otherwise pass-through):\n * - triangle + \"cân tại X\" → variant theo position của X trong labels\n * - rectangle: default 'standard' (giữ 'tall' khi đề có \"cao\"/\"hẹp\")\n * - square|rhombus|parallelogram: ép 'standard' (chỉ 1 variant hợp lệ)\n */\nexport function normalizeIntents(\n intents: readonly IntentT[],\n problem: string,\n): IntentT[] {\n // Đếm tam giác: chỉ normalize \"cân tại X\" khi đề có ĐÚNG 1 tam giác — đa tam\n // giác thì không thể bind \"cân tại X\" toàn-problem cho đúng tam giác, mà rule\n // deterministic (window) / LLM đã set variant per-intent → tin theo đó.\n const triangleCount = intents.filter(\n (i) => i.op === 'draw-shape' && i.shape === 'triangle',\n ).length;\n return intents.map((intent) => {\n if (intent.op === 'draw-shape') return normalizeShape(intent, problem, triangleCount);\n if (intent.op === 'draw-line') return normalizeLine(intent);\n return intent;\n });\n}\n\n// Builder enforce strict field per kind. LLM nhầm field giữa các kind cùng\n// schema (through/from/to/circle/which đều optional). Fix: swap field khi\n// pattern rõ ràng (no ambiguity).\n//\n// Rules:\n// - tangentAt cần `through` (điểm trên đường tròn). Nếu LLM dùng `from` → swap.\n// - tangentFromExt cần `from` (điểm ngoài). Nếu LLM dùng `through` → swap.\n// - perpThrough / parallelThrough cần `through` (điểm) + `to` (line).\n// Nếu LLM dùng `from` thay `through` → swap.\nfunction normalizeLine(intent: DrawLineIntentT): DrawLineIntentT {\n if (intent.kind === 'tangentAt' && intent.from && !intent.through) {\n const { from, ...rest } = intent;\n return { ...rest, through: from };\n }\n if (intent.kind === 'tangentFromExt' && intent.through && !intent.from) {\n const { through, ...rest } = intent;\n return { ...rest, from: through };\n }\n if (\n (intent.kind === 'perpThrough' || intent.kind === 'parallelThrough') &&\n intent.from &&\n !intent.through\n ) {\n const { from, ...rest } = intent;\n return { ...rest, through: from };\n }\n return intent;\n}\n\nfunction normalizeShape(\n intent: DrawShapeIntentT,\n problem: string,\n triangleCount: number,\n): IntentT {\n switch (intent.shape) {\n case 'triangle':\n return normalizeTriangle(intent, problem, triangleCount);\n case 'rectangle':\n return normalizeRectangle(intent, problem);\n case 'square':\n case 'rhombus':\n case 'parallelogram':\n return forceStandard(intent);\n default:\n return intent;\n }\n}\n\nfunction normalizeRectangle(\n intent: DrawShapeIntentT,\n problem: string,\n): DrawShapeIntentT {\n if (intent.variant === 'tall' && TALL_RECT_RE.test(problem)) return intent;\n if (intent.variant === 'standard') return intent;\n return { ...intent, variant: 'standard' };\n}\n\nfunction forceStandard(intent: DrawShapeIntentT): DrawShapeIntentT {\n if (intent.variant === 'standard') return intent;\n return { ...intent, variant: 'standard' };\n}\n\nfunction normalizeTriangle(\n intent: DrawShapeIntentT,\n problem: string,\n triangleCount: number,\n): DrawShapeIntentT {\n // Đa tam giác: không clobber — variant đã được set đúng per-intent ở nguồn.\n if (triangleCount !== 1) return intent;\n const m = problem.match(CAN_TAI_RE) ?? problem.match(ISOCELES_AT_RE);\n if (!m) return intent;\n const apex = m[1].toUpperCase();\n const i = intent.labels.indexOf(apex);\n if (i < 0) return intent;\n // Variant POSITIONAL theo INDEX apex (builder: isoceles-BC ⇒ apex=vertex[0]).\n // KHÔNG dùng chữ-cái-nhãn để đúng cho nhãn ≠ ABC.\n const variantByPos: Record<number, DrawShapeIntentT['variant']> = {\n 0: 'isoceles-BC',\n 1: 'isoceles-CA',\n 2: 'isoceles-AB',\n };\n const target = variantByPos[i];\n if (!target || intent.variant === target) return intent;\n return { ...intent, variant: target };\n}\n","// src/stamps/geometry-2d/ai/resolveCircleNames.ts\n//\n// Preprocessor giải quyết naming collision giữa circle name và point ref.\n// DSL schema enforce global-unique name (point + shape share namespace), nên\n// circle X + point X không cùng tồn tại được. Notation Việt \"(O)\" thường ám\n// chỉ TÂM (point) của đường tròn, nhưng Claude/LLM hay đặt circle name là \"O\"\n// → connect M→O segment fail KIND_MISMATCH.\n//\n// Pure function — không gọi AI, idempotent:\n// 1. Detect circle names được reference như point trong intent khác\n// 2. Inject add-point center (circumcenter/incenter dựa trên spec) BEFORE circle\n// 3. Rename circle \"X\" → \"X_c\"\n// 4. Rewrite các CIRCLE-context ref tới circle name → \"X_c\"\n\nimport type { IntentT } from './intent';\n\nexport function resolveCircleNameCollisions(intents: readonly IntentT[]): IntentT[] {\n const circleNames = new Set<string>();\n for (const i of intents) {\n if (i.op === 'draw-circle') circleNames.add(i.name);\n }\n if (circleNames.size === 0) return [...intents];\n\n const pointRefs = collectPointRefs(intents);\n\n const existingPoints = new Set<string>();\n for (const i of intents) {\n if (i.op === 'draw-shape') {\n for (const l of i.labels) existingPoints.add(l);\n } else if (i.op === 'add-point') {\n existingPoints.add(i.name);\n }\n }\n\n const collisions = new Set<string>();\n for (const name of circleNames) {\n if (pointRefs.has(name)) collisions.add(name);\n }\n if (collisions.size === 0) return [...intents];\n\n const rename = new Map<string, string>();\n for (const name of collisions) {\n rename.set(name, `${name}_c`);\n }\n\n const result: IntentT[] = [];\n for (const i of intents) {\n if (i.op === 'draw-circle' && collisions.has(i.name)) {\n if (!existingPoints.has(i.name)) {\n const centerIntent = makeCenterIntent(i);\n if (centerIntent) {\n result.push(centerIntent);\n existingPoints.add(i.name);\n }\n }\n result.push({ ...i, name: rename.get(i.name)! });\n } else {\n result.push(rewriteCircleRefs(i, rename));\n }\n }\n\n return result;\n}\n\nfunction makeCenterIntent(circle: Extract<IntentT, { op: 'draw-circle' }>): IntentT | null {\n if (circle.spec === 'through3' && circle.points) {\n return {\n op: 'add-point',\n name: circle.name,\n constraint: { kind: 'circumcenter', of: circle.points },\n };\n }\n if (circle.spec === 'inscribedIn' && circle.triangle) {\n return {\n op: 'add-point',\n name: circle.name,\n constraint: { kind: 'incenter', of: circle.triangle },\n };\n }\n // centerThrough/centerRadius: AI nhiều khi đặt `center === name` (vd `(O)` =\n // circle \"O\" có center \"O\") — cần inject `add-point name=center kind=free`\n // để point tồn tại sau khi circle được rename. Trường hợp center khác name\n // thì caller phải đảm bảo point center đã tồn tại (preprocessor không derive).\n if (\n (circle.spec === 'centerThrough' || circle.spec === 'centerRadius') &&\n circle.center === circle.name\n ) {\n return {\n op: 'add-point',\n name: circle.name,\n constraint: { kind: 'free' },\n };\n }\n return null;\n}\n\nfunction collectPointRefs(intents: readonly IntentT[]): Set<string> {\n const refs = new Set<string>();\n // 2-letter line/edge ref (vd \"BC\", \"AO\") → tách thành single-letter chars.\n // Cần thiết để detect collision khi line ref CHỨA tên circle (vd `line:\"AO\"`\n // + circle name \"O\" → O dùng như point ở \"AO\", phải inject center O).\n const addEdgeRef = (ref: string) => {\n if (/^[A-Za-z]{2}$/.test(ref)) {\n refs.add(ref[0]);\n refs.add(ref[1]);\n }\n };\n for (const i of intents) {\n if (i.op === 'connect') {\n refs.add(i.from);\n refs.add(i.to);\n } else if (i.op === 'add-point') {\n const c = i.constraint;\n if (c.kind === 'centroid' || c.kind === 'circumcenter' || c.kind === 'incenter' || c.kind === 'orthocenter') {\n for (const v of c.of) refs.add(v);\n } else if (c.kind === 'perpFoot' || c.kind === 'angleBisectorFoot') {\n refs.add(c.from);\n addEdgeRef(c.onLine);\n } else if (c.kind === 'tangentPoint') {\n refs.add(c.from);\n } else if (c.kind === 'secondIntersection') {\n refs.add(c.other);\n addEdgeRef(c.line);\n } else if (c.kind === 'tangencyPoint') {\n addEdgeRef(c.onLine);\n } else if (c.kind === 'midpoint' || c.kind === 'onSegment') {\n addEdgeRef(c.of);\n } else if (c.kind === 'intersection') {\n for (const r of c.of) addEdgeRef(r);\n }\n } else if (i.op === 'draw-circle') {\n if (i.center) refs.add(i.center);\n if (i.through) refs.add(i.through);\n if (i.points) for (const p of i.points) refs.add(p);\n if (i.triangle) for (const p of i.triangle) refs.add(p);\n } else if (i.op === 'draw-line') {\n if (i.through) refs.add(i.through);\n if (i.from) refs.add(i.from);\n if (i.to) addEdgeRef(i.to);\n // i.circle là circle ref — skip.\n } else if (i.op === 'mark-shape') {\n for (const l of i.labels) refs.add(l);\n }\n }\n return refs;\n}\n\nfunction rewriteCircleRefs(intent: IntentT, rename: Map<string, string>): IntentT {\n if (intent.op === 'add-point') {\n const c = intent.constraint;\n if (\n c.kind === 'tangencyPoint' ||\n c.kind === 'tangentPoint' ||\n c.kind === 'secondIntersection' ||\n c.kind === 'externalToCircle' ||\n c.kind === 'onCircle'\n ) {\n const newCircle = rename.get(c.circle);\n if (newCircle) {\n return { ...intent, constraint: { ...c, circle: newCircle } };\n }\n } else if (c.kind === 'circleIntersection') {\n const newC1 = rename.get(c.c1) ?? c.c1;\n const newC2 = rename.get(c.c2) ?? c.c2;\n if (newC1 !== c.c1 || newC2 !== c.c2) {\n return { ...intent, constraint: { ...c, c1: newC1, c2: newC2 } };\n }\n }\n } else if (intent.op === 'draw-line') {\n if (intent.circle && rename.has(intent.circle)) {\n return { ...intent, circle: rename.get(intent.circle)! };\n }\n if (intent.kind === 'radicalAxis') {\n const n1 = intent.circle1 ? rename.get(intent.circle1) : undefined;\n const n2 = intent.circle2 ? rename.get(intent.circle2) : undefined;\n if (n1 || n2) {\n return { ...intent, circle1: n1 ?? intent.circle1, circle2: n2 ?? intent.circle2 };\n }\n }\n }\n return intent;\n}\n","import type { DslPointT, DslShapeT } from '../dsl/schema';\n\n// Reposition auto-injected circle centers so two circles referenced by a\n// `circleIntersection` point actually cross at TWO points.\n//\n// Bối cảnh: builder inject free coord cho circle center theo bảng spread cách\n// nhau ~6 unit. Hai circle centerRadius cùng r=3 → distance = 6 = r1+r2 →\n// tiếp xúc ngoài (1 điểm) → JSXGraph intersection branch 0/1 trùng nhau hoặc\n// NaN → cascade hỏng (bug eval cau-08). Disjoint (d > r1+r2) còn tệ hơn.\n//\n// Điều kiện 2 giao điểm: |r1-r2| < d < r1+r2.\n// Khi d nằm ngoài \"vùng an toàn\" (sát biên tiếp xúc / disjoint), dời 1 center\n// FREE dọc theo hướng hiện tại về khoảng cách mục tiêu = trung điểm của khoảng\n// hợp lệ = (|r1-r2| + r1+r2)/2 = max(r1, r2). Giữ nguyên hướng để bố cục tương\n// đối không đảo lộn.\n\ntype FreePoint = Extract<DslPointT, { kind: 'free' }>;\n\n/** Resolve toạ độ tĩnh cho center (free hoặc midpoint của free/midpoint). */\nfunction resolveCoord(points: DslPointT[], name: string): [number, number] | null {\n const p = points.find((x) => x.name === name);\n if (!p) return null;\n if (p.kind === 'free') return [p.x, p.y];\n if (p.kind === 'midpoint') {\n const a = resolveCoord(points, p.p1);\n const b = resolveCoord(points, p.p2);\n if (!a || !b) return null;\n return [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];\n }\n return null;\n}\n\nexport function repairCircleIntersections(points: DslPointT[], shapes: DslShapeT[]): void {\n const shapeByName = new Map(shapes.map((s) => [s.name, s]));\n\n for (const pt of points) {\n if (pt.kind !== 'circleIntersection') continue;\n const c1 = shapeByName.get(pt.c1);\n const c2 = shapeByName.get(pt.c2);\n if (!c1 || !c2 || c1.kind !== 'circleCR' || c2.kind !== 'circleCR') continue;\n\n const r1 = c1.radius;\n const r2 = c2.radius;\n const lower = Math.abs(r1 - r2);\n const upper = r1 + r2;\n\n const coord1 = resolveCoord(points, c1.center);\n const coord2 = resolveCoord(points, c2.center);\n if (!coord1 || !coord2) continue;\n\n const d = Math.hypot(coord1[0] - coord2[0], coord1[1] - coord2[1]);\n const safeLow = lower * 1.05 + 1e-6;\n const safeHigh = upper * 0.95;\n if (d > safeLow && d < safeHigh) continue; // đã cắt 2 điểm gọn gàng\n\n // Cần 1 center FREE để dời. Ưu tiên center của c2 (thường inject sau), fallback c1.\n const p1 = points.find((p) => p.name === c1.center);\n const p2 = points.find((p) => p.name === c2.center);\n let mover: FreePoint | undefined;\n let anchor: [number, number] | undefined;\n if (p2?.kind === 'free') { mover = p2; anchor = coord1; }\n else if (p1?.kind === 'free') { mover = p1; anchor = coord2; }\n if (!mover || !anchor) continue; // không có center free để dời an toàn\n\n const targetD = (lower + upper) / 2; // = max(r1, r2)\n let dx = mover.x - anchor[0];\n let dy = mover.y - anchor[1];\n const len = Math.hypot(dx, dy);\n if (len < 1e-9) { dx = 1; dy = 0; }\n const norm = Math.hypot(dx, dy) || 1;\n mover.x = anchor[0] + (targetD * dx) / norm;\n mover.y = anchor[1] + (targetD * dy) / norm;\n }\n}\n","// src/stamps/geometry-2d/dsl/transpile/errors.ts\nimport type { State } from '../../../../core/scene/types';\n\nexport type TranspileErrorCode =\n | 'SCHEMA'\n | 'DUPLICATE_NAME'\n | 'UNKNOWN_REF'\n | 'KIND_MISMATCH'\n | 'CYCLE';\n\nexport interface TranspileError {\n code: TranspileErrorCode;\n message: string;\n path?: string[];\n hint?: string;\n}\n\nexport type TranspileResult =\n | { ok: true; state: State }\n | { ok: false; errors: TranspileError[] };\n\nexport function mkError(\n code: TranspileErrorCode,\n message: string,\n opts?: { path?: string[]; hint?: string },\n): TranspileError {\n return { code, message, path: opts?.path, hint: opts?.hint };\n}\n","// src/stamps/geometry-2d/dsl/transpile/refs.ts\nimport type { DslInputT, DslPointT, DslShapeT } from '../schema';\nimport { KIND_REGISTRY, LINE_LIKE_SHAPE_KINDS, CIRCLE_KINDS } from '../registry';\nimport type { RefRole, RefSpec } from '../kinds/_types';\nimport type { Symbol } from './symbols';\nimport { mkError, type TranspileError } from './errors';\n\nfunction isPointLike(sym: Symbol | undefined): boolean {\n return !!sym && sym.role === 'point';\n}\n\nfunction isLineLike(sym: Symbol | undefined): boolean {\n if (!sym || sym.role !== 'shape') return false;\n return LINE_LIKE_SHAPE_KINDS.has((sym.entity as DslShapeT).kind);\n}\n\nfunction isCircleLike(sym: Symbol | undefined): boolean {\n if (!sym || sym.role !== 'shape') return false;\n return CIRCLE_KINDS.has((sym.entity as DslShapeT).kind);\n}\n\nfunction isSegmentExact(sym: Symbol | undefined): boolean {\n return !!sym && sym.role === 'shape' && (sym.entity as DslShapeT).kind === 'segment';\n}\n\nconst ROLE_PREDICATE: Record<RefRole, (s: Symbol | undefined) => boolean> = {\n point: isPointLike,\n 'line-like': isLineLike,\n circle: isCircleLike,\n segment: isSegmentExact,\n shape: (s) => !!s && s.role === 'shape',\n 'any-existing': (s) => !!s,\n};\nconst ROLE_EXPECTED: Record<RefRole, string> = {\n point: 'point',\n 'line-like': 'line-like',\n circle: 'circle',\n segment: 'segment',\n shape: 'shape',\n 'any-existing': 'tồn tại',\n};\n\nexport interface RefsResult {\n errors: TranspileError[];\n}\n\nexport function validateRefs(dsl: DslInputT, symbols: Map<string, Symbol>): RefsResult {\n const errors: TranspileError[] = [];\n\n const check = (\n owner: string,\n field: string,\n refName: string,\n predicate: (s: Symbol | undefined) => boolean,\n expected: string,\n ) => {\n const sym = symbols.get(refName);\n if (!sym) {\n errors.push(mkError('UNKNOWN_REF',\n `${owner}.${field} tham chiếu \"${refName}\" không tồn tại`,\n { path: [owner, field] }));\n return;\n }\n if (!predicate(sym)) {\n errors.push(mkError('KIND_MISMATCH',\n `${owner}.${field}=\"${refName}\" sai kiểu (cần ${expected}, gặp ${sym.role === 'point' ? 'point' : (sym.entity as DslShapeT).kind})`,\n { path: [owner, field] }));\n }\n };\n\n // Registry-driven pass: kind nào khai refSpecs thì validate ở đây, switch bỏ qua.\n const handledByRegistry = new Set<string>();\n const runSpecs = (owner: string, entity: DslPointT | DslShapeT): boolean => {\n const mod = KIND_REGISTRY.get(entity.kind);\n const raw = mod?.refSpecs;\n if (!raw) return false;\n const specs: readonly RefSpec[] =\n typeof raw === 'function' ? raw(entity as never) : raw;\n for (const spec of specs) {\n const val = (entity as Record<string, unknown>)[spec.field];\n const names: string[] = spec.many\n ? ((val as string[]) ?? [])\n : val == null\n ? []\n : [val as string];\n names.forEach((refName, i) => {\n const field = spec.many ? `${spec.field}[${i}]` : spec.field;\n check(owner, field, refName, ROLE_PREDICATE[spec.role], ROLE_EXPECTED[spec.role]);\n });\n }\n handledByRegistry.add(owner);\n return true;\n };\n for (const p of dsl.points) runSpecs(p.name, p);\n for (const s of dsl.shapes) runSpecs(s.name, s);\n\n for (const p of dsl.points) {\n if (handledByRegistry.has(p.name)) continue;\n switch (p.kind) {\n case 'free': break;\n case 'midpoint':\n check(p.name, 'p1', p.p1, isPointLike, 'point');\n check(p.name, 'p2', p.p2, isPointLike, 'point');\n break;\n case 'onSegment':\n check(p.name, 'segmentId', p.segmentId, isSegmentExact, 'segment');\n break;\n case 'onLine':\n check(p.name, 'lineId', p.lineId, isLineLike, 'line-like');\n break;\n case 'onCircle':\n check(p.name, 'circleId', p.circleId, isCircleLike, 'circle');\n break;\n case 'perpFoot':\n check(p.name, 'from', p.from, isPointLike, 'point');\n check(p.name, 'onLine', p.onLine, isLineLike, 'line-like');\n break;\n case 'circumcenter':\n case 'incenter':\n case 'centroid':\n case 'orthocenter':\n for (let i = 0; i < 3; i++) {\n check(p.name, `vertices[${i}]`, p.vertices[i], isPointLike, 'point');\n }\n break;\n case 'intersection': {\n const refPredicate = (s: Symbol | undefined) => isLineLike(s) || isCircleLike(s);\n check(p.name, 'ref1', p.ref1, refPredicate, 'line-like hoặc circle');\n check(p.name, 'ref2', p.ref2, refPredicate, 'line-like hoặc circle');\n break;\n }\n case 'arcMidpoint':\n check(p.name, 'circle', p.circle, isCircleLike, 'circle');\n check(p.name, 'a', p.a, isPointLike, 'point');\n check(p.name, 'b', p.b, isPointLike, 'point');\n check(p.name, 'notContaining', p.notContaining, isPointLike, 'point');\n break;\n case 'excenter':\n for (let i = 0; i < 3; i++) {\n check(p.name, `vertices[${i}]`, p.vertices[i], isPointLike, 'point');\n }\n check(p.name, 'opposite', p.opposite, isPointLike, 'point');\n break;\n case 'reflectPoint':\n check(p.name, 'of', p.of, isPointLike, 'point');\n check(p.name, 'through', p.through, isPointLike, 'point');\n break;\n case 'reflectLine':\n check(p.name, 'of', p.of, isPointLike, 'point');\n check(p.name, 'through', p.through, isLineLike, 'line-like');\n break;\n }\n }\n\n for (const s of dsl.shapes) {\n if (handledByRegistry.has(s.name)) continue;\n switch (s.kind) {\n case 'segment':\n case 'line':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n break;\n case 'ray':\n check(s.name, 'origin', s.origin, isPointLike, 'point');\n check(s.name, 'through', s.through, isPointLike, 'point');\n break;\n case 'polygon':\n s.vertices.forEach((v, i) =>\n check(s.name, `vertices[${i}]`, v, isPointLike, 'point'));\n break;\n case 'perpendicular':\n case 'parallel':\n check(s.name, 'throughPoint', s.throughPoint, isPointLike, 'point');\n check(s.name, 'toLine', s.toLine, isLineLike, 'line-like');\n break;\n case 'perpBisector':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n break;\n case 'angleBisector':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'vertex', s.vertex, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n break;\n case 'tangent':\n check(s.name, 'throughPoint', s.throughPoint, isPointLike, 'point');\n check(s.name, 'toCircle', s.toCircle, isCircleLike, 'circle');\n break;\n case 'circleCP':\n check(s.name, 'center', s.center, isPointLike, 'point');\n check(s.name, 'surfacePoint', s.surfacePoint, isPointLike, 'point');\n break;\n case 'circle3':\n check(s.name, 'p1', s.p1, isPointLike, 'point');\n check(s.name, 'p2', s.p2, isPointLike, 'point');\n check(s.name, 'p3', s.p3, isPointLike, 'point');\n break;\n }\n }\n\n return { errors };\n}\n\n// Helper export cho cycles.ts: collect refs cho mỗi entity (name) trả về list ref names.\nexport function collectRefs(entity: DslPointT | DslShapeT): string[] {\n const mod = KIND_REGISTRY.get(entity.kind);\n if (!mod) throw new Error(`collectRefs: no registry entry for kind \"${entity.kind}\"`);\n return mod.collectRefs(entity as never);\n}\n","// src/stamps/geometry-2d/ai/layout/disjointOffset.ts\n//\n// Layout pass (issue #46 nhóm D, D1, Mức 1): tách các component RỜI NHAU (không\n// chia điểm/ref) theo trục ngang để không render chồng tại canonical origin.\n//\n// Pure, mutate in place (giống repairCircleIntersections). Chỉ dịch free point\n// (kind:'free' — điểm DUY NHẤT có x/y); điểm phái sinh KHÔNG có coord → transpile\n// tính lại từ ref đã dịch → tự đúng. Bất biến: ≤1 component → no-op (đề 1-figure\n// byte-identical).\n\nimport type { DslPointT, DslShapeT } from '../../dsl/schema';\nimport { collectRefs } from '../../dsl/transpile/refs';\n\nconst GAP = 2; // board-unit giữa 2 component liền kề\n\ntype FreePoint = Extract<DslPointT, { kind: 'free' }>;\ninterface Bbox { minX: number; maxX: number; minY: number; maxY: number; }\n\nexport function layoutDisjointComponents(points: DslPointT[], shapes: DslShapeT[]): void {\n // --- union-find trên mọi entity name (point + shape) ---\n const parent = new Map<string, string>();\n const find = (x: string): string => {\n const r = parent.get(x);\n if (r === undefined) { parent.set(x, x); return x; }\n if (r === x) return x;\n const root = find(r);\n parent.set(x, root);\n return root;\n };\n const union = (a: string, b: string) => {\n const ra = find(a), rb = find(b);\n if (ra !== rb) parent.set(ra, rb);\n };\n\n const entities: (DslPointT | DslShapeT)[] = [...points, ...shapes];\n for (const e of entities) {\n find(e.name); // đảm bảo node tồn tại\n for (const ref of collectRefs(e)) union(e.name, ref);\n }\n\n // --- free point + thứ tự xuất hiện trong mảng points ---\n const freeByName = new Map<string, { p: FreePoint; index: number }>();\n points.forEach((p, i) => {\n if (p.kind === 'free') freeByName.set(p.name, { p, index: i });\n });\n if (freeByName.size === 0) return;\n\n // --- gom free point theo component root + min free-index ---\n const compFree = new Map<string, { p: FreePoint; index: number }[]>();\n const compMinIndex = new Map<string, number>();\n for (const [name, rec] of freeByName) {\n const root = find(name);\n if (!compFree.has(root)) { compFree.set(root, []); compMinIndex.set(root, rec.index); }\n compFree.get(root)!.push(rec);\n compMinIndex.set(root, Math.min(compMinIndex.get(root)!, rec.index));\n }\n\n // --- bất biến: ≤1 component có free point → no-op ---\n if (compFree.size <= 1) return;\n\n // --- thứ tự component theo min free-index (= thứ tự đọc đề) ---\n const roots = [...compFree.keys()].sort(\n (a, b) => compMinIndex.get(a)! - compMinIndex.get(b)!,\n );\n\n // --- bbox per-component: free-point coords + mở rộng bán kính khi tâm là free ---\n const bboxOf = (root: string): Bbox => {\n let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;\n const ext = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n };\n for (const { p } of compFree.get(root)!) ext(p.x, p.y);\n for (const s of shapes) {\n if (find(s.name) !== root) continue;\n if (s.kind === 'circleCR') {\n const c = freeByName.get(s.center);\n if (c) { ext(c.p.x - s.radius, c.p.y - s.radius); ext(c.p.x + s.radius, c.p.y + s.radius); }\n } else if (s.kind === 'circleCP') {\n const c = freeByName.get(s.center);\n const sp = freeByName.get(s.surfacePoint);\n if (c && sp) {\n const r = Math.hypot(c.p.x - sp.p.x, c.p.y - sp.p.y);\n ext(c.p.x - r, c.p.y - r); ext(c.p.x + r, c.p.y + r);\n }\n }\n }\n return { minX, maxX, minY, maxY };\n };\n\n // --- pack ngang trái→phải (anchor giữ gốc, dx=0) ---\n let cursorX = bboxOf(roots[0]).maxX + GAP;\n for (let i = 1; i < roots.length; i++) {\n const root = roots[i];\n const bb = bboxOf(root);\n const dx = cursorX - bb.minX;\n for (const { p } of compFree.get(root)!) p.x += dx;\n cursorX = bb.maxX + dx + GAP;\n }\n}\n","// src/stamps/geometry-2d/ai/intent-builders/_types.ts\n//\n// Shared types cho intent-builders: BuildState (mutable build context),\n// newState() factory, IntentBuilderError, và IntentBuilder signature.\n// Tách ra từ intentToDsl.ts (Phase 2a, #45) — không đổi logic.\n\nimport type { DslPointT, DslShapeT } from '../../dsl/schema';\nimport type { IntentT } from '../intent';\n\nexport interface BuildState {\n points: DslPointT[];\n shapes: DslShapeT[];\n /** Map label → ensures uniqueness. */\n pointNames: Set<string>;\n shapeNames: Set<string>;\n /** Map \"AB\"/\"BA\" → segment shape name, dùng cho lookup of='BC'. */\n segmentByEnds: Map<string, string>;\n}\n\nexport function newState(): BuildState {\n return {\n points: [],\n shapes: [],\n pointNames: new Set(),\n shapeNames: new Set(),\n segmentByEnds: new Map(),\n };\n}\n\nexport class IntentBuilderError extends Error {\n constructor(\n message: string,\n public readonly intent: IntentT,\n public readonly cause?: string,\n ) {\n super(message);\n this.name = 'IntentBuilderError';\n }\n}\n\n/** Builder mutate BuildState theo 1 intent op (idempotent, giữ thứ tự gọi). */\nexport type IntentBuilder<T extends IntentT = IntentT> = (s: BuildState, intent: T) => void;\n","// src/stamps/geometry-2d/ai/intent-builders/shared.ts\n//\n// Shared helpers + canonical coord tables + SHAPE_VARIANTS cho intent-builders.\n// Move verbatim từ intentToDsl.ts (Phase 2a, #45) — không đổi logic.\n\nimport type { DslPointT, DslShapeT } from '../../dsl/schema';\nimport type { BuildState } from './_types';\n\n// ---------------------------------------------------------------------------\n// Canonical coord tables\n// ---------------------------------------------------------------------------\n\nexport type Pt = readonly [number, number];\n\nexport const SQRT3 = 1.7320508075688772;\n\nexport function triangleCanonical(variant: string): readonly [Pt, Pt, Pt] {\n switch (variant) {\n case 'equilateral':\n return [[0, 0], [4, 0], [2, 2 * SQRT3]];\n case 'isoceles-AB':\n // AB là đáy, C đỉnh cân\n return [[0, 0], [4, 0], [2, 3]];\n case 'isoceles-BC':\n // BC là đáy, A đỉnh cân\n return [[0, 3], [-2, 0], [2, 0]];\n case 'isoceles-CA':\n // CA là đáy, B đỉnh cân\n return [[0, 0], [2, 3], [4, 0]];\n case 'right-at-A':\n return [[0, 0], [4, 0], [0, 3]];\n case 'right-at-B':\n return [[0, 0], [4, 0], [4, 3]];\n case 'right-at-C':\n // C ở (4,3); AC ⊥ BC\n // chọn A=(0,0), C=(4,3), B=(7.36,1.92) sao cho CA·CB=0\n // Đơn giản hơn: A=(0,0), B=(7,0), C=(0,4) → vuông tại A. Wait — đó là right-at-A.\n // Cần vuông tại C: chọn 3 đỉnh sao cho (CA)·(CB)=0.\n // A=(0,0), B=(7,0), C=(3,4). Check: CA=(−3,−4), CB=(4,−4), dot=−12+16=4 ≠0. Sửa.\n // A=(0,0), C=(3,3), B=(6,0): CA=(−3,−3), CB=(3,−3), dot=−9+9=0 ✓\n return [[0, 0], [6, 0], [3, 3]];\n case 'any':\n default:\n // Tam giác scalene cố định, tránh vuông tại gốc\n return [[0, 0], [5, 0], [2, 3]];\n }\n}\n\nexport function squareCanonical(): readonly [Pt, Pt, Pt, Pt] {\n // Cạnh 4, gốc tại đỉnh đầu (counter-clockwise)\n return [[0, 0], [4, 0], [4, 4], [0, 4]];\n}\n\nexport function rectangleCanonical(variant: string): readonly [Pt, Pt, Pt, Pt] {\n if (variant === 'tall') return [[0, 0], [2.5, 0], [2.5, 4], [0, 4]];\n // wide / standard (default)\n return [[0, 0], [4, 0], [4, 2.5], [0, 2.5]];\n}\n\nexport function rhombusCanonical(): readonly [Pt, Pt, Pt, Pt] {\n // Đường chéo nằm trên trục, 4 đỉnh trên trục: (±2, 0) và (0, ±1.5)\n return [[-2, 0], [0, -1.5], [2, 0], [0, 1.5]];\n}\n\nexport function trapezoidCanonical(variant: string): readonly [Pt, Pt, Pt, Pt] {\n switch (variant) {\n case 'right':\n // Vuông tại A và D\n return [[0, 0], [5, 0], [3, 3], [0, 3]];\n case 'isoceles':\n // Cân — AB đáy lớn, CD đáy nhỏ\n return [[0, 0], [5, 0], [4, 3], [1, 3]];\n case 'general':\n default:\n return [[0, 0], [5, 0], [3.5, 3], [1, 3]];\n }\n}\n\nexport function parallelogramCanonical(): readonly [Pt, Pt, Pt, Pt] {\n return [[0, 0], [4, 0], [5, 3], [1, 3]];\n}\n\nexport function quadrilateralCanonical(): readonly [Pt, Pt, Pt, Pt] {\n return [[0, 0], [5, 0], [4.5, 3.5], [0.5, 3]];\n}\n\n// ---------------------------------------------------------------------------\n// Build helpers\n// ---------------------------------------------------------------------------\n\nexport function addPoint(s: BuildState, p: DslPointT) {\n if (s.pointNames.has(p.name)) return; // idempotent\n s.points.push(p);\n s.pointNames.add(p.name);\n}\n\n// Default coord cho free point khi LLM không truyền `at`. Spread theo thứ tự\n// thêm để tránh nhiều free point collide tại (3, 3) → segment degenerate,\n// circle radius=0, intersection NaN cascade (bug eval cau-14: A=B=D=(3,3)).\n// Pattern: 8 vị trí phân bố xung quanh gốc, vòng lại khi >8.\nexport const FREE_DEFAULT_SPREAD: readonly [number, number][] = [\n [3, 3],\n [-3, 3],\n [3, -3],\n [-3, -3],\n [4, 0],\n [-4, 0],\n [0, 4],\n [0, -4],\n];\n\nexport function defaultFreeCoord(s: BuildState): [number, number] {\n // Đếm số free point đã add (cả từ polygon vertices + add-point free).\n // Position trong array trùng index modulo SPREAD.\n let count = 0;\n for (const p of s.points) if (p.kind === 'free') count++;\n return [...FREE_DEFAULT_SPREAD[count % FREE_DEFAULT_SPREAD.length]];\n}\n\nexport function addShape(s: BuildState, sh: DslShapeT) {\n if (s.shapeNames.has(sh.name)) return;\n s.shapes.push(sh);\n s.shapeNames.add(sh.name);\n}\n\nexport function uniqueShapeName(s: BuildState, base: string): string {\n if (!s.shapeNames.has(base)) return base;\n let i = 2;\n while (s.shapeNames.has(`${base}${i}`)) i++;\n return `${base}${i}`;\n}\n\nexport function uniquePointName(s: BuildState, base: string): string {\n if (!s.pointNames.has(base)) return base;\n let i = 2;\n while (s.pointNames.has(`${base}${i}`)) i++;\n return `${base}${i}`;\n}\n\nexport function ensureSegment(s: BuildState, a: string, b: string): string {\n const k1 = `${a}-${b}`;\n const k2 = `${b}-${a}`;\n const existing = s.segmentByEnds.get(k1) ?? s.segmentByEnds.get(k2);\n if (existing) return existing;\n const name = uniqueShapeName(s, `${a}${b}`);\n addShape(s, { name, kind: 'segment', p1: a, p2: b });\n s.segmentByEnds.set(k1, name);\n return name;\n}\n\n// Resolve line ref cho draw-line (perpThrough/parallelThrough) với fallback:\n// LLM nhiều khi nhầm \"Đường vuông góc với AB tại B\" → to:\"A\" (1 chữ — POINT)\n// thay vì to:\"AB\" (2 chữ — LINE). Khi `ref` là 1 chữ POINT và `anchor` cũng\n// 1 chữ POINT khác, auto build segment qua 2 điểm (alphabetize canonical).\nexport function resolveLineRefWithFallback(s: BuildState, ref: string, anchor: string): string {\n // Single-letter point swap fallback — chỉ áp dụng khi cả 2 đều là POINT\n // đã định nghĩa và khác nhau.\n if (\n /^[A-Za-z]$/.test(ref) && /^[A-Za-z]$/.test(anchor) && ref !== anchor &&\n s.pointNames.has(ref) && s.pointNames.has(anchor)\n ) {\n const [a, b] = ref < anchor ? [ref, anchor] : [anchor, ref];\n return ensureSegment(s, a, b);\n }\n // Path bình thường: 2-char shorthand hoặc tên shape đã có.\n return resolveSegmentRef(s, ref);\n}\n\nexport function resolveSegmentRef(s: BuildState, ref: string): string {\n // ref có thể là tên segment ('AB') hoặc shape name đã có.\n // Nếu là 2 ký tự label đều đã tồn tại → ensure segment 2 đỉnh đó.\n if (s.shapeNames.has(ref)) return ref;\n // Tách \"AB\" → A,B\n if (ref.length === 2 && s.pointNames.has(ref[0]) && s.pointNames.has(ref[1])) {\n return ensureSegment(s, ref[0], ref[1]);\n }\n // Pattern \"A-B\" / \"AB\"\n const dashMatch = ref.match(/^([A-Za-z][A-Za-z0-9'_]*)[-_]?([A-Za-z][A-Za-z0-9'_]*)$/);\n if (dashMatch && s.pointNames.has(dashMatch[1]) && s.pointNames.has(dashMatch[2])) {\n return ensureSegment(s, dashMatch[1], dashMatch[2]);\n }\n // Trả về ref gốc (transpile sẽ báo lỗi nếu invalid)\n return ref;\n}\n\nexport function parseEnds(ref: string): [string, string] | null {\n if (ref.length === 2) return [ref[0], ref[1]];\n const m = ref.match(/^([A-Za-z][A-Za-z0-9'_]*)[-_]?([A-Za-z][A-Za-z0-9'_]*)$/);\n if (m) return [m[1], m[2]];\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// draw-shape variants\n// ---------------------------------------------------------------------------\n\n// Map shape → allowed variants (runtime check, schema cho phép enum chung)\nexport const SHAPE_VARIANTS: Record<string, readonly string[]> = {\n triangle: ['any', 'equilateral', 'isoceles-AB', 'isoceles-BC', 'isoceles-CA', 'right-at-A', 'right-at-B', 'right-at-C'],\n square: ['standard'],\n rectangle: ['standard', 'wide', 'tall'],\n rhombus: ['standard'],\n trapezoid: ['right', 'isoceles', 'general'],\n parallelogram: ['standard'],\n quadrilateral: ['any'],\n};\n","// src/stamps/geometry-2d/ai/intent-builders/draw-shape.ts\n//\n// op: draw-shape — move verbatim từ intentToDsl.ts handleDrawShape (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport {\n addPoint, addShape, uniqueShapeName,\n SHAPE_VARIANTS, triangleCanonical, squareCanonical, rectangleCanonical,\n rhombusCanonical, trapezoidCanonical, parallelogramCanonical, quadrilateralCanonical,\n type Pt,\n} from './shared';\nimport type { DrawShapeIntentT } from '../intent';\n\nexport const buildDrawShape: IntentBuilder<DrawShapeIntentT> = (s, intent) => {\n const labels = intent.labels;\n const explicit = intent.explicitCoords ?? {};\n\n // Validate variant ∈ allowed\n const allowed = SHAPE_VARIANTS[intent.shape];\n if (!allowed || !allowed.includes(intent.variant)) {\n // Fallback to default variant cho shape thay vì throw\n intent = { ...intent, variant: (allowed?.[0] ?? 'any') as typeof intent.variant };\n }\n\n let coords: readonly Pt[];\n switch (intent.shape) {\n case 'triangle': coords = triangleCanonical(intent.variant); break;\n case 'square': coords = squareCanonical(); break;\n case 'rectangle': coords = rectangleCanonical(intent.variant); break;\n case 'rhombus': coords = rhombusCanonical(); break;\n case 'trapezoid': coords = trapezoidCanonical(intent.variant); break;\n case 'parallelogram': coords = parallelogramCanonical(); break;\n case 'quadrilateral': coords = quadrilateralCanonical(); break;\n default:\n throw new IntentBuilderError(`Shape không hỗ trợ: ${intent.shape}`, intent);\n }\n\n if (coords.length !== labels.length) {\n throw new IntentBuilderError(\n `Shape ${intent.shape} cần ${coords.length} labels, nhận ${labels.length}`,\n intent,\n );\n }\n\n labels.forEach((label, i) => {\n const ec = explicit[label];\n const [x, y] = ec ?? coords[i];\n addPoint(s, { name: label, kind: 'free', x, y });\n });\n\n const polyName = uniqueShapeName(s, labels.join(''));\n addShape(s, { name: polyName, kind: 'polygon', vertices: [...labels] });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/midpoint.ts\n//\n// add-point constraint.kind=midpoint — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { IntentBuilderError } from '../_types';\nimport { addPoint, ensureSegment, parseEnds } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildMidpoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'midpoint') return;\n const name = intent.name;\n const ends = parseEnds(c.of);\n if (!ends) throw new IntentBuilderError(`midpoint.of không parse được: ${c.of}`, intent);\n // Ensure segment for the midpoint reference (optional but nice for rendering)\n ensureSegment(s, ends[0], ends[1]);\n addPoint(s, { name, kind: 'midpoint', p1: ends[0], p2: ends[1] });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/perpFoot.ts\n//\n// add-point constraint.kind=perpFoot — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildPerpFoot = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'perpFoot') return;\n const name = intent.name;\n const lineName = resolveSegmentRef(s, c.onLine);\n addPoint(s, { name, kind: 'perpFoot', from: c.from, onLine: lineName });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/centers.ts\n//\n// add-point centers: centroid/circumcenter/incenter/orthocenter/excenter\n// — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildCentroid = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'centroid') return;\n addPoint(s, { name: intent.name, kind: 'centroid', vertices: c.of });\n};\n\nexport const buildCircumcenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'circumcenter') return;\n addPoint(s, { name: intent.name, kind: 'circumcenter', vertices: c.of });\n};\n\nexport const buildIncenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'incenter') return;\n addPoint(s, { name: intent.name, kind: 'incenter', vertices: c.of });\n};\n\nexport const buildOrthocenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'orthocenter') return;\n addPoint(s, { name: intent.name, kind: 'orthocenter', vertices: c.of });\n};\n\nexport const buildExcenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'excenter') return;\n addPoint(s, { name: intent.name, kind: 'excenter', vertices: c.of, opposite: c.opposite });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/intersections.ts\n//\n// add-point intersections: intersection/secondIntersection/circleIntersection\n// — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'intersection') return;\n const r1 = resolveSegmentRef(s, c.of[0]);\n const r2 = resolveSegmentRef(s, c.of[1]);\n addPoint(s, {\n name: intent.name,\n kind: 'intersection',\n ref1: r1,\n ref2: r2,\n ...(c.branch !== undefined ? { branch: c.branch } : {}),\n });\n};\n\nexport const buildSecondIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'secondIntersection') return;\n const lineRef = resolveSegmentRef(s, c.line);\n addPoint(s, {\n name: intent.name, kind: 'secondIntersection',\n line: lineRef, circle: c.circle, other: c.other,\n });\n};\n\nexport const buildCircleIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'circleIntersection') return;\n addPoint(s, {\n name: intent.name, kind: 'circleIntersection',\n c1: c.c1, c2: c.c2, which: c.which,\n });\n};\n\nexport const buildCircleSecondIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'circleSecondIntersection') return;\n addPoint(s, {\n name: intent.name, kind: 'circleSecondIntersection',\n c1: c.c1, c2: c.c2, exclude: c.exclude,\n });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/tangency.ts\n//\n// add-point tangency: tangencyPoint/tangentPoint — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildTangencyPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'tangencyPoint') return;\n const lineRef = resolveSegmentRef(s, c.onLine);\n addPoint(s, {\n name: intent.name, kind: 'tangencyPoint',\n circle: c.circle, onLine: lineRef,\n });\n};\n\nexport const buildTangentPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'tangentPoint') return;\n addPoint(s, {\n name: intent.name, kind: 'tangentPointExt',\n from: c.from, circle: c.circle, which: c.which,\n });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/onSegment-free.ts\n//\n// add-point onSegment/free — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, defaultFreeCoord, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildOnSegment = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'onSegment') return;\n const ref = resolveSegmentRef(s, c.of);\n addPoint(s, { name: intent.name, kind: 'onSegment', segmentId: ref, t: c.t ?? 0.5 });\n};\n\nexport const buildFree = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'free') return;\n const [x, y] = c.at ?? defaultFreeCoord(s);\n addPoint(s, { name: intent.name, kind: 'free', x, y });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/angleBisectorFoot.ts\n//\n// add-point constraint.kind=angleBisectorFoot — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n// Multi-emit: angleBisector shape + ensureSegment + intersection point.\n\nimport type { BuildState } from '../_types';\nimport { IntentBuilderError } from '../_types';\nimport { addPoint, addShape, ensureSegment, parseEnds, resolveSegmentRef, uniqueShapeName } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildAngleBisectorFoot = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'angleBisectorFoot') return;\n const name = intent.name;\n const ends = parseEnds(c.onLine);\n if (!ends) throw new IntentBuilderError(`angleBisectorFoot.onLine không parse: ${c.onLine}`, intent);\n const bisName = uniqueShapeName(s, `ab_${c.from}${c.onLine}`);\n addShape(s, { name: bisName, kind: 'angleBisector', p1: ends[0], vertex: c.from, p2: ends[1] });\n ensureSegment(s, ends[0], ends[1]);\n addPoint(s, { name, kind: 'intersection', ref1: bisName, ref2: resolveSegmentRef(s, c.onLine) });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/externalAngleBisectorFoot.ts\n//\n// add-point constraint.kind=externalAngleBisectorFoot — phân giác NGOÀI (Issue #46 nhóm A).\n// Mirror buildAngleBisectorFoot, nhưng phân giác ngoài = đường VUÔNG GÓC với phân\n// giác trong tại đỉnh `from`. Multi-emit:\n// 1. angleBisector shape (phân giác TRONG — helper, làm cơ sở dựng);\n// 2. perpendicular shape qua `from`, ⊥ phân giác trong = phân giác NGOÀI;\n// 3. ensureSegment(onLine) — cạnh đối (kéo dài) để giao;\n// 4. intersection point = phân giác ngoài ∩ đường thẳng cạnh đối.\n\nimport type { BuildState } from '../_types';\nimport { IntentBuilderError } from '../_types';\nimport { addPoint, addShape, ensureSegment, parseEnds, resolveSegmentRef, uniqueShapeName } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildExternalAngleBisectorFoot = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'externalAngleBisectorFoot') return;\n const name = intent.name;\n const ends = parseEnds(c.onLine);\n if (!ends) throw new IntentBuilderError(`externalAngleBisectorFoot.onLine không parse: ${c.onLine}`, intent);\n // Phân giác trong (helper, cơ sở dựng phân giác ngoài).\n const bisName = uniqueShapeName(s, `ab_${c.from}${c.onLine}`);\n addShape(s, { name: bisName, kind: 'angleBisector', p1: ends[0], vertex: c.from, p2: ends[1] });\n // Phân giác ngoài = đường vuông góc với phân giác trong tại đỉnh `from`.\n const extName = uniqueShapeName(s, `abx_${c.from}${c.onLine}`);\n addShape(s, { name: extName, kind: 'perpendicular', throughPoint: c.from, toLine: bisName });\n ensureSegment(s, ends[0], ends[1]);\n addPoint(s, { name, kind: 'intersection', ref1: extName, ref2: resolveSegmentRef(s, c.onLine) });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/rightAngleViewing.ts\n//\n// add-point constraint.kind=rightAngleViewing — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n// Multi-emit: hidden midpoint + hidden circleCP (Thales diameter) + intersection line∩circle.\n\nimport type { BuildState } from '../_types';\nimport { addPoint, addShape, resolveSegmentRef, uniquePointName, uniqueShapeName } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildRightAngleViewing = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'rightAngleViewing') return;\n const name = intent.name;\n // ∠ a-name-b = 90° ⇔ name trên đường tròn đường kính ab (Thales).\n // Dựng: midpoint(ab) ẩn → circleCP đường kính ab ẩn → giao line∩circle.\n const midName = uniquePointName(s, `mid_${c.a}${c.b}`);\n addPoint(s, { name: midName, kind: 'midpoint', p1: c.a, p2: c.b, visible: false });\n const circName = uniqueShapeName(s, `dia_${c.a}${c.b}`);\n addShape(s, { name: circName, kind: 'circleCP', center: midName, surfacePoint: c.a, visible: false });\n const lineRef = resolveSegmentRef(s, c.onLine);\n addPoint(s, { name, kind: 'intersection', ref1: lineRef, ref2: circName, branch: c.which ?? 0 });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/arcMidpoint.ts\n//\n// add-point constraint.kind=arcMidpoint (Cụm A) — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildArcMidpoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'arcMidpoint') return;\n addPoint(s, { name: intent.name, kind: 'arcMidpoint', circle: c.circle, a: c.a, b: c.b, notContaining: c.notContaining });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/reflect.ts\n//\n// add-point reflectPoint/reflectLine (Cụm A) — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildReflectPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'reflectPoint') return;\n addPoint(s, { name: intent.name, kind: 'reflectPoint', of: c.of, through: c.through });\n};\n\nexport const buildReflectLine = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'reflectLine') return;\n const lineRef = resolveSegmentRef(s, c.through);\n addPoint(s, { name: intent.name, kind: 'reflectLine', of: c.of, through: lineRef });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/pointAtDistance.ts\n//\n// add-point constraint.kind=pointAtDistance (Cụm B) — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n// Multi-emit: ensureSegment + pointAtDistance point.\n\nimport type { BuildState } from '../_types';\nimport { addPoint, ensureSegment } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildPointAtDistance = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'pointAtDistance') return;\n ensureSegment(s, c.from, c.through);\n addPoint(s, { name: intent.name, kind: 'pointAtDistance', from: c.from, through: c.through, distance: c.distance });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/externalToCircle.ts\n//\n// add-point externalToCircle — điểm A nằm NGOÀI đường tròn `circle` (free\n// external point). Builder đọc circle shape từ build state, tính tâm+bán kính,\n// rồi đặt A = free tại [cx + d, cy] với d = max(r*2, r+2) (đảm bảo distance > r\n// → A NGOÀI). Unblock tangentFromExt render END-TO-END (đề \"Lấy A ngoài (O), kẻ\n// 2 tiếp tuyến\").\n//\n// Fail-safe (skip → A KHÔNG add → tangent UNKNOWN_REF / named-missing →\n// escalate, KHÔNG render sai):\n// - circle shape không tồn tại trong build state.\n// - tâm/bán kính không xác định được (tâm không phải free, surfacePoint thiếu).\n//\n// Field name theo dsl/schema.ts: circleCR = { center, radius }; circleCP =\n// { center, surfacePoint } (KHÔNG phải `through`).\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildExternalToCircle = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'externalToCircle') return;\n const circle = s.shapes.find((sh) => sh.name === c.circle);\n if (!circle) return; // fail-safe: A không add → escalate\n\n let cx: number | undefined;\n let cy: number | undefined;\n let r: number | undefined;\n\n if (circle.kind === 'circleCR') {\n const center = s.points.find((p) => p.name === circle.center);\n if (center && center.kind === 'free') {\n cx = center.x;\n cy = center.y;\n r = circle.radius;\n }\n } else if (circle.kind === 'circleCP') {\n const center = s.points.find((p) => p.name === circle.center);\n const surf = s.points.find((p) => p.name === circle.surfacePoint);\n if (center && center.kind === 'free' && surf && surf.kind === 'free') {\n cx = center.x;\n cy = center.y;\n r = Math.hypot(surf.x - cx, surf.y - cy);\n }\n }\n\n if (cx === undefined || cy === undefined || r === undefined || !(r > 0)) return; // fail-safe\n const d = Math.max(r * 2, r + 2);\n addPoint(s, { name: intent.name, kind: 'free', x: cx + d, y: cy });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/onCircle.ts\n//\n// add-point constraint.kind=onCircle — điểm trên đường tròn `circle` tại góc\n// `theta` (glider). Map intent.circle → DSL circleId, theta default 0. Dùng cho\n// đường thẳng Simson (issue #47): P trên đường tròn ngoại tiếp tam giác.\n\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildOnCircle = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'onCircle') return;\n addPoint(s, { name: intent.name, kind: 'onCircle', circleId: c.circle, theta: c.theta ?? 0 });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/index.ts\n//\n// Dispatcher cho op add-point: map constraint.kind → builder (Phase 2b, #45).\n// ADD_POINT_BUILDERS được export cho Phase 6 matrix script.\n\nimport type { BuildState } from '../_types';\nimport type { AddPointIntentT } from '../../intent';\nimport { buildMidpoint } from './midpoint';\nimport { buildPerpFoot } from './perpFoot';\nimport { buildCentroid, buildCircumcenter, buildIncenter, buildOrthocenter, buildExcenter } from './centers';\nimport { buildIntersection, buildSecondIntersection, buildCircleIntersection, buildCircleSecondIntersection } from './intersections';\nimport { buildTangencyPoint, buildTangentPoint } from './tangency';\nimport { buildOnSegment, buildFree } from './onSegment-free';\nimport { buildAngleBisectorFoot } from './angleBisectorFoot';\nimport { buildExternalAngleBisectorFoot } from './externalAngleBisectorFoot';\nimport { buildRightAngleViewing } from './rightAngleViewing';\nimport { buildArcMidpoint } from './arcMidpoint';\nimport { buildReflectPoint, buildReflectLine } from './reflect';\nimport { buildPointAtDistance } from './pointAtDistance';\nimport { buildExternalToCircle } from './externalToCircle';\nimport { buildOnCircle } from './onCircle';\n\nexport const ADD_POINT_BUILDERS: Record<string, (s: BuildState, intent: AddPointIntentT) => void> = {\n midpoint: buildMidpoint, perpFoot: buildPerpFoot,\n centroid: buildCentroid, circumcenter: buildCircumcenter, incenter: buildIncenter,\n orthocenter: buildOrthocenter, excenter: buildExcenter,\n intersection: buildIntersection, secondIntersection: buildSecondIntersection, circleIntersection: buildCircleIntersection,\n circleSecondIntersection: buildCircleSecondIntersection,\n tangencyPoint: buildTangencyPoint, tangentPoint: buildTangentPoint,\n onSegment: buildOnSegment, free: buildFree,\n angleBisectorFoot: buildAngleBisectorFoot, externalAngleBisectorFoot: buildExternalAngleBisectorFoot,\n rightAngleViewing: buildRightAngleViewing,\n arcMidpoint: buildArcMidpoint, reflectPoint: buildReflectPoint, reflectLine: buildReflectLine,\n pointAtDistance: buildPointAtDistance,\n externalToCircle: buildExternalToCircle,\n onCircle: buildOnCircle,\n};\n\nexport const buildAddPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const fn = ADD_POINT_BUILDERS[intent.constraint.kind];\n if (fn) fn(s, intent);\n};\n","// src/stamps/geometry-2d/ai/intent-builders/connect.ts\n//\n// op: connect — move verbatim từ intentToDsl.ts handleConnect (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { ensureSegment, addShape, uniqueShapeName } from './shared';\nimport type { ConnectIntentT } from '../intent';\n\nexport const buildConnect: IntentBuilder<ConnectIntentT> = (s, intent) => {\n const { from, to, style } = intent;\n switch (style) {\n case 'segment':\n ensureSegment(s, from, to);\n break;\n case 'line':\n addShape(s, { name: uniqueShapeName(s, `l_${from}${to}`), kind: 'line', p1: from, p2: to });\n break;\n case 'ray':\n addShape(s, { name: uniqueShapeName(s, `r_${from}${to}`), kind: 'ray', origin: from, through: to });\n break;\n case 'perpBisector':\n addShape(s, { name: uniqueShapeName(s, `pb_${from}${to}`), kind: 'perpBisector', p1: from, p2: to });\n break;\n case 'angleBisector':\n // angleBisector cần 3 điểm (p1, vertex, p2). connect chỉ có 2 điểm → bỏ qua,\n // caller nên dùng intent.add-point với incenter/internalBisector.\n throw new IntentBuilderError(\n 'connect.style=angleBisector cần 3 điểm; dùng add-point/incenter thay',\n intent,\n );\n }\n};\n","// src/stamps/geometry-2d/ai/intent-builders/draw-circle.ts\n//\n// op: draw-circle — move verbatim từ intentToDsl.ts handleDrawCircle (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { addPoint, addShape, defaultFreeCoord } from './shared';\nimport type { DrawCircleIntentT } from '../intent';\n\nexport const buildDrawCircle: IntentBuilder<DrawCircleIntentT> = (s, intent) => {\n if (intent.spec === 'centerThrough') {\n if (!intent.center || !intent.through) {\n throw new IntentBuilderError('centerThrough cần center + through', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'circleCP',\n center: intent.center,\n surfacePoint: intent.through,\n });\n } else if (intent.spec === 'through3') {\n if (!intent.points) {\n throw new IntentBuilderError('through3 cần points', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'circle3',\n p1: intent.points[0],\n p2: intent.points[1],\n p3: intent.points[2],\n });\n } else if (intent.spec === 'centerRadius') {\n if (!intent.center || intent.radius === undefined) {\n throw new IntentBuilderError('centerRadius cần center + radius', intent);\n }\n if (!s.points.find((p) => p.name === intent.center)) {\n const [x, y] = defaultFreeCoord(s);\n addPoint(s, { name: intent.center!, kind: 'free', x, y });\n }\n addShape(s, { name: intent.name, kind: 'circleCR', center: intent.center, radius: intent.radius });\n } else if (intent.spec === 'diameter') {\n if (!intent.endpoints) {\n throw new IntentBuilderError('diameter cần endpoints', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'circleDiameter',\n p1: intent.endpoints[0],\n p2: intent.endpoints[1],\n });\n } else if (intent.spec === 'inscribedIn') {\n if (!intent.triangle) throw new IntentBuilderError('inscribedIn cần triangle', intent);\n for (const v of intent.triangle) {\n if (!s.points.find((p) => p.name === v)) {\n throw new IntentBuilderError(`inscribedIn: vertex ${v} chưa định nghĩa`, intent);\n }\n }\n addShape(s, { name: intent.name, kind: 'incircle', vertices: intent.triangle });\n }\n};\n","// src/stamps/geometry-2d/ai/intent-builders/draw-line.ts\n//\n// op: draw-line — move verbatim từ intentToDsl.ts handleDrawLine (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { addShape, resolveLineRefWithFallback } from './shared';\nimport type { DrawLineIntentT } from '../intent';\n\nexport const buildDrawLine: IntentBuilder<DrawLineIntentT> = (s, intent) => {\n switch (intent.kind) {\n case 'perpThrough': {\n if (!intent.through || !intent.to) throw new IntentBuilderError('perpThrough cần through + to', intent);\n const toLine = resolveLineRefWithFallback(s, intent.to, intent.through);\n addShape(s, { name: intent.name, kind: 'perpendicular', throughPoint: intent.through, toLine });\n break;\n }\n case 'parallelThrough': {\n if (!intent.through || !intent.to) throw new IntentBuilderError('parallelThrough cần through + to', intent);\n const toLine = resolveLineRefWithFallback(s, intent.to, intent.through);\n addShape(s, { name: intent.name, kind: 'parallel', throughPoint: intent.through, toLine });\n break;\n }\n case 'tangentAt': {\n if (!intent.through || !intent.circle) throw new IntentBuilderError('tangentAt cần through + circle', intent);\n addShape(s, { name: intent.name, kind: 'tangent', throughPoint: intent.through, toCircle: intent.circle, branch: 'on' });\n break;\n }\n case 'tangentFromExt': {\n if (!intent.from || !intent.circle) throw new IntentBuilderError('tangentFromExt cần from + circle', intent);\n if (intent.which === 'both') {\n addShape(s, { name: `${intent.name}_0`, kind: 'tangent', throughPoint: intent.from, toCircle: intent.circle, branch: 0 });\n addShape(s, { name: `${intent.name}_1`, kind: 'tangent', throughPoint: intent.from, toCircle: intent.circle, branch: 1 });\n } else {\n const branch = intent.which === 'second' ? 1 : 0;\n addShape(s, { name: intent.name, kind: 'tangent', throughPoint: intent.from, toCircle: intent.circle, branch });\n }\n break;\n }\n case 'angleBisector': {\n // Phân giác TRONG của góc ∠(p1·vertex·p2), VISIBLE, KHÔNG sinh chân\n // (khác cevian \"phân giác AD\" → foot). vertex = đỉnh góc. Issue #46 nhóm A.\n if (!intent.p1 || !intent.vertex || !intent.p2) {\n throw new IntentBuilderError('angleBisector cần p1 + vertex + p2', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'angleBisector',\n p1: intent.p1,\n vertex: intent.vertex,\n p2: intent.p2,\n });\n break;\n }\n case 'lineThrough': {\n // Đường qua ≥2 điểm đồng tuyến (vd Euler line qua G/H/O — issue #47).\n if (!intent.points || intent.points.length < 2) {\n throw new IntentBuilderError('lineThrough cần ≥2 điểm', intent);\n }\n addShape(s, { name: intent.name, kind: 'lineThrough', points: intent.points });\n break;\n }\n case 'radicalAxis': {\n // Trục đẳng phương 2 đường tròn (issue #47, construct 2).\n if (!intent.circle1 || !intent.circle2) {\n throw new IntentBuilderError('radicalAxis cần circle1 + circle2', intent);\n }\n addShape(s, { name: intent.name, kind: 'radicalAxis', circle1: intent.circle1, circle2: intent.circle2 });\n break;\n }\n }\n};\n","// src/stamps/geometry-2d/ai/intent-builders/mark-shape.ts\n//\n// op: mark-shape — move verbatim từ intentToDsl.ts handleMarkShape (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { addShape, uniqueShapeName } from './shared';\nimport type { MarkShapeIntentT } from '../intent';\n\nexport const buildMarkShape: IntentBuilder<MarkShapeIntentT> = (s, intent) => {\n for (const label of intent.labels) {\n if (!s.points.find((p) => p.name === label)) {\n throw new IntentBuilderError(`mark-shape: label ${label} chưa định nghĩa`, intent);\n }\n }\n const polyName = uniqueShapeName(s, intent.labels.join(''));\n addShape(s, { name: polyName, kind: 'polygon', vertices: [...intent.labels] });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/registry.ts\n//\n// OP_BUILDERS: map intent.op → builder (Phase 2b, #45).\n// Thêm 1 op = 1 builder module + 1 dòng ở đây, không sửa switch trung tâm.\n\nimport type { BuildState } from './_types';\nimport type { IntentT } from '../intent';\nimport { buildDrawShape } from './draw-shape';\nimport { buildAddPoint } from './add-point';\nimport { buildConnect } from './connect';\nimport { buildDrawCircle } from './draw-circle';\nimport { buildDrawLine } from './draw-line';\nimport { buildMarkShape } from './mark-shape';\n\nexport const OP_BUILDERS: Record<IntentT['op'], (s: BuildState, intent: any) => void> = {\n 'draw-shape': buildDrawShape,\n 'add-point': buildAddPoint,\n 'connect': buildConnect,\n 'draw-circle': buildDrawCircle,\n 'draw-line': buildDrawLine,\n 'mark-shape': buildMarkShape,\n};\n","// src/stamps/geometry-2d/ai/intentToDsl.ts\n//\n// Stage 2: deterministic Intent[] → DslInputT builder.\n//\n// Pure function. Không gọi AI. Mỗi Intent op map sang 1 hoặc nhiều DSL entries\n// với canonical coords cố định per variant. Builder rejects intent không hợp lệ\n// (vd connect to point chưa tồn tại) thay vì silent skip.\n//\n// Phase 2b (#45): orchestrator mỏng — dispatch qua OP_BUILDERS registry.\n// Thứ tự loop intents giữ nguyên (ordering dependency: draw-shape trước add-point\n// tham chiếu điểm của nó). repairCircleIntersections chạy post-dispatch.\n\nimport type { DslInputT } from '../dsl/schema';\nimport type { IntentT } from './intent';\nimport { repairCircleIntersections } from './repairCircleIntersections';\nimport { layoutDisjointComponents } from './layout/disjointOffset';\nimport { newState } from './intent-builders/_types';\nimport { OP_BUILDERS } from './intent-builders/registry';\n\nexport { IntentBuilderError } from './intent-builders/_types';\n\nexport function intentsToDsl(intents: readonly IntentT[]): DslInputT {\n const s = newState();\n for (const intent of intents) {\n const build = OP_BUILDERS[intent.op];\n if (build) build(s, intent);\n }\n // Geometric repair: đảm bảo circle dùng cho circleIntersection thực sự cắt\n // nhau 2 điểm (dời center auto-inject nếu tiếp xúc/rời nhau).\n repairCircleIntersections(s.points, s.shapes);\n // Layout: tách các component RỜI NHAU theo trục ngang (không chồng origin).\n layoutDisjointComponents(s.points, s.shapes);\n return { version: 1, points: s.points, shapes: s.shapes };\n}\n","// src/stamps/geometry-2d/dsl/schema.ts\nimport { z } from 'zod';\nimport { NameZ } from './names';\nimport { KIND_REGISTRY, POINT_KINDS } from './registry';\n\n// Re-export NameZ for backward compat with consumers.\nexport { NameZ } from './names';\n\nfunction asTuple(arr: z.ZodObject<any>[]): [z.ZodObject<any>, z.ZodObject<any>, ...z.ZodObject<any>[]] {\n if (arr.length < 2) throw new Error('schema: need at least 2 variants for discriminatedUnion');\n return arr as never;\n}\n\nconst pointSchemas = Array.from(KIND_REGISTRY.values())\n .filter((m) => POINT_KINDS.has(m.kind))\n .map((m) => m.schema);\n\nconst shapeSchemas = Array.from(KIND_REGISTRY.values())\n .filter((m) => !POINT_KINDS.has(m.kind))\n .map((m) => m.schema);\n\n// Runtime schemas assembled from the registry (Phase 6).\nexport const DslPoint = z.discriminatedUnion('kind', asTuple(pointSchemas));\nexport const DslShape = z.discriminatedUnion('kind', asTuple(shapeSchemas));\n\nexport const DslInput = z.object({\n version: z.literal(1),\n points: z.array(DslPoint),\n shapes: z.array(DslShape).default([]),\n});\n\n// -----------------------------------------------------------------------------\n// Static types\n//\n// We cannot derive these via `z.infer<typeof DslPoint>` because the kind\n// modules use `Extract<DslPointT, { kind: '...' }>` to type their `emit` /\n// `collectRefs` callbacks. That creates a type-graph cycle\n// (schema.ts -> registry.ts -> kinds/* -> schema.ts) which TypeScript collapses\n// to `any` (and `Extract<any, ...>` to `never`) because the registry stores\n// schemas as the erased `z.ZodObject<any>`.\n//\n// Keeping the discriminated union types listed explicitly here breaks the cycle\n// while still letting `DslPoint`/`DslShape` (runtime) be registry-assembled.\n// Adding a new kind = 1 new module file + 1 entry in registry.ts + 1 variant\n// listed below (a single object literal — much smaller than duplicating the\n// full Zod schema).\n// -----------------------------------------------------------------------------\n\ntype Name = z.infer<typeof NameZ>;\n\n// scale/offset OPTIONAL (Issue #46 nhóm C): d = scale·base + offset. Absent →\n// d = base như cũ (additive, serialize/golden không đổi).\nexport type DslDistanceSpec =\n | { kind: 'circleRadius'; circle: Name; scale?: number; offset?: number }\n | { kind: 'segmentLength'; p1: Name; p2: Name; scale?: number; offset?: number }\n | { kind: 'literal'; value: number; scale?: number; offset?: number };\n\nexport type DslPointT =\n | { name: Name; kind: 'free'; x: number; y: number }\n | { name: Name; kind: 'midpoint'; p1: Name; p2: Name; visible?: boolean }\n | { name: Name; kind: 'onSegment'; segmentId: Name; t: number }\n | { name: Name; kind: 'onLine'; lineId: Name; t: number }\n | { name: Name; kind: 'onCircle'; circleId: Name; theta: number }\n | { name: Name; kind: 'perpFoot'; from: Name; onLine: Name }\n | { name: Name; kind: 'circumcenter'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'incenter'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'centroid'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'orthocenter'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'intersection'; ref1: Name; ref2: Name; branch?: 0 | 1 }\n // NEW Tier 4+5\n | { name: Name; kind: 'secondIntersection'; line: Name; circle: Name; other: Name }\n | { name: Name; kind: 'circleIntersection'; c1: Name; c2: Name; which: 0 | 1 }\n | { name: Name; kind: 'circleSecondIntersection'; c1: Name; c2: Name; exclude: Name }\n | { name: Name; kind: 'tangencyPoint'; circle: Name; onLine: Name }\n | { name: Name; kind: 'tangentPointExt'; from: Name; circle: Name; which: 0 | 1 }\n // Cụm A\n | { name: Name; kind: 'arcMidpoint'; circle: Name; a: Name; b: Name; notContaining: Name }\n | { name: Name; kind: 'excenter'; vertices: [Name, Name, Name]; opposite: Name }\n | { name: Name; kind: 'reflectPoint'; of: Name; through: Name }\n | { name: Name; kind: 'reflectLine'; of: Name; through: Name }\n // Cụm B points\n | { name: Name; kind: 'pointAtDistance'; from: Name; through: Name; distance: DslDistanceSpec };\n\nexport type DslShapeT =\n | { name: Name; kind: 'segment'; p1: Name; p2: Name }\n | { name: Name; kind: 'line'; p1: Name; p2: Name }\n | { name: Name; kind: 'ray'; origin: Name; through: Name }\n | { name: Name; kind: 'polygon'; vertices: Name[] }\n | { name: Name; kind: 'perpendicular'; throughPoint: Name; toLine: Name }\n | { name: Name; kind: 'parallel'; throughPoint: Name; toLine: Name }\n | { name: Name; kind: 'perpBisector'; p1: Name; p2: Name }\n | { name: Name; kind: 'angleBisector'; p1: Name; vertex: Name; p2: Name }\n | { name: Name; kind: 'lineThrough'; points: Name[] }\n | { name: Name; kind: 'radicalAxis'; circle1: Name; circle2: Name }\n | { name: Name; kind: 'tangent'; throughPoint: Name; toCircle: Name; branch?: 0 | 1 | 'on' }\n | { name: Name; kind: 'circleCP'; center: Name; surfacePoint: Name; visible?: boolean }\n | { name: Name; kind: 'circle3'; p1: Name; p2: Name; p3: Name }\n | { name: Name; kind: 'circleDiameter'; p1: Name; p2: Name; visible?: boolean }\n // NEW Tier 4+5\n | { name: Name; kind: 'circleCR'; center: Name; radius: number }\n | { name: Name; kind: 'incircle'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'excircle'; vertices: [Name, Name, Name]; opposite: Name };\n\nexport type DslInputT = {\n version: 1;\n points: DslPointT[];\n shapes: DslShapeT[];\n};\n","// src/stamps/geometry-2d/dsl/transpile/symbols.ts\nimport type { DslInputT, DslPointT, DslShapeT } from '../schema';\nimport { mkError, type TranspileError } from './errors';\n\nexport type Role = 'point' | 'shape';\n\nexport interface Symbol {\n name: string;\n role: Role;\n entity: DslPointT | DslShapeT;\n index: number; // vị trí trong list nguyên thuỷ (cho deterministic id assign sau)\n}\n\nexport interface SymbolResult {\n symbols: Map<string, Symbol>;\n errors: TranspileError[];\n}\n\nexport function buildSymbols(dsl: DslInputT): SymbolResult {\n const symbols = new Map<string, Symbol>();\n const errors: TranspileError[] = [];\n let counter = 0;\n\n for (const p of dsl.points) {\n if (symbols.has(p.name)) {\n errors.push(mkError('DUPLICATE_NAME', `Tên trùng: \"${p.name}\"`, { path: [p.name] }));\n continue;\n }\n symbols.set(p.name, { name: p.name, role: 'point', entity: p, index: counter++ });\n }\n\n for (const s of dsl.shapes) {\n if (symbols.has(s.name)) {\n errors.push(mkError('DUPLICATE_NAME', `Tên trùng: \"${s.name}\"`, { path: [s.name] }));\n continue;\n }\n symbols.set(s.name, { name: s.name, role: 'shape', entity: s, index: counter++ });\n }\n\n return { symbols, errors };\n}\n","// src/stamps/geometry-2d/dsl/transpile/cycles.ts\nimport type { Symbol } from './symbols';\nimport { collectRefs } from './refs';\nimport { mkError, type TranspileError } from './errors';\n\ntype Color = 'white' | 'gray' | 'black';\n\nexport interface CyclesResult {\n errors: TranspileError[];\n}\n\nexport function detectCycles(symbols: Map<string, Symbol>): CyclesResult {\n const color = new Map<string, Color>();\n const parent = new Map<string, string | null>();\n const errors: TranspileError[] = [];\n const reportedCycles = new Set<string>();\n\n for (const name of symbols.keys()) color.set(name, 'white');\n\n function reportCycle(start: string, hit: string) {\n // reconstruct chain hit ← ... ← start\n const chain: string[] = [start];\n let cur: string | null | undefined = parent.get(start);\n while (cur && cur !== hit && chain.length < symbols.size + 2) {\n chain.push(cur);\n cur = parent.get(cur);\n }\n chain.push(hit);\n // normalize cho dedupe (rotate min-first)\n const minIdx = chain.indexOf(chain.reduce((a, b) => (a < b ? a : b)));\n const rotated = [...chain.slice(minIdx), ...chain.slice(0, minIdx)];\n const key = rotated.join('→');\n if (reportedCycles.has(key)) return;\n reportedCycles.add(key);\n errors.push(mkError('CYCLE',\n `Phụ thuộc vòng: ${chain.reverse().join(' → ')}`,\n { path: [...chain], hint: 'Kiểm tra lại quan hệ midpoint/perpFoot/intersection.' }));\n }\n\n function dfs(name: string) {\n color.set(name, 'gray');\n const sym = symbols.get(name);\n if (sym) {\n for (const ref of collectRefs(sym.entity)) {\n if (!symbols.has(ref)) continue; // unknown — refs.ts handle\n const c = color.get(ref);\n if (c === 'gray') {\n reportCycle(name, ref);\n continue;\n }\n if (c === 'white') {\n parent.set(ref, name);\n dfs(ref);\n }\n }\n }\n color.set(name, 'black');\n }\n\n for (const name of symbols.keys()) {\n if (color.get(name) === 'white') {\n parent.set(name, null);\n dfs(name);\n }\n }\n\n return { errors };\n}\n","// src/stamps/geometry-2d/dsl/transpile/topology.ts\n//\n// Stable topological sort: preserve DSL insertion order khi không có constraint,\n// chỉ trì hoãn entity tới khi mọi reference đã emit. Fix bug render perpFoot\n// đứng trước segment dùng làm onLine.\n//\n// Khác DFS post-order (kéo deps lên trước): Kahn-style iterative đảm bảo\n// roundtrip stability — entity không có constraint phụ thuộc lẫn nhau giữ\n// đúng thứ tự DSL gốc.\n\nimport type { Symbol } from './symbols';\nimport { collectRefs } from './refs';\n\n/**\n * Trả về danh sách tên entity theo thứ tự topological STABLE:\n * - Mọi name X xuất hiện SAU mọi name X tham chiếu.\n * - Khi 2 entity không phụ thuộc lẫn nhau, giữ relative order từ symbols\n * (= DSL insertion order: points trước shapes, mỗi nhóm theo DSL order).\n *\n * Giả định cycles đã được loại bởi detectCycles trước đó. Nếu vẫn có cycle,\n * entity unresolved sẽ append cuối để output đủ count.\n */\nexport function topoSort(symbols: Map<string, Symbol>): string[] {\n const all = [...symbols.keys()];\n const emitted = new Set<string>();\n const order: string[] = [];\n\n // Pre-compute deps filtered xuống chỉ tên có trong symbols.\n const depsOf = new Map<string, string[]>();\n for (const name of all) {\n const sym = symbols.get(name);\n if (!sym) {\n depsOf.set(name, []);\n continue;\n }\n const refs = collectRefs(sym.entity).filter((r) => symbols.has(r));\n depsOf.set(name, refs);\n }\n\n // Lặp: mỗi vòng emit tất cả entity có deps đã emit, theo DSL order.\n // Worst case O(n^2) but n nhỏ (~20 entity/figure).\n let progressed = true;\n while (progressed) {\n progressed = false;\n for (const name of all) {\n if (emitted.has(name)) continue;\n const deps = depsOf.get(name)!;\n if (deps.every((d) => emitted.has(d))) {\n emitted.add(name);\n order.push(name);\n progressed = true;\n }\n }\n }\n\n // Cycle leftovers (defensive — detectCycles đáng lẽ catch): append đúng count.\n for (const name of all) {\n if (!emitted.has(name)) order.push(name);\n }\n\n return order;\n}\n","// src/stamps/geometry-2d/dsl/transpile/ids.ts\nimport type { Symbol } from './symbols';\nimport { KIND_REGISTRY } from '../registry';\n\nexport function assignIds(symbols: Map<string, Symbol>): Map<string, string> {\n const counters = new Map<string, number>();\n const ids = new Map<string, string>();\n for (const [name, sym] of symbols.entries()) {\n const mod = KIND_REGISTRY.get(sym.entity.kind);\n if (!mod) throw new Error(`assignIds: no registry entry for kind \"${sym.entity.kind}\"`);\n const prefix = mod.prefix;\n counters.set(prefix, (counters.get(prefix) ?? 0) + 1);\n ids.set(name, `${prefix}${counters.get(prefix)}`);\n }\n return ids;\n}\n","// src/stamps/geometry-2d/dsl/transpile.ts\nimport type { SceneObject, State } from '../../../core/scene/types';\nimport { createEmptyState } from '../../../core/scene/types';\nimport { DslInput, type DslInputT, type DslPointT, type DslShapeT } from './schema';\nimport { buildSymbols } from './transpile/symbols';\nimport { validateRefs } from './transpile/refs';\nimport { detectCycles } from './transpile/cycles';\nimport { topoSort } from './transpile/topology';\nimport { assignIds } from './transpile/ids';\nimport { mkError, type TranspileError, type TranspileResult } from './transpile/errors';\nimport { KIND_REGISTRY } from './registry';\nimport type { EmitContext, EmittedEntity, KindRole } from './kinds/_types';\n\ntype EntityKindHint = 'point' | 'line' | 'segment' | 'ray' | 'lineConstruction' | 'circle';\n\nfunction hintOf(entity: DslPointT | DslShapeT): EntityKindHint {\n const mod = KIND_REGISTRY.get(entity.kind);\n if (!mod) throw new Error(`hintOf: no registry entry for kind \"${entity.kind}\"`);\n // 'polygon' role maps to 'point' for legacy MVP behavior (polygon never used as ref target).\n return mod.role === 'polygon' ? 'point' : (mod.role as EntityKindHint);\n}\n\nfunction buildEmitContext(\n ids: Map<string, string>,\n kindHints: Map<string, EntityKindHint>,\n): EmitContext {\n const auxCounters = new Map<string, number>();\n return {\n resolveId(name) {\n const id = ids.get(name);\n if (!id) throw new Error(`emit: id not assigned for \"${name}\"`);\n return id;\n },\n hintOf(name) {\n const hint = kindHints.get(name);\n if (!hint) throw new Error(`emit: hint not assigned for \"${name}\"`);\n // EntityKindHint and KindRole share these literals; safe to widen.\n return hint as KindRole;\n },\n mintAuxId(parentName, suffix) {\n const key = `${parentName}.${suffix}`;\n auxCounters.set(key, (auxCounters.get(key) ?? 0) + 1);\n const seq = auxCounters.get(key)!;\n return `aux_${parentName}_${suffix}${seq}`;\n },\n };\n}\n\nexport function transpile(dslRaw: unknown): TranspileResult {\n // Stage 1: schema parse\n const parsed = DslInput.safeParse(dslRaw);\n if (!parsed.success) {\n const errors: TranspileError[] = parsed.error.issues.map((iss) =>\n mkError('SCHEMA', iss.message, { path: iss.path.map(String) }),\n );\n return { ok: false, errors };\n }\n // Cast: parsed.data is statically `{[x: string]: any}[]` because the registry\n // stores schemas as the erased `z.ZodObject<any>`. Runtime parse already\n // validated the variant shape, so widening to DslInputT is safe.\n const dsl = parsed.data as DslInputT;\n\n // Stage 2-4: collect errors\n const { symbols, errors: dupErrors } = buildSymbols(dsl);\n const { errors: refErrors } = validateRefs(dsl, symbols);\n const { errors: cycleErrors } = detectCycles(symbols);\n\n const allErrors = [...dupErrors, ...refErrors, ...cycleErrors];\n if (allErrors.length > 0) return { ok: false, errors: allErrors };\n\n // Stage 5: id assignment\n const ids = assignIds(symbols);\n\n // Build kindHints (DSL name → EntityKindHint) cho intersection inference.\n const kindHints = new Map<string, EntityKindHint>();\n for (const [name, sym] of symbols.entries()) {\n kindHints.set(name, hintOf(sym.entity));\n }\n\n // Stage 6: emit via registry\n const objects: Record<string, SceneObject> = {};\n const order: string[] = [];\n const ctx = buildEmitContext(ids, kindHints);\n\n const emitEntity = (entity: DslPointT | DslShapeT) => {\n const mod = KIND_REGISTRY.get(entity.kind);\n if (!mod) throw new Error(`emit: no registry entry for kind \"${entity.kind}\"`);\n const emitted: EmittedEntity[] = mod.emit(entity as never, ctx);\n for (const ent of emitted) {\n objects[ent.object.id] = ent.object;\n order.push(ent.object.id);\n }\n };\n\n // Emit theo thứ tự topological — đảm bảo entity dependent emit SAU mọi\n // reference của nó (vd perpFoot point sau segment dùng làm onLine).\n const sortedNames = topoSort(symbols);\n for (const name of sortedNames) {\n const sym = symbols.get(name);\n if (sym) emitEntity(sym.entity);\n }\n\n const empty = createEmptyState('2d');\n const state: State = {\n objects,\n order,\n counter: order.length,\n meta: empty.meta,\n };\n return { ok: true, state };\n}\n","// src/stamps/geometry-2d/ai/verify.ts\n//\n// Stage 4 verifier. Sau khi Intent[] → DSL → render, kiểm tra 3 trục:\n// - đủ (missing): intent expected nhưng DSL không có\n// - đúng (wrong): variant/labels mismatch\n// - không thừa (extra): DSL có entity không tương ứng intent nào\n//\n// Hai chế độ dùng:\n// 1. eval mode: so sánh actualIntents vs expectedIntents (golden)\n// 2. runtime mode: tự verify pipeline (intent→DSL, không có golden)\n\nimport type { DslInputT } from '../dsl/schema';\nimport type { IntentT, DrawShapeIntentT, AddPointIntentT } from './intent';\n\nexport interface VerifyIssue {\n readonly axis: 'missing' | 'wrong' | 'extra';\n readonly detail: string;\n}\n\nexport interface VerifyReport {\n readonly ok: boolean;\n readonly missing: readonly VerifyIssue[];\n readonly wrong: readonly VerifyIssue[];\n readonly extra: readonly VerifyIssue[];\n readonly geometric?: readonly VerifyIssue[];\n}\n\n// ---------------------------------------------------------------------------\n// Eval-mode: compare actual intents vs golden expected\n// ---------------------------------------------------------------------------\n\nexport function compareIntents(\n expected: readonly IntentT[],\n actual: readonly IntentT[],\n): VerifyReport {\n const expectedKey = expected.map(intentKey);\n const actualKey = actual.map(intentKey);\n\n const missing: VerifyIssue[] = [];\n const extra: VerifyIssue[] = [];\n const wrong: VerifyIssue[] = [];\n\n // Track which expected/actual entries matched.\n const matchedActual = new Set<number>();\n for (let i = 0; i < expectedKey.length; i++) {\n const ek = expectedKey[i];\n // Exact match first\n const exactIdx = actualKey.findIndex((ak, idx) => !matchedActual.has(idx) && ak === ek);\n if (exactIdx >= 0) {\n matchedActual.add(exactIdx);\n continue;\n }\n // Partial match: same op + same shape/name → \"wrong\"\n const partialIdx = actualKey.findIndex((ak, idx) =>\n !matchedActual.has(idx) && samePrefix(ak, ek, 2),\n );\n if (partialIdx >= 0) {\n matchedActual.add(partialIdx);\n wrong.push({\n axis: 'wrong',\n detail: `expected ${ek}, got ${actualKey[partialIdx]}`,\n });\n continue;\n }\n // No match → missing\n missing.push({ axis: 'missing', detail: ek });\n }\n // Unmatched actual entries → extra\n for (let i = 0; i < actualKey.length; i++) {\n if (!matchedActual.has(i)) {\n extra.push({ axis: 'extra', detail: actualKey[i] });\n }\n }\n\n return {\n ok: missing.length === 0 && wrong.length === 0 && extra.length === 0,\n missing,\n wrong,\n extra,\n };\n}\n\n// \"draw-shape/triangle/equilateral/A,B,C\" — canonical short string for compare.\nfunction intentKey(intent: IntentT): string {\n switch (intent.op) {\n case 'draw-shape':\n return [\n 'draw-shape',\n intent.shape,\n (intent as DrawShapeIntentT).variant,\n intent.labels.join(','),\n ].join('/');\n case 'add-point':\n return ['add-point', intent.name, intent.constraint.kind, constraintKey(intent.constraint)].join('/');\n case 'connect':\n return ['connect', intent.style, intent.from, intent.to].join('/');\n case 'draw-circle': {\n if (intent.spec === 'centerThrough') return `draw-circle/${intent.name}/centerThrough/${intent.center}/${intent.through}`;\n if (intent.spec === 'through3') return `draw-circle/${intent.name}/through3/${intent.points?.join(',') ?? ''}`;\n if (intent.spec === 'centerRadius') return `draw-circle/${intent.name}/centerRadius/${intent.center}/${intent.radius}`;\n if (intent.spec === 'inscribedIn') return `draw-circle/${intent.name}/inscribedIn/${intent.triangle?.join(',') ?? ''}`;\n return `draw-circle/${intent.name}/${(intent as any).spec}`;\n }\n case 'draw-line': {\n const base = [\n 'draw-line', intent.name, intent.kind,\n intent.through ?? '', intent.to ?? '', intent.from ?? '', intent.circle ?? '', intent.which ?? '',\n ].join('/');\n if (intent.kind === 'lineThrough') return `${base}/${(intent.points ?? []).join('+')}`;\n if (intent.kind === 'radicalAxis') return `${base}/${intent.circle1 ?? ''}+${intent.circle2 ?? ''}`;\n return base;\n }\n case 'mark-shape':\n return ['mark-shape', intent.shape, intent.labels.join(',')].join('/');\n }\n}\n\nfunction constraintKey(c: AddPointIntentT['constraint']): string {\n switch (c.kind) {\n case 'midpoint': return c.of;\n case 'perpFoot': return `${c.from}->${c.onLine}`;\n case 'centroid':\n case 'circumcenter':\n case 'incenter':\n case 'orthocenter':\n return c.of.join(',');\n case 'intersection': return c.of.join('×');\n case 'onSegment': return `${c.of}@${c.t ?? 'mid'}`;\n case 'free': return c.at ? c.at.join(',') : '*';\n case 'secondIntersection': return `secondIntersection:${c.line}:${c.circle}:${c.other}`;\n case 'circleIntersection': return `circleIntersection:${c.c1}:${c.c2}:${c.which}`;\n case 'circleSecondIntersection': return `circleSecondIntersection:${c.c1}:${c.c2}:${c.exclude}`;\n case 'tangencyPoint': return `tangencyPoint:${c.circle}:${c.onLine}`;\n case 'tangentPoint': return `tangentPoint:${c.from}:${c.circle}:${c.which}`;\n case 'angleBisectorFoot': return `angleBisectorFoot:${c.from}:${c.onLine}`;\n case 'externalAngleBisectorFoot': return `externalAngleBisectorFoot:${c.from}:${c.onLine}`;\n case 'arcMidpoint': return `arcMidpoint:${c.circle}:${c.a}:${c.b}:${c.notContaining}`;\n case 'reflectPoint': return `reflectPoint:${c.of}:${c.through}`;\n case 'reflectLine': return `reflectLine:${c.of}:${c.through}`;\n case 'excenter': return `excenter:${c.of.join(',')}:${c.opposite}`;\n case 'rightAngleViewing': return `rightAngleViewing:${c.a}:${c.b}:${c.onLine}:${c.which ?? 0}`;\n case 'pointAtDistance': {\n const d = c.distance;\n const dKey = d.kind === 'circleRadius' ? `r:${d.circle}`\n : d.kind === 'segmentLength' ? `seg:${d.p1}:${d.p2}`\n : `lit:${d.value}`;\n return `pointAtDistance:${c.from}:${c.through}:${dKey}`;\n }\n case 'externalToCircle': return `externalToCircle:${c.circle}`;\n case 'onCircle': return `onCircle:${c.circle}:${c.theta ?? ''}`;\n }\n}\n\nfunction samePrefix(a: string, b: string, depth: number): boolean {\n const aP = a.split('/').slice(0, depth).join('/');\n const bP = b.split('/').slice(0, depth).join('/');\n return aP === bP;\n}\n\n// ---------------------------------------------------------------------------\n// Intent metric: recall / precision / F1 (for eval)\n// ---------------------------------------------------------------------------\n\nexport interface IntentMetrics {\n recall: number;\n precision: number;\n f1: number;\n matched: number;\n expected: number;\n actual: number;\n}\n\nexport function computeIntentMetrics(\n expected: readonly IntentT[],\n actual: readonly IntentT[],\n): IntentMetrics {\n const expectedKeys = expected.map(intentKey);\n const actualKeys = actual.map(intentKey);\n const matched = new Set<number>();\n let hit = 0;\n for (const ek of expectedKeys) {\n const idx = actualKeys.findIndex((ak, i) => !matched.has(i) && ak === ek);\n if (idx >= 0) { matched.add(idx); hit++; }\n }\n const recall = expectedKeys.length === 0 ? 1 : hit / expectedKeys.length;\n const precision = actualKeys.length === 0 ? 1 : hit / actualKeys.length;\n const f1 = (recall + precision) === 0 ? 0 : (2 * recall * precision) / (recall + precision);\n return {\n recall, precision, f1,\n matched: hit,\n expected: expectedKeys.length,\n actual: actualKeys.length,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Geometric verification on DSL with resolved coords (scope: on-circle only;\n// tangent-touch / concyclic / collinear deferred until JSXGraph runtime hook).\n// ---------------------------------------------------------------------------\n\nconst GEOM_TOL = 1e-3;\n\nfunction resolveCoord(dsl: DslInputT, name: string): [number, number] | null {\n const p = dsl.points.find((x) => x.name === name);\n if (!p) return null;\n if (p.kind === 'free') return [p.x, p.y];\n if (p.kind === 'midpoint') {\n const a = resolveCoord(dsl, p.p1);\n const b = resolveCoord(dsl, p.p2);\n if (!a || !b) return null;\n return [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];\n }\n // Other kinds: computed by JSXGraph at runtime — skip static check.\n return null;\n}\n\nexport function verifyGeometric(dsl: DslInputT): VerifyReport {\n const geometric: VerifyIssue[] = [];\n\n for (const shape of dsl.shapes) {\n if (shape.kind !== 'circleCR') continue;\n // on-circle check: any point with onCircle constraint referencing this circle\n for (const p of dsl.points) {\n if (p.kind !== 'onCircle') continue;\n if (p.circleId !== shape.name) continue;\n const c = resolveCoord(dsl, shape.center);\n const pp = resolveCoord(dsl, p.name);\n if (!c || !pp) continue;\n const d = Math.hypot(pp[0] - c[0], pp[1] - c[1]);\n if (Math.abs(d - shape.radius) > GEOM_TOL) {\n geometric.push({\n axis: 'wrong',\n detail: `on-circle: |${p.name}-${shape.name}|=${d.toFixed(3)} ≠ R=${shape.radius}`,\n });\n }\n }\n }\n\n return {\n ok: geometric.length === 0,\n missing: [],\n wrong: [],\n extra: [],\n geometric,\n } as VerifyReport;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-mode: verify DSL geometry constraints\n// ---------------------------------------------------------------------------\n\nexport function verifyGeometry(intents: readonly IntentT[], dsl: DslInputT): VerifyReport {\n const issues: VerifyIssue[] = [];\n\n // Check right-triangle variant has actual right angle at named vertex.\n for (const intent of intents) {\n if (intent.op !== 'draw-shape' || intent.shape !== 'triangle') continue;\n const variant = intent.variant;\n if (!variant.startsWith('right-at-')) continue;\n const apex = variant.slice('right-at-'.length); // 'A' | 'B' | 'C'\n const [A, B, C] = intent.labels;\n const ptByName = new Map(\n dsl.points.filter((p) => p.kind === 'free').map((p) => [p.name, [p.x, p.y] as [number, number]]),\n );\n const pA = ptByName.get(A);\n const pB = ptByName.get(B);\n const pC = ptByName.get(C);\n if (!pA || !pB || !pC) continue;\n const apexP = apex === 'A' ? pA : apex === 'B' ? pB : pC;\n const other1 = apex === 'A' ? pB : apex === 'B' ? pA : pA;\n const other2 = apex === 'A' ? pC : apex === 'B' ? pC : pB;\n const v1 = [other1[0] - apexP[0], other1[1] - apexP[1]];\n const v2 = [other2[0] - apexP[0], other2[1] - apexP[1]];\n const dot = v1[0] * v2[0] + v1[1] * v2[1];\n if (Math.abs(dot) > 1e-6) {\n issues.push({\n axis: 'wrong',\n detail: `triangle ${A}${B}${C} variant=right-at-${apex} không vuông (dot=${dot.toFixed(3)})`,\n });\n }\n }\n\n return {\n ok: issues.length === 0,\n missing: [],\n wrong: issues,\n extra: [],\n };\n}\n","// src/stamps/geometry-2d/ai/deterministic/tryDeterministicFigure.ts\n//\n// Track A đầy đủ: rule NLU → coverage gate → normalize → resolve circle collisions\n// → build DSL → transpile → verifyGeometry → named-entity guard. Trả figure SẴN\n// RENDER nếu qua HẾT 4 lớp gate; ngược lại { ok:false } để router escalate AI.\n//\n// Tách khỏi buildFigureIntent để test độc lập toàn bộ logic quyết định.\nimport type { IntentT } from '../intent';\nimport type { DslInputT } from '../../dsl/schema';\nimport type { TranspileResult } from '../../dsl/transpile/errors';\nimport type { VerifyReport } from '../verify';\nimport type { CoverageReport } from './coverage';\nimport { runDeterministicIntents } from './runDeterministicIntents';\nimport { allNamedEntitiesPresent, verifyIntentFidelity } from './guards';\nimport { normalizeIntents } from '../normalizeIntent';\nimport { resolveCircleNameCollisions } from '../resolveCircleNames';\nimport { intentsToDsl } from '../intentToDsl';\nimport { transpile } from '../../dsl';\nimport { verifyGeometry } from '../verify';\n\nexport type DeterministicReason =\n | 'no-match'\n | 'incomplete-coverage'\n | 'build-throw'\n | 'transpile-throw'\n | 'transpile-fail'\n | 'verify-fail'\n | 'named-missing'\n | 'intent-dropped';\n\nexport interface DeterministicFigure {\n intents: IntentT[];\n dsl: DslInputT;\n transpile: Extract<TranspileResult, { ok: true }>;\n verify: VerifyReport;\n coverage: CoverageReport;\n}\n\nexport type TryDeterministicResult =\n | { ok: true; figure: DeterministicFigure }\n | { ok: false; reason: DeterministicReason; detail?: string; coverage?: CoverageReport };\n\nexport function tryDeterministicFigure(problem: string): TryDeterministicResult {\n const det = runDeterministicIntents(problem);\n if (!det.ok) return { ok: false, reason: det.reason, coverage: det.coverage };\n\n // Cùng các stage chuẩn hoá như Track B (LLM) để 2 path hội tụ.\n const intents = resolveCircleNameCollisions(normalizeIntents(det.intents, problem));\n\n let dsl: DslInputT;\n try {\n dsl = intentsToDsl(intents);\n } catch (e) {\n return { ok: false, reason: 'build-throw', detail: errMsg(e), coverage: det.coverage };\n }\n\n let tResult: TranspileResult;\n try {\n tResult = transpile(dsl);\n } catch (e) {\n return { ok: false, reason: 'transpile-throw', detail: errMsg(e), coverage: det.coverage };\n }\n if (!tResult.ok) {\n return {\n ok: false,\n reason: 'transpile-fail',\n detail: tResult.errors.map((x) => `${x.code}:${x.message}`).join('; '),\n coverage: det.coverage,\n };\n }\n\n const vReport = verifyGeometry(intents, dsl);\n if (!vReport.ok) {\n return { ok: false, reason: 'verify-fail', coverage: det.coverage };\n }\n\n // Guard 1: tên xuất hiện/khai báo trong đề phải có trong DSL (chống drop construct).\n const named = allNamedEntitiesPresent(problem, dsl);\n if (!named.ok) {\n return { ok: false, reason: 'named-missing', detail: named.missing.join(','), coverage: det.coverage };\n }\n\n // Guard 2: add-point phái sinh phải dựng trung thành (không bị builder drop vì\n // trùng tên đỉnh sẵn có → điểm thực tế là 'free' thay vì construct).\n const fidelity = verifyIntentFidelity(intents, dsl);\n if (!fidelity.ok) {\n return { ok: false, reason: 'intent-dropped', detail: fidelity.dropped.join(','), coverage: det.coverage };\n }\n\n return {\n ok: true,\n figure: { intents, dsl, transpile: tResult, verify: vReport, coverage: det.coverage },\n };\n}\n\nfunction errMsg(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n","// src/stamps/geometry-2d/ai/deterministic/describeMiss.ts\n//\n// Dịch lý do deterministic miss (mã kỹ thuật) → câu tiếng Việt dễ hiểu cho\n// chế độ deterministicOnly (\"dùng tạm rule base, tắt LLM\"). Phân 2 nhóm để người\n// tối ưu rule base phân biệt ngay:\n// - \"chưa phủ\" (no-match / incomplete-coverage / named-missing) → CẦN THÊM RULE.\n// - \"rule khớp nhưng dựng lỗi\" (build/transpile/verify/intent-dropped) → có thể LỖI RULE.\n// Hàm thuần, không I/O — message này được gán vào IntentFailureResult.message và\n// nổi lên AiFigureUiResult để consumer (hoctotbachkhoa) hiển thị / ghi log.\nimport type { DeterministicReason } from './tryDeterministicFigure';\nimport type { CoverageReport } from './coverage';\n\nexport interface DeterministicMiss {\n reason: DeterministicReason;\n /** Chi tiết kỹ thuật theo reason (tên thiếu, mã lỗi transpile, …). */\n detail?: string;\n /** Báo cáo coverage — dùng `uncovered[].text` để nêu cụm đề chưa phủ. */\n coverage?: CoverageReport;\n}\n\n/** \", \" sau detail nếu có (else chuỗi rỗng) — tránh \"(undefined)\". */\nfunction detailSuffix(detail?: string): string {\n const d = detail?.trim();\n return d ? `: ${d}` : '';\n}\n\n/** \"D,E\" → \"D, E\" (thêm khoảng trắng sau phẩy cho dễ đọc). */\nfunction formatNames(detail?: string): string {\n const names = (detail ?? '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n return names.length > 0 ? names.join(', ') : 'một số đối tượng';\n}\n\nexport function describeDeterministicMiss(miss: DeterministicMiss): string {\n const { reason, detail, coverage } = miss;\n switch (reason) {\n // === Nhóm \"chưa phủ\" → cần bổ sung rule ===\n case 'no-match':\n return 'Rule base chưa nhận ra cấu trúc hình học nào trong đề (cần bổ sung rule cho dạng này).';\n case 'incomplete-coverage': {\n const parts = (coverage?.uncovered ?? []).map((c) => `«${c.text}»`);\n if (parts.length === 0) {\n return 'Rule base mới phủ được một phần đề (cần bổ sung rule cho phần còn lại).';\n }\n return `Rule base mới phủ được một phần đề. Chưa dựng được: ${parts.join('; ')} (cần bổ sung rule).`;\n }\n case 'named-missing':\n return `Đề nhắc tới ${formatNames(detail)} nhưng rule base chưa dựng được (cần bổ sung rule).`;\n\n // === Nhóm \"rule khớp nhưng dựng lỗi\" → có thể lỗi rule ===\n case 'build-throw':\n return `Rule đã khớp nhưng dựng hình thất bại — có thể lỗi rule${detailSuffix(detail)}.`;\n case 'transpile-throw':\n case 'transpile-fail':\n return `Rule đã khớp nhưng biên dịch hình lỗi — có thể lỗi rule${detailSuffix(detail)}.`;\n case 'verify-fail':\n return 'Rule dựng được hình nhưng sai kiểm tra hình học — có thể lỗi rule.';\n case 'intent-dropped':\n return `Rule khớp nhưng một số điểm phái sinh bị bỏ (${formatNames(detail)}) — có thể lỗi rule.`;\n\n default: {\n // Exhaustive guard: thêm reason mới mà quên xử lý → type error tại compile.\n const _never: never = reason;\n return `Rule base chưa dựng được (${String(_never)}).`;\n }\n }\n}\n","// src/stamps/geometry-2d/ai/buildFigureIntent.ts\n//\n// Deterministic-only figure builder (rule-base, KHÔNG LLM).\n// Track A: tryDeterministicFigure() — rule engine + 4 gate\n// (coverage / transpile / verify / named-entity).\n// Success → trả figure (intents + dsl + transpile + verify).\n// Miss → trả failure `deterministic_miss` kèm lý do (describeDeterministicMiss)\n// để người tối ưu rule base thấy phần đề chưa phủ. KHÔNG fallback LLM.\n//\n// Trả về IntentGenerateResult tương thích shape cũ để consumer dùng được.\n\nimport type { TranspileResult } from '../dsl';\nimport { intentsToDsl } from './intentToDsl';\nimport type { IntentT } from './intent';\nimport { type VerifyReport } from './verify';\nimport { tryDeterministicFigure } from './deterministic/tryDeterministicFigure';\nimport { describeDeterministicMiss } from './deterministic/describeMiss';\n\nconst ZERO_USAGE: IntentTokenUsage = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n};\n\nexport interface GenerateIntentOptions {\n signal?: AbortSignal;\n}\n\nexport interface IntentTokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n}\n\nexport interface IntentSuccessResult {\n ok: true;\n intents: readonly IntentT[];\n dsl: ReturnType<typeof intentsToDsl>;\n transpile: Extract<TranspileResult, { ok: true }>;\n verify: VerifyReport;\n usage: IntentTokenUsage;\n provider: string;\n}\n\nexport interface IntentFailureResult {\n ok: false;\n reason:\n | 'builder_error'\n | 'transpile_error'\n | 'verify_error'\n | 'deterministic_miss';\n message: string;\n intents?: readonly IntentT[];\n dsl?: ReturnType<typeof intentsToDsl>;\n usage?: IntentTokenUsage;\n provider?: string;\n}\n\nexport type IntentGenerateResult = IntentSuccessResult | IntentFailureResult;\n\nexport async function generateFigureIntent(\n problem: string,\n _opts: GenerateIntentOptions = {},\n): Promise<IntentGenerateResult> {\n // === Track A: deterministic ===\n // Rule engine + 4 lớp gate (coverage/transpile/verify/named-entity). Đề dễ→trung\n // bình dựng tại đây, KHÔNG tốn token. Miss → trả deterministic_miss (KHÔNG LLM).\n const det = tryDeterministicFigure(problem);\n if (det.ok) {\n return {\n ok: true,\n intents: det.figure.intents,\n dsl: det.figure.dsl,\n transpile: det.figure.transpile,\n verify: det.figure.verify,\n usage: ZERO_USAGE,\n provider: 'deterministic',\n };\n }\n\n // Miss → trả failure kèm lý do (det.reason) để người tối ưu rule base thấy gap.\n // (no-match / incomplete-coverage / transpile-fail / named-missing / verify-fail / …)\n return {\n ok: false,\n reason: 'deterministic_miss',\n message: describeDeterministicMiss(det),\n usage: ZERO_USAGE,\n provider: 'deterministic',\n };\n}\n","// Façade HTTP transport cho rule-engine intent pipeline (generateFigureIntent).\n// Map IntentGenerateResult → AiFigureUiResult ({ ok, state }) — shape mà\n// <Whiteboard generateGeometryFigure> + playground route dùng trực tiếp.\n//\n// 2026-06-09: repurpose từ path buildFigure (free-form DSL, đã xoá) sang intent\n// pipeline DETERMINISTIC-ONLY. generateFigureIntent chạy rule engine\n// (tryDeterministicFigure → 21 rule + 4 gate); miss → deterministic_miss (KHÔNG\n// LLM). Façade chỉ cần map kết quả. Contract AiFigureUiResult GIỮ NGUYÊN →\n// consumer (playground, hoctotbachkhoa) không phải đổi route.\n\nimport type { AiFigureUiResult } from '../../shared/types';\nimport {\n generateFigureIntent,\n type GenerateIntentOptions,\n type IntentGenerateResult,\n} from './buildFigureIntent';\n\nexport interface HandleGenerateFigureInput {\n /** Đề bài tiếng Việt từ teacher. */\n problem: string;\n}\n\nexport interface HandleGenerateFigureOptions extends GenerateIntentOptions {\n /**\n * Telemetry hook: gọi cho MỖI attempt với IntentGenerateResult nội bộ trước\n * khi map sang AiFigureUiResult — consumer dùng để log usage/cost/error.\n * Không throw từ logger (swallow để không vỡ response).\n *\n * @param result IntentGenerateResult của attempt\n * @param attempt 1-indexed (1 = lần đầu, 2 = retry, ...)\n */\n onResult?: (result: IntentGenerateResult, attempt: number) => void;\n /**\n * Số attempt tối đa khi build error (transpile/builder). Default 2 (1 retry).\n * Rule base deterministic → retry hiếm khi đổi kết quả, giữ để tương thích\n * contract cũ. Clamp [1,5].\n */\n maxAttempts?: number;\n}\n\nconst DEFAULT_MAX_ATTEMPTS = 2;\n\n/**\n * Gọi rule-engine intent pipeline và trả về `AiFigureUiResult` mà\n * `<Whiteboard generateGeometryFigure>` chấp nhận trực tiếp.\n *\n * Deterministic rule base chạy trong `generateFigureIntent` — đề dễ→trung bình\n * dựng KHÔNG tốn token. Miss → `deterministic_miss` (KHÔNG LLM fallback).\n *\n * Auto-retry: chỉ retry khi `transpile_error`/`builder_error`. KHÔNG retry\n * `deterministic_miss` (rule base ổn định, retry vô nghĩa).\n *\n * Server-side caller giữ `IntentGenerateResult` đầy đủ qua `onResult` cho\n * telemetry/logging.\n */\nexport async function handleGenerateFigure(\n input: HandleGenerateFigureInput,\n opts: HandleGenerateFigureOptions = {},\n): Promise<AiFigureUiResult> {\n if (!input.problem.trim()) {\n return { ok: false, message: 'Đề bài rỗng' };\n }\n\n const { onResult, maxAttempts: rawMax, ...genOpts } = opts;\n const maxAttempts = clampAttempts(rawMax ?? DEFAULT_MAX_ATTEMPTS);\n\n let last: IntentGenerateResult | null = null;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const r = await generateFigureIntent(input.problem, genOpts);\n last = r;\n if (onResult) {\n try { onResult(r, attempt); } catch { /* swallow telemetry errors */ }\n }\n if (r.ok) return { ok: true, state: r.transpile.state };\n if ((r.reason === 'transpile_error' || r.reason === 'builder_error') && attempt < maxAttempts) {\n continue;\n }\n break;\n }\n return mapErrorToUi(last!);\n}\n\nfunction clampAttempts(n: number): number {\n if (!Number.isFinite(n)) return DEFAULT_MAX_ATTEMPTS;\n return Math.max(1, Math.min(5, Math.floor(n)));\n}\n\nfunction mapErrorToUi(result: IntentGenerateResult): AiFigureUiResult {\n if (result.ok) return { ok: true, state: result.transpile.state };\n\n switch (result.reason) {\n case 'builder_error':\n case 'transpile_error':\n case 'verify_error':\n return {\n ok: false,\n message:\n 'Không dựng được hình (đã thử lại). Vui lòng tách thành 1 yêu cầu/lần hoặc diễn đạt khác.',\n };\n case 'deterministic_miss':\n default:\n // Rule base chưa phủ đề này: `message` đã là câu tiếng Việt dễ hiểu từ\n // describeDeterministicMiss (nêu rõ cần bổ sung rule / có thể lỗi rule +\n // phần đề chưa phủ) → trả thẳng cho UI/log, không bọc jargon.\n return { ok: false, message: result.message };\n }\n}\n","// src/stamps/geometry-2d/ai/envelope.ts\n//\n// Envelope schema cho figure build I/O:\n// { decision: 'build', figure: <DslInput> }\n// { decision: 'refuse', reason: '...' }\n//\n// 1 schema, parse + validate ở 1 chỗ. Giữ cho advanced consumer muốn dùng\n// envelope build-side (FigureEnvelopeZ + envelopeBuildDsl) trực tiếp.\n\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { DslInput, type DslInputT } from '../dsl';\n\nexport const FigureEnvelopeZ = z\n .object({\n decision: z.enum(['build', 'refuse']),\n // figure: DslInput khi build; bỏ qua khi refuse.\n figure: DslInput.optional(),\n // reason: lý do từ chối (Việt) khi refuse; bỏ qua khi build.\n reason: z.string().optional(),\n })\n .refine(\n (e) => (e.decision === 'build' ? e.figure != null : e.reason != null && e.reason.length > 0),\n {\n message:\n 'decision=build cần `figure`; decision=refuse cần `reason` không rỗng',\n },\n );\n\nexport type FigureEnvelopeT = z.infer<typeof FigureEnvelopeZ>;\n\n// JSON Schema bản phẳng cho consumer cần schema constraint.\n// Note: refine() chỉ run ở Zod runtime; JSON Schema không representable.\n// Validate qua FigureEnvelopeZ để bắt vi phạm refine.\nexport function envelopeJsonSchema(): Record<string, unknown> {\n return zodToJsonSchema(FigureEnvelopeZ, {\n target: 'jsonSchema7',\n $refStrategy: 'none',\n }) as Record<string, unknown>;\n}\n\n/** Helper: ép envelope build hợp lệ về DslInputT (sau khi đã validate). */\nexport function envelopeBuildDsl(env: FigureEnvelopeT): DslInputT {\n if (env.decision !== 'build' || env.figure == null) {\n throw new Error('envelopeBuildDsl: envelope không phải decision=build hoặc thiếu figure');\n }\n // Zod infer cho DslInput rộng `{[x: string]: any}[]` (discriminatedUnion từ\n // registry với schemas erased `ZodObject<any>`); runtime parse đã validate,\n // safe widen sang DslInputT (xem comment trong schema.ts).\n return env.figure as unknown as DslInputT;\n}\n","// src/stamps/geometry-2d/ai/intent.ts\n//\n// Intent schema — replacement for free-form DSL output.\n//\n// AI emit Intent[] thay vì DSL trực tiếp. Mỗi Intent là 1 \"lệnh vẽ\" cấp\n// semantic (\"vẽ tam giác đều ABC\", \"thêm trung điểm M của BC\"). Builder\n// (intentToDsl.ts) deterministic dịch Intent → DSL với canonical coords.\n//\n// Lợi ích:\n// - AI chỉ làm NLU (đọc-tách-lệnh), không tự đặt coord → 0% hallucinate coord\n// - Variant enum loại bỏ \"tam giác vuông tại A nhưng coord vuông tại B\"\n// - Schema explicit slot cho augmentations → guard \"không thừa\"\n\nimport { z } from 'zod';\n\n// Tên label/point — alphanumeric, 1-8 chars, không trùng kind enum.\nexport const LabelZ = z.string().min(1).max(8).regex(/^[A-Za-z][A-Za-z0-9'_]*$/);\n\n// ---------------------------------------------------------------------------\n// Shape variants per shape type\n// ---------------------------------------------------------------------------\n\n// triangle variants\nexport const TriangleVariantZ = z.enum([\n 'any', // tam giác bất kỳ (scalene cố định)\n 'equilateral', // tam giác đều\n 'isoceles-AB', // cân tại C (AB đáy)\n 'isoceles-BC', // cân tại A (BC đáy)\n 'isoceles-CA', // cân tại B (CA đáy)\n 'right-at-A', // vuông tại A\n 'right-at-B', // vuông tại B\n 'right-at-C', // vuông tại C\n]);\n\nexport const QuadVariantZ = z.enum([\n 'any', // tứ giác bất kỳ\n]);\n\nexport const SquareVariantZ = z.enum([\n 'standard', // canonical\n]);\n\nexport const RectangleVariantZ = z.enum([\n 'wide', // mặc định 4×2.5\n 'tall', // 2.5×4\n]);\n\nexport const RhombusVariantZ = z.enum([\n 'standard', // canonical (diagonals 4,2)\n]);\n\nexport const TrapezoidVariantZ = z.enum([\n 'right', // vuông\n 'isoceles', // cân\n 'general', // thường\n]);\n\nexport const ParallelogramVariantZ = z.enum([\n 'standard', // mặc định\n]);\n\n// ---------------------------------------------------------------------------\n// Intent ops\n// ---------------------------------------------------------------------------\n//\n// Note: zod's discriminatedUnion không cho phép duplicate discriminator value\n// (vd nhiều 'draw-shape' schemas khác nhau). Solution: flatten — mỗi op là 1\n// schema duy nhất với `shape` là enum, runtime check variant ∈ allowed-for-shape\n// trong builder. Đánh đổi: kém type-safety hơn variant-per-shape DSU, nhưng\n// schema flatter → JSON Schema rõ ràng hơn, không nested anyOf.\n\nconst ShapeNameZ = z.enum([\n 'triangle',\n 'square',\n 'rectangle',\n 'rhombus',\n 'trapezoid',\n 'parallelogram',\n 'quadrilateral',\n]);\n\n// Tất cả variant gộp 1 enum — runtime check ở builder.\nconst ShapeVariantZ = z.enum([\n // triangle\n 'any', 'equilateral',\n 'isoceles-AB', 'isoceles-BC', 'isoceles-CA',\n 'right-at-A', 'right-at-B', 'right-at-C',\n // square / rhombus / parallelogram\n 'standard',\n // rectangle\n 'wide', 'tall',\n // trapezoid\n 'right', 'isoceles', 'general',\n]);\n\n// op: draw-shape\nexport const DrawShapeIntentZ = z.object({\n op: z.literal('draw-shape'),\n shape: ShapeNameZ,\n labels: z.array(LabelZ).min(3).max(8),\n variant: ShapeVariantZ.default('any'),\n explicitCoords: z.record(LabelZ, z.tuple([z.number(), z.number()])).optional(),\n});\n\n// op: add-point\nexport const AddPointIntentZ = z.object({\n op: z.literal('add-point'),\n name: LabelZ,\n constraint: z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('midpoint'), of: z.string() }),\n z.object({ kind: z.literal('perpFoot'), from: LabelZ, onLine: z.string() }),\n z.object({ kind: z.literal('centroid'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({ kind: z.literal('circumcenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({ kind: z.literal('incenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({ kind: z.literal('orthocenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({\n kind: z.literal('intersection'),\n of: z.tuple([z.string(), z.string()]),\n branch: z.union([z.literal(0), z.literal(1)]).optional(),\n }),\n z.object({ kind: z.literal('onSegment'), of: z.string(), t: z.number().min(0).max(1).optional() }),\n z.object({ kind: z.literal('free'), at: z.tuple([z.number(), z.number()]).optional() }),\n // Điểm A nằm NGOÀI đường tròn `circle` (free external point) — builder đọc\n // tâm+bán kính của circle từ build state rồi đặt A free tại coord ngoài\n // circle. Unblock tangentFromExt render (đề \"Lấy A ngoài (O), kẻ 2 tiếp tuyến\").\n z.object({ kind: z.literal('externalToCircle'), circle: LabelZ }),\n // Điểm trên đường tròn `circle` tại góc `theta` (mặc định 0) — glider.\n // Dùng cho đường thẳng Simson (issue #47): P trên đường tròn ngoại tiếp.\n z.object({ kind: z.literal('onCircle'), circle: LabelZ, theta: z.number().optional() }),\n // NEW Tier 4+5\n z.object({ kind: z.literal('secondIntersection'), line: z.string(), circle: LabelZ, other: LabelZ }),\n z.object({ kind: z.literal('circleIntersection'), c1: LabelZ, c2: LabelZ, which: z.union([z.literal(0), z.literal(1)]) }),\n // Giao điểm THỨ HAI của 2 đường tròn, loại điểm chung `exclude` (đề \"đường\n // tròn đường kính AB, AC đôi một cắt nhau lần thứ hai\" — điểm chung A).\n z.object({ kind: z.literal('circleSecondIntersection'), c1: LabelZ, c2: LabelZ, exclude: LabelZ }),\n z.object({ kind: z.literal('tangencyPoint'), circle: LabelZ, onLine: z.string() }),\n z.object({ kind: z.literal('tangentPoint'), from: LabelZ, circle: LabelZ, which: z.union([z.literal(0), z.literal(1)]) }),\n z.object({ kind: z.literal('angleBisectorFoot'), from: LabelZ, onLine: z.string() }),\n // Phân giác NGOÀI: chân phân giác ngoài đỉnh `from` trên đường thẳng `onLine`\n // (phân giác ngoài ⊥ phân giác trong tại `from`). Issue #46 nhóm A.\n z.object({ kind: z.literal('externalAngleBisectorFoot'), from: LabelZ, onLine: z.string() }),\n // Cụm A\n z.object({ kind: z.literal('arcMidpoint'), circle: LabelZ, a: LabelZ, b: LabelZ, notContaining: LabelZ }),\n z.object({ kind: z.literal('reflectPoint'), of: LabelZ, through: LabelZ }),\n z.object({ kind: z.literal('reflectLine'), of: LabelZ, through: z.string() }),\n z.object({ kind: z.literal('excenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]), opposite: LabelZ }),\n // Góc vuông nhìn đoạn: M trên onLine sao cho ∠ a-name-b = 90°\n z.object({ kind: z.literal('rightAngleViewing'), a: LabelZ, b: LabelZ, onLine: z.string(), which: z.union([z.literal(0), z.literal(1)]).optional() }),\n z.object({\n kind: z.literal('pointAtDistance'),\n from: LabelZ,\n through: LabelZ,\n // scale/offset OPTIONAL (Issue #46 nhóm C): d = scale·base + offset.\n // scale > 0; absent → giữ d = base như cũ (additive).\n distance: z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('circleRadius'), circle: LabelZ, scale: z.number().positive().optional(), offset: z.number().optional() }),\n z.object({ kind: z.literal('segmentLength'), p1: LabelZ, p2: LabelZ, scale: z.number().positive().optional(), offset: z.number().optional() }),\n z.object({ kind: z.literal('literal'), value: z.number().positive(), scale: z.number().positive().optional(), offset: z.number().optional() }),\n ]),\n }),\n ]),\n});\n\n// op: connect\nexport const ConnectIntentZ = z.object({\n op: z.literal('connect'),\n from: LabelZ,\n to: LabelZ,\n style: z.enum([\n 'segment',\n 'line',\n 'ray',\n 'perpBisector',\n 'angleBisector',\n ]).default('segment'),\n});\n\n// op: draw-circle — single schema, spec là enum, points conditional\nexport const DrawCircleIntentZ = z.object({\n op: z.literal('draw-circle'),\n name: LabelZ,\n spec: z.enum(['centerThrough', 'through3', 'centerRadius', 'inscribedIn', 'diameter']),\n center: LabelZ.optional(),\n through: LabelZ.optional(),\n points: z.tuple([LabelZ, LabelZ, LabelZ]).optional(),\n // NEW Tier 4+5\n radius: z.number().positive().optional(),\n triangle: z.tuple([LabelZ, LabelZ, LabelZ]).optional(),\n // spec 'diameter' — đường tròn đường kính nối 2 đầu mút.\n endpoints: z.tuple([LabelZ, LabelZ]).optional(),\n});\n\n// op: draw-line\nexport const DrawLineIntentZ = z.object({\n op: z.literal('draw-line'),\n name: LabelZ,\n kind: z.enum(['perpThrough', 'parallelThrough', 'tangentAt', 'tangentFromExt', 'angleBisector', 'lineThrough', 'radicalAxis']),\n through: LabelZ.optional(),\n to: LabelZ.optional(),\n from: LabelZ.optional(),\n circle: LabelZ.optional(),\n which: z.enum(['first', 'second', 'both']).optional(),\n // lineThrough (đường qua ≥2 điểm đồng tuyến — vd Euler line G/H/O, issue #47).\n points: z.array(LabelZ).optional(),\n // radicalAxis (trục đẳng phương 2 đường tròn — issue #47, construct 2).\n circle1: LabelZ.optional(),\n circle2: LabelZ.optional(),\n // angleBisector (phân giác TRONG của góc ∠p1·vertex·p2, VISIBLE, không foot —\n // Issue #46 nhóm A). vertex = đỉnh góc.\n p1: LabelZ.optional(),\n vertex: LabelZ.optional(),\n p2: LabelZ.optional(),\n});\n\n// op: mark-shape (sub-shape từ điểm đã có, không tạo coord mới)\nexport const MarkShapeIntentZ = z.object({\n op: z.literal('mark-shape'),\n shape: z.enum(['triangle', 'quadrilateral']),\n labels: z.array(LabelZ).min(3).max(4),\n});\n\n// Master discriminated union — 6 variants theo op\nexport const IntentZ = z.discriminatedUnion('op', [\n DrawShapeIntentZ,\n AddPointIntentZ,\n ConnectIntentZ,\n DrawCircleIntentZ,\n DrawLineIntentZ, // NEW\n MarkShapeIntentZ, // NEW\n]);\n\n// Re-export variant enums cho consumer (vd UI dropdown)\nexport {\n TriangleVariantZ as TriangleVariants,\n SquareVariantZ as SquareVariants,\n RectangleVariantZ as RectangleVariants,\n RhombusVariantZ as RhombusVariants,\n TrapezoidVariantZ as TrapezoidVariants,\n ParallelogramVariantZ as ParallelogramVariants,\n QuadVariantZ as QuadVariants,\n};\n\nexport type IntentT = z.infer<typeof IntentZ>;\nexport type DrawShapeIntentT = z.infer<typeof DrawShapeIntentZ>;\nexport type AddPointIntentT = z.infer<typeof AddPointIntentZ>;\nexport type ConnectIntentT = z.infer<typeof ConnectIntentZ>;\nexport type DrawCircleIntentT = z.infer<typeof DrawCircleIntentZ>;\nexport type DrawLineIntentT = z.infer<typeof DrawLineIntentZ>;\nexport type MarkShapeIntentT = z.infer<typeof MarkShapeIntentZ>;\n\n// ---------------------------------------------------------------------------\n// Envelope — wraps intents[] + decision\n// ---------------------------------------------------------------------------\n\nexport const IntentEnvelopeZ = z\n .object({\n decision: z.enum(['build', 'refuse']),\n intents: z.array(IntentZ).optional(),\n reason: z.string().optional(),\n })\n .refine(\n (e) =>\n e.decision === 'build'\n ? Array.isArray(e.intents) && e.intents.length > 0\n : e.reason != null && e.reason.length > 0,\n {\n message:\n 'decision=build cần intents non-empty; decision=refuse cần reason',\n },\n );\n\nexport type IntentEnvelopeT = z.infer<typeof IntentEnvelopeZ>;\n","// src/stamps/geometry-2d/ai/intentEnvelope.ts\n//\n// JSON Schema helper cho Intent envelope (giữ cho advanced consumer cần\n// schema constraint). Refine() check ở Zod runtime; JSON Schema không representable.\n\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { IntentEnvelopeZ, type IntentEnvelopeT } from './intent';\nimport type { IntentT } from './intent';\n\nexport function intentEnvelopeJsonSchema(): Record<string, unknown> {\n return zodToJsonSchema(IntentEnvelopeZ, {\n target: 'jsonSchema7',\n $refStrategy: 'none',\n }) as Record<string, unknown>;\n}\n\nexport function envelopeIntentList(env: IntentEnvelopeT): readonly IntentT[] {\n if (env.decision !== 'build' || env.intents == null) {\n throw new Error(\n 'envelopeIntentList: envelope không phải decision=build hoặc thiếu intents',\n );\n }\n return env.intents;\n}\n","// src/stamps/geometry-2d/ai/intentPrompt.ts\n//\n// System prompt cho Intent extraction (Stage 1). AI chỉ làm NLU — đọc đề\n// (VN hoặc EN), tách thành Intent[]. KHÔNG sinh DSL, KHÔNG đặt tọa độ.\n//\n// Khác prompt cũ (prompt.ts):\n// - Output là `intents: Intent[]` thay vì `figure: DSL`\n// - Bilingual: ví dụ cả VN + EN\n// - Anti-pattern explicit: AI không tự thêm intent ngoài đề\n//\n// IntentEnvelopeZ.refine() guards build/refuse semantics.\n\nimport type { IntentT, IntentEnvelopeT } from './intent';\n\ninterface IntentFixture {\n problem: string;\n intents: IntentT[];\n}\n\n// Tier 0+1 sample fixtures (in-prompt examples).\n// Note: chỉ shape examples — augmentation examples thêm khi mở Tier 1.\nconst FIXTURES: IntentFixture[] = [\n {\n problem: 'Tam giác ABC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n ],\n },\n {\n problem: 'Tam giác đều ABC cạnh 4.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'equilateral' },\n ],\n },\n {\n problem: 'Tam giác ABC vuông tại A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'right-at-A' },\n ],\n },\n {\n problem: 'Hình vuông MNPQ.',\n intents: [\n { op: 'draw-shape', shape: 'square', labels: ['M', 'N', 'P', 'Q'], variant: 'standard' },\n ],\n },\n {\n problem: 'Hình chữ nhật ABCD.',\n intents: [\n { op: 'draw-shape', shape: 'rectangle', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n ],\n },\n // \"cân tại X\" → X là đỉnh cân, cạnh đối diện là đáy\n {\n problem: 'Tam giác ABC cân tại A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'isoceles-BC' },\n ],\n },\n {\n problem: 'Tam giác MNP cân tại N.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['M', 'N', 'P'], variant: 'isoceles-CA' },\n ],\n },\n {\n problem: 'Hình thoi ABCD.',\n intents: [\n { op: 'draw-shape', shape: 'rhombus', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n ],\n },\n {\n problem: 'Hình bình hành ABCD.',\n intents: [\n { op: 'draw-shape', shape: 'parallelogram', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n ],\n },\n {\n problem: 'Hình thang ABCD cân, AB là đáy lớn.',\n intents: [\n { op: 'draw-shape', shape: 'trapezoid', labels: ['A', 'B', 'C', 'D'], variant: 'isoceles' },\n ],\n },\n // Tier 1 examples\n {\n problem: 'Tam giác ABC, M là trung điểm BC, vẽ đoạn AM.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'M', constraint: { kind: 'midpoint', of: 'BC' } },\n { op: 'connect', from: 'A', to: 'M', style: 'segment' },\n ],\n },\n {\n problem: 'Tam giác ABC, H là chân đường cao từ A xuống BC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'H', constraint: { kind: 'perpFoot', from: 'A', onLine: 'BC' } },\n { op: 'connect', from: 'A', to: 'H', style: 'segment' },\n ],\n },\n {\n problem: 'Triangle ABC with M the midpoint of BC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'M', constraint: { kind: 'midpoint', of: 'BC' } },\n ],\n },\n {\n problem: 'Triangle ABC, G is the centroid.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'G', constraint: { kind: 'centroid', of: ['A', 'B', 'C'] } },\n ],\n },\n // Compound: triangle + circumcircle (cần CẢ HAI intent)\n {\n problem: 'Đường tròn đi qua 3 điểm A, B, C.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n ],\n },\n {\n problem: 'Tam giác ABC nội tiếp đường tròn O.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n ],\n },\n // Compound: parallelogram with diagonals + intersection\n {\n problem: 'Hình bình hành ABCD, hai đường chéo AC và BD cắt nhau tại O.',\n intents: [\n { op: 'draw-shape', shape: 'parallelogram', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n { op: 'connect', from: 'A', to: 'C', style: 'segment' },\n { op: 'connect', from: 'B', to: 'D', style: 'segment' },\n { op: 'add-point', name: 'O', constraint: { kind: 'intersection', of: ['AC', 'BD'] } },\n ],\n },\n // Build examples — đề có MỆNH LỆNH proof/tính NHƯNG mô tả hình → vẫn build\n {\n problem: 'Cho tam giác ABC vuông tại A. Chứng minh rằng AB² + AC² = BC².',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'right-at-A' },\n ],\n },\n {\n problem: 'Cho tứ giác ABCD nội tiếp (O). Chứng minh rằng AC.BD = AB.CD + AD.BC.',\n intents: [\n { op: 'draw-shape', shape: 'quadrilateral', labels: ['A', 'B', 'C', 'D'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n { op: 'connect', from: 'A', to: 'C', style: 'segment' },\n { op: 'connect', from: 'B', to: 'D', style: 'segment' },\n ],\n },\n // draw-line: perpThrough — đường vuông góc với LINE, đi qua POINT\n {\n problem: 'Tam giác ABC. Vẽ đường thẳng d vuông góc với AB tại B.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-line', name: 'd', kind: 'perpThrough', through: 'B', to: 'AB' },\n ],\n },\n // draw-line: tangentAt — tiếp tuyến TẠI POINT trên CIRCLE\n {\n problem: 'Tam giác ABC nội tiếp đường tròn (O). Vẽ tiếp tuyến tại A của (O).',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n { op: 'draw-line', name: 'tA', kind: 'tangentAt', through: 'A', circle: 'O' },\n ],\n },\n // draw-line: tangentFromExt — tiếp tuyến TỪ POINT ngoài CIRCLE (chọn nhánh)\n {\n problem: 'Cho đường tròn (O) và điểm P ngoài đường tròn. Vẽ hai tiếp tuyến PT₁ và PT₂ từ P tới (O).',\n intents: [\n { op: 'draw-circle', name: 'O', spec: 'centerRadius', center: 'O', radius: 3 },\n { op: 'add-point', name: 'P', constraint: { kind: 'free' } },\n { op: 'draw-line', name: 'PT1', kind: 'tangentFromExt', from: 'P', circle: 'O', which: 'first' },\n { op: 'draw-line', name: 'PT2', kind: 'tangentFromExt', from: 'P', circle: 'O', which: 'second' },\n ],\n },\n // Refuse examples — đề THUẦN tính / KHÔNG mô tả hình hình học\n {\n problem: 'Tính sin(30°) + cos(60°).',\n intents: [],\n },\n {\n problem: 'Vẽ con mèo.',\n intents: [],\n },\n {\n problem: 'Giải phương trình x² - 5x + 6 = 0.',\n intents: [],\n },\n {\n problem: 'Tam giác ABC nội tiếp (O). M là trung điểm cung BC không chứa A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n { op: 'add-point', name: 'M', constraint: { kind: 'arcMidpoint', circle: 'O', a: 'B', b: 'C', notContaining: 'A' } },\n ],\n },\n {\n problem: 'Tam giác ABC trực tâm H. D là điểm đối xứng của H qua BC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'H', constraint: { kind: 'orthocenter', of: ['A', 'B', 'C'] } },\n { op: 'add-point', name: 'D', constraint: { kind: 'reflectLine', of: 'H', through: 'BC' } },\n ],\n },\n {\n problem: 'Tam giác ABC, J là tâm bàng tiếp góc A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'J', constraint: { kind: 'excenter', of: ['A', 'B', 'C'], opposite: 'A' } },\n ],\n },\n {\n problem: 'Cho tam giác nhọn ABC, đường cao CK, H là trực tâm. Gọi M là một điểm trên CK sao cho góc AMB = 90°.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'K', constraint: { kind: 'perpFoot', from: 'C', onLine: 'AB' } },\n { op: 'add-point', name: 'H', constraint: { kind: 'orthocenter', of: ['A', 'B', 'C'] } },\n { op: 'connect', from: 'C', to: 'K', style: 'segment' },\n { op: 'add-point', name: 'M', constraint: { kind: 'rightAngleViewing', a: 'A', b: 'B', onLine: 'CK' } },\n ],\n },\n {\n problem: 'Cho đoạn AB và đường thẳng d. Điểm M trên d sao cho góc AMB = 90°.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'D'], variant: 'any' },\n { op: 'add-point', name: 'M', constraint: { kind: 'rightAngleViewing', a: 'A', b: 'B', onLine: 'd' } },\n ],\n },\n];\n\nexport function buildIntentSystemPrompt(): string {\n const examples = FIXTURES.map((f, i) => {\n const envelope: IntentEnvelopeT =\n f.intents.length > 0\n ? { decision: 'build', intents: f.intents }\n : { decision: 'refuse', reason: 'Đề không phải hình học — không vẽ được hình.' };\n return `### Ví dụ ${i + 1}\n**Đề:** ${f.problem}\n**Output:**\n${JSON.stringify(envelope, null, 2)}`;\n }).join('\\n\\n');\n\n return `Bạn là trợ lý tách lệnh vẽ hình học 2D cho học sinh THCS / lớp 10.\nChấp nhận đề bài tiếng Việt HOẶC tiếng Anh.\n\n## Nhiệm vụ\nĐọc đề → tách thành danh sách \"intents\" (lệnh vẽ cấp cao). KHÔNG sinh tọa độ,\nKHÔNG sinh DSL chi tiết — chỉ tách lệnh.\n\n## Output format (CHỈ JSON, KHÔNG markdown, KHÔNG text khác)\n{ \"decision\": \"build\", \"intents\": [ ... ] }\nhoặc\n{ \"decision\": \"refuse\", \"reason\": \"lý do tiếng Việt\" }\n\n## Quy tắc tuyệt đối\n\n1. **MỘT intent = MỘT đối tượng nêu trong đề.** Đề nói gì, emit intent đó.\n KHÔNG tự thêm trung tuyến/đường cao/tâm nếu đề không nói.\n\n2. **Shape variant phải khớp đề:**\n - \"đều\" → variant: \"equilateral\"\n - \"vuông tại X\" → variant: \"right-at-X\" (X là label đầu tiên trong labels[] khớp đề)\n - \"cân tại X\" — X là ĐỈNH CÂN, base là cạnh đối diện:\n * \"tam giác ABC cân tại A\" → variant: \"isoceles-BC\" (BC là đáy, A là apex)\n * \"tam giác MNP cân tại N\" → variant: \"isoceles-CA\" (CA là đáy theo canonical position)\n * Rule: variant đặt tên theo position trong labels[], KHÔNG phải tên literal.\n apex ở position 0 → \"isoceles-BC\"; position 1 → \"isoceles-CA\"; position 2 → \"isoceles-AB\".\n - không có từ khoá đặc biệt → variant: \"any\"\n\n3. **Labels phải đúng đề:** \"tam giác MNP\" → labels: [\"M\",\"N\",\"P\"], không tự đổi sang ABC.\n\n4. **Augmentations (Tier 1) dùng add-point + connect:**\n - \"M trung điểm BC\" → add-point name=M, constraint=midpoint of=BC\n - \"H chân đường cao từ A xuống BC\" → add-point name=H, constraint=perpFoot from=A onLine=BC\n - \"vẽ đoạn AM\" → connect from=A to=M\n - Trọng tâm/tâm ngoại/nội/trực tâm → add-point constraint=centroid/circumcenter/incenter/orthocenter\n\n5. **KHÔNG bịa.** Nếu đề mơ hồ hoặc không thuộc hình học 2D phổ thông → decision=refuse.\n\n6. **Đặt tên draw-circle**: nếu đề có ký hiệu rõ ràng \"(X)\" (vd \"(O)\", \"(I)\", \"(I1)\") → dùng đúng ký hiệu đó làm name. KHÔNG thêm hậu tố như \"Ic\", \"In\", \"Oc\". Nếu đề không có ký hiệu thì name tự do (preprocessor xử lý mọi collision).\n\n7. **Mệnh lệnh \"Chứng minh\" / \"Tính\" / \"Tìm\" / \"Hỏi\" KHÔNG ảnh hưởng quyết định build/refuse.** Quyết định CHỈ dựa vào việc đề có MÔ TẢ hình vẽ được hay không. Nếu đề bắt đầu / kết thúc bằng \"Chứng minh rằng …\" hoặc \"Tính …\" nhưng phần MÔ TẢ (giả thiết) có hình (tam giác, tứ giác, đường tròn, giao điểm …) → vẫn decision=build, vẽ phần giả thiết. KẾT QUẢ proof / phép tính KHÔNG cần biểu diễn. Chỉ refuse khi đề THUẦN tính / đại số không kèm mô tả hình (vd \"Tính sin(30°)+cos(60°)\", \"Giải x²-5x+6=0\").\n\n## Variant enum (chỉ dùng giá trị này)\n- triangle: any | equilateral | isoceles-AB | isoceles-BC | isoceles-CA | right-at-A | right-at-B | right-at-C\n- square: standard\n- rectangle: standard (default) | wide | tall\n- rhombus: standard\n- trapezoid: right | isoceles | general\n- parallelogram: standard\n- quadrilateral: any\n\n## Constraint kinds (cho add-point)\nmidpoint, perpFoot, centroid, circumcenter, incenter, orthocenter, intersection, onSegment, free, secondIntersection, circleIntersection, tangencyPoint, tangentPoint, angleBisectorFoot, externalAngleBisectorFoot, arcMidpoint, reflectPoint, reflectLine, excenter, rightAngleViewing, pointAtDistance\n\n## Style enum (cho connect)\nsegment, line, ray, perpBisector\n\n## draw-line — phân biệt field theo kind (RẤT QUAN TRỌNG, dễ sai)\n\ndraw-line dùng cho 4 loại đường thẳng đặc biệt. Mỗi kind có schema field khác\nnhau — đặt đúng field, KHÔNG bỏ field bắt buộc, KHÔNG nhầm POINT với LINE:\n\n- **perpThrough** — đường vuông góc với một đường thẳng, đi qua một điểm.\n Fields: \\`through\\` (POINT), \\`to\\` (LINE — ≥2 chữ, vd \"AB\", \"BC\").\n - Ví dụ: \"Đường vuông góc với AB tại B\" → \\`{kind:\"perpThrough\", through:\"B\", to:\"AB\"}\\`.\n - **SAI**: \\`{through:\"B\", to:\"A\"}\\` (A là 1 chữ → POINT, không phải LINE).\n - Nếu đề chỉ nói \"vuông góc với AB\" thì \\`to:\"AB\"\\` (2 chữ); KHÔNG đặt \\`to:\"A\"\\` hay \\`to:\"B\"\\`.\n\n- **parallelThrough** — đường song song với LINE, đi qua POINT. Field giống\n perpThrough: \\`through\\` (POINT), \\`to\\` (LINE 2+ chữ).\n - Ví dụ: \"qua M kẻ đường song song với BC\" → \\`{kind:\"parallelThrough\", through:\"M\", to:\"BC\"}\\`.\n\n- **tangentAt** — tiếp tuyến TẠI điểm trên đường tròn.\n Fields: \\`through\\` (POINT, phải nằm TRÊN circle), \\`circle\\` (CIRCLE name).\n - Ví dụ: \"Tiếp tuyến tại A của (O)\" → \\`{kind:\"tangentAt\", through:\"A\", circle:\"O\"}\\`.\n - KHÔNG dùng \\`from\\` ở đây — chỉ tangentFromExt mới dùng \\`from\\`.\n\n- **tangentFromExt** — tiếp tuyến TỪ điểm NGOÀI đường tròn (có 2 nhánh).\n Fields: \\`from\\` (POINT, ngoài circle), \\`circle\\` (CIRCLE), \\`which\\` ('first'|'second'|'both').\n - Ví dụ: \"Vẽ tiếp tuyến PA và PB từ P\" → 2 intent với \\`which:\"first\"\\` và \\`which:\"second\"\\`.\n\n## Cụm A — constraint hình học nâng cao (đặt ĐÚNG field)\n\n- **arcMidpoint** — trung điểm CUNG. Fields: \\`circle\\` (tên đường tròn), \\`a\\`, \\`b\\` (2 đầu cung), \\`notContaining\\` (đỉnh KHÔNG nằm trên cung đó).\n - Ví dụ: \"M là trung điểm cung BC không chứa A của (O)\" → \\`{kind:\"arcMidpoint\", circle:\"O\", a:\"B\", b:\"C\", notContaining:\"A\"}\\`.\n - LƯU Ý: phải có draw-circle tạo \\`circle\\` trước (vd đường tròn ngoại tiếp → spec:\"through3\", points:[A,B,C]).\n\n- **reflectPoint** — đối xứng qua một ĐIỂM. Fields: \\`of\\` (điểm gốc), \\`through\\` (tâm đối xứng, 1 chữ = POINT).\n - Ví dụ: \"Q đối xứng P qua trung điểm M\" → \\`{kind:\"reflectPoint\", of:\"P\", through:\"M\"}\\`.\n\n- **reflectLine** — đối xứng qua một ĐƯỜNG. Fields: \\`of\\` (điểm gốc), \\`through\\` (đường, 2 chữ = LINE vd \"BC\").\n - Ví dụ: \"D đối xứng H qua BC\" → \\`{kind:\"reflectLine\", of:\"H\", through:\"BC\"}\\`.\n\n- **excenter** — tâm BÀNG tiếp tam giác. Fields: \\`of\\` ([A,B,C]), \\`opposite\\` (đỉnh đối diện).\n - Ví dụ: \"J là tâm bàng tiếp góc A của tam giác ABC\" → \\`{kind:\"excenter\", of:[\"A\",\"B\",\"C\"], opposite:\"A\"}\\`.\n - KHÁC incenter (tâm NỘI tiếp): bàng tiếp nằm NGOÀI tam giác.\n\n- **rightAngleViewing** — điểm GÓC VUÔNG nhìn đoạn. Fields: \\`a\\`, \\`b\\` (2 mút đoạn), \\`onLine\\` (đường điểm nằm trên), \\`which\\` (0|1, optional — chọn giao điểm).\n - Dùng khi: \"M trên <đường> sao cho góc AMB = 90°\" / \"∠AMB = 90°\" / \"góc AMB vuông\" / \"MA ⊥ MB\" / \"M nhìn AB dưới góc vuông\".\n - Chữ GIỮA của góc = tên điểm (name); 2 chữ ngoài = \\`a\\`, \\`b\\`.\n - Ví dụ: \"M trên CK sao cho góc AMB = 90°\" → \\`{op:\"add-point\", name:\"M\", constraint:{kind:\"rightAngleViewing\", a:\"A\", b:\"B\", onLine:\"CK\"}}\\`.\n - KHÔNG tự tạo đường tròn phụ — chỉ phát ra constraint này, hệ thống tự dựng đường tròn đường kính AB (Thales).\n- **pointAtDistance** — điểm trên TIA kéo dài, cách mốc một khoảng cho trước. Fields: \\`from\\` (điểm gốc của tia), \\`through\\` (điểm mốc — điểm mới nằm BÊN NGOÀI \\`through\\` trên tia from→through), \\`distance\\` — một trong:\n - \\`{kind:\"circleRadius\", circle:\"O\"}\\` = bán kính R của đường tròn (O)\n - \\`{kind:\"segmentLength\", p1:\"O\", p2:\"A\"}\\` = độ dài đoạn OA\n - \\`{kind:\"literal\", value:2}\\` = số đo cho sẵn\n - Ví dụ: \"Kéo dài AB về phía B, lấy C sao cho BC = R của (O)\" → \\`{op:\"add-point\", name:\"C\", constraint:{kind:\"pointAtDistance\", from:\"A\", through:\"B\", distance:{kind:\"circleRadius\", circle:\"O\"}}}\\`.\n - Ví dụ: \"Trên tia đối của tia BA lấy D sao cho BD = AB\" (hướng từ B ra xa A) → \\`{op:\"add-point\", name:\"D\", constraint:{kind:\"pointAtDistance\", from:\"A\", through:\"B\", distance:{kind:\"segmentLength\", p1:\"A\", p2:\"B\"}}}\\`.\n - KHÁC reflectPoint (cho 2·through−from, không cần distance) và onSegment (nằm GIỮA hai điểm, t∈[0,1]).\n\n## Quy ước LINE name\n- 2 ký tự viết liền = SEGMENT/LINE qua 2 điểm: \"AB\", \"BC\", \"MN\" → \\`to: \"AB\"\\`.\n- 1 ký tự = POINT, KHÔNG dùng cho field \\`to\\` của perpThrough/parallelThrough.\n- Nếu đề chỉ nêu 2 điểm và bạn cần đường thẳng qua chúng, gọi nó là \"AB\"\n (alphabet order canonical), KHÔNG cần emit connect intent riêng — builder\n tự suy ra đoạn.\n\n---\n\n# ${FIXTURES.length} ví dụ\n\n${examples}\n`;\n}\n","// src/stamps/geometry-2d/ai/handleGenerateFigureIntent.ts\n//\n// Façade cho HTTP transport — wrap generateFigureIntent với error mapping\n// tới AiFigureIntentUiResult (pattern giống handleGenerateFigure cũ).\n\nimport { generateFigureIntent, type GenerateIntentOptions } from './buildFigureIntent';\nimport type { IntentT } from './intent';\nimport type { DslInputT } from '../dsl/schema';\n\nexport interface HandleGenerateFigureIntentOptions extends GenerateIntentOptions {}\n\nexport interface HandleGenerateFigureIntentInput {\n problem: string;\n}\n\nexport type AiFigureIntentUiResult =\n | {\n kind: 'success';\n dsl: DslInputT;\n intents: readonly IntentT[];\n svg?: string;\n usage: { inputTokens: number; outputTokens: number };\n }\n | {\n kind: 'refused';\n message: string;\n }\n | {\n kind: 'error';\n code: string;\n message: string;\n };\n\nexport async function handleGenerateFigureIntent(\n problem: string,\n opts: HandleGenerateFigureIntentOptions = {},\n): Promise<AiFigureIntentUiResult> {\n try {\n const r = await generateFigureIntent(problem, opts);\n if (r.ok) {\n return {\n kind: 'success',\n dsl: r.dsl,\n intents: r.intents,\n usage: {\n inputTokens: r.usage.inputTokens,\n outputTokens: r.usage.outputTokens,\n },\n };\n }\n return { kind: 'error', code: r.reason, message: r.message };\n } catch (e) {\n return {\n kind: 'error',\n code: 'unexpected',\n message: e instanceof Error ? e.message : String(e),\n };\n }\n}\n","// src/stamps/geometry-2d/ai/mergeIntents.ts\n//\n// Hybrid partial-coverage (Phase 1): gộp intent deterministic + intent LLM bù\n// phần clause chưa phủ. Hai quy tắc:\n// 1. Dedup exact (cùng JSON).\n// 2. Deterministic SỞ HỮU tên (đỉnh draw-shape / name add-point/draw-circle/\n// draw-line) → LLM KHÔNG được định nghĩa lại tên đó (drop bản LLM, det thắng).\n// intent tham chiếu (connect…) KHÔNG sở hữu tên → luôn giữ.\n//\n// Det luôn đứng trước, LLM (đã lọc) nối sau — giữ thứ tự dựng.\nimport type { IntentT } from './intent';\n\n/** Tên mà 1 intent ĐỊNH NGHĨA (tạo mới). connect/ref → [] (chỉ tham chiếu). */\nfunction intentOwnedNames(intent: IntentT): string[] {\n const i = intent as unknown as { op: string; labels?: unknown; name?: unknown };\n if (i.op === 'draw-shape') {\n return Array.isArray(i.labels) ? (i.labels as string[]) : [];\n }\n // add-point / draw-circle / draw-line đều có `name` định danh entity mới.\n if (typeof i.name === 'string') return [i.name];\n return [];\n}\n\n/**\n * Gộp intent deterministic (det) + intent LLM bù (llm). Det giữ nguyên; mỗi\n * intent LLM bị loại nếu: trùng JSON với intent đã có, HOẶC định nghĩa lại tên\n * mà det đã sở hữu (det thắng — phần deterministic đã đúng, đừng để LLM ghi đè).\n */\nexport function mergeIntents(det: readonly IntentT[], llm: readonly IntentT[]): IntentT[] {\n const detOwned = new Set<string>();\n for (const i of det) for (const n of intentOwnedNames(i)) detOwned.add(n);\n\n const seen = new Set<string>(det.map((i) => JSON.stringify(i)));\n const out: IntentT[] = [...det];\n\n for (const i of llm) {\n const key = JSON.stringify(i);\n if (seen.has(key)) continue; // trùng exact\n const owned = intentOwnedNames(i);\n if (owned.some((n) => detOwned.has(n))) continue; // redefine tên det → drop\n seen.add(key);\n out.push(i);\n }\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/stamps/geometry-2d/ai/deterministic/vocabulary.ts","../src/stamps/geometry-2d/ai/deterministic/coverage.ts","../src/stamps/geometry-2d/ai/rules/_shared.ts","../src/stamps/geometry-2d/ai/rules/triangle.ts","../src/stamps/geometry-2d/ai/rules/quad.ts","../src/stamps/geometry-2d/ai/rules/connect.ts","../src/stamps/geometry-2d/ai/rules/midpoint.ts","../src/stamps/geometry-2d/ai/rules/perpBisector.ts","../src/stamps/geometry-2d/ai/rules/cevian.ts","../src/stamps/geometry-2d/ai/rules/angleBisectorAngle.ts","../src/stamps/geometry-2d/ai/rules/centers.ts","../src/stamps/geometry-2d/ai/rules/perpFoot.ts","../src/stamps/geometry-2d/ai/rules/circleRadius.ts","../src/stamps/geometry-2d/ai/rules/circleTriangle.ts","../src/stamps/geometry-2d/ai/rules/tangentFromExt.ts","../src/stamps/geometry-2d/ai/rules/externalPoint.ts","../src/stamps/geometry-2d/ai/rules/arcMidpoint.ts","../src/stamps/geometry-2d/ai/rules/excenter.ts","../src/stamps/geometry-2d/ai/rules/parallelPerp.ts","../src/stamps/geometry-2d/ai/rules/reflection.ts","../src/stamps/geometry-2d/ai/rules/pointAtDistance.ts","../src/stamps/geometry-2d/ai/rules/eulerLine.ts","../src/stamps/geometry-2d/ai/rules/radicalAxis.ts","../src/stamps/geometry-2d/ai/rules/simson.ts","../src/stamps/geometry-2d/ai/rules/ninePoint.ts","../src/stamps/geometry-2d/ai/rules/diameterCirclePairwise.ts","../src/stamps/geometry-2d/ai/rules/angleBisectorFoot.ts","../src/stamps/geometry-2d/ai/rules/intersection.ts","../src/stamps/geometry-2d/ai/rules/chord.ts","../src/stamps/geometry-2d/ai/rules/incircleTangency.ts","../src/stamps/geometry-2d/ai/rules/altitudeDiameterCircles.ts","../src/stamps/geometry-2d/ai/rules/diameterCircleCutsSides.ts","../src/stamps/geometry-2d/ai/rules/circleDiameter.ts","../src/stamps/geometry-2d/ai/rules/onCirclePoint.ts","../src/stamps/geometry-2d/ai/rules/tangentAt.ts","../src/stamps/geometry-2d/ai/rules/onSegmentPoint.ts","../src/stamps/geometry-2d/ai/rules/lineCircleIntersection.ts","../src/stamps/geometry-2d/ai/rules/incenterNamedTriangle.ts","../src/stamps/geometry-2d/ai/rules/perpThroughCutsLines.ts","../src/stamps/geometry-2d/ai/rules/tangentRay.ts","../src/stamps/geometry-2d/ai/rules/pointOnTangentRay.ts","../src/stamps/geometry-2d/ai/rules/pointOnTangentAt.ts","../src/stamps/geometry-2d/ai/rules/intersectRay.ts","../src/stamps/geometry-2d/ai/rules/tangentFromPointAt.ts","../src/stamps/geometry-2d/ai/rules/perpLineTakePoint.ts","../src/stamps/geometry-2d/ai/rules/pairSecondIntersection.ts","../src/stamps/geometry-2d/ai/rules/circleCenterRadiusSegment.ts","../src/stamps/geometry-2d/ai/rules/perpDiameters.ts","../src/stamps/geometry-2d/ai/rules/perpLineCutsTangent.ts","../src/stamps/geometry-2d/ai/rules/perpChordThroughPoint.ts","../src/stamps/geometry-2d/ai/rules/polygonInscribedCircle.ts","../src/stamps/geometry-2d/ai/rules/perpAtPointCutsLine.ts","../src/stamps/geometry-2d/ai/rules/tangentAtCutsLines.ts","../src/stamps/geometry-2d/ai/rules/diameterEndpoint.ts","../src/stamps/geometry-2d/ai/rules/circleThroughTwoCutsSides.ts","../src/stamps/geometry-2d/ai/rules/circumcircleNamedDistrib.ts","../src/stamps/geometry-2d/ai/rules/circumcirclePairMeet.ts","../src/stamps/geometry-2d/ai/rules/tangentCircleAtPoint.ts","../src/stamps/geometry-2d/ai/rules/externalBisectorCutsLines.ts","../src/stamps/geometry-2d/ai/rules/tangentTwoSidesCircle.ts","../src/stamps/geometry-2d/ai/rules/interiorPoint.ts","../src/stamps/geometry-2d/ai/rules/parallelCutsTangentAt.ts","../src/stamps/geometry-2d/ai/rules/inExCircleTangentBC.ts","../src/stamps/geometry-2d/ai/rules/tangentPointsFromExt.ts","../src/stamps/geometry-2d/ai/rules/circleExternalPoint.ts","../src/stamps/geometry-2d/ai/rules/tangentNamedFromExt.ts","../src/stamps/geometry-2d/ai/rules/secant.ts","../src/stamps/geometry-2d/ai/rules/oppositeRayPoint.ts","../src/stamps/geometry-2d/ai/rules/perpChordAtFoot.ts","../src/stamps/geometry-2d/ai/rules/diameterCircleSecant.ts","../src/stamps/geometry-2d/ai/rules/tangentsAtMeet.ts","../src/stamps/geometry-2d/ai/rules/angleBisectorCutsSideCircle.ts","../src/stamps/geometry-2d/ai/rules/circleCutsArcSecond.ts","../src/stamps/geometry-2d/ai/rules/angleBisectorCutsCircleLine.ts","../src/stamps/geometry-2d/ai/rules/tangentLineNamedAtPoint.ts","../src/stamps/geometry-2d/ai/rules/givenDiameterCircle.ts","../src/stamps/geometry-2d/ai/rules/multiDiameterCircles.ts","../src/stamps/geometry-2d/ai/rules/cutCirclesDistrib.ts","../src/stamps/geometry-2d/ai/rules/givenNamedCircle.ts","../src/stamps/geometry-2d/ai/rules/twoPerpLinesMeet.ts","../src/stamps/geometry-2d/ai/rules/circumcircleCutsLine.ts","../src/stamps/geometry-2d/ai/rules/lineConcurrency.ts","../src/stamps/geometry-2d/ai/rules/twoCirclesMeet.ts","../src/stamps/geometry-2d/ai/rules/radius.ts","../src/stamps/geometry-2d/ai/rules/perpNamedLine.ts","../src/stamps/geometry-2d/ai/rules/parallelSidePoints.ts","../src/stamps/geometry-2d/ai/rules/parallelThroughCutsCircle.ts","../src/stamps/geometry-2d/ai/rules/lineThroughCutsTwoLines.ts","../src/stamps/geometry-2d/ai/rules/rightAngleViewing.ts","../src/stamps/geometry-2d/ai/rules/registry.ts","../src/stamps/geometry-2d/ai/deterministic/normalizeText.ts","../src/stamps/geometry-2d/ai/deterministic/runDeterministicIntents.ts","../src/stamps/geometry-2d/ai/deterministic/guards.ts","../src/stamps/geometry-2d/ai/normalizeIntent.ts","../src/stamps/geometry-2d/ai/resolveCircleNames.ts","../src/stamps/geometry-2d/ai/repairCircleIntersections.ts","../src/stamps/geometry-2d/dsl/transpile/errors.ts","../src/stamps/geometry-2d/dsl/transpile/refs.ts","../src/stamps/geometry-2d/ai/layout/disjointOffset.ts","../src/stamps/geometry-2d/ai/intent-builders/_types.ts","../src/stamps/geometry-2d/ai/intent-builders/shared.ts","../src/stamps/geometry-2d/ai/intent-builders/draw-shape.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/midpoint.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/onPerpBisector.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/perpFoot.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/centers.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/intersections.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/tangency.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/onSegment-free.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/angleBisectorFoot.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/externalAngleBisectorFoot.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/rightAngleViewing.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/arcMidpoint.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/reflect.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/pointAtDistance.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/externalToCircle.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/onCircle.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/mixtilinear.ts","../src/stamps/geometry-2d/ai/intent-builders/add-point/index.ts","../src/stamps/geometry-2d/ai/intent-builders/connect.ts","../src/stamps/geometry-2d/ai/intent-builders/draw-circle.ts","../src/stamps/geometry-2d/ai/intent-builders/draw-line.ts","../src/stamps/geometry-2d/ai/intent-builders/mark-shape.ts","../src/stamps/geometry-2d/ai/intent-builders/registry.ts","../src/stamps/geometry-2d/ai/intentToDsl.ts","../src/stamps/geometry-2d/ai/intentTopo.ts","../src/stamps/geometry-2d/dsl/schema.ts","../src/stamps/geometry-2d/dsl/transpile/symbols.ts","../src/stamps/geometry-2d/dsl/transpile/cycles.ts","../src/stamps/geometry-2d/dsl/transpile/topology.ts","../src/stamps/geometry-2d/dsl/transpile/ids.ts","../src/stamps/geometry-2d/dsl/transpile.ts","../src/stamps/geometry-2d/ai/verify.ts","../src/stamps/geometry-2d/ai/deterministic/tryDeterministicFigure.ts","../src/stamps/geometry-2d/ai/deterministic/describeMiss.ts","../src/stamps/geometry-2d/ai/deterministic/partialFigure.ts","../src/stamps/geometry-2d/ai/buildFigureIntent.ts","../src/stamps/geometry-2d/ai/handleGenerateFigure.ts","../src/stamps/geometry-2d/ai/envelope.ts","../src/stamps/geometry-2d/ai/intent.ts","../src/stamps/geometry-2d/ai/intentEnvelope.ts","../src/stamps/geometry-2d/ai/intentPrompt.ts","../src/stamps/geometry-2d/ai/handleGenerateFigureIntent.ts","../src/stamps/geometry-2d/ai/mergeIntents.ts"],"names":["others","circleName","PREFILTER","TRI","TRI_EN","TRI_G","TRI_EN_G","trianglesIn","m","dm","norm","CENTER","scanClause","from","circle","NAME_BEFORE","NAME_BEFORE_EN","a","b","opposite","DISTRIB","z","normalizePointName","PREFILTER_EN","parseNum","uniqueTriangle","t","CIRCLE_CENTER","LINE","PT","CIRCLE_WORDS","CIRCLE_PAREN","resolveCircle","collect","sides","verts","intents","name","SINGLE","INSCRIBE_KW","CIRCUM_KW","RE","CIRCLE_REF","PATTERN","CIRCLE_TARGET","valid","tName","PAIR","THETA_A","THETA_B","UNNAMED_DIAMETER","center","q","tri1","tri2","shared","RE2","VN_FORM","RESOLVE_CENTER","EN_FORM","PAREN_CIRCLE","DIAMETER","vertex","side","foot","pickOther","BARE_PAREN","CIRCLE","TWO_MEET","THETA_STEP","PAR","lineNameOf","secondIntersection","addPoint","zodToJsonSchema"],"mappings":"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","file":"ai.mjs","sourcesContent":["// src/stamps/geometry-2d/ai/deterministic/vocabulary.ts\n//\n// Tập từ khóa \"geometry-relevant\" để confidence.ts đo coverage.\n// Format: lowercase, có dấu. countGeometryKeywords lowercase input rồi match.\n\nexport const GEOMETRY_KEYWORDS: readonly string[] = [\n // Base shapes\n 'tam giác', 'đường tròn', 'đương tròn', 'hình chữ nhật', 'hình vuông',\n 'hình bình hành', 'hình thoi', 'hình thang', 'tứ giác',\n // Triangle variants\n 'vuông tại', 'cân tại', 'đều',\n // Circle parts\n 'bán kính', 'tâm', 'đường kính', 'đương kính',\n // Cung (arc) + điểm trên cung. \"cung\" cực phổ biến (điểm trên cung, điểm chính\n // giữa cung, trung điểm cung) — thiếu nó các clause arc bị coi là văn xuôi\n // (hasGeometry=false) → escalate dù onCircle/arcMidpoint rule khớp. \"chính giữa\"\n // (≥9 ký tự) phủ \"điểm chính giữa cung\" mà không va chạm.\n 'cung', 'chính giữa',\n // Segments / on-segment\n 'đoạn', 'cạnh', 'thuộc', 'nằm giữa', 'nằm ngoài',\n // \"nằm trên\" — \"Gọi C,D là các điểm nằm trên (O)\" (vao10:12): clause chỉ có\n // \"nằm trên (O)\" (không \"thuộc\"/\"đường tròn\") bị coi văn xuôi → rule không\n // thấy clause (runDeterministicIntents chỉ feed clause hasGeometry) → điểm\n // không dựng dù onCirclePoint khớp.\n 'nằm trên',\n // Tia đối (opposite ray): \"Trên tia đối của tia AB lấy điểm C\" — điểm trên tia\n // đối. Thiếu \"tia đối\" thì clause này bị coi văn xuôi (hasGeometry=false).\n 'tia đối', 'tia',\n // Derived points\n 'trung điểm', 'chân đường cao', 'chân đương cao', 'hình chiếu',\n 'trọng tâm', 'trực tâm', 'tâm nội tiếp', 'tâm ngoại tiếp',\n 'đối xứng',\n // Cevian names\n 'đường cao', 'đương cao', 'trung tuyến', 'phân giác', 'trung trực',\n // Special lines/circles\n 'tiếp tuyến', 'tiếp điểm', 'tiếp xúc',\n 'nội tiếp', 'ngoại tiếp',\n // Euler line (issue #47). Đánh dấu mọi clause \"Euler\" là geo-clause để\n // mention Euler chưa được claim (suy biến tam giác đều, hoặc đường tròn Euler\n // 9 điểm defer) → escalate fail-safe thay vì silent render-nothing.\n 'euler',\n // Trục đẳng phương (issue #47, construct 2). \"đẳng phương\" (≥10 ký tự, phân\n // biệt) đánh dấu clause là geo-clause: nếu radicalAxis rule miss (đồng tâm /\n // ≠2 đường tròn) → clause không phủ → escalate fail-safe (KHÔNG silent\n // render-nothing). Lowercase vì countGeometryKeywords lowercase input.\n 'đẳng phương',\n // Đường thẳng Simson (issue #47, construct 3). \"simson\" (danh từ riêng phân\n // biệt) đánh dấu clause là geo-clause: nếu simson rule miss (thiếu đường tròn\n // ngoại tiếp / >1 tam giác / P trùng đỉnh) → clause không phủ → escalate\n // fail-safe (KHÔNG silent render-nothing). Lowercase vì countGeometryKeywords\n // lowercase input.\n 'simson',\n // Đường tròn chín điểm / đường tròn Euler (issue #47, construct 4). \"chín điểm\"\n // đánh dấu clause là geo-clause: \"đường tròn Euler\" đã geo qua \"đường tròn\"/\n // \"euler\" sẵn, nhưng \"chín điểm\" (≥8 ký tự, phân biệt) phủ thêm cách diễn đạt\n // trần \"đường tròn chín điểm\" + làm fail-safe tường minh (nếu ninePoint rule\n // miss vì >1 tam giác → clause không phủ → escalate, KHÔNG silent render-nothing).\n // Lowercase vì countGeometryKeywords lowercase input.\n 'chín điểm',\n // Relations\n 'song song', 'vuông góc', 'giao điểm', 'cắt', 'đường thẳng', 'đương thẳng',\n // Ký hiệu (symbol-only phrasing tương đương từ chữ): \"⊥\" ≡ \"vuông góc\".\n // perpFoot rule đã nhận \"⊥\" ở tầng construct (PERP_DRAW), nhưng gate\n // hasGeometry trước đây CHỈ nhận chữ \"vuông góc\" → clause mà \"⊥\" là tín hiệu\n // hình học DUY NHẤT bị coi là văn xuôi (hasGeometry=false). Thêm \"⊥\" để 2\n // phrasing hành xử như nhau ở gate coverage (issue #46 nhóm A).\n '⊥',\n // Ký hiệu giao \"∩\" (\"A1 = BC ∩ AP\"): tương đương \"giao điểm\". Thiếu nó, clause\n // chỉ dùng \"∩\" (không chữ \"giao điểm/cắt\") bị coi văn xuôi (hasGeometry=false)\n // → điểm giao KHÔNG dựng (silent-incomplete) dù intersection rule khớp \"∩\".\n '∩',\n\n // === EN keywords (issue #46 group B) =======================================\n // Bộ từ khoá tiếng Anh để 1 clause TOÀN tiếng Anh được tính là geo-clause\n // (countGeometryKeywords > 0) → coverage gate không escalate sai dù rule EN đã\n // match. countGeometryKeywords lowercase input nên lưu lowercase ở đây.\n //\n // CHỈ thêm danh từ construct ĐA-KÝ-TỰ phân biệt, KHÔNG va chạm có hại như\n // substring của text tiếng Việt hay của nhau. KHÔNG thêm từ ngắn mơ hồ (\"on\",\n // \"at\", \"line\", \"point\", \"right\") vì dễ false-positive (\"point\" ⊂ \"appoint\",\n // \"at\" ⊂ \"tại\"…). Một danh từ construct / clause là đủ để đánh dấu geo.\n //\n // GOTCHA substring: \"centre\" ⊃ \"center\" KHÔNG xảy ra (khác chính tả); \"circle\"\n // KHÔNG ⊂ từ VN. \"radius\"/\"diameter\"/\"center\" là danh từ riêng cho circle.\n 'triangle',\n 'circle',\n 'square',\n 'rectangle',\n 'parallelogram',\n 'rhombus',\n 'trapezoid',\n 'trapezium',\n 'quadrilateral',\n 'midpoint',\n 'radius',\n 'diameter',\n 'center',\n 'centre',\n 'equilateral',\n 'isosceles',\n // Triangle centers (issue #46 group B). \"orthocenter\"/\"circumcenter\"/\n // \"incenter\" already contain \"center\" (already a keyword) — but list all four\n // explicitly for clarity + robustness. British -centre spellings included.\n 'centroid',\n 'orthocenter',\n 'orthocentre',\n 'circumcenter',\n 'circumcentre',\n 'incenter',\n 'incentre',\n // perpBisector + reflection EN (issue #46 group B). Hai danh từ này biến clause\n // \"perpendicular bisector …\" / \"reflection …\" tiếng Anh thành geo-clause để\n // coverage gate hoạt động: nếu rule EN match đủ thì clause được phủ; nếu clause\n // malformed (thiếu cặp đỉnh / thiếu trục) thì geo-clause không được phủ →\n // escalate (fail-safe), KHÔNG silent-incomplete. Đều ≥8 ký tự, phân biệt, không\n // substring của từ VN/EN nào hiện có (không va chạm).\n 'bisector',\n 'reflection',\n // tangentFromExt EN (issue #46 group B). Clause \"Draw the tangents from A to\n // (O)\" dùng ký hiệu \"(O)\" — KHÔNG có text keyword nào khác → coverage gate = 0\n // → escalate dù rule match. \"tangent\" (≥7 ký tự, phân biệt, KHÔNG substring của\n // từ VN/EN nào hiện có) đánh dấu clause là geo-clause. indexOf nên \"tangent\" tự\n // khớp trong \"tangents\"/\"tangent lines\" — KHÔNG cần thêm \"tangents\" riêng.\n 'tangent',\n // perpFoot EN (issue #46 group B). Clause \"Let H be the projection of A onto\n // BC\" / \"foot of the perpendicular from A to BC\" / \"Draw AH perpendicular to\n // BC\" → đánh dấu geo-clause để coverage gate fail-safe: nếu rule EN miss thì\n // geo-clause không phủ → escalate, KHÔNG silent-incomplete (triangle-only bỏ\n // điểm H). Cả hai ≥10 ký tự, phân biệt, không substring của từ VN/EN nào hiện\n // có. \"perpendicular bisector of BC\" đã có 'bisector' → 'perpendicular' chỉ\n // tăng count, không đổi hành vi.\n 'perpendicular',\n 'projection',\n // pointAtDistance EN (issue #46 group B). Clause \"On ray BA extended beyond A,\n // take D such that AD = AB\" / \"Extend AB beyond B to D ...\" / \"On the opposite\n // ray of ray BA, take D ...\" → mark geo-clause. \"extend\" (indexOf also matches\n // \"extended\"/\"extending\") + the phrase \"opposite ray\" (geometry-specific). If\n // the rule misses a malformed clause → geo-clause unclaimed → escalate\n // (fail-safe), NOT silent-drop of point D. No harmful substring collision with\n // any existing VN/EN keyword.\n 'extend',\n 'opposite ray',\n 'outside',\n // cevian EN (issue #46 group B). Clause \"Draw the median AM\" / \"Draw the\n // altitude AH\" → mark geo-clause. Nếu rule không parse được clause median/\n // altitude bị lỗi → geo-clause không phủ → escalate (fail-safe), KHÔNG\n // silent-incomplete (triangle-only bỏ điểm chân). ('bisector' đã có ở trên.)\n // Cả hai đều là danh từ hình học riêng, không substring va chạm có hại.\n 'median',\n 'altitude',\n // connect EN (issue #46 nhóm B). VN \"đoạn\" LÀ keyword → \"segment\" parity để\n // \"Draw segment XY\" standalone là geo-clause: rule connect EN claim → render;\n // clause malformed (\"segment\" không cặp HOA) → geo unclaimed → escalate\n // (fail-safe). ≥7 ký tự, phân biệt, không substring va chạm. \"line\"/\"ray\"/\"draw\"/\n // \"join\"/\"connect\" CỐ Ý KHÔNG thêm (đối VN \"đường thẳng\"/\"tia\"/… cũng không phải\n // keyword → parity: render in-context, escalate standalone).\n 'segment',\n];\n\nexport function countGeometryKeywords(text: string): number {\n const lower = text.toLowerCase();\n let count = 0;\n for (const kw of GEOMETRY_KEYWORDS) {\n let from = 0;\n while (true) {\n const i = lower.indexOf(kw, from);\n if (i < 0) break;\n count++;\n from = i + kw.length;\n }\n }\n return count;\n}\n","// src/stamps/geometry-2d/ai/deterministic/coverage.ts\n//\n// Clause segmentation + coverage cho deterministic-first gate.\n// Track A chỉ \"tự tin\" dùng kết quả khi MỌI clause mang nội dung hình học\n// đều được ít nhất 1 rule match claim. Còn sót → escalate AI.\nimport { countGeometryKeywords } from './vocabulary';\n\nexport interface Clause {\n id: number;\n text: string;\n /** clause chứa ≥1 từ khoá hình học → tính vào mẫu số coverage. */\n hasGeometry: boolean;\n}\n\nexport interface CoverageReport {\n complete: boolean;\n coveredClauseIds: number[];\n uncovered: Clause[];\n ratio: number;\n}\n\ninterface MatchLike {\n clauseIds: number[];\n}\n\n// Mask dấu câu KHÔNG phải ranh giới clause trước khi split, unmask sau khi split.\n// Sentinel = control char không bao giờ xuất hiện trong đề.\nconst MASK_SEMI = '\\u0001';\nconst MASK_DOT = '\\u0002';\nconst MASK_COMMA = '\\u0003';\n\n// 1) Dấu ;/./, BÊN TRONG ngoặc ngắn không lồng: \"(O;R)\", \"(M, N thuộc đường tròn;\n// AM khác AN)\" — chú thích/tên đường tròn, không phải ranh giới clause. Giới hạn\n// ≤40 ký tự để ngoặc OCR không cân \"(O. Gọi…\" không nuốt phần sau.\n// 2) \";\" giữa phần tử LIST (\"đường cao AD; BE; CF cắt nhau tại H\"): \";\" theo sau là\n// token điểm/đoạn ngắn rồi tới \";\" \",\" hoặc \"cắt nhau\"/\"đồng quy\" → phân cách\n// liệt kê. \";\" trước mệnh đề thật (\"…tại E; AE và BC kéo dài…\") vẫn split vì\n// sau token là từ khác (\"và\", \"kéo\"…).\nfunction maskNonBoundaryPunct(s: string): string {\n return s\n .replace(/\\(([^()\\n]{1,40})\\)/g, (m) =>\n m.replace(/;/g, MASK_SEMI).replace(/\\./g, MASK_DOT).replace(/,/g, MASK_COMMA),\n )\n .replace(\n /;(?=\\s*[A-Z][A-Z]?['′]?\\d?\\s*(?:[;,]|cắt nhau|đồng quy))/gu,\n MASK_SEMI,\n );\n}\n\nfunction unmask(s: string): string {\n return s\n .replace(/\\u0001/g, ';')\n .replace(/\\u0002/g, '.')\n .replace(/\\u0003/g, ',');\n}\n\n/**\n * Tách đề thành clause theo dấu câu (. ; xuống dòng) và dấu phẩy đứng trước\n * từ dẫn (\"Gọi\", \"Vẽ\", \"Kẻ\"…). Clause thuần văn xuôi (không từ khoá hình học)\n * vẫn được giữ nhưng `hasGeometry=false` để không ép escalate.\n */\nexport function segmentClauses(problem: string): Clause[] {\n // Comma-split lookahead: tách clause ở dấu phẩy đứng TRƯỚC từ dẫn. VN dùng\n // (Gọi|Vẽ|Kẻ|Cho|Lấy|Dựng|trên|với). EN ADDITIVE (issue #46 group B): các từ\n // dẫn sub-clause viết HOA đầu câu (Let|Draw|Mark|Take|Construct|Join) — \"Triangle\n // ABC, let M be the midpoint of BC\" tách thành 2 clause. Thuần additive: không\n // đổi segmentation VN (alternation rời nhau, không trùng từ).\n let proofMode = false;\n\n return maskNonBoundaryPunct(problem)\n .split(\n // (?!\\p{L}) thay \\b: \"Vẽ\"/\"Kẻ\" kết thúc bằng chữ Việt — \\b ASCII không bao\n // giờ khớp trước space → split chết im lặng (bug class \\b+tiếng Việt).\n /[.;\\n]+|,\\s*(?=(?:Gọi|Vẽ|Kẻ|Cho|Lấy|Dựng|trên|với|Let|Draw|Mark|Take|Construct|Join)(?!\\p{L}))/u,\n )\n .map((s) => unmask(s).trim())\n .filter((s) => s.length > 0)\n .map((text, id) => {\n const hasGeometryKeyword = countGeometryKeywords(text) > 0;\n const proofOnly = isProofOnlyClause(text, proofMode);\n if (startsProofSection(text)) proofMode = true;\n // Mệnh đề LOCUS (\"điểm A di chuyển/di động trên (O)\") = điều kiện chuyển\n // động trên điểm Đà dựng (đỉnh), KHÔNG phải construct → loại khỏi coverage.\n const locusOnly = LOCUS_CLAUSE.test(text) && !CONSTRUCTION_LEAD.test(text);\n return { id, text, hasGeometry: hasGeometryKeyword && !proofOnly && !locusOnly };\n });\n}\n\n// Tiền tố đánh số mục: \"1.\", \"2)\", \"a)\", \"b.\", \"II.\" — có thể lặp (\"1. a)\").\n// Strip trước khi nhận diện từ dẫn proof/construction (đề thi hay đánh số câu/ý).\nconst ENUM_PREFIX = '(?:[0-9]+\\\\s*[.)]?\\\\s*|[a-zA-Z]\\\\s*[.)]\\\\s*)*';\n\n// Locus: \"(Điểm)? X di chuyển/di động trên (O)/cung/đường tròn\" — điểm chạy\n// trên đường tròn/cung thường là ĐỈNH đã dựng (animation), KHÔNG construct mới.\n// NHƯNG \"di chuyển/di động trên cạnh/đoạn AC\" GIỚI THIỆU điểm free mới (P) cần\n// dựng để các construct sau (BP, …) có ref hợp lệ → KHÔNG coi là locus.\nconst LOCUS_CLAUSE = /(?:di\\s*chuyển|di\\s*động)\\s+trên\\s+(?:\\(|đường\\s*tròn|đương\\s*tròn|cung|nửa)/u;\n\n// \"C/m\"/\"CMR\" — viết tắt \"Chứng minh (rằng)\" phổ biến trong đề OCR (vao10:254\n// \"a.C/m: Bốn điểm…\"); thiếu nó clause proof bị coi geo-clause → escalate oan.\nconst PROOF_SECTION_START = new RegExp(\n `^${ENUM_PREFIX}(?:[Cc]hứng\\\\s*minh|C/m|CMR|[Tt]ính|[Tt]ìm|[Xx]ác\\\\s*định|[Hh]ãy\\\\s+xác\\\\s*định)(?!\\\\p{L})`,\n 'u',\n);\n\nconst CONSTRUCTION_LEAD = new RegExp(\n `^${ENUM_PREFIX}(?:[Cc]ho|[Gg]ọi|[Vv]ẽ|[Kk]ẻ|[Ll]ấy|[Dd]ựng|[Qq]ua|[Tt]ừ|[Tt]rên|[Nn]ối|Let|Draw|Mark|Take|Construct|Join)(?!\\\\p{L})`,\n 'u',\n);\n\nfunction startsProofSection(text: string): boolean {\n return PROOF_SECTION_START.test(text);\n}\n\nfunction isProofOnlyClause(text: string, proofMode: boolean): boolean {\n if (PROOF_SECTION_START.test(text) && !CONSTRUCTION_LEAD.test(text)) return true;\n return proofMode && !CONSTRUCTION_LEAD.test(text);\n}\n\nexport function computeCoverage(\n clauses: readonly Clause[],\n matches: readonly MatchLike[],\n): CoverageReport {\n const claimed = new Set<number>();\n for (const m of matches) for (const id of m.clauseIds) claimed.add(id);\n\n const geoClauses = clauses.filter((c) => c.hasGeometry);\n const uncovered = geoClauses.filter((c) => !claimed.has(c.id));\n const coveredClauseIds = geoClauses\n .filter((c) => claimed.has(c.id))\n .map((c) => c.id);\n\n return {\n complete: uncovered.length === 0 && geoClauses.length > 0,\n coveredClauseIds,\n uncovered,\n ratio: geoClauses.length === 0 ? 0 : coveredClauseIds.length / geoClauses.length,\n };\n}\n","// src/stamps/geometry-2d/ai/rules/_shared.ts\n//\n// Helper dùng chung cho rule module: intent factory (cast IntentT tập trung 1 chỗ)\n// + trích tên điểm từ lời dẫn tiếng Việt. Rule module KHÔNG tự cast `as any`.\nimport type { IntentT } from '../intent';\n\n// --- Intent factories (cast tập trung) ---------------------------------------\n// variant/shape/kind là string runtime; zod validate lại ở builder/transpile,\n// nên cast qua unknown an toàn trong phạm vi NLU.\n\nexport function drawShape(\n shape: string,\n labels: string[],\n variant = 'any',\n explicitCoords?: Record<string, readonly [number, number]>,\n): IntentT {\n return {\n op: 'draw-shape',\n shape,\n labels,\n variant,\n ...(explicitCoords ? { explicitCoords } : {}),\n } as unknown as IntentT;\n}\n\nexport function addPoint(name: string, constraint: Record<string, unknown>): IntentT {\n return { op: 'add-point', name, constraint } as unknown as IntentT;\n}\n\nexport function connect(from: string, to: string, style = 'segment'): IntentT {\n return { op: 'connect', from, to, style } as unknown as IntentT;\n}\n\nexport function drawCircle(\n name: string,\n spec: string,\n extra: Record<string, unknown> = {},\n): IntentT {\n return { op: 'draw-circle', name, spec, ...extra } as unknown as IntentT;\n}\n\nexport function drawLine(\n name: string,\n kind: string,\n extra: Record<string, unknown> = {},\n): IntentT {\n return { op: 'draw-line', name, kind, ...extra } as unknown as IntentT;\n}\n\n/** Đa giác con (triangle|quadrilateral) nối các ĐIỂM Đà CÓ — không tạo coord mới. */\nexport function markShape(shape: string, labels: string[]): IntentT {\n return { op: 'mark-shape', shape, labels } as unknown as IntentT;\n}\n\n// --- Point-name extraction ----------------------------------------------------\n\n// KHÔNG dùng \\b quanh chữ Việt: \\b của JS theo ASCII nên 'à'/'ẽ' là non-word-char\n// → `là\\b` chết khi sau là space (và khớp NHẦM \"làm\"). Neo bằng lookaround Unicode.\nconst INTRO_NAME =\n /(?:Gọi|Lấy|Dựng|Vẽ|Kẻ|Đặt|Xác định)\\s+(?:điểm\\s+)?([A-Z])['′]?(?![\\p{L}\\d])/u;\nconst NAME_LA = /(?<![\\p{L}\\d])([A-Z])['′]?\\s+là(?!\\p{L})/u;\n\n/**\n * Trích tên điểm được giới thiệu trong clause:\n * \"Gọi M là trung điểm BC\" → \"M\"\n * \"Lấy điểm D trên cạnh AB\" → \"D\"\n * \"H là trực tâm\" → \"H\"\n * Trả undefined nếu không tìm thấy (caller tự quyết fallback / bỏ qua).\n */\nexport function extractPointName(clauseText: string): string | undefined {\n const intro = INTRO_NAME.exec(clauseText);\n if (intro) return intro[1];\n const la = NAME_LA.exec(clauseText);\n if (la) return la[1];\n return undefined;\n}\n\n/** Tách \"BC\" → [\"B\",\"C\"]; \"AB\" → [\"A\",\"B\"]. Trả [] nếu không phải cặp đỉnh. */\nexport function pairFromToken(token: string): string[] {\n const m = /^([A-Z])([A-Z])$/u.exec(token.trim());\n return m ? [m[1], m[2]] : [];\n}\n\n// --- Side / segment prefix ----------------------------------------------------\n// Tiền tố \"cạnh\"/\"đoạn\" tuỳ chọn TRƯỚC cặp đỉnh, cho phép bổ ngữ \"huyền\"/\"thẳng\"\n// chen giữa: \"cạnh BC\", \"cạnh huyền BC\", \"đoạn AC\", \"đoạn thẳng AC\". Fail-safe:\n// \"cạnh thẳng\"/\"đoạn huyền\" (sai cặp) KHÔNG khớp vì bổ ngữ bị buộc đúng loại.\n// Là FRAGMENT regex (string, không cờ) để nhúng vào pattern lớn hơn — bổ ngữ là\n// optional nên prefix vẫn khớp dạng trần \"cạnh BC\".\n// \"dây (cung)\" cũng là đoạn thẳng — \"trung điểm của dây MN\" (vao10:254).\nexport const SIDE_PREFIX = '(?:cạnh(?:\\\\s+huyền)?\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+|dây(?:\\\\s+cung)?\\\\s+)?';\n\n/** \"đường\" và typo \"đương\" (thiếu dấu huyền). */\nexport const DUONG_KW = '[Đđ]ư[ờơ]ng';\n\n/** \"đường tròn\" và typo \"đương tròn\". */\nexport const CIRCLE_KW = DUONG_KW + '\\\\s*tròn';\n\n/**\n * Kiểm tra tên có phải là nhãn điểm (tâm) hay không.\n * Thỏa mãn: 1 chữ HOA + tuỳ chọn dấu phẩy/số (vd: O, O', O1).\n */\nexport function isCenterName(name: string): boolean {\n return /^[A-Z]['′]?\\d*$/u.test(name);\n}\n","// src/stamps/geometry-2d/ai/rules/triangle.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { drawShape, addPoint, drawCircle, markShape } from './_shared';\n\n// MULTI-MATCH: 1 clause có thể chứa NHIỀU tam giác (\"tam giác ABC và tam giác\n// ABD vuông tại A\", \"tam giác đều DEF nội tiếp tam giác ABC\"). Bắt MỌI tam giác\n// (cờ 'g'), variant bind từ TEXT WINDOW giữa tam giác này và tam giác KẾ — KHÔNG\n// vơ chữ \"đều\"/\"vuông tại X\" của tam giác khác.\n//\n// leadMod = từ bổ nghĩa ĐỨNG TRƯỚC bộ 3 đỉnh (\"tam giác đều DEF\", \"tam giác\n// vuông ABC\", \"tam giác cân ABC\"). leadMod \"đều\" → equilateral ngay; \"vuông\"/\n// \"cân\" leadMod (không có \"tại X\") không đủ thông tin chọn đỉnh → để window xử lý.\n// leadMod gồm cả \"nhọn\"/\"tù\" (acute/obtuse) — KHÔNG ngụ ý variant (→ 'any') nhưng\n// PHẢI nuốt để bộ 3 đỉnh khớp (\"tam giác nhọn ABC\"). variantForVi bỏ qua chúng.\n// leadMod (group 1) = tính từ variant ĐẦU TIÊN (đều/vuông/cân/nhọn/tù). Sau đó\n// một CHUỖI tính từ phụ (đứng trước bộ 3 đỉnh) được NUỐT không-bắt: \"không cân/đều/\n// vuông\" (phủ định → 'any') + lặp lại các tính từ trên, ngăn bằng dấu phẩy/khoảng\n// trắng. Phủ \"tam giác nhọn, không cân ABC\" / \"tam giác không cân ABC\" (olympiad).\n// (?!\\p{L}) thay \\b quanh ký tự Việt.\nconst TRI_G =\n /tam giác\\s+(?:(đều|vuông|cân|nhọn|tù)(?!\\p{L})\\s*,?\\s*)?(?:(?:không\\s+(?:cân|đều|vuông)|đều|vuông|cân|nhọn|tù)(?!\\p{L})\\s*,?\\s*)*([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n// Tên ĐỨNG TRƯỚC: \"ABC là tam giác (vuông|cân|đều)? …\" — variant suy từ window\n// SAU \"tam giác\" (vd \"ABC là tam giác vuông tại A\" → window \"vuông tại A\").\nconst TRI_BEFORE_G = /(?<![A-Z])([A-Z])([A-Z])([A-Z])(?![A-Z])\\s+là\\s+tam\\s*giác/gu;\nconst RIGHT_AT = /vuông\\s+tại\\s+([A-Z])(?![A-Za-z])/u;\nconst ISO_AT = /cân\\s+tại\\s+([A-Z])(?![A-Za-z])/u;\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Dùng lookaround \\p{L} để chặn match giữa từ dài hơn.\nconst EQUILATERAL = /(?<!\\p{L})đều(?!\\p{L})/u;\n\n// === EN patterns (issue #46 group B) ========================================\n// MULTI-MATCH như VN: cờ 'g'. leadMod ĐỨNG TRƯỚC \"triangle\" (mirror \"tam giác đều\n// DEF\"): \"equilateral triangle ABC\", \"right triangle ABC\", \"isosceles triangle\n// ABC\". First-letter case flexibility ([Tt], [Ee]…) — KHÔNG cờ 'i' (sẽ phá [A-Z]\n// nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]).\nconst TRI_EN_G =\n /(?:([Ee]quilateral|[Rr]ight-angled|[Rr]ight|[Ii]sosceles)\\s+)?[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n// Window modifiers (đứng SAU nhãn): \"right angle at A\" / \"right-angled at A\".\nconst RIGHT_AT_EN = /[Rr]ight(?:\\s+angle|-angled)\\s+at\\s+([A-Z])(?![A-Za-z])/u;\n// \"with apex A\" / \"apex at A\" / \"apex A\". CHỈ nhận khi ngữ cảnh cân (isosceles).\nconst APEX_AT_EN = /apex\\s+(?:at\\s+)?([A-Z])(?![A-Za-z])/u;\n// \"... is equilateral\" / \"equilateral triangle …\" trong window riêng tam giác này.\nconst EQUILATERAL_EN = /(?<![A-Za-z])[Ee]quilateral(?![A-Za-z])/u;\nconst ISOSCELES_EN = /(?<![A-Za-z])[Ii]sosceles(?![A-Za-z])/u;\n\n/** Chuẩn hoá leadMod EN về token canonical: 'equilateral'|'right'|'isosceles'. */\nfunction normLeadEn(lead: string | undefined): string | undefined {\n if (!lead) return undefined;\n const l = lead.toLowerCase();\n if (l === 'equilateral') return 'equilateral';\n if (l === 'right' || l === 'right-angled') return 'right';\n if (l === 'isosceles') return 'isosceles';\n return undefined;\n}\n\ninterface TriHit {\n labels: string[];\n /** leadMod đứng ngay trước bộ 3 đỉnh, hoặc undefined. */\n lead?: string;\n /** ngôn ngữ của hit — quyết định dùng window VN hay EN khi suy variant. */\n lang: 'vi' | 'en';\n /** offset bắt đầu match (để sắp xếp + tính window theo thứ tự text). */\n start: number;\n /** vị trí ngay sau match (đầu window). */\n end: number;\n}\n\n/**\n * Suy variant cho 1 tam giác từ: leadMod (\"tam giác đều DEF\") + WINDOW text\n * (đoạn từ ngay sau bộ 3 đỉnh tới đầu tam giác kế / hết clause). \"vuông tại X\" /\n * \"cân tại X\" CHỈ áp nếu X ∈ labels của tam giác NÀY (tránh bind nhầm sang tam\n * giác khác cùng clause). Quy ước enum (xem TriangleVariantZ): cân tại A ⇒\n * isoceles-BC (đáy CYCLIC: apex A→BC, B→CA, C→AB); vuông tại A ⇒ right-at-A.\n */\n// Variant enum là POSITIONAL theo INDEX đỉnh đặc biệt trong labels (builder\n// triangleCanonical: isoceles-BC ⇒ apex = vertex[0], right-at-A ⇒ vertex[0]\n// vuông). KHÔNG dùng chữ-cái-nhãn: tam giác [A,C,D] \"cân tại A\" (apex idx 0) →\n// isoceles-BC (positional), KHÔNG phải \"isoceles-CD\". Với nhãn ABC chuẩn,\n// positional trùng label nên tương thích ngược.\nconst RIGHT_BY_IDX = ['right-at-A', 'right-at-B', 'right-at-C'];\nconst ISO_BY_IDX = ['isoceles-BC', 'isoceles-CA', 'isoceles-AB'];\n\n// === Thales: tam giác VUÔNG nội tiếp đường tròn → đường kính + glider ===========\n// Vuông tại A nội tiếp (O) ⟺ BC là ĐƯỜNG KÍNH (góc nội tiếp chắn nửa đường tròn).\n// Dựng RÀNG BUỘC (kéo vẫn vuông): 2 đầu mút đường kính free + tâm O = trung điểm +\n// đường tròn centerThrough (bán kính theo đầu mút) + apex là glider onCircle.\n// → góc vuông tại apex luôn đúng; AB<AC chọn bằng vị trí đầu mút cạnh ngắn (bên trái).\n//\n// CHỈ kích hoạt khi tam giác VUÔNG + có ngữ cảnh \"nội tiếp đường tròn/(O)\" SAU nhãn\n// (window). \"đường tròn nội tiếp tam giác\" (incircle) đứng TRƯỚC nhãn → KHÔNG ở\n// trong window → không kích hoạt (đúng: incircle không liên quan góc vuông).\nconst THALES_R = 4;\nconst THALES_THETA = 2.3; // ~131° (góc phần tư II) → apex gần đầu mút TRÁI = cạnh ngắn\n\n// \"nội tiếp (trong)? (đường tròn (O)/tâm O)? | (O)\" — circumcircle tam giác inscribed.\nconst TRI_INSCRIBED =\n /nội\\s*tiếp\\s+(?:trong\\s+)?(?:đường\\s*tròn\\s*(?:\\(\\s*([A-Z])\\s*\\)|tâm\\s+([A-Z]))?|\\(\\s*([A-Z])\\s*\\))/u;\n// Bất đẳng thức cạnh \"AB < AC\" / \"AC > AB\" (2 cạnh chia sẻ đỉnh vuông).\nconst INEQ = /([A-Z])([A-Z])\\s*([<>])\\s*([A-Z])([A-Z])/u;\n\n/** Tên đường tròn ngoại tiếp từ window; undefined nếu không có \"nội tiếp …\". */\nfunction inscribedCircleName(window: string): string | undefined {\n const m = TRI_INSCRIBED.exec(window);\n if (!m) return undefined;\n return m[1] ?? m[2] ?? m[3] ?? ''; // '' → caller default 'O'\n}\n\n/** Đầu mút (≠ apex) của cạnh NGẮN hơn theo \"AB < AC\"; default others[0]. */\nfunction shorterLegEnd(window: string, apex: string, others: string[]): string {\n const m = INEQ.exec(window);\n if (m) {\n const op = m[3];\n const o1 = m[1] === apex ? m[2] : m[2] === apex ? m[1] : undefined; // cạnh 1 (≠apex)\n const o2 = m[4] === apex ? m[5] : m[5] === apex ? m[4] : undefined; // cạnh 2 (≠apex)\n if (o1 && o2 && others.includes(o1) && others.includes(o2)) {\n return op === '<' ? o1 : o2; // '<' → cạnh 1 ngắn; '>' → cạnh 2 ngắn\n }\n }\n return others[0];\n}\n\n/**\n * Dựng Thales cho tam giác vuông (apex tại index `apexIdx`) nội tiếp đường tròn\n * `circleNameRaw`. Trả null nếu tên tâm đụng nhãn đỉnh (fail-safe → drawShape).\n */\nfunction thalesIntents(\n labels: string[],\n apexIdx: number,\n circleNameRaw: string,\n window: string,\n): IntentT[] | null {\n const apex = labels[apexIdx];\n const others = labels.filter((_, i) => i !== apexIdx); // 2 đầu mút đường kính\n const cn = circleNameRaw || 'O';\n if (labels.includes(cn)) return null; // tên tâm trùng đỉnh → bỏ Thales (an toàn)\n const shortEnd = shorterLegEnd(window, apex, others);\n const longEnd = others[0] === shortEnd ? others[1] : others[0];\n return [\n addPoint(shortEnd, { kind: 'free', at: [-THALES_R, 0] }), // cạnh ngắn: đầu mút TRÁI\n addPoint(longEnd, { kind: 'free', at: [THALES_R, 0] }),\n addPoint(cn, { kind: 'midpoint', of: shortEnd + longEnd }), // tâm O = trung điểm đường kính\n drawCircle(cn, 'centerThrough', { center: cn, through: shortEnd }),\n addPoint(apex, { kind: 'onCircle', circle: cn, theta: THALES_THETA }), // apex glider (gần TRÁI)\n markShape('triangle', labels),\n ];\n}\n\nfunction variantFor(hit: TriHit, window: string): string {\n return hit.lang === 'en' ? variantForEn(hit, window) : variantForVi(hit, window);\n}\n\nfunction variantForVi(hit: TriHit, window: string): string {\n const { labels, lead } = hit;\n // \"tam giác đều DEF\" hoặc chữ \"đều\" trong window riêng của tam giác này.\n if (lead === 'đều' || EQUILATERAL.test(window)) return 'equilateral';\n\n const ra = RIGHT_AT.exec(window);\n if (ra) {\n const i = labels.indexOf(ra[1]);\n if (i >= 0) return RIGHT_BY_IDX[i];\n }\n\n const iso = ISO_AT.exec(window);\n if (iso) {\n const i = labels.indexOf(iso[1]);\n if (i >= 0) return ISO_BY_IDX[i];\n }\n\n return 'any';\n}\n\n/**\n * EN variant — mirror VN POSITIONAL semantics. leadMod canonical ('equilateral'/\n * 'right'/'isosceles') + WINDOW riêng tam giác này. \"right triangle ABC\" KHÔNG có\n * \"right angle at X\" → 'any' (đủ thông tin loại nhưng không biết đỉnh, fail-safe\n * như VN \"tam giác vuông ABC\"). \"isosceles\" không \"apex X\" → 'any'. apex/right-at\n * CHỈ áp nếu đỉnh ∈ labels (tránh bind nhầm / đỉnh ngoài tam giác).\n */\nfunction variantForEn(hit: TriHit, window: string): string {\n const { labels, lead } = hit;\n if (lead === 'equilateral' || EQUILATERAL_EN.test(window)) return 'equilateral';\n\n // \"right angle at A\" / \"right-angled at A\" → positional. CHỈ trong window\n // (không vơ modifier của tam giác kế).\n const ra = RIGHT_AT_EN.exec(window);\n if (ra) {\n const i = labels.indexOf(ra[1]);\n if (i >= 0) return RIGHT_BY_IDX[i];\n }\n\n // Apex CHỈ có nghĩa trong ngữ cảnh cân: leadMod 'isosceles' HOẶC từ \"isosceles\"\n // trong window. \"with apex A\" → isoceles theo INDEX của A trong labels.\n const isoCtx = lead === 'isosceles' || ISOSCELES_EN.test(window);\n if (isoCtx) {\n const ap = APEX_AT_EN.exec(window);\n if (ap) {\n const i = labels.indexOf(ap[1]);\n if (i >= 0) return ISO_BY_IDX[i];\n }\n }\n\n return 'any';\n}\n\n/**\n * \"tam giác ABC\" / \"triangle ABC\" → draw-shape triangle. NHIỀU tam giác / clause\n * → emit-all (mỗi tam giác 1 intent), variant bind theo cú pháp gần (leadMod +\n * window) để KHÔNG mis-render (vd không gán \"đều\"/\"equilateral\" của DEF cho ABC).\n *\n * EN ADDITIVE (issue #46 group B): quét THÊM TRI_EN_G. Hit VN+EN gom chung, sắp\n * theo vị trí TEXT; window mỗi hit = từ sau nhãn tới START của hit KẾ (modifier\n * tiền-vị của tam giác kế KHÔNG lọt vào window hit hiện tại). VN behavior giữ\n * nguyên: với chỉ-VN, start hit kế = vị trí \"tam giác\" kế ≡ logic indexOf cũ.\n */\nexport const triangleRule: LanguageRule = {\n id: 'triangle',\n priority: 100,\n languages: ['vi', 'en'],\n patterns: [TRI_G, TRI_EN_G, TRI_BEFORE_G],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const hits: TriHit[] = [];\n\n TRI_G.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(c.text)) !== null) {\n hits.push({\n lead: m[1],\n lang: 'vi',\n labels: [m[2], m[3], m[4]],\n start: m.index,\n end: m.index + m[0].length,\n });\n }\n\n TRI_EN_G.lastIndex = 0;\n while ((m = TRI_EN_G.exec(c.text)) !== null) {\n hits.push({\n lead: normLeadEn(m[1]),\n lang: 'en',\n labels: [m[2], m[3], m[4]],\n start: m.index,\n end: m.index + m[0].length,\n });\n }\n\n // Name-before: \"ABC là tam giác …\" (variant từ window sau \"tam giác\").\n TRI_BEFORE_G.lastIndex = 0;\n while ((m = TRI_BEFORE_G.exec(c.text)) !== null) {\n hits.push({\n lead: undefined,\n lang: 'vi',\n labels: [m[1], m[2], m[3]],\n start: m.index,\n end: m.index + m[0].length,\n });\n }\n\n if (hits.length === 0) continue;\n\n // Sắp theo vị trí TEXT để window mỗi hit kết thúc ở START hit kế (gồm cả\n // modifier tiền-vị của hit kế) → không leak modifier giữa các tam giác.\n hits.sort((a, b) => a.start - b.start);\n\n const intents = hits.flatMap((hit, idx) => {\n const next = hits[idx + 1];\n const windowEnd = next ? next.start : c.text.length;\n const window = c.text.slice(hit.end, windowEnd);\n const variant = variantFor(hit, window);\n // Thales: tam giác VUÔNG + nội tiếp đường tròn (window) → dựng ràng buộc\n // (đường kính + apex glider) thay draw-shape free (free chỉ \"may mắn\" vuông,\n // kéo là vỡ + không thoả AB<AC). circle3 của circleTriangle bị idempotent\n // loại (cùng tên → centerThrough của triangle prio 100 thắng).\n const rightIdx = RIGHT_BY_IDX.indexOf(variant);\n if (rightIdx >= 0) {\n const circleName = inscribedCircleName(window);\n if (circleName !== undefined) {\n const thales = thalesIntents(hit.labels, rightIdx, circleName, window);\n if (thales) return thales;\n }\n }\n return [drawShape('triangle', hit.labels, variant)];\n });\n\n out.push({ ruleId: 'triangle', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/quad.ts\n//\n// Tứ giác / đa giác 4 đỉnh: hình vuông, chữ nhật, bình hành, thoi, thang\n// (cân/vuông/thường), tứ giác chung. Mỗi loại trích 4 ký tự HOA liền sau tên\n// hình → draw-shape với shape + variant tương ứng.\nimport type { LanguageRule, RuleContext, RuleMatch } from './_types';\nimport { drawShape, drawCircle, addPoint, markShape } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Dùng lookaround \\p{L} (cờ 'u') ở prefilter để chặn biên từ.\n// 4 đỉnh = ĐÚNG 4 ký tự HOA liền nhau (vd \"ABCD\") neo ngay sau tên hình; neo\n// biên cuối (?![A-Z]) để 5+ đỉnh (\"ABCDE\") KHÔNG match → escalate qua guard.\nconst QUAD = '([A-Z])([A-Z])([A-Z])([A-Z])(?![A-Z])';\n\n// Mỗi entry: regex tên hình (đã neo trước 4 đỉnh) → shape + variant.\n// CỜ 'g' để matchAll quét MỌI khai báo hình trong cùng một clause (vd \"hình\n// bình hành ABCD và hình chữ nhật EFGH\" → 2 shape, theo thứ tự TEXT).\n// Thứ tự QUAN TRỌNG: loại cụ thể (hình thang cân/vuông) phải đứng TRƯỚC loại\n// chung (hình thang), và mọi \"hình ...\" phải đứng trước \"tứ giác\" chung — vì\n// engine consume vùng text đã match nên loại cụ thể giành quyền trước.\ninterface QuadKind {\n name: RegExp;\n shape: string;\n variant: string;\n}\n\nconst KINDS: QuadKind[] = [\n // hình thang cân / vuông (modifier TRƯỚC đỉnh) — phải match trước thang chung\n {\n name: new RegExp('hình\\\\s+thang\\\\s+cân\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'isoceles',\n },\n {\n name: new RegExp('hình\\\\s+thang\\\\s+vuông\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'right',\n },\n // hình thang chung — sau đó dò modifier 'vuông'/'cân' đứng SAU đỉnh\n // (\"hình thang ABCD vuông tại A\" → right; \"...cân\" → isoceles).\n {\n name: new RegExp('hình\\\\s+thang\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'general',\n },\n {\n name: new RegExp('hình\\\\s+vuông\\\\s+' + QUAD, 'gu'),\n shape: 'square',\n variant: 'standard',\n },\n {\n name: new RegExp('hình\\\\s+chữ\\\\s+nhật\\\\s+' + QUAD, 'gu'),\n shape: 'rectangle',\n variant: 'wide',\n },\n {\n name: new RegExp('hình\\\\s+bình\\\\s+hành\\\\s+' + QUAD, 'gu'),\n shape: 'parallelogram',\n variant: 'standard',\n },\n {\n name: new RegExp('hình\\\\s+thoi\\\\s+' + QUAD, 'gu'),\n shape: 'rhombus',\n variant: 'standard',\n },\n {\n name: new RegExp('tứ\\\\s+giác(?:\\\\s+lồi)?\\\\s+' + QUAD, 'gu'),\n shape: 'quadrilateral',\n variant: 'any',\n },\n\n // === EN names (issue #46 group B) — same shape/variant mapping as VN ========\n // First-letter case flex ([Ss]quare…) — KHÔNG cờ 'i' (sẽ phá [A-Z] nhãn QUAD).\n // Modifier EN đứng TRƯỚC tên (\"isosceles trapezoid ABCD\") → entry riêng cho\n // isosceles/right trapezoid, đặt TRƯỚC trapezoid chung để giành quyền (overlaps).\n // KHÔNG có post-positional modifier EN trong slice này (chỉ pre-positional).\n {\n name: new RegExp('[Ii]sosceles\\\\s+(?:[Tt]rapezoid|[Tt]rapezium)\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'isoceles',\n },\n {\n name: new RegExp('[Rr]ight\\\\s+(?:[Tt]rapezoid|[Tt]rapezium)\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'right',\n },\n {\n name: new RegExp('(?:[Tt]rapezoid|[Tt]rapezium)\\\\s+' + QUAD, 'gu'),\n shape: 'trapezoid',\n variant: 'general',\n },\n {\n name: new RegExp('[Ss]quare\\\\s+' + QUAD, 'gu'),\n shape: 'square',\n variant: 'standard',\n },\n {\n name: new RegExp('[Rr]ectangle\\\\s+' + QUAD, 'gu'),\n shape: 'rectangle',\n variant: 'wide',\n },\n {\n name: new RegExp('[Pp]arallelogram\\\\s+' + QUAD, 'gu'),\n shape: 'parallelogram',\n variant: 'standard',\n },\n {\n name: new RegExp('[Rr]hombus\\\\s+' + QUAD, 'gu'),\n shape: 'rhombus',\n variant: 'standard',\n },\n {\n name: new RegExp('[Qq]uadrilateral\\\\s+' + QUAD, 'gu'),\n shape: 'quadrilateral',\n variant: 'any',\n },\n];\n\n// Prefilter toàn đề: bất kỳ tên hình 4 đỉnh nào (VN + EN).\nconst PREFILTER =\n /hình\\s+(?:vuông|chữ\\s+nhật|bình\\s+hành|thoi|thang)|tứ\\s+giác|[Ss]quare|[Rr]ectangle|[Pp]arallelogram|[Rr]hombus|[Tt]rapezoid|[Tt]rapezium|[Qq]uadrilateral/u;\n\n// \"hình thang ABCD vuông tại A\" / \"...cân ...\" — modifier đứng SAU đỉnh, ngay\n// sau cụm 4 đỉnh (cho phép xen khoảng trắng). Cờ 'u' bắt buộc cho ký tự Việt.\nconst RIGHT_AFTER = /vuông(?!\\p{L})/u;\nconst ISO_AFTER = /(?<!\\p{L})cân(?!\\p{L})/u;\n// Biên cắt tail: KHÔNG cho modifier \"vuông\"/\"cân\" của hình SAU (\"…và hình vuông\n// EFGH\") bị gán nhầm cho hình thang đứng trước → dừng tail ở khai báo hình kế.\nconst NEXT_SHAPE = /hình\\s|tứ\\s+giác/u;\n\ninterface Hit {\n index: number;\n shape: string;\n variant: string;\n labels: string[];\n /** offset ngay sau cụm 4 đỉnh, để dò modifier hậu vị cho hình thang chung. */\n afterEnd: number;\n}\n\n/**\n * Quét MỌI khai báo hình trong một clause. Mỗi vị trí ký tự chỉ thuộc một kind\n * (kind cụ thể giành trước nhờ thứ tự KINDS). Trả về danh sách hit đã sắp theo\n * vị trí TEXT để emit đúng thứ tự xuất hiện trong đề.\n */\nfunction scanClause(text: string): Hit[] {\n const claimed: Hit[] = [];\n const taken: Array<[number, number]> = []; // vùng [start,end) đã thuộc kind trước\n\n const overlaps = (start: number, end: number) =>\n taken.some(([s, e]) => start < e && end > s);\n\n for (const k of KINDS) {\n k.name.lastIndex = 0;\n for (const m of text.matchAll(k.name)) {\n const start = m.index ?? 0;\n const end = start + m[0].length;\n if (overlaps(start, end)) continue; // đã bị kind cụ thể hơn chiếm\n taken.push([start, end]);\n\n let variant = k.variant;\n // Hình thang chung: dò modifier hậu vị ngay sau 4 đỉnh (\"ABCD vuông tại A\").\n // Cắt tail tại khai báo hình kế tiếp để không nuốt modifier của hình sau.\n if (k.shape === 'trapezoid' && k.variant === 'general') {\n let tail = text.slice(end, end + 24);\n const next = NEXT_SHAPE.exec(tail);\n if (next) tail = tail.slice(0, next.index);\n if (RIGHT_AFTER.test(tail)) variant = 'right';\n else if (ISO_AFTER.test(tail)) variant = 'isoceles';\n }\n claimed.push({\n index: start,\n shape: k.shape,\n variant,\n labels: [m[1], m[2], m[3], m[4]],\n afterEnd: end,\n });\n }\n }\n\n claimed.sort((a, b) => a.index - b.index);\n return claimed;\n}\n\n// --- Tứ giác nội tiếp đường tròn (cyclic quadrilateral) — issue #46 nhóm C/B --\n//\n// \"Cho tứ giác ABCD nội tiếp đường tròn (O)\" hiện chỉ vẽ tứ giác, BỎ đường tròn\n// (render coverage-complete nhưng thiếu hình). Bổ sung đường tròn ngoại tiếp đi\n// qua đúng 4 đỉnh — đặt 4 đỉnh ĐỒNG VIÊN để circle3 thực sự đi qua cả 4.\n//\n// EN (nhóm B Tier 2, fix silent-incomplete): detectCyclic nay nhận thêm các dạng\n// tiếng Anh — Pattern A \"(is/are) inscribed in (a/the) circle (O)\", Pattern B\n// \"circle (O) circumscribes/(is) circumscribed (about/around) ...\". Trước đây đề\n// EN render quad-ONLY (rớt circle âm thầm); nay parity VN (quad concyclic +\n// through3). TRIANGLE_DECL cũng nhận \"Triangle ABC\" để fail-safe ownedByOthers\n// chặn silent-wrong khi tứ giác EN chia đỉnh với tam giác EN.\n//\n// KIẾN TRÚC single-emitter: quadRule LÀ emitter DUY NHẤT của hình tứ giác. Khi\n// phát hiện ngữ cảnh nội tiếp, CHÍNH rule này emit (circle + 4 glider + polygon)\n// — KHÔNG dùng draw-shape (vốn tạo đỉnh FREE) cho nhánh nội tiếp.\n//\n// FIX 2026-06-09 (bug \"đỉnh D không trên đường tròn, kéo đường tròn D không theo\"):\n// trước đây nhánh nội tiếp emit draw-shape (4 đỉnh FREE ở toạ độ đồng viên TĨNH) +\n// circle3 qua 3 đỉnh → đỉnh thứ 4 chỉ TÌNH CỜ nằm trên circle, KHÔNG ràng buộc →\n// kéo 1 trong 3 đỉnh kia (định nghĩa lại circle3) thì đỉnh 4 ở lại, rời đường tròn.\n// NAY: đường tròn centerRadius (tâm O hiện) + 4 đỉnh là glider `onCircle` (theta cố\n// định) → TẤT CẢ ràng buộc trên đường tròn; kéo tâm O cả 4 di chuyển theo, luôn\n// đồng viên. polygon nối 4 đỉnh qua mark-shape (không tạo coord mới).\n//\n// 4 đỉnh trên đường tròn bán kính 5 (đồng viên), góc theta cố định cho layout lồi\n// A→B→C→D (chiều kim đồng hồ), bảo toàn bố cục cũ.\nconst CYCLIC_QUAD_COORDS: readonly [number, number][] = [\n [-3, 4],\n [4, 3],\n [3, -4],\n [-4, -3],\n];\n// Bán kính + góc theta dẫn xuất TỪ toạ độ trên (đồng bộ layout): glider đặt tại\n// (cos θ, sin θ)·r quanh tâm → giữ đúng vị trí lồi như bản free cũ.\nconst CYCLIC_RADIUS = Math.hypot(CYCLIC_QUAD_COORDS[0][0], CYCLIC_QUAD_COORDS[0][1]);\nconst CYCLIC_QUAD_THETAS: readonly number[] = CYCLIC_QUAD_COORDS.map(([x, y]) =>\n Math.atan2(y, x),\n);\n\n// Tên tâm tuỳ chọn: \"(O)\" hoặc \"tâm O\" (mượn idiom của circleTriangle).\nconst CENTER = '(?:\\\\(\\\\s*([A-Z])\\\\s*\\\\)|tâm\\\\s+([A-Z]))?';\n\n// Pattern A — tứ giác nội tiếp đường tròn: \"ABCD nội tiếp (trong) đường tròn\n// (O)/tâm O\". Neo ^ vào phần text NGAY SAU 4 đỉnh (hit.afterEnd). Center group 1|2.\nconst QUAD_INSCRIBED_IN_CIRCLE = new RegExp(\n '^[\\\\s,]*(?:nội\\\\s*tiếp\\\\s+(?:trong\\\\s+)?(?:một\\\\s+)?đường\\\\s*tròn|(?:is\\\\s+|are\\\\s+)?inscribed\\\\s+in\\\\s+(?:a\\\\s+|the\\\\s+)?circle)\\\\s*' +\n CENTER,\n 'iu',\n);\n\n// Pattern B — đường tròn ngoại tiếp tứ giác: \"đường tròn (O)/tâm O ngoại tiếp\"\n// đứng NGAY TRƯỚC \"tứ giác ABCD\". Neo $ vào phần text TRƯỚC hit.index. Center 1|2.\nconst CIRCLE_CIRCUMSCRIBES_QUAD = new RegExp(\n '(?:đường\\\\s*tròn|circle)\\\\s*' +\n CENTER +\n '\\\\s*(?:ngoại\\\\s*tiếp|(?:is\\\\s+|are\\\\s+)?circumscrib(?:es|ed)(?:\\\\s+(?:about|around))?)\\\\s+$',\n 'iu',\n);\n\n// Khai báo tam giác bất kỳ trong đề — 3 đỉnh HOA của nó \"thuộc\" tam giác (không\n// được dời sang toạ độ đồng viên của tứ giác). Cờ 'g' để quét mọi khai báo.\nconst TRIANGLE_DECL = /(?:tam\\s*giác|[Tt]riangle)\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n/**\n * Tập ký tự đỉnh \"thuộc về hình khác\" trong TOÀN đề: mọi đỉnh tam giác + đỉnh\n * của mọi tứ giác hit KHÁC (chuỗi nhãn khác hit hiện tại). Nếu 4 đỉnh của tứ\n * giác này giao tập đó → KHÔNG áp dụng đồng viên (đặt chúng theo CYCLIC_QUAD\n * sẽ phá toạ độ đã có của hình kia → silent-wrong).\n */\nfunction ownedByOthers(ctx: RuleContext, selfLabels: string[]): Set<string> {\n const owned = new Set<string>();\n TRIANGLE_DECL.lastIndex = 0;\n for (const m of ctx.problem.matchAll(TRIANGLE_DECL)) {\n owned.add(m[1]);\n owned.add(m[2]);\n owned.add(m[3]);\n }\n const selfKey = selfLabels.join('');\n for (const c of ctx.clauses) {\n for (const h of scanClause(c.text)) {\n if (h.labels.join('') === selfKey) continue; // chính tứ giác này\n for (const lbl of h.labels) owned.add(lbl);\n }\n }\n return owned;\n}\n\n/**\n * Phát hiện ngữ cảnh nội tiếp cho 1 hit tứ giác chung trong clause `text`.\n * Trả tên tâm (hoặc '') nếu khớp Pattern A/B; undefined nếu không nội tiếp.\n */\nfunction detectCyclic(text: string, hit: Hit): string | undefined {\n // Pattern A: phần text NGAY SAU 4 đỉnh.\n const a = QUAD_INSCRIBED_IN_CIRCLE.exec(text.slice(hit.afterEnd));\n if (a) return a[1] ?? a[2] ?? '';\n // Pattern B: phần text TRƯỚC \"tứ giác\" (hit.index = đầu \"tứ giác\").\n const b = CIRCLE_CIRCUMSCRIBES_QUAD.exec(text.slice(0, hit.index));\n if (b) return b[1] ?? b[2] ?? '';\n return undefined;\n}\n\n/**\n * Tứ giác / đa giác 4 đỉnh → draw-shape. Duyệt từng clause, quét EMIT-ALL mọi\n * khai báo hình (theo thứ tự text). KHÔNG trích được ĐÚNG 4 đỉnh HOA liền (vd\n * \"ABCDE\" 5 đỉnh) → bỏ qua khai báo đó (escalate AI qua guard).\n *\n * Tứ giác CHUNG (shape 'quadrilateral') có ngữ cảnh nội tiếp đường tròn → emit\n * THÊM draw-circle (through3) + đặt 4 đỉnh đồng viên qua explicitCoords. Hình\n * có tên (vuông/chữ nhật/...) NGOÀI phạm vi increment này (giữ hành vi cũ).\n *\n * GIỚI HẠN Đà BIẾT (defer, không sửa): nếu CÙNG nhãn tứ giác được khai báo ở\n * HAI clause (vd \"Cho tứ giác ABCD. Đường tròn ngoại tiếp tứ giác ABCD\") — một\n * plain + một cyclic — cả hai draw-shape sống sót qua JSON dedup (explicitCoords\n * khác nhau) → polygon trùng \"ABCD2\" chồng lên nhau. Hiếm gặp + lành tính\n * (polygon trùng khít, không sai hình học). Test/probe để 1-clause để né.\n */\nexport const quadRule: LanguageRule = {\n id: 'quad',\n priority: 100,\n languages: ['vi', 'en'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n for (const hit of scanClause(c.text)) {\n let intents = [drawShape(hit.shape, hit.labels, hit.variant)];\n // Chỉ tứ giác CHUNG: thử phát hiện đường tròn ngoại tiếp.\n if (hit.shape === 'quadrilateral') {\n const center = detectCyclic(c.text, hit);\n if (center !== undefined) {\n // Fail-safe: đỉnh dùng chung với hình khác → giữ quad-only.\n const owned = ownedByOthers(ctx, hit.labels);\n const shared = hit.labels.some((lbl) => owned.has(lbl));\n if (!shared) {\n const centerName = center || 'O';\n // Đường tròn centerRadius (tâm `centerName`) — resolveCircleNames sẽ\n // inject point tâm + rename circle khi name trùng center (\"(O)\"=tâm O).\n // 4 đỉnh = glider onCircle (theta cố định, layout lồi) → CONSTRAINED.\n // polygon nối 4 đỉnh qua mark-shape (đỉnh đã có, không tạo coord mới).\n // Thứ tự: circle TRƯỚC (glider ref nó), rồi 4 glider, rồi polygon.\n intents = [\n drawCircle(centerName, 'centerRadius', {\n center: centerName,\n radius: CYCLIC_RADIUS,\n }),\n ...hit.labels.map((lbl, i) =>\n addPoint(lbl, { kind: 'onCircle', circle: centerName, theta: CYCLIC_QUAD_THETAS[i] }),\n ),\n markShape(hit.shape, hit.labels),\n ];\n }\n }\n }\n out.push({\n ruleId: 'quad',\n clauseIds: [c.id],\n intents,\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/connect.ts\n//\n// Construct 'connect': vẽ đoạn / đường thẳng / tia giữa 2 đỉnh có tên.\n// BẢO THỦ (priority thấp 40): chỉ claim clause khi có TỪ KHOÁ vẽ rõ ràng\n// (đoạn | cạnh | nối | kẻ | đường thẳng | tia) đi kèm cặp 2 ký tự HOA.\n// KHÔNG khớp \"tam giác ABC\" (3 ký tự liền) hay tên đường 1 ký tự (\"đường d\").\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { connect } from './_shared';\nimport type { IntentT } from '../intent';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Dùng lookaround \\p{L}; cờ 'u' bắt buộc cho mọi regex Việt.\n// Cặp đỉnh = 2 ký tự HOA liền; (?![A-Z]) chặn \"ABC\" (tam giác) khỏi bị bắt.\n\n// LƯU Ý case: KHÔNG dùng cờ 'i' (nó khiến [A-Z] khớp chữ thường → \"đoạn THẳng\"\n// bắt \"th\" làm cặp T,H rác, vỡ pipeline). Nhưng vẫn cần khớp keyword HOA đầu câu\n// (\"Kẻ\", \"Nối\", \"Đoạn\") → case-insensitive CHỈ ở ký tự đầu keyword bằng [Xx].\n// Vertices LUÔN strict [A-Z].\n// \"đường thẳng AB\" → line. \"đường thẳng\" phải đứng trước cặp.\nconst LINE_KW = /[Đđ]ường\\s*thẳng\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"tia AB\" → ray. Không bắt \"tia phân giác\", \"tia đối\" (theo sau là chữ thường).\nconst RAY_KW = /(?<!\\p{L})[Tt]ia\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"tia đối của tia XY\": cụm tia ĐỐI — match \"tia XY\" bên trong KHÔNG được emit ray\n// naive X→Y vì điểm mới nằm trên tia NGƯỢC hướng (gốc X, đi xa Y). Vẽ ray X→Y\n// sẽ minh hoạ SAI hướng (tia gốc thay vì tia đối). pointAtDistance đã dựng điểm\n// mới đúng trên tia đối; connect suppress để tránh ray double/sai hướng.\n// Kiểm tra text NGAY TRƯỚC vị trí match \"tia\": kết thúc bằng \"đối của \" (≥0 space).\nconst TIA_DOI_BEFORE = /tia\\s*đối\\s+của\\s+$/u;\n// \"nối A với/và B\" → segment. Tên 1 ký tự, không phải cặp.\nconst NOI_KW = /(?<!\\p{L})[Nn]ối\\s+([A-Z])\\s+(?:với|và)\\s+([A-Z])(?![A-Za-z])/gu;\n// \"Nối CD\" → segment (cặp 2 ký tự HOA liền, KHÔNG \"với/và\"). (?![A-Z]) chặn \"Nối ABC\".\nconst NOI_PAIR_KW = /(?<!\\p{L})[Nn]ối\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"đoạn (thẳng) AB\" | \"cạnh AB\" | \"kẻ AB\" → segment.\nconst SEG_KW =\n /(?<!\\p{L})(?:[Đđ]oạn(?:\\s*thẳng)?|[Cc]ạnh|[Kk]ẻ)\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n\n// ============ EN connect forms (issue #46 nhóm B) ============================\n// connect.ts vốn VN-only. Mirror các form VN sang EN, GIỮ NGUYÊN parity ở gate\n// vocab: VN \"đoạn\" LÀ keyword → EN \"segment\" cũng vào vocab (standalone render).\n// VN \"đường thẳng\"/\"tia\"/\"nối\"/\"kẻ\" KHÔNG phải keyword → EN \"line\"/\"ray\"/\"connect\"/\n// \"join\"/\"draw\" cũng KHÔNG vào vocab → chỉ render IN-CONTEXT (vd có tam giác), đề\n// standalone → escalate (geoClauses=0). Đối xứng VN/EN tuyệt đối + tôn trọng\n// do-not-add list (\"line\" đã bị cấm trong vocabulary.ts).\n//\n// runDeterministicIntents dedup intent theo JSON.stringify CROSS-RULE → \"Draw AH\n// perpendicular to BC\" khớp CẢ perpFoot (emit connect(A,H,'segment')) lẫn DRAW_PAIR_EN\n// (cũng connect(A,H,'segment')) → IDENTICAL → deduped, vô hại.\n\n// \"segment XY\" → segment (đối VN \"đoạn\"). Group 1,2 = cặp HOA.\nconst SEG_NOUN_EN = /(?<![A-Za-z])[Ss]egment\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"line XY\" → line (đối VN \"đường thẳng\").\nconst LINE_NOUN_EN = /(?<![A-Za-z])[Ll]ine\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// Guard cho segment/line noun: BỎ match nếu cặp thuộc clause của rule prio cao\n// hơn đã SỞ HỮU cặp: perpBisector (\"(perpendicular) bisector (segment|line) PAIR\")\n// / perpFoot (\"perpendicular to (line|segment) PAIR\") / pointAtDistance (\"Extend(ed)\n// segment|line XY beyond …\"). 3 rule đó emit cặp đúng style HOẶC dựng điểm phái sinh;\n// connect KHÔNG được double-emit segment/line trần — đặc biệt với pointAtDistance:\n// clause malformed (thiếu distance / sai hướng) → pointAtDistance KHÔNG emit → clause\n// cần ESCALATE; connect claim sẽ MASK escalate đó (silent-incomplete, bỏ điểm mới).\n// Case flex [Bb]/[Pp]/[Ee] (BẮT BUỘC: HOA đầu clause không được slip — bài học batch16).\nconst NOUN_OWNED_BEFORE_EN = /(?:[Bb]isector|[Pp]erpendicular\\s+to|[Ee]xtend(?:ed)?)\\s+$/u;\n// \"ray XY\" → ray (đối VN \"tia\"). 2 guard:\n// (a) preceding \"opposite ray of ray XY\" (OPPOSITE_RAY_BEFORE_EN): điểm mới nằm trên\n// tia ĐỐI → vẽ ray X→Y SAI hướng (EN mirror VN TIA_DOI_BEFORE, batch9 8ee33af).\n// (b) trailing \"(?!\\s*,?\\s*extended)\": \"ray XY extended beyond Z\" là construct CỦA\n// pointAtDistance (RAY_EXTENDED_EN). connect KHÔNG claim — nếu malformed (thiếu\n// distance / Z≠Y sai hướng) pointAtDistance escalate fail-safe; connect claim sẽ\n// MASK (silent-incomplete bỏ điểm D). Well-formed thì pointAtDistance đã lo điểm\n// D — connect đứng ngoài để giữ EN-cũ (batch15) byte-identical.\n// \"Draw ray AB\" trần (không \"extended\"/không \"opposite ray of\") → vẫn vẽ ray A→B.\nconst RAY_NOUN_EN = /(?<![A-Za-z])[Rr]ay\\s+([A-Z])([A-Z])(?![A-Za-z])(?!\\s*,?\\s*extended)/gu;\nconst OPPOSITE_RAY_BEFORE_EN = /opposite\\s+ray\\s+of\\s+$/u;\n// \"Connect/Join XY\" → segment (đối VN \"nối\", form cặp HOA).\nconst JOIN_PAIR_EN = /(?<![A-Za-z])(?:[Cc]onnect|[Jj]oin)\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n// \"Connect/Join X and/to/with Y\" → segment (tên 1 ký tự, mirror VN NOI_KW).\nconst JOIN_AND_EN =\n /(?<![A-Za-z])(?:[Cc]onnect|[Jj]oin)\\s+([A-Z])\\s+(?:and|to|with)\\s+([A-Z])(?![A-Za-z])/gu;\n// \"Draw XY\" trần → segment (đối VN \"kẻ\"). perpFoot draw-form \"Draw AH perpendicular\n// to BC\" cũng khớp nhưng emit connect(A,H,'segment') IDENTICAL → deduped.\n// perpBisector/cevian/tangent draw-form có \"the\"/\"two\"/chữ thường sau \"Draw\" →\n// KHÔNG cặp HOA → KHÔNG match ở đây.\nconst DRAW_PAIR_EN = /(?<![A-Za-z])[Dd]raw\\s+([A-Z])([A-Z])(?![A-Za-z])/gu;\n\nfunction collect(\n re: RegExp,\n text: string,\n style: string,\n used: Set<string>,\n out: IntentT[],\n // Guard tuỳ chọn: bỏ qua match nếu text NGAY TRƯỚC vị trí match khớp regex này\n // (vd \"tia đối của \" trước \"tia XY\" → không emit ray naive sai hướng).\n skipIfPrecededBy?: RegExp,\n): void {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n if (skipIfPrecededBy && skipIfPrecededBy.test(text.slice(0, m.index))) {\n continue;\n }\n const a = m[1].toUpperCase();\n const b = m[2].toUpperCase();\n // Dedup theo cặp đỉnh trong cùng clause: vẽ trùng AB nhiều lần vô nghĩa,\n // và tránh 2 từ khoá khác nhau cùng claim 1 cặp (vd \"đoạn AB\" + \"kẻ AB\").\n const key = `${a}${b}`;\n if (used.has(key)) continue;\n used.add(key);\n out.push(connect(a, b, style));\n }\n}\n\n/**\n * Mỗi clause khớp ≥1 từ khoá vẽ → push 1 RuleMatch (gom mọi cặp tìm được).\n * Nhiều cặp trong cùng clause ⇒ nhiều intent, cùng clauseId.\n * Priority 40: thấp để rule chuyên biệt (trung trực, phân giác…) claim trước.\n */\nexport const connectRule: LanguageRule = {\n id: 'connect',\n priority: 40,\n languages: ['vi', 'en'],\n patterns: [\n LINE_KW, RAY_KW, NOI_KW, NOI_PAIR_KW, SEG_KW,\n SEG_NOUN_EN, LINE_NOUN_EN, RAY_NOUN_EN, JOIN_PAIR_EN, JOIN_AND_EN, DRAW_PAIR_EN,\n ],\n match(ctx) {\n const result: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents: IntentT[] = [];\n // Dùng span-key để 1 vị trí không bị 2 từ khoá double-count, nhưng cho\n // phép nhiều cặp khác vị trí trong cùng clause.\n const used = new Set<string>();\n // Thứ tự quan trọng: \"đường thẳng AB\" phải claim trước SEG (chứa \"thẳng\"\n // KHÔNG match SEG vì SEG yêu cầu \"đoạn thẳng\"/\"cạnh\"/\"kẻ\", không \"đường\").\n collect(LINE_KW, c.text, 'line', used, intents);\n // RAY: suppress ray naive khi nằm trong cụm \"tia đối của tia XY\" (hướng tia\n // gốc X→Y sai so với điểm mới trên tia đối). pointAtDistance lo điểm mới.\n collect(RAY_KW, c.text, 'ray', used, intents, TIA_DOI_BEFORE);\n collect(NOI_KW, c.text, 'segment', used, intents);\n collect(NOI_PAIR_KW, c.text, 'segment', used, intents);\n collect(SEG_KW, c.text, 'segment', used, intents);\n // EN forms (issue #46 nhóm B). `used` dedup cặp đã claim bởi form VN trong\n // cùng clause (clause trộn ngôn ngữ hiếm, nhưng an toàn). Thứ tự: noun trước,\n // verb sau; DRAW cuối (trần nhất).\n collect(SEG_NOUN_EN, c.text, 'segment', used, intents, NOUN_OWNED_BEFORE_EN);\n collect(LINE_NOUN_EN, c.text, 'line', used, intents, NOUN_OWNED_BEFORE_EN);\n collect(RAY_NOUN_EN, c.text, 'ray', used, intents, OPPOSITE_RAY_BEFORE_EN);\n collect(JOIN_PAIR_EN, c.text, 'segment', used, intents);\n collect(JOIN_AND_EN, c.text, 'segment', used, intents);\n collect(DRAW_PAIR_EN, c.text, 'segment', used, intents);\n if (intents.length > 0) {\n result.push({ ruleId: 'connect', clauseIds: [c.id], intents });\n }\n }\n return result;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/midpoint.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, pairFromToken, SIDE_PREFIX } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\n\n// Prefilter toàn đề. \"trung điểm\" KHÔNG khớp \"trung trực\" (an toàn, rule khác lo).\nconst MIDPOINT = /trung\\s*điểm/u;\n\n// Dạng A (GLOBAL): tên điểm ĐỨNG TRƯỚC \"(là) trung điểm (của (cạnh|đoạn)) <PAIR>\".\n// \"Gọi M là trung điểm BC\" | \"M là trung điểm của BC\" | \"M trung điểm cạnh BC\"\n// | \"M là trung điểm cạnh huyền BC\" | \"trung điểm đoạn thẳng AC\"\n// Tên = ký tự HOA NGAY TRƯỚC cụm trung điểm (cục bộ quanh match, KHÔNG quét intro).\nconst NAME_BEFORE_G = new RegExp(\n `([A-Z])(?:['′]?)\\\\s+(?:là\\\\s+|=\\\\s+)?trung\\\\s*điểm\\\\s+(?:của\\\\s+)?${SIDE_PREFIX}([A-Z])([A-Z])(?!\\\\p{L})`,\n 'gu',\n);\n\n// Dạng B (GLOBAL): tên điểm ĐỨNG SAU \"trung điểm <NAME> của (cạnh|đoạn) <PAIR>\".\n// \"trung điểm I của (cạnh huyền) AB\" | \"trung điểm I của đoạn thẳng BC\"\nconst NAME_AFTER_G = new RegExp(\n `trung\\\\s*điểm\\\\s+([A-Z])(?:['′]?)\\\\s+của\\\\s+${SIDE_PREFIX}([A-Z])([A-Z])(?!\\\\p{L})`,\n 'gu',\n);\n\n// Distributive \"lần lượt\": \"M, N (, P) lần lượt là trung điểm AB, AC (, BC)\" →\n// zip 1-1: M=mid(AB), N=mid(AC), P=mid(BC). group1 = blob tên (≥2, phẩy),\n// group2 = blob cặp đỉnh (≥2, phẩy). Số tên PHẢI bằng số cặp (else bỏ qua,\n// escalate — không đoán lệch). SIDE_PREFIX cho \"(các) cạnh/đoạn\" trước blob cặp.\n// \"lần lượt\"/\"theo thứ tự\" OPTIONAL: cấu trúc song song \"D, E, F là trung điểm\n// của NP, PM, MN\" cũng là zip (≥2 tên liệt kê phẩy NGAY trước \"(là) trung điểm\"\n// → an toàn; dạng đơn \"M là trung điểm BC\" không có blob tên ≥2 nên không dính).\nconst DISTRIB = new RegExp(\n `((?:[A-Z](?:['′]?)\\\\s*(?:,|và)\\\\s*)+[A-Z](?:['′]?))\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?(?:là\\\\s+)?(?:điểm\\\\s+)?trung\\\\s*điểm\\\\s+(?:của\\\\s+)?(?:các\\\\s+)?${SIDE_PREFIX}((?:[A-Z][A-Z]\\\\s*,\\\\s*)*(?:[A-Z][A-Z]\\\\s*,\\\\s*)?[A-Z][A-Z](?:\\\\s*và\\\\s*[A-Z][A-Z])?)`,\n 'u',\n);\n\n// Distributive NAME-AFTER: \"(Gọi)? trung điểm của AC, AB lần lượt là K, L\" →\n// K=mid(AC), L=mid(AB). group1 = blob cặp đỉnh, group2 = blob tên. Zip 1-1.\nconst DISTRIB_AFTER = new RegExp(\n `trung\\\\s*điểm\\\\s+(?:của\\\\s+)?(?:các\\\\s+)?${SIDE_PREFIX}((?:[A-Z][A-Z]\\\\s*(?:,|và)\\\\s*)+[A-Z][A-Z])(?![A-Z])\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?là\\\\s+((?:[A-Z](?:['′]?)\\\\s*(?:,|và)\\\\s*)+[A-Z](?:['′]?))(?!\\\\p{L})`,\n 'u',\n);\n\n// Tách 1 token tên trong blob distributive → \"M\" / \"M'\" (prime normalize ′→').\nfunction nameToken(raw: string): string | undefined {\n const m = /^([A-Z])(['′]?)/u.exec(raw.trim());\n if (!m) return undefined;\n return m[2] ? `${m[1]}'` : m[1];\n}\n\n// === EN patterns (issue #46 group B) ========================================\n// Prefilter EN: \"midpoint\" (first-letter case flex [Mm], KHÔNG cờ 'i' — phá [A-Z]).\nconst MIDPOINT_EN = /[Mm]idpoint/u;\n// EN side/segment prefix tuỳ chọn TRƯỚC cặp đỉnh: \"segment BC\", \"side BC\".\nconst SIDE_PREFIX_EN = '(?:segment\\\\s+|side\\\\s+)?';\n\n// EN dạng A (GLOBAL): tên ĐỨNG TRƯỚC. \"M is the midpoint of BC\" | \"let M be the\n// midpoint of segment BC\". Tên = HOA NGAY TRƯỚC \"is/be the midpoint\" (cục bộ).\n// (?![A-Za-z]) neo cuối cặp đỉnh (chặn \"BCD\" 3 chữ → escalate-safe).\nconst NAME_BEFORE_EN_G = new RegExp(\n `([A-Z])(?:['′]?)\\\\s+(?:is|be)\\\\s+the\\\\s+midpoint\\\\s+of\\\\s+${SIDE_PREFIX_EN}([A-Z])([A-Z])(?![A-Za-z])`,\n 'gu',\n);\n\n// EN dạng B (GLOBAL): tên ĐỨNG SAU. \"midpoint M of BC\" | \"midpoint I of segment AB\".\nconst NAME_AFTER_EN_G = new RegExp(\n `[Mm]idpoint\\\\s+([A-Z])(?:['′]?)\\\\s+of\\\\s+${SIDE_PREFIX_EN}([A-Z])([A-Z])(?![A-Za-z])`,\n 'gu',\n);\n\n/**\n * \"Gọi M là trung điểm BC\" → add-point M {kind:'midpoint', of:'BC'}.\n *\n * GLOBAL: emit MỌI cụm \"trung điểm <PAIR>\" trong clause (vd \"M là trung điểm BC\n * và N là trung điểm AC\" → 2 add-point). Tên điểm bind THEO TỪNG MATCH cục bộ:\n * - dạng A: ký tự HOA NGAY TRƯỚC \"(là) trung điểm\" — KHÔNG quét lời dẫn\n * toàn clause (tránh \"Lấy điểm D, gọi M là trung điểm BC\" gán nhầm 'D').\n * - dạng B: ký tự HOA NGAY SAU \"trung điểm\" (\"trung điểm I của AB\").\n * Match nào không có tên cục bộ HOẶC cặp đỉnh không hợp lệ → BỎ QUA match đó\n * (escalate AI), không bịa tên.\n */\nexport const midpointRule: LanguageRule = {\n id: 'midpoint',\n priority: 50,\n languages: ['vi', 'en'],\n patterns: [MIDPOINT, MIDPOINT_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const hasVi = MIDPOINT.test(c.text);\n const hasEn = MIDPOINT_EN.test(c.text);\n if (!hasVi && !hasEn) continue;\n\n const emit = (name: string, pairToken: string, clauseId: number) => {\n const pair = pairFromToken(pairToken);\n if (!name || pair.length !== 2) return;\n out.push({\n ruleId: 'midpoint',\n clauseIds: [clauseId],\n intents: [addPoint(name, { kind: 'midpoint', of: pair.join('') })],\n });\n };\n\n if (hasVi) {\n // Distributive \"lần lượt\" ưu tiên: \"M, N lần lượt là trung điểm AB, AC\"\n // → M=mid(AB), N=mid(AC). Số tên = số cặp mới emit (else bỏ qua → escalate).\n const dm = DISTRIB.exec(c.text);\n if (dm) {\n const names = dm[1]\n .split(/\\s*,\\s*|\\s+và\\s+/u)\n .map((s) => nameToken(s))\n .filter((x): x is string => !!x);\n const pairs = dm[2]\n .split(/\\s*,\\s*|\\s+và\\s+/u)\n .map((s) => s.trim())\n .filter(Boolean);\n if (names.length >= 2 && names.length === pairs.length) {\n for (let i = 0; i < names.length; i++) emit(names[i], pairs[i], c.id);\n continue; // clause đã xử lý bằng distributive — skip dạng A/B + EN\n }\n }\n\n // Distributive NAME-AFTER: \"trung điểm của AC, AB lần lượt là K, L\".\n const da = DISTRIB_AFTER.exec(c.text);\n if (da) {\n const pairs = da[1].split(/\\s*,\\s*|\\s+và\\s+/u).map((s) => s.trim()).filter(Boolean);\n const names = da[2].split(/\\s*,\\s*|\\s+và\\s+/u).map((s) => nameToken(s)).filter((x): x is string => !!x);\n if (names.length >= 2 && names.length === pairs.length) {\n for (let i = 0; i < names.length; i++) emit(names[i], pairs[i], c.id);\n continue;\n }\n }\n\n // Theo dõi vị trí cụm \"trung điểm\" đã được dạng A claim, để dạng B không\n // nhân đôi cùng một occurrence.\n const consumed = new Set<number>();\n\n // Dạng A — tên đứng trước. Vị trí cụm \"trung điểm\" = chỉ số bắt đầu match\n // (gần đúng: match bắt đầu ở ký tự tên, \"trung điểm\" theo ngay sau).\n NAME_BEFORE_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_BEFORE_G)) {\n const tdIdx = c.text.indexOf('trung', m.index ?? 0);\n if (tdIdx >= 0) consumed.add(tdIdx);\n emit(m[1], m[2] + m[3], c.id);\n }\n\n // Dạng B — tên đứng sau \"trung điểm\". Bỏ qua occurrence đã được dạng A claim.\n NAME_AFTER_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_AFTER_G)) {\n const tdIdx = m.index ?? 0;\n if (consumed.has(tdIdx)) continue;\n emit(m[1], m[2] + m[3], c.id);\n }\n }\n\n // --- EN (issue #46 group B) — dạng A (name before) + B (name after) -----\n // EN dạng A khớp \"X is/be the midpoint of …\"; dạng B khớp \"midpoint X of …\".\n // 2 dạng không chồng (A cần \"is/be the\", B cần HOA ngay sau \"midpoint\") nên\n // KHÔNG cần consumed-set như VN.\n if (hasEn) {\n NAME_BEFORE_EN_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_BEFORE_EN_G)) {\n emit(m[1], m[2] + m[3], c.id);\n }\n NAME_AFTER_EN_G.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_AFTER_EN_G)) {\n emit(m[1], m[2] + m[3], c.id);\n }\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpBisector.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, pairFromToken } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Dùng lookaround \\p{L} (cờ 'u') thay cho \\b.\n//\n// \"(đường) trung trực (của) (đoạn|đoạn thẳng|cạnh) <PAIR>\"\n// \"đường trung trực của BC\" → connect('B','C','perpBisector')\n// \"trung trực AB\" → connect('A','B','perpBisector')\n// \"d là đường trung trực BC\" → connect('B','C','perpBisector') (tên 'd' bỏ qua;\n// connect không nhận name)\n//\n// Cụm nối giữa \"trung trực\" và cặp đỉnh: optional \"của\", \"đoạn\", \"đoạn thẳng\",\n// \"cạnh\" (lặp tự do). Cặp đỉnh = 2 ký tự HOA liền.\n// Cờ 'g' để bắt MỌI cụm \"trung trực <PAIR>\" trong 1 clause (vd \"trung trực BC\n// và trung trực CA\" → emit cả 2). Reset lastIndex trước mỗi clause.\nconst PERP_BISECTOR =\n /(?<!\\p{L})[Tt]rung\\s*trực\\s+(?:(?:của|đoạn|đoạn\\s+thẳng|cạnh)\\s+)*([A-Z][A-Z])(?!\\p{L})/gu;\n\n// \"(đường) trung trực (của) PAIR1 cắt [đường thẳng|đoạn|cạnh|tia]? PAIR2 tại D\":\n// đường trung trực CỦA PAIR1 (line dựng) ∩ đường PAIR2 = điểm D.\n// \"Đường trung trực của BC cắt AB tại D\" → perpBisector(B,C) + D=giao(pb_BC, AB)\n// group1 = PAIR1 (đoạn lấy trung trực); group2 = PAIR2 (đường bị cắt); group3 = D.\n//\n// perpBisector là LINE dựng (không phải đoạn) nên KHÔNG dùng intersection rule\n// generic (vốn chỉ nhận cặp đỉnh): rule này tự đặt perpBisector + intersection ref\n// TÊN shape mà connect builder sinh ('pb_<PAIR1>', deterministic + dedup JSON nên\n// duy nhất). PAIR1/PAIR2 chia sẻ đỉnh là BÌNH THƯỜNG (pb là đường khác đoạn PAIR2).\nconst PERP_BIS_CUT =\n /(?<!\\p{L})[Tt]rung\\s*trực\\s+(?:(?:của|đoạn|đoạn\\s+thẳng|cạnh)\\s+)*([A-Z][A-Z])(?!\\p{L})\\s+cắt\\s+(?:đường\\s*thẳng\\s+|đoạn(?:\\s+thẳng)?\\s+|cạnh\\s+|tia\\s+)?([A-Z][A-Z])(?!\\p{L})\\s+tại\\s+([A-Z])(?!\\p{L})/gu;\n\n// Phân phối: \"Trung trực của CA, AB cắt PA tại E, F\" → trung trực(CA)∩PA=E,\n// trung trực(AB)∩PA=F. group1=PAIR1, 2=PAIR2, 3=đường bị cắt, 4=P1, 5=P2.\nconst PERP_BIS_CUT_DISTRIB =\n /(?<!\\p{L})[Tt]rung\\s*trực\\s+(?:(?:của|đoạn|đoạn\\s+thẳng|cạnh)\\s+)*([A-Z][A-Z])\\s*,\\s*([A-Z][A-Z])(?!\\p{L})\\s+cắt\\s+(?:đường\\s*thẳng\\s+|đoạn(?:\\s+thẳng)?\\s+|cạnh\\s+|tia\\s+)?([A-Z][A-Z])(?!\\p{L})\\s+(?:lần\\s*lượt\\s+)?tại\\s+([A-Z])\\s*,\\s*([A-Z])(?!\\p{L})/gu;\n\n/** prefilter nhanh trên toàn đề. */\nconst PREFILTER = /[Tt]rung\\s*trực/u;\n\n// === EN (issue #46 group B) ===\n// \"(the)? perpendicular bisector (of|the|segment|line|side)* PAIR\" → connect(P1,P2,'perpBisector').\n// First-letter flex [Pp] (KHÔNG cờ 'i'). Global để bắt nhiều cụm/clause như VN.\nconst PERP_BISECTOR_EN =\n /[Pp]erpendicular\\s+bisector\\s+(?:(?:of|the|segment|line|side)\\s+)*([A-Z][A-Z])(?!\\p{L})/gu;\nconst PERP_BISECTOR_EN_PRE = /[Pp]erpendicular\\s+bisector/u;\n\n/**\n * \"(đường) trung trực của <PAIR>\" → connect(P1, P2, 'perpBisector').\n *\n * GLOBAL: 1 clause có thể chứa nhiều cụm trung trực (\"trung trực BC và trung\n * trực CA\") → emit connect cho MỖI cặp. Lấy cặp đỉnh ngay sau mỗi \"trung trực\"\n * (bỏ qua \"của/đoạn/cạnh\" xen giữa). Cụm không trích được cặp đỉnh hợp lệ →\n * bỏ qua cụm đó (escalate AI, an toàn hơn đoán sai). Tên đường (vd \"d là …\")\n * không cần — connect không nhận name.\n */\nexport const perpBisectorRule: LanguageRule = {\n id: 'perpBisector',\n priority: 70,\n languages: ['vi', 'en'],\n patterns: [PREFILTER, PERP_BISECTOR_EN_PRE],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n PERP_BISECTOR.lastIndex = 0; // regex 'g' có state — reset mỗi clause\n for (const m of c.text.matchAll(PERP_BISECTOR)) {\n const pair = pairFromToken(m[1]);\n if (pair.length !== 2) continue; // không trích được cặp đỉnh → bỏ cụm\n out.push({\n ruleId: 'perpBisector',\n clauseIds: [c.id],\n intents: [connect(pair[0], pair[1], 'perpBisector')],\n });\n }\n\n // \"trung trực PAIR1 cắt PAIR2 tại D\" → perpBisector(PAIR1) + giao điểm D.\n // Emit connect(perpBisector) NGAY TRƯỚC intersection (cùng match) để shape\n // 'pb_<PAIR1>' tồn tại khi transpile resolve ref của intersection (connect\n // trùng với loop plain ở trên sẽ bị dedup JSON → an toàn).\n PERP_BIS_CUT.lastIndex = 0;\n for (const m of c.text.matchAll(PERP_BIS_CUT)) {\n const pb = pairFromToken(m[1]);\n const line = pairFromToken(m[2]);\n const d = m[3];\n if (pb.length !== 2 || line.length !== 2) continue;\n // Giao điểm phải là điểm MỚI: D không trùng đỉnh nào của 2 cặp.\n if (new Set([pb[0], pb[1], line[0], line[1]]).has(d)) continue;\n const pbName = `pb_${pb[0]}${pb[1]}`; // khớp connect builder uniqueShapeName('pb_BC')\n out.push({\n ruleId: 'perpBisector',\n clauseIds: [c.id],\n intents: [\n connect(pb[0], pb[1], 'perpBisector'),\n addPoint(d, { kind: 'intersection', of: [pbName, m[2]] }),\n ],\n });\n }\n\n // Phân phối \"trung trực CA, AB cắt PA tại E, F\" → 2 perpBisector + 2 giao.\n PERP_BIS_CUT_DISTRIB.lastIndex = 0;\n for (const m of c.text.matchAll(PERP_BIS_CUT_DISTRIB)) {\n const pb1 = pairFromToken(m[1]);\n const pb2 = pairFromToken(m[2]);\n const line = pairFromToken(m[3]);\n const [d1, d2] = [m[4], m[5]];\n if (pb1.length !== 2 || pb2.length !== 2 || line.length !== 2 || d1 === d2) continue;\n out.push({\n ruleId: 'perpBisector',\n clauseIds: [c.id],\n intents: [\n connect(pb1[0], pb1[1], 'perpBisector'),\n connect(pb2[0], pb2[1], 'perpBisector'),\n addPoint(d1, { kind: 'intersection', of: [`pb_${pb1[0]}${pb1[1]}`, m[3]] }),\n addPoint(d2, { kind: 'intersection', of: [`pb_${pb2[0]}${pb2[1]}`, m[3]] }),\n ],\n });\n }\n\n // --- EN (issue #46 group B) — mirror VN: global, emit-all, escalate-safe ---\n PERP_BISECTOR_EN.lastIndex = 0;\n for (const m of c.text.matchAll(PERP_BISECTOR_EN)) {\n const pair = pairFromToken(m[1]);\n if (pair.length !== 2) continue;\n out.push({\n ruleId: 'perpBisector',\n clauseIds: [c.id],\n intents: [connect(pair[0], pair[1], 'perpBisector')],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/cevian.ts\n//\n// Cevian (đường đồng quy từ đỉnh): đường cao / trung tuyến / phân giác.\n// Phrasing thực tế: tên cevian dạng VF = đỉnh + chân (vd \"đường cao AH\",\n// \"AM là trung tuyến\", \"vẽ phân giác AD\"). Cần triangle context (ctx.problem)\n// để suy ra cạnh đối diện đỉnh = 2 đỉnh còn lại.\n//\n// Mỗi cevian khớp → RuleMatch với 2 intent cùng clauseId:\n// - add-point (chân: perpFoot / midpoint / angleBisectorFoot)\n// - connect (đoạn cevian visible VF, style segment)\n//\n// Nguyên tắc fail-safe:\n// - 1 clause có thể chứa NHIỀU cevian (cùng/khác loại): dùng matchAll (cờ /g)\n// để emit ĐỦ, không chỉ match đầu tiên.\n// - foot trùng đỉnh tam giác (\"đường cao AB\" → foot=B) → SKIP (đừng tạo\n// add-point sẽ bị builder hạ về 'free' → fidelity guard escalate).\n// - 2 cevian KHÁC nhau cùng đặt 1 tên chân (vd \"đường cao AH\" + \"trung tuyến\n// BH\" — cùng tên H nhưng ràng buộc mâu thuẫn) → SKIP tất cả cevian mang tên\n// chân đó (không claim → coverage escalate). Thà escalate còn hơn dựng SAI.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect } from './_shared';\n\n// Tam giác từ toàn đề (cần để suy cạnh đối diện). LƯU Ý: \\b không khớp quanh\n// ký tự Việt → dùng class trực tiếp, có cờ 'u'.\nconst TRI = /tam\\s*giác(?:\\s+(?:vuông|cân|đều|nhọn|tù))?\\s+([A-Z])([A-Z])([A-Z])/u;\n\n// === EN (issue #46 group B) =================================================\n// Tam giác tiếng Anh: \"triangle ABC\" (first-letter case flex [Tt], KHÔNG cờ 'i'\n// — sẽ phá [A-Z] nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]). Adjective\n// \"right/isosceles/…\" chỉ đứng TRƯỚC \"triangle\" nên vẫn khớp (vd \"right triangle\n// ABC\"). Đề VN không chứa \"triangle\" và đề EN không chứa \"tam giác\" → VN\n// byte-identical.\nconst TRI_EN = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\n\n// Cevian type → patterns. Mỗi pattern capture đỉnh (g1) + chân (g2): 2 ký tự\n// HOA liền (vd \"AH\"). (?![A-Z]) chặn match nhầm vào cụm 3 ký tự (vd \"ABC\").\n// TẤT CẢ pattern dùng cờ /g để matchAll bắt MỌI cevian trong 1 clause.\ntype CevianType = 'altitude' | 'median' | 'bisector' | 'externalBisector';\n\n// LƯU Ý case: KHÔNG dùng cờ 'i' (làm [A-Z] khớp chữ thường → bắt rác). Nhưng\n// keyword có thể HOA ở đầu câu (\"Đường cao AH\", \"Trung tuyến AM\", \"Phân giác AD\")\n// → ký tự đầu keyword + verb dùng [Xx]; vertices LUÔN strict [A-Z].\nconst CEVIAN_PATTERNS: ReadonlyArray<{ type: CevianType; patterns: readonly RegExp[] }> = [\n {\n type: 'altitude',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Hh]ạ|[Dd]ựng)\\s+[Đđ]ường\\s*cao\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /[Đđ]ường\\s*cao\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?đường\\s*cao/gu,\n // EN (issue #46 group B). g1=apex g2=foot, nhãn strict [A-Z], NO cờ 'i'.\n // First-letter flex [Aa] (HOA đầu câu \"Altitude AH\"); KHÔNG cờ 'i' (phá nhãn).\n // forward \"altitude AH\" (lời dẫn \"Draw the \" phía trước bỏ qua). \"foot of\n // the altitude from A to BC\" KHÔNG khớp: sau \"altitude\" là \"from\" (chữ\n // thường), không cặp HOA → perpFoot.ts sở hữu.\n /[Aa]ltitude\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n // reverse \"AH is/be the altitude\". (?![A-Za-z]) chặn \"altitudes\"/nối chữ.\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:is|be)\\s+(?:the\\s+)?altitude(?![A-Za-z])/gu,\n ],\n },\n {\n type: 'median',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+(?:[Đđ]ường\\s*)?[Tt]rung\\s*tuyến\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /[Tt]rung\\s*tuyến\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n // \"AM là (đường)? trung tuyến\" — \"đường\" tuỳ chọn (\"AM là đường trung tuyến\").\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?(?:đường\\s*)?trung\\s*tuyến/gu,\n // EN (issue #46 group B). g1=apex g2=foot. First-letter flex [Mm].\n /[Mm]edian\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:is|be)\\s+(?:the\\s+)?median(?![A-Za-z])/gu,\n ],\n },\n {\n // \"phân giác (trong) AD\": từ \"trong\" (phân giác TRONG = internal bisector,\n // loại thường) tuỳ chọn chen giữa \"phân giác\" và cặp đỉnh. \"phân giác NGOÀI\"\n // (external bisector) CHƯA hỗ trợ: forward tự reject (sau \"phân giác\" là chữ\n // thường \"ngoài\", không HOA pair); suffix cần (?!\\s+ngoài) để KHÔNG nhận nhầm\n // \"AD là phân giác ngoài\" thành internal → escalate (fail-safe).\n type: 'bisector',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+(?:[Đđ]ường\\s*|[Tt]ia\\s+)?phân\\s*giác(?:\\s+trong)?\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?:[Đđ]ường\\s*phân\\s*giác|[Tt]ia\\s+phân\\s*giác|[Pp]hân\\s*giác)(?:\\s+trong)?\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?(?:đường\\s*|tia\\s+)?phân\\s*giác(?:\\s+trong)?(?!\\s+ngoài)/gu,\n // EN (issue #46 group B) — internal bisector ONLY. g1=apex g2=foot.\n // forward \"(angle)? bisector AD\". 3 negative lookbehind:\n // (?<![Pp]erpendicular\\s) — \"perpendicular bisector AD\" thuộc perpBisector.ts\n // (EN regex của nó CŨNG khớp cặp HOA) → tránh double-emit.\n // (?<![Ee]xternal\\s)/(?<![Ee]xterior\\s) — external bisector EN DEFER → KHÔNG\n // nhận nhầm thành internal (silent-wrong).\n // Dạng \"of angle\"/\"angle bisector of\" (angleBisectorAngle.ts) tự loại: cần\n // cặp HOA NGAY sau \"bisector\", \"of\" chen vào sẽ phá khớp. First-letter flex\n // [Bb] (HOA đầu câu) — lookbehind PHẢI first-letter flex [Pp]/[Ee] để chặn cả\n // \"Perpendicular\"/\"External\" HOA đầu clause (else double-emit silent-wrong).\n /(?<![Pp]erpendicular\\s)(?<![Ee]xternal\\s)(?<![Ee]xterior\\s)(?:[Aa]ngle\\s+)?[Bb]isector\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n // reverse \"AD is/be the (angle)? bisector\". (?!\\s+of) chặn \"is the bisector\n // of …\" (thuộc angleBisectorAngle). \"the perpendicular/external bisector\"\n // tự loại: từ chen giữa \"the\" và \"bisector\" phá (?:angle\\s+)?bisector.\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:is|be)\\s+(?:the\\s+)?(?:angle\\s+)?bisector(?!\\s+of)(?![A-Za-z])/gu,\n ],\n },\n {\n // \"phân giác NGOÀI AD\" (external bisector, Issue #46 nhóm A). Nhánh RIÊNG,\n // BẮT BUỘC có từ \"ngoài\" sau \"phân giác\" (forward) hoặc trước/sau cặp đỉnh\n // (suffix). Phân giác ngoài ⊥ phân giác trong tại đỉnh → builder dựng qua\n // angleBisector(trong) + perpendicular. KHÔNG đụng pattern 'bisector' nội bộ\n // (vốn đã reject \"ngoài\" qua chữ thường forward + (?!\\s+ngoài) suffix).\n type: 'externalBisector',\n patterns: [\n /(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+(?:[Đđ]ường\\s*|[Tt]ia\\s+)?phân\\s*giác\\s+ngoài\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?:[Đđ]ường\\s*phân\\s*giác|[Tt]ia\\s+phân\\s*giác|[Pp]hân\\s*giác)\\s+ngoài\\s+([A-Z])([A-Z])(?![A-Z])/gu,\n /(?<![A-Z])([A-Z])([A-Z])\\s+(?:là\\s+|=\\s+)?(?:đường\\s*|tia\\s+)?phân\\s*giác\\s+ngoài/gu,\n ],\n },\n];\n\n// Distributive LIST: \"(các)? đường cao AD, BE, CF\" / \"trung tuyến AM, BN\" /\n// \"phân giác AD, BE\" — 1 keyword + ≥2 cặp đỉnh phẩy. Single-pattern chỉ bắt cặp\n// ĐẦU (cặp sau thiếu keyword). Capture blob → tách từng cặp (apex+foot).\n// Cặp đỉnh có thể có PRIME ở chân (\"BB'\", \"CC'\") — đề olympiad đặt chân đường cao\n// B', C'. apex = chữ đầu, foot = chữ + prime optional.\nconst PAIR_LIST = String.raw`(?:[A-Z][A-Z](?:['′])?\\s*,\\s*)+[A-Z][A-Z](?:['′])?`;\nconst CEVIAN_LISTS: ReadonlyArray<{ type: CevianType; re: RegExp }> = [\n { type: 'altitude', re: new RegExp(String.raw`[Đđ]ường\\s*cao\\s+(${PAIR_LIST})(?![A-Z])`, 'gu') },\n // Reverse-distributive (tên TRƯỚC, list): \"AD,BE,CF (là) (các) đường cao\"\n // (hinh9 #119: \"Gọi AD,BE,CF là các đường cao và H là trực tâm\"). DISTRIB_LIST\n // ở trên cần keyword TRƯỚC list nên bỏ sót dạng này. Capture group 1 = PAIR_LIST\n // (giống forward) → tái dùng nguyên path split→splitCevianPair→addCandidate\n // (apex=chữ đầu, foot=chữ sau, onLine=cạnh đối) — KHÔNG dựng lại logic chân.\n // CHỈ altitude (median/bisector reverse-list ngoài phạm vi). (?!\\p{L}) chặn\n // nuốt chữ nối (\"đường cao nhất\"…). dedup theo (apex,foot,type) né trùng single.\n {\n type: 'altitude',\n re: new RegExp(String.raw`(${PAIR_LIST})\\s+(?:là\\s+)?(?:các\\s+)?đường\\s*cao(?!\\p{L})`, 'gu'),\n },\n { type: 'median', re: new RegExp(String.raw`[Tt]rung\\s*tuyến\\s+(${PAIR_LIST})(?![A-Z])`, 'gu') },\n {\n type: 'bisector',\n re: new RegExp(String.raw`(?:[Đđ]ường\\s*phân\\s*giác|[Tt]ia\\s+phân\\s*giác|[Pp]hân\\s*giác)(?:\\s+trong)?\\s+(${PAIR_LIST})(?![A-Z])`, 'gu'),\n },\n];\n\n// Tách 1 token cặp \"BB'\" → [apex \"B\", foot \"B'\" (prime normalize ′→')].\nfunction splitCevianPair(tok: string): [string, string] | null {\n const m = /^([A-Z])([A-Z])(['′]?)$/u.exec(tok.trim());\n if (!m) return null;\n return [m[1], m[3] ? `${m[2]}'` : m[2]];\n}\n\n// Prefilter: bất kỳ từ khoá cevian nào trên toàn đề (hoa đầu câu → [Đđ]/[Tt]/[Pp]).\n// EN (issue #46 group B): runRules prefilter theo `patterns` (BỎ QUA field\n// `languages`) → đề EN thuần cần EN prefilter thì match() mới chạy. Đây là cờ\n// boolean .test() thuần (KHÔNG capture nhãn) nên cờ 'i' AN TOÀN.\nconst PREFILTER = [\n /[Đđ]ường\\s*cao/u,\n /[Tt]rung\\s*tuyến/u,\n /[Pp]hân\\s*giác/u,\n /median/i,\n /altitude/i,\n /bisector/i,\n];\n\n/** Cạnh đối diện đỉnh V trong tam giác = 2 đỉnh còn lại, join token (vd \"BC\"). */\nfunction opposite(tri: readonly string[], vertex: string): string | undefined {\n const rest = tri.filter((v) => v !== vertex);\n return rest.length === 2 ? rest[0] + rest[1] : undefined;\n}\n\ninterface Cevian {\n clauseId: number;\n type: CevianType;\n apex: string;\n foot: string;\n opp: string;\n}\n\n/**\n * \"đường cao AH\" / \"trung tuyến AM\" / \"phân giác AD\" → add-point(chân) +\n * connect(VF). apex PHẢI là đỉnh tam giác (else bỏ qua: tránh match nhầm\n * cặp như \"BD cắt\"). Không có tam giác hoặc apex ngoài tam giác → escalate.\n */\nexport const cevianRule: LanguageRule = {\n id: 'cevian',\n priority: 60,\n languages: ['vi', 'en'],\n patterns: PREFILTER,\n match(ctx) {\n // Tam giác gate: VN trước, EN fallback (mirror angleBisectorAngle). Đề VN\n // không chứa \"triangle\", đề EN không chứa \"tam giác\" → VN byte-identical.\n const triMatch = TRI.exec(ctx.problem);\n const triMatchEN = TRI_EN.exec(ctx.problem);\n const tri = triMatch\n ? [triMatch[1], triMatch[2], triMatch[3]]\n : triMatchEN\n ? [triMatchEN[1], triMatchEN[2], triMatchEN[3]]\n : null;\n if (!tri) return []; // không có tam giác → escalate\n\n // ── Pass 1: gom MỌI cevian hợp lệ (apex là đỉnh, foot không trùng đỉnh) ──\n // Dedup theo (apex,foot,type) — KHÔNG dedup chỉ theo tên chân: 2 cevian\n // khác nhau cùng tên chân là XUNG ĐỘT (xử ở pass 2), không phải trùng lặp.\n const candidates: Cevian[] = [];\n const seen = new Set<string>(); // \"apex|foot|type\"\n\n // Helper: thêm 1 cevian candidate sau khi validate apex/foot.\n const addCandidate = (clauseId: number, type: CevianType, apex: string, foot: string) => {\n if (!tri.includes(apex)) return;\n if (tri.includes(foot)) return;\n const opp = opposite(tri, apex);\n if (!opp) return;\n const key = `${apex}|${foot}|${type}`;\n if (seen.has(key)) return;\n seen.add(key);\n candidates.push({ clauseId, type, apex, foot, opp });\n };\n\n for (const c of ctx.clauses) {\n // Distributive list \"đường cao AD, BE, CF\" → tách từng cặp.\n for (const cl of CEVIAN_LISTS) {\n cl.re.lastIndex = 0;\n for (const m of c.text.matchAll(cl.re)) {\n for (const tok of m[1].split(',').map((s) => s.trim())) {\n const pair = splitCevianPair(tok);\n if (pair) addCandidate(c.id, cl.type, pair[0], pair[1]);\n }\n }\n }\n for (const cp of CEVIAN_PATTERNS) {\n for (const re of cp.patterns) {\n re.lastIndex = 0;\n for (const m of c.text.matchAll(re)) {\n const apex = m[1];\n const foot = m[2];\n // apex phải là đỉnh tam giác; else có thể là cặp cạnh ngẫu nhiên.\n if (!tri.includes(apex)) continue;\n // foot trùng đỉnh tam giác (\"đường cao AB\" → foot=B) → SKIP sớm:\n // builder sẽ hạ điểm về 'free' → fidelity guard escalate; bỏ ở đây\n // cho sạch (không claim → coverage escalate trực tiếp).\n if (tri.includes(foot)) continue;\n const opp = opposite(tri, apex);\n if (!opp) continue; // apex không suy ra được cạnh đối diện → bỏ qua\n\n const key = `${apex}|${foot}|${cp.type}`;\n if (seen.has(key)) continue;\n seen.add(key);\n candidates.push({ clauseId: c.id, type: cp.type, apex, foot, opp });\n }\n }\n }\n }\n\n // ── Pass 2: phát hiện XUNG ĐỘT tên chân ──\n // Nếu 1 tên chân được ≥2 cevian khác nhau đặt (vd \"đường cao AH\" +\n // \"trung tuyến BH\" cùng tên H, ràng buộc mâu thuẫn) → bỏ TẤT cevian mang\n // tên đó. Không claim → escalate (thà escalate còn hơn dựng SAI ngữ nghĩa).\n const footCount = new Map<string, number>();\n for (const cv of candidates) footCount.set(cv.foot, (footCount.get(cv.foot) ?? 0) + 1);\n\n const out: RuleMatch[] = [];\n for (const cv of candidates) {\n if ((footCount.get(cv.foot) ?? 0) > 1) continue; // tên chân xung đột → skip\n\n let pointIntent;\n if (cv.type === 'altitude') {\n pointIntent = addPoint(cv.foot, { kind: 'perpFoot', from: cv.apex, onLine: cv.opp });\n } else if (cv.type === 'median') {\n pointIntent = addPoint(cv.foot, { kind: 'midpoint', of: cv.opp });\n } else if (cv.type === 'externalBisector') {\n pointIntent = addPoint(cv.foot, {\n kind: 'externalAngleBisectorFoot',\n from: cv.apex,\n onLine: cv.opp,\n });\n } else {\n pointIntent = addPoint(cv.foot, {\n kind: 'angleBisectorFoot',\n from: cv.apex,\n onLine: cv.opp,\n });\n }\n\n out.push({\n ruleId: 'cevian',\n clauseIds: [cv.clauseId],\n intents: [pointIntent, connect(cv.apex, cv.foot, 'segment')],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/angleBisectorAngle.ts\n//\n// Phân giác theo GÓC (3-point angle, KHÔNG đặt tên chân) — Issue #46 nhóm A.\n//\n// Phrasing đề thi RẤT phổ biến: \"Vẽ tia phân giác của góc BAC\", \"phân giác góc\n// BAC\", \"đường phân giác của góc A\"… → vẽ phân giác TRONG của góc, VISIBLE,\n// KHÔNG có tên chân (khác hẳn cevian \"phân giác AD\" foot-named).\n//\n// Emit 1 intent draw-line/angleBisector (VISIBLE), KHÔNG add-point foot, KHÔNG\n// connect. vertex = đỉnh góc:\n// - \"góc XYZ\" (3 ký tự HOA): vertex = chữ GIỮA (Y), p1=X, p2=Z.\n// - \"góc A\" (1 ký tự, trong tam giác): vertex=A, p1/p2 = 2 đỉnh còn lại\n// (suy như cevian opposite). Không có tam giác để suy 2 tia → escalate.\n//\n// Discriminator: PHẢI có \"góc\" + (cụm 3 HOA HOẶC 1 HOA là đỉnh tam giác). KHÔNG\n// đụng cevian \"phân giác AD\"/\"phân giác ngoài AD\" (2 ký tự foot-named): cevian\n// pattern yêu cầu cặp HOA NGAY sau \"phân giác\", nhưng ở đây sau \"phân giác\" là\n// \"góc\" (chữ thường) → cevian không khớp → KHÔNG double-emit.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { drawLine } from './_shared';\n\n// Tam giác từ toàn đề (cần để suy 2 cạnh cho \"góc A\"). \\b không khớp quanh ký\n// tự Việt → dùng class trực tiếp, cờ 'u'.\nconst TRI = /tam\\s*giác(?:\\s+(?:vuông|cân|đều|nhọn|tù))?\\s+([A-Z])([A-Z])([A-Z])/u;\n\n// === EN (issue #46 group B) =================================================\n// Tam giác tiếng Anh: \"triangle ABC\" (first-letter case flex [Tt], KHÔNG cờ 'i'\n// — sẽ phá [A-Z] nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]). Không cần\n// 'g' (chỉ cần tam giác đầu tiên để fallback suy 2 cạnh, như TRI VN).\nconst TRI_EN = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\n\n// Prefilter: VN cần \"phân giác\" + \"góc\"; EN cần \"angle bisector\" (Form B) hoặc\n// \"bisector of (the)? angle/∠\" (Form A). `.some` → ANY khớp là trigger match().\n// \"languages\" là metadata thuần (runRules prefilter theo `patterns`, BỎ QUA nó).\nconst PREFILTER = [\n /[Pp]hân\\s*giác/u,\n /góc/u,\n /[Aa]ngle\\s+bisector/u, // Form B EN\n /[Bb]isector\\s+of\\s+(?:the\\s+)?(?:[Aa]ngle|∠)/u, // Form A EN\n];\n\n// \"phân giác … góc XYZ\" (3 ký tự HOA liền). (?![A-Z]) chặn cụm 4+ ký tự.\n// Cho phép cụm dẫn \"(đường|tia) phân giác (của)? góc\" — bổ ngữ optional.\n// \"(?:trong\\s+)?\" — bổ ngữ \"phân giác TRONG (của) góc …\" (phân giác trong =\n// phân giác mặc định angleBisector vẽ). \"ngoài\" KHÔNG nhận (phân giác ngoài =\n// construct khác). Trước đây \"trong\" chen vào phá khớp → bỏ sót (phang:14).\nconst ANGLE3 =\n /phân\\s*giác\\s+(?:trong\\s+)?(?:(?:của|cho)\\s+)?góc\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/giu;\n// \"phân giác … góc A\" (1 ký tự HOA, không theo sau bởi HOA khác → không phải 3-point).\nconst ANGLE1 =\n /phân\\s*giác\\s+(?:trong\\s+)?(?:(?:của|cho)\\s+)?góc\\s+([A-Z])(?![A-Z])/giu;\n\n// \"chân (của)? (đường|tia)? \" NGAY TRƯỚC \"phân giác\" → cụm \"CHÂN phân giác\" là\n// FOOT (điểm), thuộc angleBisectorFoot.ts. angleBisectorAngle né để KHÔNG vẽ tia\n// phân giác trùng (foot builder đã tự dựng tia bên trong) → tránh double-emit.\nconst CHAN_BEFORE = /chân\\s+(?:của\\s+)?(?:đường\\s*|tia\\s+)?$/u;\n\n// === EN regex (issue #46 group B) ===========================================\n// First-letter flex [Bb]/[Aa] (KHÔNG cờ 'i' — sẽ phá [A-Z] nhãn). Nhãn HOA\n// strict, neo (?![A-Z]). Cờ 'g' để emit-all + matchAll. Yêu cầu chữ\n// \"angle\"/∠ → KHÔNG khớp \"perpendicular bisector of BC\" (không có \"angle\").\n//\n// Form A: \"(the)? bisector of (the)? (angle|∠) XYZ\" — bổ ngữ \"the\" optional.\n// \"Draw the bisector of angle BAC.\" → {p1:B, vertex:A, p2:C}\n// Form B: \"(the)? angle bisector of XYZ\" — \"of\" sau \"bisector\", KHÔNG \"angle/∠\".\n// \"The angle bisector of MNP.\" → {M,N,P}\nconst ANGLE3_EN_A =\n /[Bb]isector\\s+of\\s+(?:the\\s+)?(?:[Aa]ngle|∠)\\s*([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\nconst ANGLE3_EN_B =\n /[Aa]ngle\\s+bisector\\s+of\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n// 1-letter \"angle A\" (Form A only — Form B \"angle bisector of A\" hiếm/mơ hồ,\n// defer). Cần tam giác EN để suy 2 cạnh.\nconst ANGLE1_EN_A =\n /[Bb]isector\\s+of\\s+(?:the\\s+)?(?:[Aa]ngle|∠)\\s*([A-Z])(?![A-Z])/gu;\n\n/** 2 đỉnh còn lại của tam giác (≠ vertex), giữ thứ tự xuất hiện trong tri. */\nfunction others(tri: readonly string[], vertex: string): string[] {\n return tri.filter((v) => v !== vertex);\n}\n\ninterface Hit {\n clauseId: number;\n p1: string;\n vertex: string;\n p2: string;\n}\n\n/**\n * \"phân giác (của) góc XYZ/A\" → draw-line/angleBisector VISIBLE (1 intent,\n * không foot, không connect). vertex = chữ giữa (3-point) hoặc đỉnh tam giác\n * (1-letter, suy 2 cạnh từ tam giác). Mơ hồ / không suy được 2 tia → escalate.\n */\nexport const angleBisectorAngleRule: LanguageRule = {\n id: 'angleBisectorAngle',\n // Cao hơn cevian (60) — chạy trước; tuy nhiên 2 rule không tranh chấp vì\n // discriminator \"góc\" loại cevian khỏi cụm này.\n priority: 62,\n languages: ['vi', 'en'],\n patterns: PREFILTER,\n match(ctx) {\n // Tam giác fallback (suy 2 cạnh cho \"góc A\"/\"angle A\"): VN trước, EN sau.\n // Đề VN không chứa \"triangle\" và đề EN không chứa \"tam giác\" → KHÔNG đụng\n // nhau (VN byte-identical).\n const triMatch = TRI.exec(ctx.problem);\n const triMatchEN = TRI_EN.exec(ctx.problem);\n const tri = triMatch\n ? [triMatch[1], triMatch[2], triMatch[3]]\n : triMatchEN\n ? [triMatchEN[1], triMatchEN[2], triMatchEN[3]]\n : null;\n\n const hits: Hit[] = [];\n const seen = new Set<string>(); // \"p1|vertex|p2\" dedup\n\n for (const c of ctx.clauses) {\n // ── 3-point \"góc XYZ\": vertex = chữ giữa, không cần tam giác ──\n ANGLE3.lastIndex = 0;\n for (const m of c.text.matchAll(ANGLE3)) {\n if (CHAN_BEFORE.test(c.text.slice(0, m.index))) continue; // \"chân … phân giác\" = foot\n const [p1, vertex, p2] = [m[1], m[2], m[3]];\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n\n // ── 1-letter \"góc A\": cần tam giác để suy 2 cạnh ──\n // Dùng pattern ANGLE1 nhưng BỎ QUA những match đã bị ANGLE3 nuốt (cùng vị\n // trí bắt đầu): so vị trí của vertex 1-letter với các 3-point đã thấy.\n ANGLE1.lastIndex = 0;\n for (const m of c.text.matchAll(ANGLE1)) {\n if (CHAN_BEFORE.test(c.text.slice(0, m.index))) continue; // \"chân … phân giác\" = foot\n const vertex = m[1];\n if (!tri) continue; // không tam giác → escalate\n if (!tri.includes(vertex)) continue; // đỉnh ngoài tam giác → bỏ qua\n const rest = others(tri, vertex);\n if (rest.length !== 2) continue; // không suy được 2 tia → bỏ qua\n const [p1, p2] = rest;\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n\n // ── EN 3-point: Form A \"(bisector of) angle XYZ\" + Form B \"angle bisector\n // of XYZ\". vertex = chữ giữa, không cần tam giác. seen dedup chung VN.\n for (const re of [ANGLE3_EN_A, ANGLE3_EN_B]) {\n re.lastIndex = 0;\n for (const m of c.text.matchAll(re)) {\n const [p1, vertex, p2] = [m[1], m[2], m[3]];\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n }\n\n // ── EN 1-letter \"angle A\" (Form A): cần tam giác EN/VN để suy 2 cạnh.\n ANGLE1_EN_A.lastIndex = 0;\n for (const m of c.text.matchAll(ANGLE1_EN_A)) {\n const vertex = m[1];\n if (!tri) continue; // không tam giác → escalate\n if (!tri.includes(vertex)) continue; // đỉnh ngoài tam giác → bỏ qua\n const rest = others(tri, vertex);\n if (rest.length !== 2) continue; // không suy được 2 tia → bỏ qua\n const [p1, p2] = rest;\n const key = `${p1}|${vertex}|${p2}`;\n if (seen.has(key)) continue;\n seen.add(key);\n hits.push({ clauseId: c.id, p1, vertex, p2 });\n }\n }\n\n return hits.map<RuleMatch>((h) => ({\n ruleId: 'angleBisectorAngle',\n clauseIds: [h.clauseId],\n intents: [\n drawLine(`bis${h.p1}${h.vertex}${h.p2}`, 'angleBisector', {\n p1: h.p1,\n vertex: h.vertex,\n p2: h.p2,\n }) as IntentT,\n ],\n }));\n },\n};\n","// src/stamps/geometry-2d/ai/rules/centers.ts\n//\n// Tâm tam giác: trọng tâm (centroid), trực tâm (orthocenter), tâm đường tròn\n// ngoại tiếp (circumcenter), tâm đường tròn nội tiếp (incenter).\n//\n// Mọi kind này cần bộ 3 đỉnh of=[A,B,C]. Bind theo tam giác NÊU TRONG CÙNG\n// CLAUSE với cụm từ khoá (vd \"trọng tâm tam giác DEF\" → of=[D,E,F]) — KHÔNG lấy\n// tam giác đầu đề. Chỉ fallback tam giác toàn đề khi clause không nêu tam giác\n// nào VÀ đề có ĐÚNG 1 tam giác. Nhập nhằng (clause không nêu, đề >1 tam giác)\n// → bỏ qua (escalate). Không có tam giác nào → bỏ qua (escalate).\n// Tên điểm phải trích được (HOA ngay sau cụm từ khoá, hoặc \"X là <từ khoá>\");\n// nếu không → bỏ qua, KHÔNG bịa tên.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// Tam giác (global): quét mọi tam giác nêu trong một đoạn text.\nconst TRI_G = /tam giác\\s+(?:(?:cân|vuông|đều|nhọn|tù)(?:\\s+(?:tại|ở|đỉnh|có\\s+ba\\s+góc))?\\s+)*(?:[^\\s,.;:()]*\\s+){0,2}?([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n// === EN (issue #46 group B) =================================================\n// Tam giác tiếng Anh: \"triangle ABC\" (first-letter case flex [Tt], KHÔNG cờ 'i'\n// — sẽ phá [A-Z] nhãn). Nhãn = ĐÚNG 3 ký tự HOA liền, neo (?![A-Z]). ADDITIVE:\n// quét THÊM cùng TRI_G; merge theo vị trí TEXT để VN behavior giữ nguyên.\nconst TRI_EN_G = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n// Từ khoá tâm. \\b không khớp quanh ký tự Việt nên dùng lookaround \\p{L}.\n// \"trọng tâm\" — chặn nhầm với \"trung tâm\" bằng cách yêu cầu đúng \"trọng\".\nconst CENTROID_KW = /(?<!\\p{L})trọng\\s*tâm(?!\\p{L})/u;\n// \"trực tâm\" — chặn nhầm với \"trung trực\" (kết thúc bằng \"trực\", không phải \"trực tâm\").\nconst ORTHO_KW = /(?<!\\p{L})trực\\s*tâm(?!\\p{L})/u;\n// \"ngoại tiếp\" → circumcenter.\nconst CIRCUM_KW = /(?<!\\p{L})ngoại\\s*tiếp(?!\\p{L})/u;\n// \"nội tiếp\" → incenter (chỉ khi nói về TÂM, không phải \"tam giác nội tiếp đường tròn\").\nconst INSCRIBE_KW = /(?<!\\p{L})nội\\s*tiếp(?!\\p{L})/u;\n// \"tâm (đường tròn) nội tiếp\" tường minh = incenter THẬT (phân biệt \"tam giác …\n// nội tiếp\"). Dùng để cho phép incenter SONG SONG circumcenter cùng clause\n// (vd \"tâm ngoại tiếp O và tâm nội tiếp I\").\nconst TAM_INSCRIBE = /(?<!\\p{L})tâm\\s*(?:đường\\s*tròn\\s*)?nội\\s*tiếp(?!\\p{L})/u;\n// Tên tâm đứng trước \"tâm\" qua \"là\": \"O là tâm\", \"Gọi O là tâm (đường tròn)…\".\nconst NAME_BEFORE_TAM = /(?<!\\p{L})([A-Z])\\s+là\\s+tâm(?!\\p{L})/u;\n\n// Distributive tâm: \"O và H lần lượt là tâm (đường tròn)? ngoại tiếp và trực\n// tâm (của tam giác ABC)?\" → O=circumcenter, H=orthocenter (zip tên↔loại). Hỗ\n// trợ mọi cặp loại tâm. Bài 30/31/84.\nconst CENTER_TYPE =\n '(tâm\\\\s*(?:đường\\\\s*tròn\\\\s*)?ngoại\\\\s*tiếp|tâm\\\\s*(?:đường\\\\s*tròn\\\\s*)?nội\\\\s*tiếp|trực\\\\s*tâm|trọng\\\\s*tâm)';\nconst DISTRIB_CENTERS = new RegExp(\n `([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])\\\\s+lần\\\\s*lượt\\\\s+là\\\\s+${CENTER_TYPE}\\\\s+và\\\\s+${CENTER_TYPE}` +\n '(?:\\\\s+(?:của\\\\s+)?tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z]))?',\n 'u',\n);\n// Incenter ĐẶT TÊN tường minh qua cụm \"tâm (đường tròn)? nội tiếp\": \"I là tâm\n// đường tròn nội tiếp\" / \"tâm đường tròn nội tiếp (tam giác XYZ)? là I\". Dùng\n// khi clause CŨNG có \"nội tiếp\" theo nghĩa tam-giác-nội-tiếp-(O) (INSCRIBE_KW\n// thường khớp nhầm occurrence đầu) — Bài 84.\nconst INCENTER_NAMED = /(?:([A-Z])\\s+là\\s+tâm\\s*(?:đường\\s*tròn\\s*)?nội\\s*tiếp|tâm\\s*(?:đường\\s*tròn\\s*)?nội\\s*tiếp(?:\\s+tam\\s*giác\\s+[A-Z]{3})?\\s+là\\s+([A-Z])(?!\\p{L}))/u;\n\nfunction centerTypeToKind(t: string): 'circumcenter' | 'incenter' | 'orthocenter' | 'centroid' {\n if (/ngoại/u.test(t)) return 'circumcenter';\n if (/nội/u.test(t)) return 'incenter';\n if (/trực/u.test(t)) return 'orthocenter';\n return 'centroid';\n}\n\n// === EN keyword (issue #46 group B) =========================================\n// Từ khoá tâm tiếng Anh. First-letter case flex ([Cc], [Oo]…) — KHÔNG cờ 'i'\n// (sẽ phá [A-Z] nhãn). British spelling -centre cũng nhận. Neo (?![A-Za-z]) để\n// không khớp giữa từ dài hơn. centroid → centroid; orthocenter/-centre →\n// orthocenter; circumcenter/-centre → circumcenter; incenter/-centre → incenter.\nconst CENTROID_KW_EN = /(?<![A-Za-z])[Cc]entroid(?![A-Za-z])/u;\nconst ORTHO_KW_EN = /(?<![A-Za-z])[Oo]rthocent(?:er|re)(?![A-Za-z])/u;\nconst CIRCUM_KW_EN = /(?<![A-Za-z])[Cc]ircumcent(?:er|re)(?![A-Za-z])/u;\nconst INCENTER_KW_EN = /(?<![A-Za-z])[Ii]ncent(?:er|re)(?![A-Za-z])/u;\n\n// Tên điểm đứng NGAY SAU cụm từ khoá: \"trọng tâm G\", \"tâm (đường tròn) ngoại tiếp O\".\nfunction nameAfter(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const rest = text.slice(m.index + m[0].length);\n // bỏ qua các từ chêm phổ biến (\"của\", \"là\", \"tam giác\", \"đường tròn\", dấu câu)\n const after = /^[\\s,:của là]*?(?:tam\\s*giác\\s+)?([A-Z])(?!\\p{L})/u.exec(rest);\n return after ? after[1] : undefined;\n}\n\n// Tên điểm đứng TRƯỚC cụm từ khoá: \"G là trọng tâm\", \"H là trực tâm\".\nfunction nameBefore(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const before = text.slice(0, m.index);\n // \"...<HOA> (là)? \" ngay trước từ khoá\n const mm = /(?<!\\p{L})([A-Z])\\s+(?:là\\s+)?$/u.exec(before);\n return mm ? mm[1] : undefined;\n}\n\nfunction resolveName(text: string, kw: RegExp): string | undefined {\n return nameBefore(text, kw) ?? nameAfter(text, kw);\n}\n\n// Tâm đường tròn ngoại/nội tiếp: tên đứng trước \"tâm\" (qua \"là\") — vd \"Gọi O là\n// tâm đường tròn ngoại tiếp\" — hoặc sau cụm từ khoá — vd \"ngoại tiếp O\".\nfunction resolveCenterName(text: string, kw: RegExp): string | undefined {\n const before = NAME_BEFORE_TAM.exec(text);\n if (before) return before[1];\n return nameAfter(text, kw);\n}\n\n// --- EN name resolution (issue #46 group B) ---------------------------------\n// Tên điểm đứng TRƯỚC cụm từ khoá EN qua \"is/be the\": \"G is the centroid\",\n// \"Let H be the orthocenter\". Tên = ký tự HOA NGAY TRƯỚC \"is/be the <kw>\"\n// (cục bộ, KHÔNG quét lời dẫn toàn clause). KHÔNG cờ 'i' (giữ [A-Z]).\nfunction nameBeforeEn(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const before = text.slice(0, m.index);\n // \"...<HOA> (is|be) the \" ngay trước từ khoá.\n const mm = /(?<![A-Za-z])([A-Z])\\s+(?:is|be)\\s+the\\s+$/u.exec(before);\n return mm ? mm[1] : undefined;\n}\n\n// Tên điểm đứng NGAY SAU cụm từ khoá EN: \"centroid G\", \"orthocenter H\".\n// Bỏ qua từ chêm \"of\"/\"the\" KHÔNG được phép ở đây — nếu sau từ khoá là \"of …\"\n// (vd \"centroid of triangle ABC\") thì KHÔNG có tên điểm → undefined (fail-safe,\n// KHÔNG bịa tên).\nfunction nameAfterEn(text: string, kw: RegExp): string | undefined {\n const m = kw.exec(text);\n if (!m) return undefined;\n const rest = text.slice(m.index + m[0].length);\n const after = /^\\s+([A-Z])(?![A-Za-z])/u.exec(rest);\n return after ? after[1] : undefined;\n}\n\nfunction resolveNameEn(text: string, kw: RegExp): string | undefined {\n return nameBeforeEn(text, kw) ?? nameAfterEn(text, kw);\n}\n\n/** Một tam giác phát hiện trong text: bộ 3 đỉnh + offset bắt đầu match. */\ninterface TriHit {\n tri: string[];\n index: number;\n}\n\n/**\n * Tập tam giác (bộ 3 đỉnh + vị trí) nêu trong một đoạn text, gồm CẢ VN\n * (\"tam giác ABC\") VÀ EN (\"triangle ABC\"), sắp theo vị trí TEXT. ADDITIVE:\n * với đề thuần VN, chỉ TRI_G khớp ⇒ kết quả identical với hành vi cũ.\n */\nfunction triangleHits(text: string): TriHit[] {\n const hits: TriHit[] = [];\n TRI_G.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(text)) !== null) {\n hits.push({ tri: [m[1], m[2], m[3]], index: m.index });\n }\n TRI_EN_G.lastIndex = 0;\n while ((m = TRI_EN_G.exec(text)) !== null) {\n hits.push({ tri: [m[1], m[2], m[3]], index: m.index });\n }\n hits.sort((a, b) => a.index - b.index);\n return hits;\n}\n\n/**\n * Tập tam giác (mỗi tam giác = bộ 3 đỉnh) nêu trong một đoạn text. Trùng (cùng\n * 3 chữ liền) được giữ theo lượt xuất hiện; caller dedup nếu cần.\n */\nfunction trianglesIn(text: string): string[][] {\n return triangleHits(text).map((h) => h.tri);\n}\n\n/**\n * Tam giác để bind 'of' cho 1 clause:\n * 1. Ưu tiên tam giác nêu NGAY TRONG clause (gần cụm từ khoá nhất theo index).\n * 2. Nếu clause không nêu tam giác nào → fallback tam giác toàn đề CHỈ KHI đề\n * có duy nhất 1 tam giác (theo bộ đỉnh, dedup). Nhiều tam giác → undefined\n * (nhập nhằng, escalate). Không có tam giác → undefined.\n */\nfunction resolveTriangle(\n clauseText: string,\n kwIndex: number,\n uniqueProblemTri: string[] | undefined,\n): string[] | undefined {\n const inClause = triangleHits(clauseText);\n if (inClause.length > 0) {\n // chọn tam giác gần cụm từ khoá nhất (ưu tiên đứng SAU; nếu không có thì lấy\n // tam giác gần nhất bất kể phía). Gồm cả tam giác VN lẫn EN trong clause.\n let best: { tri: string[]; dist: number } | undefined;\n for (const h of inClause) {\n const idx = h.index;\n // khoảng cách: ưu tiên tam giác đứng sau từ khoá (idx >= kwIndex).\n const after = idx >= kwIndex;\n const dist = Math.abs(idx - kwIndex) + (after ? 0 : 1_000);\n if (!best || dist < best.dist) best = { tri: h.tri, dist };\n }\n return best?.tri;\n }\n return uniqueProblemTri;\n}\n\n/**\n * Tâm tam giác → add-point với of=[A,B,C]. Một clause có thể nêu nhiều tâm\n * (vd \"trọng tâm G và trực tâm H\"); emit từng intent, cùng claim clause.\n */\nexport const centersRule: LanguageRule = {\n id: 'centers',\n priority: 70,\n languages: ['vi', 'en'],\n patterns: [\n CENTROID_KW,\n ORTHO_KW,\n CIRCUM_KW,\n INSCRIBE_KW,\n CENTROID_KW_EN,\n ORTHO_KW_EN,\n CIRCUM_KW_EN,\n INCENTER_KW_EN,\n ],\n match(ctx) {\n // Tam giác duy nhất toàn đề (dedup theo bộ đỉnh) — dùng làm fallback khi\n // clause KHÔNG tự nêu tam giác. Nhiều tam giác khác nhau → undefined (nhập\n // nhằng → escalate). Không có → undefined (không dựng được → escalate).\n const allTri = trianglesIn(ctx.problem);\n const distinct = new Set(allTri.map((t) => t.join('')));\n const uniqueProblemTri = distinct.size === 1 ? allTri[0] : undefined;\n\n // helper: bind 'of' cho 1 cụm từ khoá tại vị trí kwIndex trong clause.\n const ofFor = (text: string, kw: RegExp): string[] | undefined => {\n const m = kw.exec(text);\n const kwIndex = m ? m.index : 0;\n return resolveTriangle(text, kwIndex, uniqueProblemTri);\n };\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents = [];\n\n // Distributive \"N1 và N2 lần lượt là <loại1> và <loại2>\" — zip tên↔loại.\n const dc = DISTRIB_CENTERS.exec(c.text);\n if (dc) {\n const of = dc[5] && dc[6] && dc[7] ? [dc[5], dc[6], dc[7]] : uniqueProblemTri;\n if (of) {\n intents.push(addPoint(dc[1], { kind: centerTypeToKind(dc[3]), of }));\n intents.push(addPoint(dc[2], { kind: centerTypeToKind(dc[4]), of }));\n out.push({ ruleId: 'centers', clauseIds: [c.id], intents });\n continue; // clause đã xử lý bằng distributive\n }\n }\n\n if (CENTROID_KW.test(c.text)) {\n const name = resolveName(c.text, CENTROID_KW);\n const of = ofFor(c.text, CENTROID_KW);\n if (name && of) intents.push(addPoint(name, { kind: 'centroid', of }));\n }\n if (ORTHO_KW.test(c.text)) {\n const name = resolveName(c.text, ORTHO_KW);\n const of = ofFor(c.text, ORTHO_KW);\n if (name && of) intents.push(addPoint(name, { kind: 'orthocenter', of }));\n }\n // circumcenter: \"ngoại tiếp\".\n let circumName: string | undefined;\n if (CIRCUM_KW.test(c.text)) {\n circumName = resolveCenterName(c.text, CIRCUM_KW);\n const of = ofFor(c.text, CIRCUM_KW);\n if (circumName && of) intents.push(addPoint(circumName, { kind: 'circumcenter', of }));\n }\n // incenter: \"nội tiếp\". Khi clause CŨNG có \"ngoại tiếp\", chỉ emit nếu có\n // cụm \"tâm … nội tiếp\" tường minh + tên RIÊNG (vd \"tâm ngoại tiếp O và tâm\n // nội tiếp I\") — tránh nuốt incenter. Không có \"tâm …\" ⇒ giữ guard cũ (ưu\n // tiên ngoại tiếp, né nhập nhằng \"tam giác nội tiếp\").\n if (INSCRIBE_KW.test(c.text)) {\n const allow = CIRCUM_KW.test(c.text) ? TAM_INSCRIBE.test(c.text) : true;\n // Ưu tiên tên qua cụm \"tâm … nội tiếp … là I\"/\"I là tâm … nội tiếp\"\n // (tường minh, không nhầm với \"tam giác nội tiếp (O)\") — Bài 84.\n const namedM = INCENTER_NAMED.exec(c.text);\n const name = (namedM && (namedM[1] ?? namedM[2])) ?? resolveCenterName(c.text, INSCRIBE_KW);\n const of = ofFor(c.text, INSCRIBE_KW);\n if ((allow || namedM) && name && of && name !== circumName) {\n intents.push(addPoint(name, { kind: 'incenter', of }));\n }\n }\n\n // --- EN (issue #46 group B) — mirror VN semantics, mỗi từ khoá độc lập --\n // Các danh từ tâm EN là chính tả riêng biệt (centroid/orthocenter/\n // circumcenter/incenter) nên KHÔNG nhập nhằng lẫn nhau như \"ngoại/nội\n // tiếp\" VN — xử lý từng cái độc lập. Tên + of giải qua helper EN; thiếu\n // tên HOẶC of không bind được → bỏ qua (escalate, KHÔNG bịa).\n if (CENTROID_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, CENTROID_KW_EN);\n const of = ofFor(c.text, CENTROID_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'centroid', of }));\n }\n if (ORTHO_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, ORTHO_KW_EN);\n const of = ofFor(c.text, ORTHO_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'orthocenter', of }));\n }\n if (CIRCUM_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, CIRCUM_KW_EN);\n const of = ofFor(c.text, CIRCUM_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'circumcenter', of }));\n }\n if (INCENTER_KW_EN.test(c.text)) {\n const name = resolveNameEn(c.text, INCENTER_KW_EN);\n const of = ofFor(c.text, INCENTER_KW_EN);\n if (name && of) intents.push(addPoint(name, { kind: 'incenter', of }));\n }\n\n if (intents.length > 0) {\n out.push({ ruleId: 'centers', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpFoot.ts\n//\n// Hình chiếu vuông góc / chân đường vuông góc (đường cao):\n// \"Gọi H là hình chiếu (vuông góc) của A trên/lên/xuống (đường thẳng|cạnh)? BC\"\n// \"Gọi H là chân đường vuông góc (hạ|kẻ) từ A (đến|xuống) BC\"\n// \"H, K lần lượt là hình chiếu của B trên AC và của C trên AB\" → 2 foot\n// → addPoint('H', { kind:'perpFoot', from:'A', onLine:'BC' })\n//\n// onLine giữ nguyên token sau giới từ (pair 'BC' hoặc tên đường 1 ký tự 'd').\n//\n// Tên foot bind CỤC BỘ (ký tự HOA + \"là\" NGAY TRƯỚC cụm \"hình chiếu\"/\"chân đường\"),\n// KHÔNG lấy lời dẫn đầu clause — tránh gán nhầm cho \"Gọi N là điểm bất kỳ, H là …\".\n// Match GLOBAL để dựng đủ nhiều foot trong cùng clause.\n//\n// SKIP (để pipeline escalate AI thay vì đoán sai):\n// - không trích được tên foot cục bộ;\n// - modifier \"trung điểm (của)? hình chiếu …\" — đổi nghĩa, foot không còn là điểm cần dựng.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, DUONG_KW } from './_shared';\n\n// LƯU Ý: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt. Mọi\n// regex chứa ký tự Việt dùng cờ 'u' + tránh \\b.\n\n// Prefilter toàn đề: \"hình chiếu\" / \"chân đường (cao|vuông góc)\" / ký hiệu ⊥ /\n// \"vuông góc\" (cho dạng \"Kẻ AH ⊥ BC tại H\"). \"vuông góc\" rộng nhưng match() chỉ\n// emit khi pattern khớp thật → an toàn.\nconst PREFILTER = new RegExp(\n 'hình\\\\s*chiếu|chân\\\\s+(?:của\\\\s+)?' +\n DUONG_KW +\n '\\\\s+(?:cao|vuông\\\\s*góc)|' +\n DUONG_KW +\n '\\\\s*cao|⊥|vuông\\\\s*góc',\n 'u',\n);\n// EN prefilter (issue #46 group B). runRules prefilter theo `patterns` (BỎ QUA\n// field `languages`) → BẮT BUỘC có 1 EN regex thì match() mới chạy cho đề EN\n// thuần. Rộng nhưng match() chỉ emit khi core khớp thật → an toàn.\nconst PREFILTER_EN = /projection|perpendicular|foot\\s+of/i;\n\n// onLine token: tên đường 1 ký tự HOA HOẶC cặp đỉnh 2 ký tự HOA (vd 'BC'). Chấp\n// nhận tiền tố \"đường thẳng\" / \"cạnh\" / \"đoạn\" trước token.\nconst LINE = '(?:' + DUONG_KW + '\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?([A-Z]{1,2})(?![A-Z])';\nconst PREP = '(?:trên|lên|xuống|đến|tới)';\n// \"lần lượt\" và các biến thể đồng nghĩa \"(theo)? thứ tự\" (vao10:218 \"M, N thứ tự\n// là hình chiếu …\"). Optional — chỉ THÊM match, không đổi ngữ nghĩa.\nconst LANLUOT_OPT = '(?:(?:lần\\\\s*lượt|theo\\\\s+thứ\\\\s+tự|thứ\\\\s+tự)\\\\s+)?';\n\n// \"hình chiếu (vuông góc)? (của)? (điểm)? X PREP [cạnh|đường thẳng] LINE\"\nconst PROJ_CORE = `hình\\\\s*chiếu\\\\s+(?:vuông\\\\s*góc\\\\s+)?(?:của\\\\s+)?(?:điểm\\\\s+)?([A-Z])\\\\s+${PREP}\\\\s+${LINE}`;\n// \"chân đường (vuông góc|cao) (hạ|kẻ|vẽ|dựng)? (từ)? (điểm)? X PREP LINE\"\nconst FOOT_CORE = `chân\\\\s+(?:của\\\\s+)?${DUONG_KW}\\\\s+(?:vuông\\\\s*góc|cao)\\\\s*(?:hạ\\\\s+|kẻ\\\\s+|vẽ\\\\s+|dựng\\\\s+)?(?:từ\\\\s+)?(?:điểm\\\\s+)?([A-Z])\\\\s+${PREP}\\\\s+${LINE}`;\n\n// Phân phối \"X, Y lần lượt là <core của FROM1 ... LINE1> và (của|từ)? FROM2 PREP LINE2\".\n// groups: 1=name1 2=name2 | PROJ: 3=from1 4=line1 | FOOT: 5=from1 6=line1 | tail: 7=from2 8=line2\nconst LANLUOT = new RegExp(\n `([A-Z])(?:[′'])?\\\\s*,\\\\s*([A-Z])(?:[′'])?\\\\s+lần\\\\s+lượt\\\\s+là\\\\s+(?:${PROJ_CORE}|${FOOT_CORE})\\\\s+và\\\\s+(?:của\\\\s+|từ\\\\s+)?([A-Z])\\\\s+${PREP}\\\\s+${LINE}`,\n 'gu',\n);\n\n// Một foot đơn (projection hoặc chân đường).\n// groups: PROJ 1=from 2=line | FOOT 3=from 4=line\nconst SINGLE = new RegExp(`(?:${PROJ_CORE})|(?:${FOOT_CORE})`, 'gu');\n\n// Distributive SHARED-FROM: \"X, Y, Z lần lượt là hình chiếu (vuông góc)? của D\n// trên BC, CA, AB\" → zip tên↔cạnh, MỘT `from` (D) chung. KHÁC LANLUOT (2 chân,\n// mỗi chân from riêng, nối \"và\"): ở đây 1 from + DANH SÁCH cạnh ngăn phẩy (≥2).\n// Số tên PHẢI bằng số cạnh (else bỏ → escalate, không đoán lệch).\n// groups: 1=names blob (≥2, phẩy) | 2=from | 3=lines blob (≥2, phẩy)\nconst NAMES_BLOB = \"((?:[A-Z](?:['′]?)\\\\s*(?:,|và)\\\\s*)+[A-Z](?:['′]?))\";\n// Cạnh ngăn bằng \",\" HOẶC \"và\" (vd \"BC,CN và NB\" — dấu cuối là \"và\").\nconst LINES_BLOB = '((?:[A-Z]{1,2}\\\\s*(?:,|và)\\\\s*)+[A-Z]{1,2})(?!\\\\p{L})';\n// Tiền tố trước DANH SÁCH cạnh: \"(các)? (đường thẳng|cạnh|đoạn)?\".\nconst LINES_PREFIX = '(?:các\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?';\n// \"lần lượt\" optional → bắt cả \"X, Y là các hình chiếu của F trên L1, L2\".\nconst DISTRIB_PROJ = new RegExp(\n NAMES_BLOB +\n '\\\\s+' + LANLUOT_OPT + '(?:là\\\\s+)?(?:các\\\\s+)?hình\\\\s*chiếu\\\\s+(?:vuông\\\\s*góc\\\\s+)?(?:của\\\\s+)?(?:điểm\\\\s+)?([A-Z])(?!\\\\p{L})' +\n '\\\\s+(?:trên|lên|xuống|đến)\\\\s+' +\n LINES_PREFIX +\n LINES_BLOB,\n 'gu',\n);\nconst DISTRIB_FOOT = new RegExp(\n NAMES_BLOB +\n '\\\\s+' + LANLUOT_OPT + '(?:là\\\\s+)?(?:các\\\\s+)?chân\\\\s+(?:của\\\\s+)?(?:các\\\\s+)?đường\\\\s+(?:vuông\\\\s*góc|cao)\\\\s*(?:hạ\\\\s+|kẻ\\\\s+|vẽ\\\\s+|dựng\\\\s+)?(?:từ\\\\s+)?(?:điểm\\\\s+)?([A-Z])(?!\\\\p{L})' +\n '\\\\s+(?:đến|xuống|trên|tới)\\\\s+' +\n LINES_PREFIX +\n LINES_BLOB,\n 'gu',\n);\n\n// SHARED-FROM 2 đường nối bằng \"và\": \"I, K lần lượt là hình chiếu (vuông góc)?\n// của H trên AC và BC\" → I↔AC, K↔BC, MỘT from H. KHÁC DISTRIB_* (danh sách cạnh\n// ngăn PHẨY ≥2): ở đây ĐÚNG 2 cạnh nối \"và\". Hỗ trợ cả \"hình chiếu\" lẫn \"chân\n// đường (vuông góc|cao)\".\n// groups: 1=name1 2=name2 3=from 4=line1 5=line2\nconst TWO_LINES_PREP = '(?:trên|lên|xuống|đến|tới)';\nconst TWO_LINES_LINE = '(?:các\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])';\n// Tên ngăn bằng \",\" HOẶC \"và\" (\"E, F\" / \"E và F\"). Cụm \"chân đường vuông góc\"\n// cho phép verb dựng \"(kẻ|hạ|vẽ|dựng)\" giữa \"vuông góc\" và \"(từ|của)\".\nconst SHARED_FROM_TWO = new RegExp(\n \"([A-Z])(?:['′])?\\\\s*(?:,|và)\\\\s*([A-Z])(?:['′])?\\\\s+(?:lần\\\\s+lượt\\\\s+)?(?:là\\\\s+)?(?:các\\\\s+)?\" +\n '(?:hình\\\\s*chiếu\\\\s+(?:vuông\\\\s*góc\\\\s+)?|chân\\\\s+(?:của\\\\s+)?(?:các\\\\s+)?đường\\\\s+(?:vuông\\\\s*góc|cao)\\\\s+)' +\n '(?:kẻ\\\\s+|hạ\\\\s+|vẽ\\\\s+|dựng\\\\s+)?(?:của\\\\s+|từ\\\\s+)?(?:điểm\\\\s+)?([A-Z])\\\\s+' +\n TWO_LINES_PREP + '\\\\s+' + TWO_LINES_LINE + '\\\\s+và\\\\s+' + TWO_LINES_LINE,\n 'gu',\n);\n\n// 2 chân từ 2 GỐC khác nhau, CÙNG 1 đường: \"(Hai/Các điểm)? E, F lần lượt là\n// chân (đường)? vuông góc (kẻ)? từ B, C (đến|xuống) AA'\" → E=foot(B,AA'),\n// F=foot(C,AA'). KHÁC SHARED_FROM_TWO (1 from, 2 đường) + ALTITUDE_FEET_FROM\n// (đường cao suy từ tam giác). Đường chung 1-2 ký tự + prime (vao10:58 \"AA'\").\n// groups: 1=name1 2=from1... thực ra 1=n1 2=n2 3=from1 4=from2 5=line\nconst FEET_FROM_SHARED_LINE = new RegExp(\n \"(?:[Hh]ai\\\\s+điểm\\\\s+|[Cc]ác\\\\s+điểm\\\\s+)?([A-Z])(?:['′])?\\\\s*(?:,|và)\\\\s*([A-Z])(?:['′])?\\\\s+\" +\n 'lần\\\\s*lượt\\\\s+là\\\\s+chân\\\\s+(?:các\\\\s+)?(?:đường\\\\s+)?(?:vuông\\\\s*góc|cao)\\\\s+' +\n \"(?:kẻ\\\\s+|hạ\\\\s+|vẽ\\\\s+|dựng\\\\s+)?(?:từ\\\\s+)?([A-Z](?:['′])?)\\\\s*(?:,|và)\\\\s*([A-Z](?:['′])?)\\\\s+\" +\n \"(?:đến|xuống|trên|tới)\\\\s+(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2}(?:['′])?)(?![A-Z])\",\n 'gu',\n);\n\n// \"Kẻ/Vẽ/Dựng XY,XZ (lần lượt)? (⊥|vuông góc với?) L1,L2 (tại Z1,Z2)?\" — phân\n// phối: cặp XY,XZ CÙNG chữ đầu (from), chân = chữ thứ 2, zip với L1,L2. Bài 4\n// (\"Kẻ HE,HF ⊥ AB,AC\"), Bài 35 (\"Vẽ ME,MF ⊥ AC,AB tại E,F\").\n// groups: 1=from1 2=foot1 3=from2 4=foot2 5=line1 6=line2\nconst PERP_DRAW_DISTRIB = new RegExp(\n '(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng|[Hh]ạ)\\\\s+([A-Z])([A-Z])\\\\s*,\\\\s*([A-Z])([A-Z])(?![A-Z])\\\\s+' +\n '(?:lần\\\\s*lượt\\\\s+)?(?:⊥|vuông\\\\s*góc(?:\\\\s+với)?)\\\\s+(?:với\\\\s+)?(?:các\\\\s+)?' +\n '(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{2})\\\\s*,\\\\s*([A-Z]{2})(?![A-Z])',\n 'gu',\n);\n\n// \"Hạ/Kẻ XY và ZW cùng vuông góc (với)? L\" — 2 cặp from+foot KHÁC chữ đầu,\n// CÙNG một đường L (vao10 51/76/84: \"Hạ BE và CF cùng vuông góc với AK\").\n// groups: 1=from1 2=foot1 3=from2 4=foot2 5=line\nconst PERP_SHARED_CUNG = new RegExp(\n '(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng|[Hh]ạ)\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+và\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+cùng\\\\s+vuông\\\\s*góc\\\\s+(?:với\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])',\n 'gu',\n);\n\n// \"từ M kẻ MP, MQ vuông góc với các cạnh AB, AC\" → P=foot(M,AB), Q=foot(M,AC).\n// Cặp MP/MQ phải cùng chữ đầu với điểm from. Số pair/line cố định 2 vì đây là\n// dạng đề lớp 9 phổ biến; zip nhiều hơn đã có DISTRIB_PROJ/FOOT theo tên điểm.\nconst FROM_DRAW_DISTRIB = new RegExp(\n 'từ\\\\s+([A-Z])(?!\\\\p{L})\\\\s+kẻ\\\\s+([A-Z]{2})\\\\s*,\\\\s*([A-Z]{2})\\\\s+vuông\\\\s*góc\\\\s+với\\\\s+các\\\\s+cạnh\\\\s+([A-Z]{2})\\\\s*,\\\\s*([A-Z]{2})(?![A-Z])',\n 'gu',\n);\n\n/** Tách blob tên distributive \"X, Y, Z\" → ['X','Y','Z'] (chuẩn hoá prime ′→'). */\nfunction splitNames(blob: string): string[] {\n return blob\n .split(/,|và/)\n .map((s) => {\n const mm = /^([A-Z])(['′]?)/u.exec(s.trim());\n return mm ? (mm[2] ? `${mm[1]}'` : mm[1]) : '';\n })\n .filter(Boolean);\n}\n\n// \"Kẻ/Vẽ/Dựng XY (⊥|vuông góc với?) [cạnh|đường thẳng]? LINE (tại Z)?\"\n// \"Kẻ AH ⊥ BC tại H\" | \"Vẽ AH vuông góc với BC\" | \"Dựng AH vuông góc cạnh BC\"\n// Tên foot = chữ thứ 2 của cặp XY (g2); from = g1; onLine = g3. \"tại Z\" (g4) nếu\n// có PHẢI trùng foot (else xung đột → skip). connect.ts (SEG_KW \"Kẻ AH\") đã lo\n// đoạn AH → rule này CHỈ emit add-point, KHÔNG connect (tránh double).\n// groups: 1=from 2=foot 3=onLine 4=tại-point(optional)\n// `⊥\\\\s*` (KHÔNG `\\\\s+`): OCR hay dính ký hiệu vào cạnh (\"AK ⊥BC\"). Dạng chữ\n// \"vuông góc\" giữ `\\\\s+` (không bao giờ dính \"vuông gócBC\").\nconst PERP_DRAW = new RegExp(\n `(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng|[Hh]ạ)\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+(?:⊥\\\\s*|vuông\\\\s*góc(?:\\\\s+với)?\\\\s+)(?:với\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])(?:\\\\s+tại\\\\s+([A-Z]))?`,\n 'gu',\n);\n\n// Cặp ⊥ KHÔNG verb dẫn (\"XY ⊥ L\") — dùng cho phần SAU dấu phẩy của directive\n// \"Kẻ AC ⊥ MB, BD ⊥ MA\" (PERP_DRAW chỉ bắt cặp đầu có verb). CHỈ chạy khi clause\n// có verb dựng (Kẻ/Vẽ/Dựng) → tránh nuốt quan hệ ⊥ trong câu chứng minh.\nconst PERP_BARE = new RegExp(\n `([A-Z])([A-Z])(?![A-Z])\\\\s+(?:⊥\\\\s*|vuông\\\\s*góc(?:\\\\s+với)?\\\\s+)(?:với\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])(?:\\\\s+tại\\\\s+([A-Z]))?`,\n 'gu',\n);\nconst DRAW_VERB = /[Kk]ẻ|[Vv]ẽ|[Dd]ựng/u;\n\n// modifier \"trung điểm (của)?\" NGAY TRƯỚC cụm → đổi nghĩa, không dựng foot.\nconst MID_BEFORE = /trung\\s+điểm(?:\\s+của)?\\s*$/u;\n// Tên foot cục bộ: ký tự HOA + \"là\" NGAY TRƯỚC cụm (vd \"Gọi H là \", \"… , H là \").\nconst NAME_BEFORE = /([A-Z])(?:[′'])?\\s+là\\s+$/u;\n\n// === EN (issue #46 group B) ==================================================\n// Additive — KHÔNG đụng building block VN ở trên. Nhãn STRICT [A-Z] (KHÔNG cờ\n// 'i' — sẽ nuốt chữ thường); first-letter flex của verb bằng [Dd]/[Cc].\n//\n// onLine token EN: tiền tố \"line \"/\"side \"/\"segment \" optional + 1-2 ký tự HOA,\n// neo (?![A-Z]) để chặn cụm 3+ ký tự.\nconst LINE_EN = '(?:line\\\\s+|side\\\\s+|segment\\\\s+)?([A-Z]{1,2})(?![A-Z])';\n\n// Form A — \"(orthogonal)? projection of X (onto|on|to) LINE\"\n// groups: 1=from 2=line\nconst PROJ_CORE_EN = `(?:orthogonal\\\\s+)?projection\\\\s+of\\\\s+([A-Z])\\\\s+(?:onto|on|to)\\\\s+${LINE_EN}`;\n// Form B — \"foot of (the)? (perpendicular|altitude) from X (to|onto|on) LINE\"\n// groups: 1=from 2=line\nconst FOOT_CORE_EN = `foot\\\\s+of\\\\s+(?:the\\\\s+)?(?:perpendicular|altitude)\\\\s+from\\\\s+([A-Z])\\\\s+(?:to|onto|on)\\\\s+${LINE_EN}`;\n\n// Single EN core (projection HOẶC foot-of). Ghép 2 group block → group dịch:\n// PROJ: 1=from 2=line | FOOT: 3=from 4=line → đọc bằng m[1]??m[3], m[2]??m[4].\nconst SINGLE_EN = new RegExp(`(?:${PROJ_CORE_EN})|(?:${FOOT_CORE_EN})`, 'gu');\n\n// Form C draw — \"Draw|Construct|Drop XY perpendicular to (line|side|segment)? LINE (at Z)?\"\n// \"Draw AH perpendicular to BC at H\" | \"Construct AH perpendicular to BC\"\n// foot = chữ thứ 2 cặp XY (g2); from = g1; onLine = g3; at = g4 (optional).\n// \"Draw the perpendicular bisector …\" KHÔNG khớp: sau \"Draw\" là \"the\" (chữ\n// thường) chứ không phải cặp HOA → perpBisector territory, không double-emit.\n// groups: 1=from 2=foot 3=onLine 4=at(optional)\nconst PERP_DRAW_EN = new RegExp(\n `(?:[Dd]raw|[Cc]onstruct|[Dd]rop)\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+perpendicular\\\\s+to\\\\s+(?:line\\\\s+|side\\\\s+|segment\\\\s+)?([A-Z]{1,2})(?![A-Z])(?:\\\\s+at\\\\s+([A-Z]))?`,\n 'gu',\n);\n\n// \"hai đường cao BE, CF cắt nhau tại H\" / \"Các đường cao AD, BE, CF của tam\n// giác ABC cắt nhau tại H\". Mỗi token XY: X là đỉnh, Y là chân đường cao; cạnh\n// đối diện X được suy từ tam giác bind được. Nếu có \"cắt nhau tại H\" thì H là\n// trực tâm. Chỉ nhận 2-3 đường cao để tránh vơ một đoạn rời.\n// Separator giữa các token đường cao: dấu phẩy HOẶC \"và\" (\"BD và CE\", \"AD, BE,\n// CF\"). parseAltitudeBundle split theo cùng pattern.\nconst ALTITUDE_BUNDLE = new RegExp(\n `(?:hai\\\\s+|ba\\\\s+|các\\\\s+)?${DUONG_KW}\\\\s+cao\\\\s+((?:[A-Z]{2}\\\\s*(?:,|và)\\\\s*){0,2}[A-Z]{2})(?![A-Z])(?:\\\\s+của\\\\s+tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z]))?[^.]{0,60}?(?:cắt\\\\s+nhau|đồng\\\\s*quy|cùng\\\\s+đi\\\\s+qua)\\\\s+(?:tại\\\\s+|qua\\\\s+)?(?:điểm\\\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\nconst TRI_G = /tam\\s*giác\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n// \"D, E lần lượt là chân (các)? đường cao (của tam giác XYZ)? (kẻ|hạ)? từ A, B\" →\n// chân đường cao ĐẶT TÊN + đỉnh xuất phát qua \"từ A,B\"; cạnh đối suy từ tam giác.\n// Bài 112: \"Gọi D,E lần lượt là chân các đường cao của tam giác ABC hạ từ A,B\".\n// groups: 1=names blob | 2,3,4=tam giác (optional) | 5=from blob\nconst ALTITUDE_FEET_FROM = new RegExp(\n `((?:[A-Z](?:['′]?)\\\\s*,\\\\s*)+[A-Z](?:['′]?))\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?là\\\\s+(?:các\\\\s+)?chân\\\\s+(?:các\\\\s+)?${DUONG_KW}\\\\s+cao` +\n `(?:\\\\s+của\\\\s+tam\\\\s*giác\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z]))?\\\\s*(?:kẻ\\\\s+|hạ\\\\s+|vẽ\\\\s+)?(?:từ|của)\\\\s+((?:[A-Z]\\\\s*,\\\\s*)+[A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// \"BE, CF là (hai)? đường cao\" — token đường cao ĐỨNG TRƯỚC \"là … đường cao\"\n// (KHÁC ALTITUDE_BUNDLE: token sau \"đường cao\"). Mỗi token XY: X=đỉnh, Y=chân\n// trên cạnh đối X (suy từ tam giác). KHÔNG cần \"cắt nhau tại H\".\nconst ALTITUDE_BEFORE = new RegExp(\n `((?:[A-Z]{2}\\\\s*,\\\\s*)+[A-Z]{2})(?![A-Z])\\\\s+là\\\\s+(?:hai\\\\s+|ba\\\\s+)?${DUONG_KW}\\\\s+cao(?!\\\\s*[A-Z])`,\n 'gu',\n);\n\n// Tên foot ĐỨNG TRƯỚC core qua \"Let X be the …\" / \"X is the …\".\n// \"Let H be the projection …\" | \"K is the orthogonal projection …\"\nconst NAME_BEFORE_EN = /([A-Z])(?:[′'])?\\s+(?:be|is)\\s+(?:the\\s+)?$/u;\n\ninterface Foot {\n name: string;\n from: string;\n onLine: string;\n /** Emit thêm connect(from, foot) — đoạn vuông góc từ điểm tới chân. Dùng cho:\n * Form C (EN draw \"Draw AH ⊥ BC\") + distributive VN \"X,Y,Z hình chiếu của D…\"\n * (thể hiện hình chiếu DX/DY/DZ). Foot đơn VN KHÔNG set → byte-identical. */\n withSegment?: boolean;\n}\n\nfunction trianglesIn(text: string): string[][] {\n const out: string[][] = [];\n TRI_G.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(text)) !== null) out.push([m[1], m[2], m[3]]);\n return out;\n}\n\nfunction uniqueTriangle(problem: string): string[] | undefined {\n const all = trianglesIn(problem);\n const distinct = new Map(all.map((t) => [t.join(''), t]));\n return distinct.size === 1 ? [...distinct.values()][0] : undefined;\n}\n\nfunction oppositeSide(vertex: string, tri: readonly string[]): string | undefined {\n if (!tri.includes(vertex)) return undefined;\n return tri.filter((p) => p !== vertex).join('');\n}\n\nfunction parseAltitudeBundle(text: string, fallbackTri: string[] | undefined): Foot[] {\n const out: Foot[] = [];\n ALTITUDE_BUNDLE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = ALTITUDE_BUNDLE.exec(text)) !== null) {\n const localTri = m[2] && m[3] && m[4] ? [m[2], m[3], m[4]] : fallbackTri;\n if (!localTri) continue;\n const tokens = m[1]\n .split(/,|và/)\n .map((s) => s.trim())\n .filter(Boolean);\n if (tokens.length < 2 || tokens.length > 3) continue;\n let ok = true;\n const local: Foot[] = [];\n for (const token of tokens) {\n const from = token[0];\n const name = token[1];\n const onLine = oppositeSide(from, localTri);\n if (!onLine || localTri.includes(name)) {\n ok = false;\n break;\n }\n local.push({ name, from, onLine, withSegment: true });\n }\n if (ok) out.push(...local, { name: m[5], from: '', onLine: localTri.join('') });\n }\n return out;\n}\n\n/** Parse mọi foot trong 1 clause. Trả [] nếu không bind được tên / bị skip. */\nfunction parseFeet(text: string, fallbackTri?: string[]): Foot[] {\n const out: Foot[] = [];\n const consumed: Array<[number, number]> = [];\n\n // -1) Bundle đường cao đề thi. Orthocenter được encode tạm bằng Foot sentinel\n // name=H/from='' để flatMap bên dưới emit addPoint orthocenter đúng thứ tự.\n const bundled = parseAltitudeBundle(text, fallbackTri);\n if (bundled.length > 0) return bundled;\n\n // -0.5) \"BE, CF là (hai) đường cao\" — token TRƯỚC, không cần \"cắt nhau tại H\".\n ALTITUDE_BEFORE.lastIndex = 0;\n for (const m of text.matchAll(ALTITUDE_BEFORE)) {\n if (!fallbackTri) continue;\n const tokens = m[1].split(',').map((s) => s.trim()).filter(Boolean);\n let ok = true;\n const local: Foot[] = [];\n for (const token of tokens) {\n const from = token[0];\n const name = token[1];\n const onLine = oppositeSide(from, fallbackTri);\n if (!onLine || fallbackTri.includes(name)) { ok = false; break; }\n local.push({ name, from, onLine, withSegment: true });\n }\n if (ok && local.length > 0) return local;\n }\n\n // -0.4) \"D,E lần lượt là chân (các) đường cao (của tam giác XYZ)? hạ từ A,B\" →\n // chân = tên ĐẶT; đỉnh từ blob \"từ A,B\"; cạnh đối suy từ tam giác. Zip 1-1.\n ALTITUDE_FEET_FROM.lastIndex = 0;\n for (const m of text.matchAll(ALTITUDE_FEET_FROM)) {\n const localTri = m[2] && m[3] && m[4] ? [m[2], m[3], m[4]] : fallbackTri;\n if (!localTri) continue;\n const names = splitNames(m[1]);\n const froms = m[5].split(',').map((s) => s.trim()).filter(Boolean);\n if (names.length < 2 || names.length !== froms.length) continue;\n let ok = true;\n const local: Foot[] = [];\n for (let i = 0; i < names.length; i++) {\n const onLine = oppositeSide(froms[i], localTri);\n if (!onLine || localTri.includes(names[i])) { ok = false; break; }\n local.push({ name: names[i], from: froms[i], onLine, withSegment: true });\n }\n if (ok) return local;\n }\n\n // 0) Distributive SHARED-FROM: \"X, Y, Z lần lượt là hình chiếu/chân vuông góc\n // của D trên BC, CA, AB\" → zip tên↔cạnh (from D chung). Span đã khớp →\n // consumed để SINGLE không xử lại. Zip lệch (số tên ≠ số cạnh) → bỏ.\n for (const re of [DISTRIB_PROJ, DISTRIB_FOOT]) {\n re.lastIndex = 0;\n for (const dm of text.matchAll(re)) {\n const names = splitNames(dm[1]);\n const from = dm[2];\n const lines = dm[3].split(/,|và/).map((s) => s.trim()).filter(Boolean);\n if (names.length < 2 || names.length !== lines.length) continue; // zip lệch → escalate\n // withSegment: vẽ kèm đoạn vuông góc from→foot (DX/DY/DZ) để THỂ HIỆN hình\n // chiếu (render perpFoot chỉ tạo điểm chân, không tự vẽ đường rớt vuông góc).\n names.forEach((name, i) => out.push({ name, from, onLine: lines[i], withSegment: true }));\n consumed.push([dm.index ?? 0, (dm.index ?? 0) + dm[0].length]);\n }\n }\n\n FROM_DRAW_DISTRIB.lastIndex = 0;\n for (const fm of text.matchAll(FROM_DRAW_DISTRIB)) {\n const from = fm[1];\n const pair1 = fm[2];\n const pair2 = fm[3];\n if (pair1[0] !== from || pair2[0] !== from) continue;\n const foot1 = pair1[1];\n const foot2 = pair2[1];\n const line1 = fm[4];\n const line2 = fm[5];\n if (line1.includes(foot1) || line2.includes(foot2) || foot1 === foot2) continue;\n out.push({ name: foot1, from, onLine: line1, withSegment: true });\n out.push({ name: foot2, from, onLine: line2, withSegment: true });\n consumed.push([fm.index ?? 0, (fm.index ?? 0) + fm[0].length]);\n }\n\n // 0b) SHARED-FROM 2 đường nối \"và\": \"I, K lần lượt là hình chiếu của H trên\n // AC và BC\" → I↔AC, K↔BC, from=H chung.\n SHARED_FROM_TWO.lastIndex = 0;\n for (const sm of text.matchAll(SHARED_FROM_TWO)) {\n const start = sm.index ?? 0;\n if (consumed.some(([a, b]) => start >= a && start < b)) continue; // DISTRIB đã xử (overlap \"và\")\n const [n1, n2, from, l1, l2] = [sm[1], sm[2], sm[3], sm[4], sm[5]];\n if (l1.includes(n1) || l2.includes(n2) || n1 === n2) continue;\n out.push({ name: n1, from, onLine: l1, withSegment: true });\n out.push({ name: n2, from, onLine: l2, withSegment: true });\n consumed.push([sm.index ?? 0, (sm.index ?? 0) + sm[0].length]);\n }\n\n // 0c) 2 GỐC khác nhau, CÙNG 1 đường: \"E, F lần lượt là chân ⊥ từ B, C đến AA'\"\n // → E↔B, F↔C, onLine=AA' chung. Normalize prime ′→' cho từ/đường.\n FEET_FROM_SHARED_LINE.lastIndex = 0;\n for (const fm of text.matchAll(FEET_FROM_SHARED_LINE)) {\n const start = fm.index ?? 0;\n if (consumed.some(([a, b]) => start >= a && start < b)) continue;\n const norm = (s: string) => s.replace(/′/g, \"'\");\n const [n1, n2, f1, f2, line] = [fm[1], fm[2], norm(fm[3]), norm(fm[4]), norm(fm[5])];\n if (n1 === n2 || f1 === f2 || line.includes(n1) || line.includes(n2)) continue;\n out.push({ name: n1, from: f1, onLine: line, withSegment: true });\n out.push({ name: n2, from: f2, onLine: line, withSegment: true });\n consumed.push([start, start + fm[0].length]);\n }\n\n // 1) \"X, Y lần lượt là … và …\" → 2 foot (name bind sẵn trong cú pháp).\n LANLUOT.lastIndex = 0;\n let lm: RegExpExecArray | null;\n while ((lm = LANLUOT.exec(text)) !== null) {\n if (MID_BEFORE.test(text.slice(0, lm.index))) continue; // \"trung điểm của …\" → skip\n const from1 = lm[3] ?? lm[5];\n const line1 = lm[4] ?? lm[6];\n out.push({ name: lm[1], from: from1, onLine: line1 });\n out.push({ name: lm[2], from: lm[7], onLine: lm[8] });\n consumed.push([lm.index, lm.index + lm[0].length]);\n }\n\n // 2) foot đơn — bind tên CỤC BỘ. Bỏ qua nếu nằm trong span \"lần lượt\" đã xử lý.\n SINGLE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = SINGLE.exec(text)) !== null) {\n const start = m.index;\n if (consumed.some(([a, b]) => start >= a && start < b)) continue;\n const before = text.slice(0, start);\n if (MID_BEFORE.test(before)) continue; // \"trung điểm của hình chiếu …\" → đổi nghĩa\n const nm = NAME_BEFORE.exec(before);\n if (!nm) continue; // không có tên cục bộ → escalate AI\n out.push({ name: nm[1], from: m[1] ?? m[3], onLine: m[2] ?? m[4] });\n }\n\n // 2b) \"Kẻ/Vẽ XY,XZ ⊥ L1,L2\" phân phối — cặp cùng chữ đầu (from), chân = chữ\n // thứ 2, zip với L1,L2. Span consumed để PERP_DRAW không xử lại cặp đầu.\n PERP_DRAW_DISTRIB.lastIndex = 0;\n for (const ddm of text.matchAll(PERP_DRAW_DISTRIB)) {\n const [from1, foot1, from2, foot2, line1, line2] = [ddm[1], ddm[2], ddm[3], ddm[4], ddm[5], ddm[6]];\n if (from1 !== from2) continue; // không cùng điểm gốc → không phải dạng này\n if (line1.includes(foot1) || line2.includes(foot2) || foot1 === foot2) continue;\n out.push({ name: foot1, from: from1, onLine: line1, withSegment: true });\n out.push({ name: foot2, from: from2, onLine: line2, withSegment: true });\n consumed.push([ddm.index ?? 0, (ddm.index ?? 0) + ddm[0].length]);\n }\n\n // 2c) \"Hạ XY và ZW cùng vuông góc (với)? L\" — 2 chân khác gốc, CÙNG đường L.\n PERP_SHARED_CUNG.lastIndex = 0;\n for (const sm of text.matchAll(PERP_SHARED_CUNG)) {\n const [f1, t1, f2, t2, line] = [sm[1], sm[2], sm[3], sm[4], sm[5]];\n if (t1 === t2 || line.includes(t1) || line.includes(t2)) continue;\n out.push({ name: t1, from: f1, onLine: line, withSegment: true });\n out.push({ name: t2, from: f2, onLine: line, withSegment: true });\n consumed.push([sm.index ?? 0, (sm.index ?? 0) + sm[0].length]);\n }\n\n // 3) \"Kẻ XY ⊥ LINE (tại Z)\" — tên foot lấy từ cặp XY (không cần \"X là\").\n PERP_DRAW.lastIndex = 0;\n let pm: RegExpExecArray | null;\n while ((pm = PERP_DRAW.exec(text)) !== null) {\n const from = pm[1];\n const foot = pm[2];\n const onLine = pm[3];\n const at = pm[4]; // \"tại Z\" (optional)\n if (at && at !== foot) continue; // \"tại K\" ≠ chân H → xung đột → escalate\n if (onLine.includes(foot)) continue; // chân trùng đỉnh của đường → degenerate\n out.push({ name: foot, from, onLine });\n }\n\n // 3b) Cặp ⊥ phân phối sau dấu phẩy (\"Kẻ AC ⊥ MB, BD ⊥ MA\" — cặp 2 thiếu verb).\n // Chỉ khi clause là directive dựng (có Kẻ/Vẽ/Dựng). Bỏ chân đã có (cặp đầu\n // PERP_DRAW emit rồi) + chân trùng đỉnh đường.\n if (DRAW_VERB.test(text)) {\n PERP_BARE.lastIndex = 0;\n let bm: RegExpExecArray | null;\n while ((bm = PERP_BARE.exec(text)) !== null) {\n const from = bm[1];\n const foot = bm[2];\n const onLine = bm[3];\n const at = bm[4]; // \"tại Z\" (optional) — Z ≠ foot ⇒ xung đột ⇒ bỏ (escalate)\n if (at && at !== foot) continue;\n if (onLine.includes(foot)) continue;\n if (out.some((o) => o.name === foot)) continue;\n out.push({ name: foot, from, onLine });\n }\n }\n\n // 4) EN projection / foot-of — tên bind ĐỨNG TRƯỚC qua \"Let X be the …\"/\"X is\n // the …\". Không có tên-trước → escalate (fail-safe). \"trung điểm\" KHÔNG\n // áp dụng EN; MID_BEFORE giữ nguyên VN, ở đây không cần.\n SINGLE_EN.lastIndex = 0;\n let em: RegExpExecArray | null;\n while ((em = SINGLE_EN.exec(text)) !== null) {\n const before = text.slice(0, em.index);\n const nm = NAME_BEFORE_EN.exec(before);\n if (!nm) continue; // không có \"X be/is the\" → escalate AI\n const from = em[1] ?? em[3];\n const onLine = em[2] ?? em[4];\n out.push({ name: nm[1], from, onLine });\n }\n\n // 5) EN draw form \"Draw XY perpendicular to LINE (at Z)\" — foot = chữ 2 cặp XY.\n // connect.ts VN-only → tự emit connect(from, foot) để vẽ đoạn (parity VN).\n PERP_DRAW_EN.lastIndex = 0;\n let dm: RegExpExecArray | null;\n while ((dm = PERP_DRAW_EN.exec(text)) !== null) {\n const from = dm[1];\n const foot = dm[2];\n const onLine = dm[3];\n const at = dm[4]; // \"at Z\" (optional)\n if (at && at !== foot) continue; // \"at K\" ≠ chân H → xung đột → escalate\n if (onLine.includes(foot)) continue; // chân trùng đỉnh đường → degenerate\n out.push({ name: foot, from, onLine, withSegment: true });\n }\n return out;\n}\n\n/**\n * Mỗi clause → 0..n add-point perpFoot. Tên foot bind cục bộ theo cú pháp gần,\n * match global để dựng đủ (vd \"H, K lần lượt …\" = 2 foot).\n */\nexport const perpFootRule: LanguageRule = {\n id: 'perpFoot',\n priority: 65,\n languages: ['vi', 'en'],\n patterns: [PREFILTER, PREFILTER_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n const fallbackTri = uniqueTriangle(ctx.problem);\n for (const c of ctx.clauses) {\n const feet = parseFeet(c.text, fallbackTri);\n if (feet.length === 0) continue;\n // Foot add-point TRƯỚC; với EN draw form (withSegment) push THÊM connect\n // NGAY SAU add-point của foot đó (H phải tồn tại trước khi connect tham\n // chiếu). VN feet không set withSegment → byte-identical.\n const intents = feet.flatMap((f) => {\n if (f.from === '') return [addPoint(f.name, { kind: 'orthocenter', of: f.onLine.split('') })];\n const add = addPoint(f.name, { kind: 'perpFoot', from: f.from, onLine: f.onLine });\n return f.withSegment ? [add, connect(f.from, f.name, 'segment')] : [add];\n });\n out.push({ ruleId: 'perpFoot', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleRadius.ts\n//\n// Đường tròn theo TÂM: bán kính số / bán kính ký hiệu CHỮ / \"đi qua <điểm>\".\n// - \"đường tròn (tâm) O bán kính 3\" → centerRadius {center:'O', radius:3}\n// - \"(O; 3)\" / \"(O, 3)\" → centerRadius {center:'O', radius:3}\n// - \"(O; R)\" / \"(I; r)\" / \"bán kính R\" → centerRadius bán kính CANONICAL\n// (issue #46 nhóm A — xem dưới)\n// - \"đường tròn tâm O đi qua A\" → centerThrough {center:'O', through:'A'}\n//\n// CHỈ emit khi có bán kính SỐ, bán kính ký hiệu CHỮ (R/r), hoặc \"đi qua <điểm>\".\n// \"(O)\" trơ (không số/chữ/\"đi qua\") → bỏ qua (chỉ tham chiếu; rule khác/AI xử lý).\n//\n// BÁN KÍNH KÝ HIỆU CHỮ (issue #46): \"Cho đường tròn (O; R)\" cực phổ biến ở đề thi.\n// R là KÝ HIỆU (giá trị thực không cho) → vẽ với bán kính CANONICAL dương để minh\n// hoạ (fail-safe: không sai ngữ nghĩa — đường tròn tâm O bán kính tuỳ ý). CHỈ nhận\n// đúng [Rr] đứng riêng: hệ số \"2R\" (defer Cụm C) và chữ khác \"(A; B)\" → bỏ qua.\n//\n// GOTCHA segmentation: segmentClauses() tách trên '.' ';' ',' nên ký hiệu gọn\n// \"(O; 3)\" / \"(O, 2.5)\" BỊ cắt ngang clause (\"(O\" và \"3)\" thành 2 clause). Vì\n// vậy nhánh PAREN quét trên TOÀN đề (ctx.problem) rồi gán match cho clause chứa\n// fragment \"(<tâm>\". Nhánh WORDS / THROUGH segment nguyên vẹn → quét per-clause.\n//\n// GOTCHA \\b: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { Clause } from '../deterministic/coverage';\nimport { drawCircle, CIRCLE_KW, DUONG_KW } from './_shared';\n\n// \"đường tròn tâm O bán kính 3\" / \"(O) bán kính 3\" / \"O bán kính 3\".\n// Tâm 1 ký tự HOA; \"tâm\" optional; có thể bọc trong ngoặc \"(O)\".\n// Hỗ trợ PAREN tên chữ (alpha, omega...).\n//\n// GLOBAL (/gu) vì 1 clause có thể nêu NHIỀU đường tròn (\"tâm I bán kính 2 và\n// tâm O bán kính 5\" không có dấu câu tách → cùng clause). matchAll quét hết.\n//\n// Gap tâm→\"bán kính\" dùng tempered quantifier `(?:(?!đường|và\\s)[^A-Z])*?` để\n// KHÔNG nhảy qua một \"đường tròn\" khác hay liên từ \"và \" (ranh giới giữa 2 hình).\n// Nếu nhảy qua được, \"tâm O và … tâm I bán kính 5\" sẽ bind nhầm 5 vào O. Chặn ở\n// đây ⇒ match bắt đầu từ O thất bại, regex tự dời tới \"tâm I bán kính 5\" (đúng),\n// còn \"tâm O\" trơ (không số) không bị nuốt → không claim → escalate phần đó.\nconst CENTER_RADIUS_WORDS_G = new RegExp(\n CIRCLE_KW +\n '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?:\\\\s*\\\\))?(?:(?!đường|và\\\\s)[^A-Z])*?bán\\\\s*kính\\\\s+(\\\\d+(?:[.,]\\\\d+)?)',\n 'gu',\n);\n\n// \"đường tròn tâm O đi qua A\" / \"(O) đi qua A\" / \"O đi qua A\".\n// GLOBAL: nhiều \"đường tròn … đi qua …\" trong 1 clause.\nconst CENTER_THROUGH_G = new RegExp(\n CIRCLE_KW + '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?:\\\\s*\\\\))?\\\\s+đi\\\\s+qua\\\\s+([A-Z])',\n 'gu',\n);\n\n// Phần \"đi qua B và C\" (≥2 điểm surface): chưa hỗ trợ (DSL centerThrough 1 điểm).\n// Phát hiện để SKIP match đó → điểm thứ 2 (C) thiếu trong DSL → named-entity\n// guard escalate AI (an toàn) thay vì render thiếu C.\nconst THROUGH_MULTI = /đi\\s+qua\\s+[A-Z]\\s*(?:và|,)\\s*[A-Z]/u;\n\n// Ký hiệu gọn \"(O; 3)\" / \"(O, 3)\" — quét toàn đề (global) vì có thể nhiều.\nconst CENTER_RADIUS_PAREN_G = /\\(\\s*([A-Z])\\s*[;,]\\s*(\\d+(?:[.,]\\d+)?)\\s*(?:cm|dm|mm|m)?\\s*\\)/gu;\n\n// KHAI BÁO ĐỘC LẬP: cả CLAUSE chỉ là \"(Cho)? (nửa)? đường tròn (tâm)? (O)\n// (cố định)?\" — KHÔNG quan hệ nào khác. Bare \"(O)\"/\"O\" nhưng standalone ⇒ chắc\n// chắn là đường tròn nền PHẢI vẽ (httcd:82, mohinh:12 OCR-split \"O;R\"). KHÁC\n// \"(O)\" giữa câu (chỉ tham chiếu — full-match $ loại). Guard isInscribed/Diameter\n// (circleTriangle/circleDiameter sở hữu) vẫn áp dụng ở caller.\nconst STANDALONE_BARE = /^(?:[Cc]ho\\s+)?(?:nửa\\s+)?đường\\s*tròn\\s*(?:tâm\\s+)?\\(?\\s*([A-Z])(?:['′]?)\\s*\\)?\\s*(?:cố\\s*định)?\\s*$/u;\n\n/**\n * Bán kính CANONICAL (board units) khi đề cho bán kính KÝ HIỆU CHỮ (\"(O; R)\",\n * \"bán kính R\"). Giá trị thực là ký hiệu → vẽ minh hoạ; khớp scale với bán kính\n * số mặc định nhỏ (vd \"(O; 3)\"). circleCR yêu cầu radius > 0.\n */\nexport const SYMBOLIC_RADIUS = 3;\n\n// Ký hiệu gọn bán kính CHỮ \"(O; R)\" / \"(I; r)\" — quét toàn đề. Bán kính CHỈ [Rr]\n// đứng RIÊNG (theo sau là ')'): \"2R\" (hệ số, defer) và chữ khác \"(A; B)\" KHÔNG\n// khớp → escalate (fail-safe). Center 1 ký tự HOA như nhánh số.\nconst CENTER_RADIUS_LETTER_PAREN_G = /\\(\\s*([A-Z])\\s*[;,]\\s*[Rr]\\s*\\)/gu;\n\n// \"đường tròn tâm O bán kính R\" — words, bán kính CHỮ. Mirror tempered của\n// CENTER_RADIUS_WORDS_G; (?![A-Za-z]) chặn \"Ra\"/\"Rồi\"… và phần số (\"2R\") để\n// nhánh số lo. GLOBAL: nhiều đường tròn / clause.\n// \"đường tròn tâm O bán kính R\" — words, bán kính CHỮ. Mirror tempered của\n// CENTER_RADIUS_WORDS_G; (?![A-Za-z]) chặn \"Ra\"/hệ số \"2R\" (nhánh số lo phần \"2\", nhưng \"radius 2R\"\n// hiếm; vẫn fail-safe vì \\d không có sau \"radius\" khi viết \"radius R\").\nconst CENTER_RADIUS_LETTER_WORDS_G = new RegExp(\n CIRCLE_KW +\n '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?:\\\\s*\\\\))?(?:(?!đường|và\\\\s)[^A-Z])*?bán\\\\s*kính\\\\s+[Rr](?![A-Za-z])',\n 'gu',\n);\n\n// === EN words patterns (issue #46 group B) ==================================\n// Tiền tố tâm EN dùng chung cho cả 3 dạng (radius số / radius CHỮ / passing\n// through). Chấp nhận: \"circle with center O\", \"circle centered at O\", \"circle\n// of center O\" + chính tả Anh-Anh \"centre\". cent(?:er|re) + (?:ed)? + (?:at|of)?\n// First-letter case flex [Cc] — KHÔNG cờ 'i' (sẽ phá [A-Z] tâm/điểm).\n//\n// Gap tâm→keyword: tempered `(?:(?![Cc]ircle)[^A-Z])*?` — KHÔNG nhảy qua \"circle\"\n// khác (ranh giới giữa 2 đường tròn) và KHÔNG nuốt chữ HOA (tâm/điểm kế). Lazy →\n// dừng ở \"radius\"/\"passing\" gần nhất. GLOBAL: nhiều đường tròn / clause.\nconst CIRCLE_CENTER_EN =\n '[Cc]ircle\\\\s+(?:with\\\\s+|of\\\\s+)?cent(?:er|re)(?:ed)?\\\\s+(?:at\\\\s+|of\\\\s+)?([A-Z])(?![A-Za-z])';\nconst EN_GAP = '(?:(?![Cc]ircle)[^A-Z])*?';\n\n// \"circle with center O and radius 3\" / \"circle centered at O with radius 3\" /\n// \"circle of center O radius 3\" → centerRadius số.\nconst CIRCLE_CR_EN_G = new RegExp(\n CIRCLE_CENTER_EN + EN_GAP + 'radius\\\\s+(\\\\d+(?:[.,]\\\\d+)?)',\n 'gu',\n);\n\n// \"circle with center O and radius R\" (bán kính CHỮ ký hiệu) → canonical.\n// (?![A-Za-z]) chặn \"Ra\"/hệ số \"2R\" (nhánh số lo phần \"2\", nhưng \"radius 2R\"\n// hiếm; vẫn fail-safe vì \\d không có sau \"radius\" khi viết \"radius R\").\nconst CIRCLE_CR_LETTER_EN_G = new RegExp(\n CIRCLE_CENTER_EN + EN_GAP + 'radius\\\\s+[Rr](?![A-Za-z])',\n 'gu',\n);\n\n// \"circle with center O passing through A\" / \"circle centered at O passing\n// through A\" → centerThrough. Điểm = 1 ký tự HOA neo (?![A-Za-z]).\nconst CIRCLE_THROUGH_EN_G = new RegExp(\n CIRCLE_CENTER_EN + EN_GAP + 'passing\\\\s+through\\\\s+([A-Z])(?![A-Za-z])',\n 'gu',\n);\n\n// Prefilter EN (NON-global để không vướng lastIndex ở .some(test)).\nconst EN_PREFILTER = new RegExp(CIRCLE_CENTER_EN, 'u');\n\n/** \"3\" / \"3.5\" / \"3,5\" → number. NaN nếu không parse được. */\nfunction parseNum(raw: string): number {\n return Number(raw.replace(',', '.'));\n}\n\n/**\n * Circle này là đường tròn NGOẠI/NỘI TIẾP tam giác? (\"tam giác ABC nội tiếp\n * đường tròn (O; 3)\") → circleTriangle sở hữu (through3/inscribedIn theo 3 đỉnh);\n * circleRadius KHÔNG emit thêm 1 đường tròn rời (sẽ chồng + không nhất quán).\n * Bán kính chỉ là chú thích — circumcircle xác định bởi 3 đỉnh, bỏ radius là OK.\n */\nfunction isInscribedCircumscribed(problem: string, center: string): boolean {\n // Quan hệ \"nội/ngoại tiếp\" (VN) + \"inscribed/circumscribes/circumscribed\" (EN,\n // issue #46 group B). EN mirror chống silent-WRONG: \"Triangle ABC inscribed in\n // circle (O; 3)\" — circleTriangle EN sở hữu through3 (qua 3 đỉnh) → circleRadius\n // KHÔNG emit centerRadius rời quanh O.\n const REL = '(?:(?:nội|ngoại)\\\\s*tiếp|[Ii]nscribed|[Cc]ircumscrib(?:es|ed))';\n // Chiều 1 — quan hệ ĐỨNG TRƯỚC circle: \"(tam giác) nội/ngoại tiếp … (O\".\n // Gap [^.]{0,30}? đủ nuốt \"in circle \" trước \"(O\" (EN).\n const after = new RegExp(\n `${REL}[^.]{0,30}?(?:đường\\\\s*tròn\\\\s*|[Cc]ircle\\\\s*)?\\\\(?\\\\s*${center}(?![A-Z])`,\n 'u',\n );\n // Chiều 2 — circle ĐỨNG TRƯỚC quan hệ: ký hiệu \"(O; R) … ngoại/nội tiếp\".\n // circleTriangle sở hữu circumcircle/incircle (qua 3 đỉnh) → circleRadius bỏ\n // để tránh DOUBLE-circle quanh O. [^()]* không vượt ngoặc khác; [^.]{0,30}?\n // không nhảy câu (giữ proximity, tránh false-positive với circle rời khác).\n const before = new RegExp(\n `\\\\(\\\\s*${center}\\\\s*[;,][^()]*\\\\)[^.]{0,30}?${REL}`,\n 'u',\n );\n return after.test(problem) || before.test(problem);\n}\n\nfunction isDiameterCircle(problem: string, center: string): boolean {\n const parenThenDiameter = new RegExp(\n `\\\\(\\\\s*${center}\\\\s*[;,][^()]*\\\\)[^.]{0,40}?${DUONG_KW}\\\\s*kính\\\\s+[A-Z]{2}(?![A-Z])`,\n 'u',\n );\n const namedThenDiameter = new RegExp(\n `${CIRCLE_KW}\\\\s*\\\\(\\\\s*${center}\\\\s*\\\\)[^.]{0,40}?${DUONG_KW}\\\\s*kính\\\\s+[A-Z]{2}(?![A-Z])`,\n 'u',\n );\n return parenThenDiameter.test(problem) || namedThenDiameter.test(problem);\n}\n\n/** Clause chứa fragment \"(<center>\" (ký hiệu gọn bị segmentation cắt vào đây). */\nfunction findParenClauseId(\n clauses: readonly Clause[],\n center: string,\n): number | undefined {\n const frag = new RegExp(`\\\\(\\\\s*${center}(?![A-Z])`, 'u');\n for (const c of clauses) if (frag.test(c.text)) return c.id;\n return undefined;\n}\n\nexport const circleRadiusRule: LanguageRule = {\n id: 'circleRadius',\n priority: 75,\n languages: ['vi', 'en'],\n patterns: [\n CENTER_RADIUS_WORDS_G,\n CENTER_THROUGH_G,\n /\\(\\s*[A-Z]\\s*[;,]\\s*\\d/u,\n /\\(\\s*[A-Z]\\s*[;,]\\s*[Rr]\\s*\\)/u, // ký hiệu bán kính CHỮ \"(O; R)\"\n /bán\\s*kính\\s+[Rr](?![A-Za-z])/u, // words bán kính CHỮ \"bán kính R\"\n EN_PREFILTER, // EN \"circle with center O …\" (issue #46 group B)\n ],\n match(ctx) {\n const out: RuleMatch[] = [];\n\n // --- Per-clause: dạng \"bán kính <số>\" + \"đi qua <điểm>\" (segment nguyên) ---\n for (const c of ctx.clauses) {\n // 1) \"đi qua <điểm>\" (centerThrough). GLOBAL: nhiều đường tròn / clause.\n // \"đi qua B và C\" (≥2 điểm) → SKIP toàn bộ centerThrough clause này:\n // chưa hỗ trợ multi-surface-point, để guard escalate (không render thiếu).\n const throughMulti = THROUGH_MULTI.test(c.text);\n if (!throughMulti) {\n CENTER_THROUGH_G.lastIndex = 0;\n let ct: RegExpExecArray | null;\n while ((ct = CENTER_THROUGH_G.exec(c.text)) !== null) {\n const center = ct[1];\n const through = ct[2];\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerThrough', { center, through })],\n });\n }\n }\n\n // 2) \"bán kính <số>\". GLOBAL: \"tâm I bán kính 2 và tâm O bán kính 5\" emit\n // 2 intent. Gap tempered (xem CENTER_RADIUS_WORDS_G) ⇒ không bind nhầm.\n // radius CHỮ (\"R\") → \\d không match → bỏ qua → escalate.\n CENTER_RADIUS_WORDS_G.lastIndex = 0;\n let crw: RegExpExecArray | null;\n while ((crw = CENTER_RADIUS_WORDS_G.exec(c.text)) !== null) {\n const center = crw[1];\n const radius = parseNum(crw[2]);\n if (!Number.isFinite(radius) || radius <= 0) continue;\n if (isInscribedCircumscribed(ctx.problem, center) || isDiameterCircle(ctx.problem, center)) continue;\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius })],\n });\n }\n\n // 3) \"bán kính R/r\" (bán kính CHỮ ký hiệu) → centerRadius bán kính canonical.\n // Clause có \"nội/ngoại tiếp\" → mơ hồ (circleTriangle/escalate sở hữu) → bỏ\n // (clause-local, không ảnh hưởng nhánh số ở clause khác).\n if (!/(?:nội|ngoại)\\s*tiếp/u.test(c.text)) {\n CENTER_RADIUS_LETTER_WORDS_G.lastIndex = 0;\n let clw: RegExpExecArray | null;\n while ((clw = CENTER_RADIUS_LETTER_WORDS_G.exec(c.text)) !== null) {\n const center = clw[1];\n if (isInscribedCircumscribed(ctx.problem, center) || isDiameterCircle(ctx.problem, center)) continue;\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n }\n\n // 4) KHAI BÁO ĐỘC LẬP bare \"(O)\"/\"O\" — cả clause chỉ là khai báo đường tròn.\n // Vẽ canonical (nền cho tiếp tuyến/cát tuyến). Guard: KHÔNG nội/ngoại tiếp,\n // KHÔNG đường kính (circleTriangle/circleDiameter sở hữu).\n const sb = STANDALONE_BARE.exec(c.text.trim());\n if (sb) {\n const center = sb[1];\n if (!isInscribedCircumscribed(ctx.problem, center) && !isDiameterCircle(ctx.problem, center)) {\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n }\n\n // --- EN words (issue #46 group B) ---------------------------------------\n // Fail-safe: clause có \"inscribed\"/\"circumscribed\" → circle phụ thuộc\n // tam giác/hình (circleTriangle EN OUT OF SCOPE) → KHÔNG emit lone circle.\n if (!/[Ii]nscribed|[Cc]ircumscribed/u.test(c.text)) {\n // 1) passing through → centerThrough.\n CIRCLE_THROUGH_EN_G.lastIndex = 0;\n let ent: RegExpExecArray | null;\n while ((ent = CIRCLE_THROUGH_EN_G.exec(c.text)) !== null) {\n const center = ent[1];\n const through = ent[2];\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerThrough', { center, through })],\n });\n }\n\n // 2) radius <số> → centerRadius.\n CIRCLE_CR_EN_G.lastIndex = 0;\n let ecr: RegExpExecArray | null;\n while ((ecr = CIRCLE_CR_EN_G.exec(c.text)) !== null) {\n const center = ecr[1];\n const radius = parseNum(ecr[2]);\n if (!Number.isFinite(radius) || radius <= 0) continue;\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius })],\n });\n }\n\n // 3) radius R/r (ký hiệu CHỮ) → centerRadius canonical.\n CIRCLE_CR_LETTER_EN_G.lastIndex = 0;\n let ecl: RegExpExecArray | null;\n while ((ecl = CIRCLE_CR_LETTER_EN_G.exec(c.text)) !== null) {\n const center = ecl[1];\n out.push({\n ruleId: 'circleRadius',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n }\n }\n\n // --- Toàn đề: ký hiệu gọn \"(O; 3)\" / \"(O, 3)\" (bị segmentation cắt) -------\n CENTER_RADIUS_PAREN_G.lastIndex = 0;\n let pm: RegExpExecArray | null;\n while ((pm = CENTER_RADIUS_PAREN_G.exec(ctx.problem)) !== null) {\n const center = pm[1];\n const radius = parseNum(pm[2]);\n if (!Number.isFinite(radius) || radius <= 0) continue;\n if (isInscribedCircumscribed(ctx.problem, center) || isDiameterCircle(ctx.problem, center)) continue;\n const clauseId = findParenClauseId(ctx.clauses, center);\n out.push({\n ruleId: 'circleRadius',\n clauseIds: clauseId === undefined ? [] : [clauseId],\n intents: [drawCircle(center, 'centerRadius', { center, radius })],\n });\n }\n\n // --- Toàn đề: ký hiệu bán kính CHỮ \"(O; R)\" / \"(I; r)\" (segmenter cắt ';') ---\n // Bán kính ký hiệu → bán kính canonical. Guard 2 chiều bỏ qua khi đường tròn\n // nội/ngoại tiếp tam giác (circleTriangle sở hữu).\n CENTER_RADIUS_LETTER_PAREN_G.lastIndex = 0;\n let lpm: RegExpExecArray | null;\n while ((lpm = CENTER_RADIUS_LETTER_PAREN_G.exec(ctx.problem)) !== null) {\n const center = lpm[1];\n if (isInscribedCircumscribed(ctx.problem, center) || isDiameterCircle(ctx.problem, center)) continue;\n const clauseId = findParenClauseId(ctx.clauses, center);\n out.push({\n ruleId: 'circleRadius',\n clauseIds: clauseId === undefined ? [] : [clauseId],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleTriangle.ts\n//\n// Đường tròn nội/ngoại tiếp tam giác:\n// \"đường tròn ngoại tiếp tam giác ABC\" → circumcircle → drawCircle through3\n// \"đường tròn nội tiếp tam giác ABC\" → incircle → drawCircle inscribedIn\n//\n// LƯU Ý disambiguate \"nội tiếp\" có 2 nghĩa ngược nhau tuỳ ngữ cảnh:\n// - \"ĐƯỜNG TRÒN nội tiếp tam giác\" → incircle (inscribedIn)\n// - \"TAM GIÁC nội tiếp đường tròn\" → circumcircle (through3) — tam giác nội\n// tiếp tức đường tròn NGOẠI tiếp tam giác.\n// \"ngoại tiếp\" (đường tròn ngoại tiếp tam giác) luôn là circumcircle.\n//\n// QUAN TRỌNG (chống mis-render):\n// - \"đường tròn ngoại/nội tiếp\" PHẢI theo sau bởi \"tam giác <XYZ>\" (token \"tam\n// giác\" bắt buộc). Nếu theo sau là \"tứ giác\"/\"hình ...\" (vd \"đường tròn\n// ngoại tiếp tứ giác BCEF\") → CHƯA hỗ trợ → KHÔNG claim để escalate AI, KHÔNG\n// được vơ tam giác đầu đề (mis-render circle qua 3 đỉnh khác).\n// - Bind tam giác từ cụm ngay SAU từ khoá trong clause (không phải tam giác\n// đầu tiên trong đề). Nhiều cấu trúc / clause → emit-all (matchAll cờ 'g').\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawCircle, CIRCLE_KW } from './_shared';\n\n// \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Dùng lookaround \\p{L} + cờ 'u'.\nconst HAS_INSCRIBE = /(?<!\\p{L})(?:nội|ngoại)\\s*tiếp(?!\\p{L})/iu;\n\n// Tên tâm tuỳ chọn xen giữa \"đường tròn\" và \"ngoại/nội tiếp\": \"(O)\" hoặc \"tâm O\".\n// (?:...)? để có thể vắng. Cờ 'i' an toàn ở cụm từ khoá; ([A-Z]) vẫn HOA-only.\n// PAREN hỗ trợ cả tên chữ (alpha, omega, (O)...).\nconst CENTER = '(?:\\\\(\\\\s*([^\\\\s;,).:]+)\\\\s*\\\\)|tâm\\\\s+([A-Z]))?';\n\n// \"đường tròn [ (O)/tâm O ] ngoại tiếp tam giác XYZ\" → circumcircle (through3).\n// Token \"tam giác\" + 3 đỉnh HOA BẮT BUỘC ngay sau \"ngoại tiếp\". Cờ 'g' để bắt\n// MỌI cấu trúc trong clause; 'i' để hoa đầu câu (\"Đường\"/\"Ngoại\"/\"Tam\") cũng\n// khớp — nhưng group đỉnh ([A-Z]) KHÔNG dùng 'i' (regex 'i' không tác động lên\n// lớp ký tự đã chỉ định HOA → vẫn chỉ khớp HOA, tránh nuốt chữ thường).\n// Guard \"(?<!tâm\\s)\": \"tâm đường tròn nội/ngoại tiếp tam giác\" = TÂM (điểm,\n// centers rule lo) — KHÔNG vẽ đường tròn ở đây (tránh circle thừa đụng tên).\nconst CIRCUM_TRI = new RegExp(\n '(?<!tâm\\\\s)' + CIRCLE_KW + '\\\\s*' +\n CENTER +\n '\\\\s*ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\n\n// \"đường tròn [ (I)/tâm I ] nội tiếp tam giác XYZ\" → incircle (inscribedIn).\nconst INCIRCLE_TRI = new RegExp(\n '(?<!tâm\\\\s)' + CIRCLE_KW + '\\\\s*' +\n CENTER +\n '\\\\s*nội\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\n\n// \"tam giác XYZ nội tiếp (trong) đường tròn [ (O)/tâm O ]\" → circumcircle.\n// Tam giác đứng TRƯỚC, đường tròn đứng SAU. Center (nếu có) đứng sau \"đường tròn\".\nconst TRI_INSCRIBED_IN_CIRCLE = new RegExp(\n 'tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?nội\\\\s*tiếp\\\\s+(?:trong\\\\s+)?' +\n CIRCLE_KW +\n '\\\\s*' +\n CENTER,\n 'giu',\n);\n\n// \"tam giác XYZ ngoại tiếp đường tròn [ (I)/tâm I ]\" → incircle (inscribedIn).\n// Tam giác NGOẠI tiếp (circumscribes) đường tròn = đường tròn NỘI tiếp tam giác.\n// \"đường tròn\" BẮT BUỘC NGAY sau \"ngoại tiếp\" (KHÔNG optional) để phân biệt với\n// \"đường tròn ngoại tiếp tam giác\" (circumcircle — đường tròn đứng TRƯỚC, \"ngoại\n// tiếp\" theo sau bởi \"tam giác\"). [^.]{0,40}? không vượt dấu '.' (không nhảy câu).\nconst TRI_CIRCUMSCRIBES_CIRCLE = new RegExp(\n 'tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?ngoại\\\\s*tiếp\\\\s+' +\n CIRCLE_KW +\n '\\\\s*' +\n CENTER,\n 'giu',\n);\n\n// Dạng TẮT: \"(O)\"/\"(I)\" NGAY sau \"nội/ngoại tiếp\" — KHÔNG có chữ \"đường tròn\"\n// (vd \"tam giác ABC nội tiếp (O)\"). Phổ biến ở đề olympiad; thiếu nhánh này thì\n// circumcircle O không được tạo → arcMidpoint tham chiếu O fail (transpile).\n// Paren BẮT BUỘC (1 ký tự HOA trong ngoặc) để KHÔNG over-match \"nội tiếp\" trần.\n// Phân biệt với TRI_INSCRIBED_IN_CIRCLE/TRI_CIRCUMSCRIBES_CIRCLE: ở đó sau \"tiếp\"\n// là \"đường tròn\" → 2 nhánh không chồng (dedup theo spec:tri vẫn an toàn nếu có).\n// Paren cho phép hậu tố bán kính \"(O; R)\" / \"(O; 3)\" (đề olympiad rất hay viết\n// \"tam giác ABC nội tiếp (O; R)\" — KHÔNG chữ \"đường tròn\"). Suffix [;,][^()]*\n// optional. circleRadius bỏ qua \"(O;R)\" khi có \"nội/ngoại tiếp\" nên không double.\n// Khoảng đệm giữa \"tam giác XYZ\" và \"nội/ngoại tiếp (X)\" KHÔNG được vượt qua\n// \"đường tròn\": nếu có \"đường tròn\" chêm vào thì đó là \"(tam giác …) đường tròn\n// nội/ngoại tiếp (X)\" — SUBJECT là ĐƯỜNG TRÒN (in/circumcircle, ngữ nghĩa NGƯỢC),\n// KHÔNG phải \"tam giác nội/ngoại tiếp (X)\". Tempered token chặn over-match đó.\n// (vd \"tam giác ABC, đường tròn nội tiếp (I)\" → KHÔNG được hiểu là tam giác ABC\n// nội tiếp (I) = circumcircle; đây là incircle (I), incircleTangency lo.)\nconst GAP_NO_CIRCLE = `(?:(?!${CIRCLE_KW})[^.]){0,40}?`;\nconst TRI_INSCRIBED_IN_PAREN = new RegExp(\n 'tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])' + GAP_NO_CIRCLE + 'nội\\\\s*tiếp\\\\s+(?:trong\\\\s+)?\\\\(\\\\s*([A-Z])(?:\\\\s*[;,][^()]*)?\\\\s*\\\\)',\n 'giu',\n);\nconst TRI_CIRCUMSCRIBES_PAREN = new RegExp(\n 'tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])' + GAP_NO_CIRCLE + 'ngoại\\\\s*tiếp\\\\s+\\\\(\\\\s*([A-Z])(?:\\\\s*[;,][^()]*)?\\\\s*\\\\)',\n 'giu',\n);\n\n// Standalone circle-SUBJECT: \"đường tròn nội/ngoại tiếp <tâm>\" — tâm (paren /\n// \"tâm X\" / chữ trần) ĐỨNG NGAY SAU \"nội/ngoại tiếp\" và KHÔNG kèm \"tam giác\".\n// Bind tam giác DUY NHẤT của đề (giống centers.ts). Hoàn tất ngữ nghĩa: \"đường\n// tròn nội tiếp (I)\" = INCIRCLE (inscribedIn), \"đường tròn ngoại tiếp (O)\" =\n// circumcircle (through3) — đối xứng với \"tam giác ABC nội/ngoại tiếp (X)\".\n// Tâm BẮT BUỘC (NAMED_AFTER) để không over-match \"đường tròn nội tiếp\" trần.\n// \"tâm\" (â) ≠ \"tam\" (a) nên \"đường tròn nội tiếp tam giác ABC\" KHÔNG khớp (đỉnh\n// không cấp tâm) → INCIRCLE_TRI lo.\n// KHÔNG cờ 'i': dưới 'i', `[A-Z]` khớp CẢ chữ thường (vd nuốt \"t\" của \"tứ giác\")\n// → mis-render. CIRCLE_KW đã mã hoá [Đđ] nên \"Đường\" đầu câu vẫn khớp; \"nội/ngoại\n// tiếp\" luôn viết thường (đứng sau \"đường tròn\").\nconst NAMED_AFTER = '(?:\\\\(\\\\s*([A-Z])\\\\s*\\\\)|tâm\\\\s+([A-Z])|([A-Z])(?![A-Za-z]))';\nconst CIRCLE_INCIRCLE_NAMED_NOTRI = new RegExp(CIRCLE_KW + '\\\\s*nội\\\\s*tiếp\\\\s*' + NAMED_AFTER, 'gu');\nconst CIRCLE_CIRCUM_NAMED_NOTRI = new RegExp(CIRCLE_KW + '\\\\s*ngoại\\\\s*tiếp\\\\s*' + NAMED_AFTER, 'gu');\n\n// Tam giác DUY NHẤT trong đề (dedup theo bộ đỉnh). Nhiều tam giác khác nhau →\n// undefined (nhập nhằng → không bind standalone, escalate).\nconst TRI_SCAN_G = /tam\\s*giác\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])/giu;\nfunction uniqueProblemTriangle(problem: string): [string, string, string] | undefined {\n const map = new Map<string, [string, string, string]>();\n TRI_SCAN_G.lastIndex = 0;\n for (const m of problem.matchAll(TRI_SCAN_G)) {\n map.set(`${m[1]}${m[2]}${m[3]}`, [m[1], m[2], m[3]]);\n }\n return map.size === 1 ? [...map.values()][0] : undefined;\n}\n\n// --- Ký hiệu ngoặc \"(O; R)\" quét TOÀN ĐỀ (segmenter cắt ';') ------------------\n// \"(đường tròn)? (O; R) ngoại/nội tiếp tam giác XYZ\" — circle ĐỨNG TRƯỚC. R là\n// CHỮ (bán kính ký hiệu) nên circleRadius bỏ qua (cần \\d). Guard\n// (?![^)]*[A-Z]\\s*[;,]) chặn paren méo nhiều dấu chấm phẩy \"(A; B; C)\".\nconst PAREN_CENTER =\n '(?:' + CIRCLE_KW + '\\\\s*)?\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)\\\\s*';\nconst CIRCUM_TRI_PAREN = new RegExp(\n PAREN_CENTER + 'ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\nconst INCIRCLE_TRI_PAREN = new RegExp(\n PAREN_CENTER + 'nội\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'giu',\n);\n\n// === EN patterns (issue #46 group B) ========================================\n// Semantics đối xứng VN. Phân biệt through3 (circumcircle) vs inscribedIn\n// (incircle) bằng SUBJECT (triangle/circle) + verb:\n// - triangle inscribed in circle → through3 (circle ngoại tiếp tam giác)\n// - triangle circumscribes/circumscribed about circle → inscribedIn (incircle)\n// - circle inscribed in triangle → inscribedIn (incircle)\n// - circle circumscribes/circumscribed about triangle → through3 (circumcircle)\n//\n// KHÔNG cờ 'i' (sẽ nuốt chữ thường vào group nhãn/center [A-Z]). First-letter\n// flex bằng [Tt]riangle / [Cc]ircle / [Ii]nscribed / [Cc]ircumscrib. Group\n// nhãn/center [A-Z] STRICT. Gap token = [^.]{0,N}? (non-greedy, không vượt '.').\n//\n// Center EN sau \"circle\": \"(O)\" (paren) hoặc bare \"O\" (neo (?![A-Za-z])).\nconst EN_CIRCLE_CENTER = '[Cc]ircle\\\\s+(?:\\\\(\\\\s*([A-Z])\\\\s*\\\\)|([A-Z])(?![A-Za-z]))';\nconst EN_TRI = '[Tt]riangle\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])';\n\n// SUBJECT=triangle + \"inscribed in\" circle → through3 (circumcircle).\n// \"triangle ABC (is)? inscribed in (the)? circle (O)\".\nconst EN_TRI_INSCRIBED_IN_CIRCLE = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n EN_CIRCLE_CENTER,\n 'gu',\n);\n\n// SUBJECT=triangle + \"circumscribes / circumscribed about|around\" circle → inscribedIn.\nconst EN_TRI_CIRCUMSCRIBES_CIRCLE = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n EN_CIRCLE_CENTER,\n 'gu',\n);\n\n// SUBJECT=circle + \"inscribed in\" triangle → inscribedIn (incircle).\nconst EN_CIRCLE_INSCRIBED_IN_TRI = new RegExp(\n EN_CIRCLE_CENTER +\n '[^.]{0,12}?[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// SUBJECT=circle + \"circumscribes / circumscribed about|around\" triangle → through3.\nconst EN_CIRCLE_CIRCUMSCRIBES_TRI = new RegExp(\n EN_CIRCLE_CENTER +\n '[^.]{0,12}?[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// --- EN paren whole-problem (segmenter cắt ';' trong \"(O; R)\") ----------------\n// Mirror VN PAREN: center \"(O\" bị cắt khỏi \"R)\". circle ĐỨNG TRƯỚC hoặc SAU.\n// Center = \"(\" + 1 ký tự HOA + \";\"/\",\" (KHÔNG đóng ngoặc cùng clause vì bị cắt).\n// Guard (?![^)]*[A-Z]\\s*[;,]) chặn paren méo nhiều dấu chấm phẩy.\nconst EN_PAREN_CIRCLE =\n '[Cc]ircle\\\\s+\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)\\\\s*';\n\n// \"triangle XYZ inscribed in circle (O; R)\" → through3.\nconst EN_TRI_INSCRIBED_PAREN = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n '[Cc]ircle\\\\s+\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)',\n 'gu',\n);\n\n// \"circle (O; R) circumscribes triangle XYZ\" → through3.\nconst EN_PAREN_CIRCLE_CIRCUMSCRIBES_TRI = new RegExp(\n EN_PAREN_CIRCLE +\n '[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// \"circle (I; r) inscribed in triangle XYZ\" → inscribedIn.\nconst EN_PAREN_CIRCLE_INSCRIBED_TRI = new RegExp(\n EN_PAREN_CIRCLE +\n '[Ii]nscribed\\\\s+in\\\\s+(?:the\\\\s+)?' +\n EN_TRI,\n 'gu',\n);\n\n// \"triangle XYZ circumscribes circle (I; r)\" → inscribedIn.\nconst EN_TRI_CIRCUMSCRIBES_PAREN = new RegExp(\n EN_TRI +\n '[^.]{0,12}?[Cc]ircumscrib(?:es|ed)\\\\s+(?:about\\\\s+|around\\\\s+)?' +\n '[Cc]ircle\\\\s+\\\\(\\\\s*([A-Z])\\\\s*[;,]\\\\s*(?![^)]*[A-Z]\\\\s*[;,])[^()]*?\\\\)',\n 'gu',\n);\n\n// Prefilter EN (NON-global cho .test). Chỉ \"inscribed\"/\"circumscrib\" mới quan tâm.\nconst HAS_INSCRIBE_EN = /[Ii]nscribed|[Cc]ircumscrib/u;\n\ninterface CircHit {\n index: number;\n spec: 'through3' | 'inscribedIn';\n tri: [string, string, string];\n /** tên tâm; '' nếu không khai báo (default 'O' khi emit). */\n center: string;\n}\n\nfunction pushAll(\n text: string,\n re: RegExp,\n spec: 'through3' | 'inscribedIn',\n // index của 3 group đỉnh trong match; center luôn group 1+2.\n triStart: number,\n out: CircHit[],\n): void {\n re.lastIndex = 0;\n for (const m of text.matchAll(re)) {\n const center = m[1] ?? m[2] ?? '';\n out.push({\n index: m.index ?? 0,\n spec,\n tri: [m[triStart], m[triStart + 1], m[triStart + 2]],\n center,\n });\n }\n}\n\n/**\n * Quét MỌI cấu trúc \"(đường tròn) ngoại/nội tiếp tam giác XYZ\" trong 1 clause.\n * Vùng text [start,end) đã thuộc 1 cấu trúc thì cấu trúc khác bỏ qua (tránh\n * trùng — \"tam giác XYZ nội tiếp đường tròn\" KHÔNG bị INCIRCLE_TRI quét lại).\n */\nfunction scanClause(text: string): CircHit[] {\n const hits: CircHit[] = [];\n // CIRCUM_TRI / INCIRCLE_TRI: center là group 1|2, đỉnh là group 3,4,5.\n pushAll(text, CIRCUM_TRI, 'through3', 3, hits);\n pushAll(text, INCIRCLE_TRI, 'inscribedIn', 3, hits);\n // TRI_INSCRIBED_IN_CIRCLE: đỉnh là group 1,2,3, center là group 4|5.\n TRI_INSCRIBED_IN_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(TRI_INSCRIBED_IN_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'through3',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n // TRI_CIRCUMSCRIBES_CIRCLE: tam giác ngoại tiếp đường tròn → incircle (inscribedIn).\n TRI_CIRCUMSCRIBES_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(TRI_CIRCUMSCRIBES_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'inscribedIn',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n // Dạng tắt \"(O)\"/\"(I)\" không kèm \"đường tròn\": center là group 4.\n TRI_INSCRIBED_IN_PAREN.lastIndex = 0;\n for (const m of text.matchAll(TRI_INSCRIBED_IN_PAREN)) {\n hits.push({ index: m.index ?? 0, spec: 'through3', tri: [m[1], m[2], m[3]], center: m[4] ?? '' });\n }\n TRI_CIRCUMSCRIBES_PAREN.lastIndex = 0;\n for (const m of text.matchAll(TRI_CIRCUMSCRIBES_PAREN)) {\n hits.push({ index: m.index ?? 0, spec: 'inscribedIn', tri: [m[1], m[2], m[3]], center: m[4] ?? '' });\n }\n\n // --- EN (issue #46 group B) ---------------------------------------------\n // SUBJECT=triangle (group 1,2,3) → center group 4|5.\n EN_TRI_INSCRIBED_IN_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(EN_TRI_INSCRIBED_IN_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'through3',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n EN_TRI_CIRCUMSCRIBES_CIRCLE.lastIndex = 0;\n for (const m of text.matchAll(EN_TRI_CIRCUMSCRIBES_CIRCLE)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'inscribedIn',\n tri: [m[1], m[2], m[3]],\n center: m[4] ?? m[5] ?? '',\n });\n }\n // SUBJECT=circle (center group 1|2) → triangle group 3,4,5.\n EN_CIRCLE_INSCRIBED_IN_TRI.lastIndex = 0;\n for (const m of text.matchAll(EN_CIRCLE_INSCRIBED_IN_TRI)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'inscribedIn',\n tri: [m[3], m[4], m[5]],\n center: m[1] ?? m[2] ?? '',\n });\n }\n EN_CIRCLE_CIRCUMSCRIBES_TRI.lastIndex = 0;\n for (const m of text.matchAll(EN_CIRCLE_CIRCUMSCRIBES_TRI)) {\n hits.push({\n index: m.index ?? 0,\n spec: 'through3',\n tri: [m[3], m[4], m[5]],\n center: m[1] ?? m[2] ?? '',\n });\n }\n\n // Khử trùng: 2 hit cùng 3 đỉnh + cùng spec → giữ 1 (vd câu vừa khớp\n // CIRCUM_TRI lẫn TRI_INSCRIBED_IN_CIRCLE hiếm khi xảy ra, nhưng an toàn).\n const seen = new Set<string>();\n const dedup: CircHit[] = [];\n hits.sort((a, b) => a.index - b.index);\n for (const h of hits) {\n const key = `${h.spec}:${h.tri.join('')}`;\n if (seen.has(key)) continue;\n seen.add(key);\n dedup.push(h);\n }\n return dedup;\n}\n\ninterface ParenHit {\n spec: 'through3' | 'inscribedIn';\n tri: [string, string, string];\n center: string;\n /** text khớp trên TOÀN đề (để gán clauseId qua substring-inclusion). */\n matchedText: string;\n}\n\n/**\n * Quét TOÀN đề cho ký hiệu ngoặc \"(O; R) ngoại/nội tiếp tam giác XYZ\" — dạng bị\n * segmenter cắt ngang ';' nên per-clause không bắt được. circle ĐỨNG TRƯỚC.\n */\nfunction scanProblemParen(problem: string): ParenHit[] {\n const out: ParenHit[] = [];\n const push = (re: RegExp, spec: 'through3' | 'inscribedIn') => {\n re.lastIndex = 0;\n for (const m of problem.matchAll(re)) {\n out.push({\n spec,\n tri: [m[2], m[3], m[4]],\n center: m[1] ?? '',\n matchedText: m[0],\n });\n }\n };\n push(CIRCUM_TRI_PAREN, 'through3');\n push(INCIRCLE_TRI_PAREN, 'inscribedIn');\n\n // --- EN (issue #46 group B): center group khác vị trí tuỳ SUBJECT ----------\n // SUBJECT=triangle (group 1,2,3) → center group 4.\n const pushTriFirst = (re: RegExp, spec: 'through3' | 'inscribedIn') => {\n re.lastIndex = 0;\n for (const m of problem.matchAll(re)) {\n out.push({ spec, tri: [m[1], m[2], m[3]], center: m[4] ?? '', matchedText: m[0] });\n }\n };\n pushTriFirst(EN_TRI_INSCRIBED_PAREN, 'through3');\n pushTriFirst(EN_TRI_CIRCUMSCRIBES_PAREN, 'inscribedIn');\n // SUBJECT=circle (center group 1) → triangle group 2,3,4.\n push(EN_PAREN_CIRCLE_CIRCUMSCRIBES_TRI, 'through3');\n push(EN_PAREN_CIRCLE_INSCRIBED_TRI, 'inscribedIn');\n return out;\n}\n\nfunction intentFor(spec: 'through3' | 'inscribedIn', tri: string[], center: string) {\n const name = center || 'O';\n return spec === 'inscribedIn'\n ? drawCircle(name, 'inscribedIn', { triangle: tri })\n : drawCircle(name, 'through3', { points: tri });\n}\n\n/**\n * Mỗi clause: quét emit-all các \"(đường tròn) nội/ngoại tiếp tam giác XYZ\".\n * - circumcircle (through3): \"đường tròn ngoại tiếp tam giác ABC\",\n * \"tam giác ABC nội tiếp đường tròn (O)\".\n * - incircle (inscribedIn): \"đường tròn nội tiếp tam giác ABC\",\n * \"tam giác ABC ngoại tiếp đường tròn (I)\".\n * Cộng nhánh TOÀN đề cho ký hiệu \"(O; R) ngoại/nội tiếp tam giác\" (bị cắt ';').\n * \"ngoại/nội tiếp\" mà KHÔNG có \"tam giác XYZ\" ngay sau (vd \"tứ giác\", \"hình\n * ...\", hoặc \"nội tiếp\" trần) → KHÔNG claim → escalate AI.\n */\nexport const circleTriangleRule: LanguageRule = {\n id: 'circleTriangle',\n priority: 72,\n languages: ['vi', 'en'],\n patterns: [HAS_INSCRIBE, HAS_INSCRIBE_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n const emitted = new Set<string>(); // \"spec:tri\" — dedup cross per-clause/paren.\n\n // 1) Per-clause (VN giữ nguyên hành vi cũ; EN thêm qua HAS_INSCRIBE_EN).\n for (const c of ctx.clauses) {\n if (!HAS_INSCRIBE.test(c.text) && !HAS_INSCRIBE_EN.test(c.text)) continue;\n const hits = scanClause(c.text);\n if (hits.length === 0) continue; // có \"ngoại/nội tiếp\" nhưng không tam giác\n for (const h of hits) emitted.add(`${h.spec}:${h.tri.join('')}`);\n out.push({\n ruleId: 'circleTriangle',\n clauseIds: [c.id],\n intents: hits.map((h) => intentFor(h.spec, h.tri, h.center)),\n });\n }\n\n // 1.6) Standalone circle-SUBJECT: \"đường tròn nội/ngoại tiếp <tâm>\" (tâm ngay\n // sau, KHÔNG kèm \"tam giác\") → bind tam giác DUY NHẤT của đề. Cho phép\n // \"Cho tam giác ABC có đường tròn nội tiếp (I)\" vẽ INCIRCLE (không phải\n // circumcircle). Dedup theo emitted (spec:tri) — KHÔNG đụng các nhánh trên.\n const uniqTri = uniqueProblemTriangle(ctx.problem);\n if (uniqTri) {\n for (const c of ctx.clauses) {\n for (const [re, spec] of [\n [CIRCLE_INCIRCLE_NAMED_NOTRI, 'inscribedIn'],\n [CIRCLE_CIRCUM_NAMED_NOTRI, 'through3'],\n ] as const) {\n re.lastIndex = 0;\n const m = re.exec(c.text);\n if (!m) continue;\n const key = `${spec}:${uniqTri.join('')}`;\n if (emitted.has(key)) continue;\n emitted.add(key);\n const center = m[1] ?? m[2] ?? m[3] ?? '';\n out.push({\n ruleId: 'circleTriangle',\n clauseIds: [c.id],\n intents: [intentFor(spec, uniqTri, center)],\n });\n }\n }\n }\n\n // 1.5) Toàn đề: PAREN dạng tắt \"tam giác XYZ nội/ngoại tiếp (O; R)\" (KHÔNG chữ\n // \"đường tròn\"). segmenter cắt ';' → per-clause mất ')'. Whole-problem giữ\n // \"(O; R)\" nguyên. Dedup theo emitted (spec:tri).\n for (const [re, spec] of [\n [TRI_INSCRIBED_IN_PAREN, 'through3'],\n [TRI_CIRCUMSCRIBES_PAREN, 'inscribedIn'],\n ] as const) {\n re.lastIndex = 0;\n for (const m of ctx.problem.matchAll(re)) {\n const tri = [m[1], m[2], m[3]];\n const key = `${spec}:${tri.join('')}`;\n if (emitted.has(key)) continue;\n emitted.add(key);\n const clauseIds = ctx.clauses.filter((c) => m[0].includes(c.text)).map((c) => c.id);\n out.push({ ruleId: 'circleTriangle', clauseIds, intents: [intentFor(spec, tri, m[4] ?? '')] });\n }\n }\n\n // 2) Toàn đề: ký hiệu \"(O; R)\" (segmenter cắt ';'). Bỏ qua nếu (spec:tri) đã\n // emit ở per-clause. clauseId = mọi clause là substring của đoạn khớp\n // (đoạn này trải qua nhiều clause do bị cắt) → coverage tính phủ cả 2.\n for (const h of scanProblemParen(ctx.problem)) {\n const key = `${h.spec}:${h.tri.join('')}`;\n if (emitted.has(key)) continue;\n emitted.add(key);\n const clauseIds = ctx.clauses\n .filter((c) => h.matchedText.includes(c.text))\n .map((c) => c.id);\n out.push({\n ruleId: 'circleTriangle',\n clauseIds,\n intents: [intentFor(h.spec, h.tri, h.center)],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentFromExt.ts\n//\n// Tiếp tuyến TỪ điểm NGOÀI đường tròn (2 nhánh):\n// \"Kẻ hai tiếp tuyến từ A đến (O)\" → drawLine(t, tangentFromExt, {from:'A', circle:'O', which:'both'})\n// \"Vẽ tiếp tuyến từ điểm A tới đường tròn O\" → drawLine(t, tangentFromExt, {from:'A', circle:'O', which:'both'})\n// \"Từ A vẽ tiếp tuyến với (O)\" → drawLine(t, tangentFromExt, {from:'A', circle:'O', which:'both'})\n//\n// Phân biệt với tangentAt (\"tiếp tuyến TẠI A của (O)\") — chỗ đó dùng \"tại\",\n// còn ở đây là \"từ <điểm ngoài>\". Rule này CHỈ match \"từ\"/\"Từ ... vẽ tiếp tuyến\".\n//\n// GOTCHA: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\n// from / circle là 1 ký tự HOA; name của line default 't' (LabelZ cho phép).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawLine, addPoint } from './_shared';\n\n// Prefilter toàn đề: phải có \"tiếp tuyến\".\nconst HAS_TANGENT = /tiếp\\s*tuyến/u;\n\n// Target đường tròn: PHẢI có dấu hiệu đường tròn — \"(X)\" hoặc \"đường tròn X\".\n// KHÔNG nhận chữ HOA TRẦN (vd \"tiếp tuyến từ A đến BC\": \"BC\" là đoạn thẳng, không\n// phải đường tròn → không claim, escalate). Hai alternative → 2 capture nhóm,\n// caller lấy nhóm nào khớp.\nconst CIRCLE_TARGET = String.raw`(?:đường\\s*tròn\\s*([A-Z])(?:['′]?)|\\(\\s*([A-Z])(?:['′]?)\\s*\\))`;\n\n// \"(kẻ|vẽ) (hai)? tiếp tuyến từ (điểm)? A (đến|tới|với) <đường tròn>\"\n// - động từ kẻ/vẽ BẮT BUỘC: chặn ngữ cảnh TÍNH/giả thiết (\"Độ dài tiếp tuyến\n// từ A đến (O) bằng 5\" → không có kẻ/vẽ → không match, escalate).\n// - \"hai\"/\"một\" optional (1 hay 2 nhánh vẫn coi là tiếp tuyến từ điểm ngoài).\n// - from = 1 ký tự HOA sau \"từ (điểm)?\".\n// - giới từ đến/tới/với nối qua đường tròn (bắt buộc có dấu hiệu — CIRCLE_TARGET).\nconst FROM_FORM = new RegExp(\n String.raw`(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:một\\s+|hai\\s+)?tiếp\\s*tuyến\\s+từ\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)\\s+(?:đến|tới|với)\\s+` +\n CIRCLE_TARGET,\n 'u',\n);\n\n// Biến thể đảo: \"Từ (điểm)? A ... (kẻ|vẽ) (hai)? tiếp tuyến (đến|tới|với) <đường tròn>\".\n// - kẻ|vẽ vẫn bắt buộc (đã có sẵn trong cú pháp đảo).\nconst TU_FORM = new RegExp(\n String.raw`(?<!\\p{L})[Tt]ừ\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)(?!\\p{L})[^.]{0,40}?(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:một\\s+|hai\\s+)?tiếp\\s*tuyến\\s+(?:đến|tới|với)\\s+` +\n CIRCLE_TARGET,\n 'u',\n);\n\n// === EN patterns (issue #46 group B) ========================================\n// Target đường tròn EN: \"(X)\" (language-agnostic, giống VN) HOẶC \"circle X\" /\n// \"circle (X)\". KHÔNG nhận chữ HOA TRẦN (\"from A to BC\": BC là đoạn → không\n// claim → escalate). Hai alternative → 2 capture nhóm (caller lấy nhóm nào khớp).\n// - nhóm 1: ([A-Z]) sau \"circle\" (có thể bọc \"(...)\").\n// - nhóm 2: ([A-Z]) trong \"(...)\" trần (không từ \"circle\").\n// First-letter flex [Cc]; KHÔNG cờ 'i' (giữ [A-Z] strict cho nhãn).\nconst CIRCLE_TARGET_EN = String.raw`(?:[Cc]ircle\\s*\\(?\\s*([A-Z])(?:['′]?)\\s*\\)?|\\(\\s*([A-Z])(?:['′]?)\\s*\\))`;\n\n// \"(Draw|Construct) (the|two)? tangent(s)? (lines)? from (the)? A to (the)? <circle>\"\n// - động từ Draw/Construct BẮT BUỘC: chặn ngữ cảnh TÍNH (\"The length of the\n// tangent from A to (O) is 5\" → không có Draw/Construct → không match,\n// escalate). Mirror ràng buộc verb của FROM_FORM (VN).\n// - giới từ \"from <A> to <circle>\" BẮT BUỘC: phân biệt với tangentAt\n// (\"tangent ... at A\" → không có \"from ... to\" → không match ở đây).\n// - from = 1 ký tự HOA sau \"from (the)?\".\n// - circle bắt buộc có dấu hiệu (CIRCLE_TARGET_EN — \"(X)\" hoặc \"circle X\").\n// GROUP INDEX: from = nhóm 1; circle = nhóm 2 (\"circle X\") HOẶC nhóm 3 (\"(X)\").\nconst FROM_FORM_EN = new RegExp(\n String.raw`(?:[Dd]raw|[Cc]onstruct)\\s+(?:the\\s+|two\\s+|the\\s+two\\s+)?tangents?(?:\\s+lines?)?\\s+from\\s+(?:the\\s+)?([A-Z])(?:['′]?)\\s+to\\s+(?:the\\s+)?` +\n CIRCLE_TARGET_EN,\n 'u',\n);\n\n// Biến thể đảo EN: \"From (the)? A, ... (draw|construct) (the|two)? tangent(s)?\n// (lines)? to (the)? <circle>\".\n// - verb draw/construct vẫn bắt buộc (nằm sau \"From A\").\n// - \"from A ... to <circle>\" vẫn đầy đủ (from ở đầu, to trước circle).\n// GROUP INDEX: from = nhóm 1; circle = nhóm 2 (\"circle X\") HOẶC nhóm 3 (\"(X)\").\nconst FROM_INV_EN = new RegExp(\n String.raw`(?<![A-Za-z])[Ff]rom\\s+(?:the\\s+)?([A-Z])(?:['′]?)(?![A-Za-z])[^.]{0,40}?(?:[Dd]raw|[Cc]onstruct)\\s+(?:the\\s+|two\\s+|the\\s+two\\s+)?tangents?(?:\\s+lines?)?\\s+to\\s+(?:the\\s+)?` +\n CIRCLE_TARGET_EN,\n 'u',\n);\n\n// === NAMED tangent points (issue #46) =======================================\n// \"Vẽ hai tiếp tuyến AB, AC từ A đến (O)\" — B, C LÀ tiếp điểm (named). Khác với\n// nhánh UNNAMED ở trên (regex unnamed FAIL vì \"AB, AC\" chen giữa \"tiếp tuyến\" và\n// \"từ\"). Hai regex dưới bắt 2 đoạn tiếp tuyến + đường tròn trong 1 match.\n// GROUP INDEX (cả VN & EN): m[1]=chữ đầu đoạn 1 (điểm ngoài x1),\n// m[2]=tiếp điểm 1 (B), m[3]=chữ đầu đoạn 2 (x2), m[4]=tiếp điểm 2 (C),\n// m[5]/m[6] = circle (qua CIRCLE_TARGET / CIRCLE_TARGET_EN).\nconst NAMED_FROM_VN = new RegExp(\n String.raw`(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:một\\s+|hai\\s+)?tiếp\\s*tuyến\\s+([A-Z])([A-Z])\\s*(?:,|và)\\s*([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?(?:đến|tới|với)\\s+` +\n CIRCLE_TARGET,\n 'u',\n);\nconst NAMED_FROM_EN = new RegExp(\n String.raw`(?:[Dd]raw|[Cc]onstruct)\\s+(?:the\\s+|two\\s+|the\\s+two\\s+)?tangents?(?:\\s+lines?)?\\s+([A-Z])([A-Z])\\s*(?:,|and)\\s*([A-Z])([A-Z])(?![A-Z])[^.]{0,40}?to\\s+(?:the\\s+)?` +\n CIRCLE_TARGET_EN,\n 'u',\n);\n\nexport const tangentFromExtRule: LanguageRule = {\n id: 'tangentFromExt',\n priority: 65,\n languages: ['vi', 'en'],\n // EN prefilter \"tangent\" để runRules (prefilter qua patterns[], bỏ qua\n // languages) chạy match() cho đề EN thuần (không có \"tiếp tuyến\").\n patterns: [HAS_TANGENT, /[Tt]angent/u],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // NOTE: \"từ P kẻ tiếp tuyến tiếp xúc với (O) tại M\" (1 tiếp tuyến + tiếp\n // điểm đặt tên, từ điểm ngoài P PHÁI SINH) tách sang rule riêng\n // tangentFromPointAt (priority < point-on-tangent-ray) để P được dựng\n // TRƯỚC khi tham chiếu — xem tangentFromPointAt.ts.\n // === NAMED tangent points (issue #46): \"tiếp tuyến AB, AC ... (O)\" → dựng\n // tiếp điểm B,C (tangentPointExt) cộng với 2 tiếp tuyến. from = chữ cái đầu\n // CHUNG của 2 đoạn (điểm ngoài); tiếp điểm = chữ cái thứ 2 mỗi đoạn.\n const named = NAMED_FROM_VN.exec(c.text) ?? NAMED_FROM_EN.exec(c.text);\n if (named) {\n const from = named[1];\n const tpB = named[2];\n const x2 = named[3];\n const tpC = named[4];\n const circle = named[5] ?? named[6];\n // Hợp lệ: cùng điểm ngoài (m1===m3), 2 tiếp điểm phân biệt & khác điểm ngoài.\n if (\n circle && from === x2 &&\n tpB !== from && tpC !== from && tpB !== tpC\n ) {\n out.push({\n ruleId: 'tangentFromExt',\n clauseIds: [c.id],\n intents: [\n drawLine('t', 'tangentFromExt', { from, circle, which: 'both' }),\n addPoint(tpB, { kind: 'tangentPoint', from, circle, which: 0 }),\n addPoint(tpC, { kind: 'tangentPoint', from, circle, which: 1 }),\n ],\n });\n continue; // clause handled — skip unnamed path\n }\n // not valid named form → fall through to unnamed logic (will likely escalate)\n }\n // VN trước (FROM_FORM / TU_FORM), giữ nguyên hành vi cũ; EN sau (FROM_FORM_EN\n // / FROM_INV_EN). circle bắt qua 1 trong các alternative capture group.\n const m =\n FROM_FORM.exec(c.text) ??\n TU_FORM.exec(c.text) ??\n FROM_FORM_EN.exec(c.text) ??\n FROM_INV_EN.exec(c.text);\n if (!m) continue;\n const from = m[1];\n // circle bắt qua 1 trong 2 alternative:\n // VN: \"đường tròn X\" = m[2], \"(X)\" = m[3].\n // EN: \"circle X\" = m[2], \"(X)\" = m[3] (cùng index — cả 2 dạng đều có\n // circle ở nhóm 2/3 vì from luôn là nhóm 1, CIRCLE_TARGET(_EN) có 2\n // alternative nhóm 2 & 3).\n const circle = m[2] ?? m[3];\n // Không xác định được from hoặc circle → bỏ qua (escalate AI).\n if (!from || !circle) continue;\n out.push({\n ruleId: 'tangentFromExt',\n clauseIds: [c.id],\n intents: [\n drawLine('t', 'tangentFromExt', { from, circle, which: 'both' }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/externalPoint.ts\n//\n// Điểm nằm NGOÀI đường tròn (free external point):\n// \"Lấy điểm A nằm ngoài đường tròn (O)\" → addPoint(A, {externalToCircle, circle:'O'})\n// \"Lấy điểm A ở ngoài (O)\" → addPoint(A, {externalToCircle, circle:'O'})\n// \"Gọi A là điểm nằm ngoài (O)\" → addPoint(A, {externalToCircle, circle:'O'})\n// \"Take a point A outside the circle (O).\" (EN) → addPoint(A, {externalToCircle, circle:'O'})\n//\n// Mục đích: UNBLOCK tangentFromExt render END-TO-END. tangentFromExt emit\n// drawLine(from:'A', circle:'O') nhưng KHÔNG rule nào dựng điểm A ngoài circle\n// → transpile UNKNOWN_REF A → escalate. Rule này dựng A (qua builder\n// externalToCircle, đọc tâm+bán kính từ build state, đặt A free ngoài circle).\n//\n// PRIORITY 68: sau circleRadius (75) / circleTriangle (72) để circle build\n// TRƯỚC, trước tangentFromExt (65) để A build TRƯỚC tangent. Build order:\n// circle → A → tangent (đúng phụ thuộc).\n//\n// GOTCHA \\b: ký tự Việt \"ngoài\" → KHÔNG dùng \\b. Cờ 'u' cho mọi regex.\n// `[^.A-Z]` giữa name và \"ngoài\"/\"outside\" chặn nhảy qua nhãn HOA khác / dấu chấm.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// VN: \"(Lấy|Gọi) (điểm)? A ... ngoài (đường tròn (X) | (X))\".\n// - from = nhóm 1 (1 ký tự HOA).\n// - circle = nhóm 2 (\"đường tròn X\") HOẶC nhóm 3 (\"(X)\").\n// - [^.A-Z]{0,14}? cho \"nằm\"/\"ở\" chen giữa, chặn dấu chấm / nhãn HOA khác.\nconst VN_FORM = new RegExp(\n String.raw`(?:[Ll]ấy|[Gg]ọi)\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)[^.A-Z]{0,14}?ngoài\\s+(?:đường\\s*tròn\\s*\\(?\\s*([A-Z])\\s*\\)?|\\(\\s*([A-Z])\\s*\\))`,\n 'u',\n);\n\n// VN không nêu tên circle: \"(Lấy|Gọi) (điểm)? A ... ngoài đường tròn\" (KHÔNG\n// \"(X)\" theo sau) → resolve circle DUY NHẤT trong đề. Phổ biến: \"Lấy điểm C nằm\n// ngoài đường tròn và …\". group1 = A. Circle suy từ \"(X)\" duy nhất toàn đề.\nconst VN_FORM_UNNAMED = new RegExp(\n String.raw`(?:[Ll]ấy|[Gg]ọi)\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)[^.A-Z]{0,14}?ngoài\\s+đường\\s*tròn(?!\\s*\\(?\\s*[A-Z]\\s*\\)?)`,\n 'u',\n);\nconst ONLY_CIRCLE = /\\(\\s*([A-Z])\\s*\\)/u;\n\n// EN: \"(Take|Let|Mark|Choose|Pick) (a)? (point)? A ... outside (the)? (circle (X) | (X))\".\n// - from = nhóm 1; circle = nhóm 2 (\"circle X\") HOẶC nhóm 3 (\"(X)\").\n// - [^.A-Z]{0,24}? cho \"be a point\"/\"nằm\" chen giữa, chặn dấu chấm / nhãn HOA.\nconst EN_FORM = new RegExp(\n String.raw`(?:[Tt]ake|[Ll]et|[Mm]ark|[Cc]hoose|[Pp]ick)\\s+(?:a\\s+)?(?:point\\s+)?([A-Z])(?:['′]?)[^.A-Z]{0,24}?outside\\s+(?:the\\s+)?(?:[Cc]ircle\\s*\\(?\\s*([A-Z])\\s*\\)?|\\(\\s*([A-Z])\\s*\\))`,\n 'u',\n);\n\nexport const externalPointRule: LanguageRule = {\n id: 'externalPoint',\n priority: 68,\n languages: ['vi', 'en'],\n // Prefilter toàn đề (runRules prefilter qua patterns[], BỎ QUA languages):\n // cần bắt cả VN (\"ngoài\") lẫn EN (\"outside\"). match() mới có regex chặt.\n patterns: [/ngoài/u, /[Oo]utside/u],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = VN_FORM.exec(c.text) ?? EN_FORM.exec(c.text);\n let from: string | undefined;\n let circle: string | undefined;\n if (m) {\n from = m[1];\n circle = m[2] ?? m[3];\n } else {\n // Fallback: \"ngoài đường tròn\" KHÔNG nêu tên → circle duy nhất toàn đề.\n const u = VN_FORM_UNNAMED.exec(c.text);\n const oc = ONLY_CIRCLE.exec(ctx.problem);\n if (u && oc) {\n from = u[1];\n circle = oc[1];\n }\n }\n if (!from || !circle) continue; // escalate-safe\n out.push({\n ruleId: 'externalPoint',\n clauseIds: [c.id],\n intents: [addPoint(from, { kind: 'externalToCircle', circle })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/arcMidpoint.ts\n//\n// Điểm chính giữa cung: \"Gọi M là điểm chính giữa cung BC (không chứa A)\".\n// → add-point M {kind:'arcMidpoint', circle:'O', a:'B', b:'C', notContaining:'A'}\n//\n// circle lấy từ toàn đề (\"(O)\" / \"đường tròn (tâm) O\"); KHÔNG có circle → bỏ qua\n// (escalate AI — không thể dựng cung mà không biết đường tròn).\n//\n// notContaining (PHẢI là đỉnh thứ 3, ∉ {a,b}):\n// - \"không chứa X\" → X (chỉ nhận nếu X ∉ {a,b}; X∈{a,b} vô nghĩa → bỏ qua)\n// - không nêu nhưng có tam giác → đỉnh thứ 3 (đỉnh tam giác không thuộc cặp cung)\n// - cả hai đều không suy được → bỏ qua (escalate)\n//\n// CHỈ xử lý cú pháp \"cung (nhỏ)? <PAIR> không chứa <Z>\" (containment ÂM, cung nhỏ).\n// Vượt scope → bỏ qua (escalate, an toàn — đừng mis-render):\n// - \"cung lớn <PAIR>\" → cung lớn, ngữ nghĩa cung đối → defer\n// - \"chứa X\" (containment DƯƠNG, không có \"không\" đứng trước) → defer\n//\n// Tên điểm qua extractPointName / ký tự HOA trước \"(là) điểm chính giữa\"; không\n// trích được tên → bỏ qua (đừng bịa tên).\n//\n// EN (issue #46 group B): hỗ trợ thêm các dạng tiếng Anh tương đương —\n// \"Let M be the midpoint of arc BC not containing A\"\n// \"M is the midpoint of the (minor) arc BC\" (suy notContaining từ \"Triangle ABC\")\n// \"major arc\" → defer (mirror \"cung lớn\"); \"containing X\" dương → defer.\n// Tên điểm EN qua \"X is/be the midpoint of … arc\" (extractPointName là VN-only).\n// Collision midpoint EN (rule prio 50): KHÔNG xảy ra — midpoint EN cần\n// \"midpoint of (segment|side)? [A-Z][A-Z]\", nhưng sau \"of\" ở đây là \"arc\" (chữ\n// thường) → [A-Z] fail → midpoint không grab \"BC\".\n//\n// GOTCHA \\b: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\",\"ạ\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawCircle, extractPointName, pairFromToken } from './_shared';\n\n// Prefilter toàn đề: \"chính giữa cung\" hoặc \"trung điểm cung\".\nconst ARC_MID = /(?:chính\\s+giữa|trung\\s*điểm)\\s+(?:của\\s+)?cung/u;\n\n// Cụm cung + cặp đỉnh: \"điểm chính giữa cung (nhỏ|lớn) BC\".\n// \"nhỏ|lớn\" optional; \"của\" optional. Cặp đỉnh = 2 ký tự HOA liền.\n// group1 = tính từ cung (nhỏ|lớn) optional, group2+3 = cặp đỉnh.\nconst ARC_PAIR =\n /(?:chính\\s+giữa|trung\\s*điểm)\\s+(?:của\\s+)?cung\\s+(nhỏ\\s+|lớn\\s+)?([A-Z])([A-Z])/u;\n\n// Tên điểm đứng TRƯỚC cụm: \"M (là) (điểm) (chính giữa|trung điểm) cung\".\nconst NAME_BEFORE =\n /([A-Z])(?:['′]?)\\s+(?:là\\s+)?(?:điểm\\s+)?(?:chính\\s+giữa|trung\\s*điểm)\\s+(?:của\\s+)?cung/u;\n\n// Tam giác trong toàn đề → 3 đỉnh (dùng suy notContaining khi đề không nêu).\nconst TRI = /tam giác\\s+([A-Z])([A-Z])([A-Z])/u;\n\n// Tên đường tròn trong toàn đề: \"đường tròn (tâm) O\" / \"(O)\".\n// - \"đường tròn tâm O\" / \"đường tròn O\" → O\n// - \"(O)\" đứng riêng (1 ký tự HOA trong ngoặc, không phải cặp đỉnh / số)\nconst CIRCLE_WORDS = /đường\\s*tròn\\s*(?:\\(\\s*)?(?:tâm\\s+)?([A-Z])(?![A-Z])/u;\n// \"(O)\" bare HOẶC compact \"(O;R)\"/\"(O,R)\" — vao10:35 \"Cho nửa (O;R) đường kính\n// AB\" không có chữ \"đường tròn\" → CIRCLE_WORDS fail, fallback paren phải nhận ;R.\nconst CIRCLE_PAREN = /\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)/u;\n\n// === EN patterns (issue #46 group B) =========================================\n// First-letter case-flex [Mm]/[Tt]; KHÔNG cờ 'i' (phá nhãn [A-Z]). Nhãn STRICT\n// [A-Z] + neo (?![A-Za-z]) cuối cặp đỉnh (chặn \"BCD\" 3 chữ → escalate-safe).\n// Prefilter EN: \"midpoint of (the)? (minor|major)? arc\".\nconst ARC_MID_EN = /[Mm]idpoint\\s+of\\s+(?:the\\s+)?(?:minor\\s+|major\\s+)?arc/u;\n// Cụm cung + cặp đỉnh EN.\nconst ARC_PAIR_EN =\n /[Mm]idpoint\\s+of\\s+(?:the\\s+)?(?:minor\\s+|major\\s+)?arc\\s+([A-Z])([A-Z])(?![A-Za-z])/u;\n// Tên đứng TRƯỚC: \"M is/be the midpoint of arc\". (EN không có lời dẫn VN; extractPointName VN-only.)\nconst NAME_BEFORE_EN =\n /([A-Z])(?:['′]?)\\s+(?:is|be)\\s+the\\s+midpoint\\s+of\\s+(?:the\\s+)?(?:minor\\s+|major\\s+)?arc/u;\n// Tam giác EN (suy notContaining khi không nêu \"not containing\").\nconst TRI_EN = /[Tt]riangle\\s+([A-Z])([A-Z])([A-Z])(?![A-Za-z])/u;\n// Scope guard: \"major arc\" → defer (mirror VN \"cung lớn\").\nconst MAJOR_ARC_EN = /major\\s+arc/u;\n\n// === Containment (chứa / không chứa) =========================================\n// Một mệnh đề containment = \"(không )?chứa X\". `rel:'not'` ⇒ notContaining,\n// `rel:'in'` ⇒ containing. Trích THEO THỨ TỰ để zip với danh sách tên (phân phối).\n// /g + lastIndex reset 0; ký tự Việt ⇒ lookaround \\p{L} thay \\b.\ntype Containment = { rel: 'not' | 'in'; point: string };\nfunction parseContainmentsVN(text: string): Containment[] {\n const re = /(không\\s+)?chứa\\s+(?:điểm\\s+|đỉnh\\s+)?([A-Z])(?!\\p{L})/gu;\n const out: Containment[] = [];\n let m: RegExpExecArray | null;\n while ((m = re.exec(text))) out.push({ rel: m[1] ? 'not' : 'in', point: m[2] });\n return out;\n}\nfunction parseContainmentsEN(text: string): Containment[] {\n const re = /(not\\s+)?containing\\s+(?:the\\s+)?(?:point\\s+|vertex\\s+)?([A-Z])(?![A-Za-z])/gu;\n const out: Containment[] = [];\n let m: RegExpExecArray | null;\n while ((m = re.exec(text))) out.push({ rel: m[1] ? 'not' : 'in', point: m[2] });\n return out;\n}\n\n// Trường constraint từ 1 mệnh đề containment (notContaining XOR containing).\nfunction containmentField(ct: Containment): { notContaining: string } | { containing: string } {\n return ct.rel === 'in' ? { containing: ct.point } : { notContaining: ct.point };\n}\n\n// Phân phối VN: \"N, T lần lượt là (điểm) (chính giữa|trung điểm) (của) cung (nhỏ|lớn)? BC <tail>\".\n// group1 = blob tên (≥2, phẩy), group2/3 = cặp đỉnh, group4 = đuôi chứa danh sách containment.\nconst DISTRIB_VN = new RegExp(\n '((?:[A-Z](?:[\\'′]?)\\\\s*,\\\\s*)+[A-Z](?:[\\'′]?))\\\\s+lần\\\\s*lượt\\\\s+(?:là\\\\s+)?(?:điểm\\\\s+)?' +\n '(?:chính\\\\s+giữa|trung\\\\s*điểm)\\\\s+(?:của\\\\s+)?cung\\\\s+(?:nhỏ\\\\s+|lớn\\\\s+)?([A-Z])([A-Z])\\\\s+(.+)',\n 'u',\n);\n\n// Phân phối 2 CUNG: \"N và P lần lượt là (điểm)? chính giữa (của)? cung AM và cung\n// MB\" → zip N↔cung AM, P↔cung MB (httcd:237; tên nối \"và\"/phẩy, mỗi cung nêu\n// \"cung XY\" riêng). KHÁC DISTRIB_VN (1 cung + nhiều containment). Không containment\n// (nửa đường tròn / cung nêu tường minh từng cặp). groups: 1=n1 2=n2 3=a1 4=b1 5=a2 6=b2.\nconst DISTRIB_TWO_ARCS = new RegExp(\n \"([A-Z])(?:['′]?)\\\\s*(?:,|và)\\\\s*([A-Z])(?:['′]?)\\\\s+lần\\\\s*lượt\\\\s+(?:là\\\\s+)?(?:điểm\\\\s+)?\" +\n '(?:chính\\\\s+giữa|trung\\\\s*điểm)\\\\s+(?:của\\\\s+)?cung\\\\s+(?:nhỏ\\\\s+|lớn\\\\s+)?([A-Z])([A-Z])(?![A-Z])' +\n '\\\\s+và\\\\s+(?:điểm\\\\s+)?(?:(?:chính\\\\s+giữa|trung\\\\s*điểm)\\\\s+)?(?:của\\\\s+)?cung\\\\s+(?:nhỏ\\\\s+|lớn\\\\s+)?([A-Z])([A-Z])(?![A-Z])',\n 'u',\n);\n\n/** Tên đường tròn từ toàn đề; undefined nếu không tìm thấy. */\nfunction resolveCircle(problem: string): string | undefined {\n const w = CIRCLE_WORDS.exec(problem);\n if (w) return w[1];\n const p = CIRCLE_PAREN.exec(problem);\n if (p) return p[1];\n return undefined;\n}\n\n/**\n * Tên cho circumcircle NGẦM (khi đề không nêu \"(O)\"): ưu tiên 'O' (quy ước), né\n * nếu đã là token HOA đứng riêng trong đề (vd điểm O); else 'O1'/'O2'/'W'.\n */\nfunction synthCircleName(problem: string): string {\n for (const cand of ['O', 'O1', 'O2', 'W']) {\n if (!new RegExp(`(?<!\\\\p{L})${cand}(?![\\\\p{L}\\\\d])`, 'u').test(problem)) return cand;\n }\n return 'O'; // fallback (resolveCircleNameCollisions sẽ dedup nếu cần)\n}\n\n/**\n * \"Gọi M là điểm chính giữa cung nhỏ BC không chứa A\" → add-point M\n * {kind:'arcMidpoint', circle, a:'B', b:'C', notContaining:'A'}.\n *\n * Một clause khớp khi: trích được tên điểm, cặp đỉnh cung, đường tròn, và\n * notContaining (nêu \"không chứa X\" hoặc suy từ đỉnh thứ 3 của tam giác). Thiếu\n * bất kỳ thành phần nào → bỏ qua clause (escalate AI thay vì đoán sai).\n */\nexport const arcMidpointRule: LanguageRule = {\n id: 'arcMidpoint',\n priority: 60,\n languages: ['vi', 'en'],\n patterns: [ARC_MID, ARC_MID_EN],\n match(ctx) {\n const explicitCircle = resolveCircle(ctx.problem);\n const tri = TRI.exec(ctx.problem);\n const triEnM0 = TRI_EN.exec(ctx.problem);\n // Tam giác để suy circumcircle NGẦM khi đề KHÔNG nêu \"(O)\" (VN ưu tiên, EN fallback).\n const circumTri: string[] | null = tri\n ? [tri[1], tri[2], tri[3]]\n : triEnM0\n ? [triEnM0[1], triEnM0[2], triEnM0[3]]\n : null;\n // \"(O)\" tường minh thắng; else circumcircle ngầm của tam giác (tên synth).\n const circle = explicitCircle ?? (circumTri ? synthCircleName(ctx.problem) : undefined);\n if (!circle) return []; // không circle tường minh + không tam giác → escalate\n const usesCircum = !explicitCircle;\n\n const out: RuleMatch[] = [];\n // Khi dùng circumcircle ngầm, prepend drawCircle(through3) vào arcMidpoint ĐẦU\n // TIÊN dùng nó → circle emit TRƯỚC điểm (transpile resolve ref theo thứ tự).\n let circumEmitted = false;\n const withCircum = (ap: IntentT): IntentT[] => {\n if (usesCircum && !circumEmitted && circumTri) {\n circumEmitted = true;\n return [drawCircle(circle, 'through3', { points: circumTri }), ap];\n }\n return [ap];\n };\n // Circumcircle ngầm chỉ hợp lệ khi 2 đầu mút cung LÀ đỉnh tam giác.\n const arcOnCircum = (a: string, b: string): boolean =>\n !usesCircum || (!!circumTri && circumTri.includes(a) && circumTri.includes(b));\n\n // Đẩy 1 arcMidpoint (containment đã phân loại). endpoint-cung làm tham chiếu\n // containment ⇒ vô nghĩa → trả false (caller escalate). Trả true nếu emit OK.\n const pushArc = (\n c: { id: number }, name: string, a: string, b: string, ct: Containment,\n ): boolean => {\n if (ct.point === a || ct.point === b) return false; // tham chiếu = đầu mút cung → vô nghĩa\n out.push({\n ruleId: 'arcMidpoint',\n clauseIds: [c.id],\n intents: withCircum(addPoint(name, { kind: 'arcMidpoint', circle, a, b, ...containmentField(ct) })),\n });\n return true;\n };\n\n for (const c of ctx.clauses) {\n if (!ARC_MID.test(c.text)) continue;\n\n // Phân phối 2 cung \"N và P … cung AM và cung MB\" → zip (chạy TRƯỚC dạng đơn\n // vì ARC_PAIR chỉ bắt cung ĐẦU, bỏ sót điểm thứ hai).\n const twoArcs = DISTRIB_TWO_ARCS.exec(c.text);\n if (twoArcs) {\n const [, n1, n2, a1, b1, a2, b2] = twoArcs;\n const pairs: Array<[string, string, string]> = [\n [n1, a1, b1],\n [n2, a2, b2],\n ];\n const ok = pairs.every(\n ([n, a, b]) => arcOnCircum(a, b) && n !== a && n !== b,\n );\n if (ok) {\n for (const [n, a, b] of pairs) {\n out.push({\n ruleId: 'arcMidpoint',\n clauseIds: [c.id],\n intents: withCircum(addPoint(n, { kind: 'arcMidpoint', circle, a, b })),\n });\n }\n }\n continue;\n }\n\n const pairM = ARC_PAIR.exec(c.text);\n if (!pairM) continue;\n // Vượt scope CỤC BỘ: cung ĐANG lấy trung điểm là \"lớn\" → cung đối, defer.\n // (Kiểm trên match — KHÔNG quét cả clause: clause gộp phẩy có thể chứa\n // \"cung lớn\" ở định nghĩa khác, vd \"M thuộc cung lớn AB, P là … cung AM\".)\n if (pairM[1] && /lớn/u.test(pairM[1])) continue;\n const pair = pairFromToken(pairM[2] + pairM[3]);\n if (pair.length !== 2) continue;\n const [a, b] = pair;\n if (!arcOnCircum(a, b)) continue; // circumcircle ngầm: cung phải là 2 đỉnh tam giác\n\n // --- Phân phối \"X, Y lần lượt là … cung BC <containment1> và <containment2>\" ---\n const dm = DISTRIB_VN.exec(c.text);\n if (dm) {\n const names = dm[1].split(/\\s*,\\s*/u).map((s) => s.replace(/['′]/gu, ''));\n const contains = parseContainmentsVN(dm[4]);\n // Zip 1-1: số tên phải = số mệnh đề containment, ≥2. Lệch → escalate (fail-safe).\n if (names.length >= 2 && names.length === contains.length) {\n const mark = out.length;\n let ok = true;\n for (let i = 0; i < names.length && ok; i++) ok = pushArc(c, names[i], a, b, contains[i]);\n if (!ok) out.length = mark; // 1 phần tử lỗi (endpoint cung) → bỏ TOÀN clause\n }\n continue; // clause phân phối: xử lý xong (hoặc escalate), không rơi xuống dạng đơn\n }\n\n // --- Dạng đơn: tên qua lời dẫn \"Gọi/Lấy X là …\" ưu tiên, fallback HOA trước cụm ---\n const before = NAME_BEFORE.exec(c.text);\n // Ưu tiên tên CỤC BỘ (ngay trước \"chính giữa cung\") hơn lời dẫn clause-wide:\n // clause gộp phẩy \"I là tâm…, P là điểm chính giữa cung…\" → extractPointName\n // bắt nhầm \"I\"; NAME_BEFORE bắt đúng \"P\".\n const name = (before ? before[1] : undefined) ?? extractPointName(c.text);\n if (!name) continue; // không trích được tên → bỏ qua\n\n // Containment: \"(không) chứa X\" tường minh (lấy mệnh đề đầu), else đỉnh thứ 3 tam giác.\n const conts = parseContainmentsVN(c.text);\n if (conts.length >= 1) {\n pushArc(c, name, a, b, conts[0]);\n } else if (tri) {\n const third = [tri[1], tri[2], tri[3]].find((v) => v !== a && v !== b);\n if (third) pushArc(c, name, a, b, { rel: 'not', point: third });\n } else {\n // Không \"chứa\" tường minh + không tam giác → cung KHÔNG mơ hồ (nửa đường\n // tròn đường kính AB: điểm chính giữa cung = đỉnh duy nhất). arcMidpoint\n // không containment (notContaining/containing optional trong DSL).\n out.push({\n ruleId: 'arcMidpoint',\n clauseIds: [c.id],\n intents: withCircum(addPoint(name, { kind: 'arcMidpoint', circle, a, b })),\n });\n }\n }\n\n // --- EN (issue #46 group B) ---------------------------------------------------\n // Tam giác EN để suy notContaining (đỉnh thứ 3) khi đề không nêu \"not containing\".\n const triEnVerts = triEnM0 ? [triEnM0[1], triEnM0[2], triEnM0[3]] : undefined;\n\n for (const c of ctx.clauses) {\n if (!ARC_MID_EN.test(c.text)) continue;\n // Vượt scope (mirror VN): \"major arc\" → cung đối, defer → escalate.\n if (MAJOR_ARC_EN.test(c.text)) continue;\n\n const pairM = ARC_PAIR_EN.exec(c.text);\n if (!pairM) continue;\n const pair = pairFromToken(pairM[1] + pairM[2]);\n if (pair.length !== 2) continue;\n const [a, b] = pair;\n if (!arcOnCircum(a, b)) continue; // circumcircle ngầm: cung phải là 2 đỉnh tam giác\n\n // Tên điểm: \"M is/be the midpoint of arc\" (HOA trước). Không có → bỏ qua.\n const before = NAME_BEFORE_EN.exec(c.text);\n const name = before ? before[1] : undefined;\n if (!name) continue;\n\n // Containment: \"(not) containing X\" tường minh (mệnh đề đầu), else đỉnh thứ 3 tam giác EN.\n const conts = parseContainmentsEN(c.text);\n if (conts.length >= 1) {\n pushArc(c, name, a, b, conts[0]);\n } else if (triEnVerts) {\n const third = triEnVerts.find((v) => v !== a && v !== b);\n if (third) pushArc(c, name, a, b, { rel: 'not', point: third });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/excenter.ts\n//\n// Tâm đường tròn bàng tiếp (excenter): \"J là tâm bàng tiếp góc A\".\n// → add-point J {kind:'excenter', of:['A','B','C'], opposite:'A'}\n//\n// excenter cần BỘ 3 đỉnh tam giác (of) + ĐỈNH ĐỐI DIỆN (opposite — góc mà đường\n// tròn bàng tiếp ứng với). DSL/intent/render đã support; rule này chỉ lo NLU.\n//\n// Tam giác: nêu trong clause → lấy; else tam giác DUY NHẤT toàn đề; nhập nhằng /\n// không có → bỏ qua (escalate). Đỉnh đối PHẢI thuộc tam giác (else escalate).\n//\n// Tên tâm: ký tự HOA đứng TRƯỚC \"(là) tâm (đường tròn)? bàng tiếp\" (cục bộ, KHÔNG\n// quét lời dẫn toàn clause). Không trích được tên → bỏ qua (đừng bịa).\n//\n// KHÔNG dùng extractPointName (_shared) ở đây: NAME_LA của nó dùng `là\\b` (ASCII\n// \\b sau 'à' không khớp) nên không bắt được \"X là …\". Rule tự neo qua NAME_BEFORE.\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt. Regex chứa ký\n// tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\n//\n// Chỉ dựng ĐIỂM tâm (excenter). \"Vẽ đường tròn bàng tiếp\" (excircle) chưa có\n// intent path → clause không đặt tên tâm sẽ KHÔNG match → escalate (an toàn).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// Prefilter toàn đề.\nconst EXCENTER_KW = /bàng\\s*tiếp/u;\n\n// Tam giác (1 lần) trong 1 đoạn text.\nconst TRI = /tam\\s*giác\\s+(?:(?:cân|vuông|đều|nhọn|tù)(?:\\s+(?:tại|ở|đỉnh|có\\s+ba\\s+góc))?\\s+)*(?:[^\\s,.;:()]*\\s+){0,2}?([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\nconst TRI_G = /tam\\s*giác\\s+(?:(?:cân|vuông|đều|nhọn|tù)(?:\\s+(?:tại|ở|đỉnh|có\\s+ba\\s+góc))?\\s+)*(?:[^\\s,.;:()]*\\s+){0,2}?([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n// Đỉnh đối diện: \"bàng tiếp (trong)? (góc|đỉnh|ứng với (đỉnh)?|đối diện (đỉnh)?) X\".\nconst OPPOSITE =\n /bàng\\s*tiếp\\s+(?:trong\\s+)?(?:góc|đỉnh|ứng\\s+với(?:\\s+đỉnh)?|đối\\s+diện(?:\\s+đỉnh)?)\\s+([A-Z])(?!\\p{L})/u;\n\n// Tên tâm đứng TRƯỚC: \"Ja (là)? tâm (của)? (đường tròn)? bàng tiếp\". Tên có thể\n// kèm CHỈ SỐ: \"Ja\" (J + a chỉ góc A), \"J1\", \"J'\", \"J_a\" — đề hay đặt vậy. Token\n// = HOA + (chữ thường | số | prime | _<chữ/số>). DSL LabelZ chấp nhận.\nconst NAME_BEFORE =\n /([A-Z](?:[a-z0-9]|['′]|_[A-Za-z0-9])?)\\s+(?:là\\s+)?(?:tâm\\s+)?(?:(?:của\\s+)?đường\\s*tròn\\s+)?bàng\\s*tiếp/u;\n\n/**\n * of=[A,B,C] cho 1 clause: ưu tiên tam giác nêu trong clause; else tam giác DUY\n * NHẤT toàn đề (dedup theo bộ đỉnh). Nhiều tam giác khác nhau / không có →\n * undefined (escalate).\n */\nfunction resolveTriangleOf(clauseText: string, problem: string): string[] | undefined {\n const inClause = TRI.exec(clauseText);\n if (inClause) return [inClause[1], inClause[2], inClause[3]];\n TRI_G.lastIndex = 0;\n const all: string[] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) all.push(m[1] + m[2] + m[3]);\n const distinct = new Set(all);\n if (distinct.size === 1) {\n const t = all[0];\n return [t[0], t[1], t[2]];\n }\n return undefined;\n}\n\n/**\n * \"J là tâm bàng tiếp góc A\" → add-point J {kind:'excenter', of:[A,B,C], opposite:'A'}.\n * Thiếu đỉnh đối / tam giác / tên → bỏ qua clause (escalate AI thay vì đoán sai).\n */\nexport const excenterRule: LanguageRule = {\n id: 'excenter',\n priority: 60,\n languages: ['vi'],\n patterns: [EXCENTER_KW],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!EXCENTER_KW.test(c.text)) continue;\n\n const oppM = OPPOSITE.exec(c.text);\n if (!oppM) continue; // không xác định đỉnh đối → escalate\n const opposite = oppM[1];\n\n const of = resolveTriangleOf(c.text, ctx.problem);\n if (!of) continue; // không có/nhập nhằng tam giác → escalate\n if (!of.includes(opposite)) continue; // đỉnh đối phải thuộc tam giác\n\n const nameM = NAME_BEFORE.exec(c.text);\n const name = nameM ? nameM[1] : undefined;\n if (!name) continue; // không trích được tên → bỏ qua (đừng bịa)\n\n out.push({\n ruleId: 'excenter',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'excenter', of, opposite })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/parallelPerp.ts\n//\n// Đường thẳng QUA 1 điểm, song song / vuông góc với 1 đường (cặp đỉnh):\n// \"Qua A kẻ đường thẳng song song với BC\" → draw-line parallelThrough A→BC\n// \"Từ A vẽ đường thẳng vuông góc với BC\" → draw-line perpThrough A→BC\n//\n// Phân biệt với perpFoot (\"Kẻ AH vuông góc BC\" → chân H): rule này BẮT BUỘC mở\n// đầu \"Qua/Từ <P>\" (P = điểm đường thẳng đi qua, KHÔNG sinh chân). perpFoot\n// không có tiền tố \"Qua/Từ\" nên 2 rule không chồng.\n//\n// Tên line không nêu trong đề → synthesize (\"parA\"/\"prpA\"); guard chỉ track điểm\n// HOA nên line name không bị đòi. Nếu đề có \"cắt … tại N\" (giao điểm) → phần đó\n// KHÔNG được claim → coverage/guard escalate (an toàn) thay vì dựng thiếu N.\n//\n// GOTCHA \\b: dùng (?!\\p{L}) + cờ 'u' quanh ký tự Việt.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawLine, addPoint } from './_shared';\n\n// \"Qua/Từ <P> [kẻ/vẽ/dựng đường thẳng (d)] song song|vuông góc [với] [cạnh|đoạn] <PAIR>\".\n// group1 = through point; group2 = kind keyword; group3+4 = cặp đỉnh đường tham chiếu.\n// [^.]{0,24}? bắc cầu cụm \"kẻ đường thẳng (d) \" nhưng KHÔNG vượt dấu '.'.\nconst RE = new RegExp(\n '(?:Qua|qua|Từ|từ)\\\\s+(?:điểm\\\\s+)?([A-Z])(?:[\\'′]?)(?!\\\\p{L})' +\n '[^.]{0,24}?(song\\\\s*song|vuông\\\\s*góc)\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?' +\n '([A-Z])([A-Z])(?!\\\\p{L})',\n 'gu',\n);\n\n// Đường thẳng qua P (song song|vuông góc) PAIR rồi CẮT 1 đường khác tại F:\n// \"F là giao điểm của đường thẳng qua D vuông góc với BC và (đường)? CE\"\n// \"đường thẳng qua D vuông góc với BC cắt CE tại F\"\n// → drawLine(prpD/parD) + F = intersection(line, line2). line2 = cặp đỉnh.\nconst THROUGH_LINE =\n 'đường\\\\s*thẳng\\\\s+qua\\\\s+([A-Z])(?:[\\'′]?)(?!\\\\p{L})[^.]{0,24}?(song\\\\s*song|vuông\\\\s*góc)\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?([A-Z])([A-Z])(?!\\\\p{L})';\n// Tên TRƯỚC: \"F là giao điểm của <perp line> và (đường)? <pair>\".\nconst RE_GIAO = new RegExp(\n '([A-Z])(?:[\\'′]?)(?!\\\\p{L})\\\\s+là\\\\s+giao\\\\s*điểm\\\\s+(?:của\\\\s+)?' + THROUGH_LINE +\n '\\\\s+(?:và|với)\\\\s+(?:đường\\\\s*(?:thẳng\\\\s*)?)?([A-Z])([A-Z])(?!\\\\p{L})',\n 'gu',\n);\n// Tên SAU: \"<perp line> cắt <pair> tại F\".\nconst RE_CUT = new RegExp(\n THROUGH_LINE + '\\\\s+cắt\\\\s+(?:đường\\\\s*(?:thẳng\\\\s*)?)?([A-Z])([A-Z])(?!\\\\p{L})\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// Prefilter toàn đề (NON-global cho .test).\nconst PREFILTER =\n /(?:Qua|qua|Từ|từ)\\s+(?:điểm\\s+)?[A-Z][^.]{0,24}?(?:song\\s*song|vuông\\s*góc)|đường\\s*thẳng\\s+qua\\s+[A-Z][^.]{0,24}?(?:song\\s*song|vuông\\s*góc)/u;\n\nfunction lineNameOf(isParallel: boolean, through: string): string {\n return (isParallel ? 'par' : 'prp') + through;\n}\n\nexport const parallelPerpRule: LanguageRule = {\n id: 'parallelPerp',\n priority: 58,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // Line through P + CẮT đường khác tại F (tên trước/sau). Xử TRƯỚC RE để\n // không double-emit line (RE cũng khớp phần \"qua D vuông góc BC\").\n const cutSpans: Array<[number, number]> = [];\n const emitCut = (\n through: string, kw: string, refA: string, refB: string, line2: string, name: string,\n start: number, end: number,\n ) => {\n const isParallel = /song/.test(kw);\n const to = refA + refB;\n if (isParallel && to.includes(through)) return;\n const lineName = lineNameOf(isParallel, through);\n if (line2.includes(name) || lineName === name) return;\n out.push({\n ruleId: 'parallelPerp',\n clauseIds: [c.id],\n intents: [\n drawLine(lineName, isParallel ? 'parallelThrough' : 'perpThrough', { through, to }),\n addPoint(name, { kind: 'intersection', of: [lineName, line2] }),\n ],\n });\n cutSpans.push([start, end]);\n };\n RE_GIAO.lastIndex = 0;\n for (const m of c.text.matchAll(RE_GIAO)) {\n emitCut(m[2], m[3], m[4], m[5], m[6] + m[7], m[1], m.index ?? 0, (m.index ?? 0) + m[0].length);\n }\n RE_CUT.lastIndex = 0;\n for (const m of c.text.matchAll(RE_CUT)) {\n emitCut(m[1], m[2], m[3], m[4], m[5] + m[6], m[7], m.index ?? 0, (m.index ?? 0) + m[0].length);\n }\n\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n // Bỏ qua nếu span nằm trong 1 match CẮT đã xử (tránh double drawLine).\n if (cutSpans.some(([a, b]) => (m.index ?? 0) >= a && (m.index ?? 0) < b)) continue;\n const through = m[1];\n const isParallel = /song/.test(m[2]);\n const to = m[3] + m[4];\n // Song song với đường CHỨA chính điểm qua → trùng đường đó (degenerate) → bỏ.\n if (isParallel && to.includes(through)) continue;\n const kind = isParallel ? 'parallelThrough' : 'perpThrough';\n const name = lineNameOf(isParallel, through);\n out.push({\n ruleId: 'parallelPerp',\n clauseIds: [c.id],\n intents: [drawLine(name, kind, { through, to })],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/reflection.ts\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, extractPointName } from './_shared';\n\n// LƯU Ý: \\b của JS dựa trên ASCII word-char nên KHÔNG khớp quanh ký tự Việt\n// (\"đ\",\"ề\"…). Mọi regex chứa ký tự Việt dùng cờ 'u' + tránh \\b.\n\n// Prefilter toàn đề: \"đối xứng\" (cho phép viết liền \"đốixứng\" hiếm gặp → giữ \\s*).\nconst REFLECT = /đối\\s*xứng/u;\n\n// Dạng A: tên điểm ĐỨNG TRƯỚC.\n// \"D đối xứng (với) H qua BC\"\n// \"D là (điểm) đối xứng (của|với) H qua (đường thẳng|cạnh|trục) <Z>\"\n// \"M' là điểm đối xứng của M qua AB\" (tên ẢNH CÓ PRIME)\n// PRIME phải nằm TRONG group bắt tên (ảnh M') + group gốc (M') — nếu để\n// (?:['′]?) non-capturing thì \"M'\" → \"M\", sinh phụ thuộc vòng M→M (d80:10).\n// normalizePointName chuẩn hoá ′→' để đồng bộ naming layer.\nconst PT = `[A-Z](?:['′])?`;\nconst NAME_BEFORE = new RegExp(\n `(${PT})\\\\s+(?:là\\\\s+)?(?:điểm\\\\s+)?đối\\\\s*xứng\\\\s+(?:của\\\\s+|với\\\\s+)?(?:điểm\\\\s+)?(${PT})\\\\s+qua\\\\s+(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+|trục\\\\s+|trung\\\\s*điểm\\\\s+|tâm\\\\s+|điểm\\\\s+)?([A-Za-z][A-Za-z′']?)`,\n 'u',\n);\n\n// Dạng phân phối: \"P, Q lần lượt (là điểm)? đối xứng (của|với) (điểm)? A qua L1, L2\"\n// → P = đối xứng A qua L1; Q = đối xứng A qua L2 (CÙNG gốc A, 2 trục/điểm).\nconst DISTRIB = new RegExp(\n `(${PT})\\\\s*,\\\\s*(${PT})\\\\s+lần\\\\s*lượt\\\\s+(?:là\\\\s+)?(?:điểm\\\\s+)?đối\\\\s*xứng\\\\s+(?:của\\\\s+|với\\\\s+)?(?:điểm\\\\s+)?(${PT})\\\\s+qua\\\\s+([A-Za-z]{1,2})(?:['′]?)\\\\s*(?:,|và)\\\\s*([A-Za-z]{1,2})(?:['′]?)`,\n 'u',\n);\n\n// Dạng B: KHÔNG có tên dẫn trước \"đối xứng\" (lấy tên từ lời dẫn \"Gọi/Lấy …\").\n// \"Gọi D là điểm đối xứng của H qua BC\"\n// \"Lấy điểm đối xứng của H qua M\"\nconst NAME_AFTER = new RegExp(\n `(?:điểm\\\\s+)?đối\\\\s*xứng\\\\s+(?:của\\\\s+|với\\\\s+)?(?:điểm\\\\s+)?(${PT})\\\\s+qua\\\\s+(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+|trục\\\\s+|trung\\\\s*điểm\\\\s+|tâm\\\\s+|điểm\\\\s+)?([A-Za-z][A-Za-z′']?)`,\n 'u',\n);\n\nfunction normalizePointName(name: string): string {\n return name.replace(/['′]/gu, \"'\");\n}\n\n// === EN (issue #46 group B) ===\n// \"<Name> is/be the reflection of <Of> (over|across|in|about|through) (the)? (line|point|segment)? <Z>\"\n// Name đứng TRƯỚC (qua \"is\"/\"be the\" — gồm \"Let D be the reflection...\"). KHÔNG cờ 'i'.\n// (?<![A-Za-z]) đảm bảo Name là nhãn đơn. Z phân loại bằng classifyThrough (reuse).\nconst REFLECT_EN =\n /(?<![A-Za-z])([A-Z])(?:['′]?)\\s+(?:is|be)\\s+the\\s+reflection\\s+of\\s+([A-Z])(?:['′]?)\\s+(?:over|across|in|about|through)\\s+(?:the\\s+)?(?:line\\s+|point\\s+|segment\\s+)?([A-Za-z][A-Za-z′']?)/u;\nconst REFLECT_EN_PRE = /[Rr]eflection/u;\n\n// Phân loại token Z (đã strip dấu phẩy/′):\n// \"M\" → điểm (1 ký tự HOA) → reflectPoint\n// \"BC\" → đường (cặp 2 ký tự HOA) → reflectLine\n// \"d\" → đường (tên đường, chữ thường) → reflectLine\nfunction classifyThrough(raw: string): { kind: 'point' | 'line'; value: string } | undefined {\n const z = raw.replace(/['′]/gu, '').trim();\n if (/^[A-Z]$/u.test(z)) return { kind: 'point', value: z };\n if (/^[A-Z][A-Z]$/u.test(z)) return { kind: 'line', value: z };\n // tên đường thẳng chữ thường (d, d1, a, xy…) → đường\n if (/^[a-z][A-Za-z0-9]*$/u.test(z)) return { kind: 'line', value: z };\n return undefined;\n}\n\n/**\n * Đối xứng (Cụm A reflection):\n * \"D đối xứng H qua BC\" → reflectLine (qua ĐƯỜNG: cặp đỉnh BC / tên đường d)\n * \"Q đối xứng P qua M\" → reflectPoint (qua ĐIỂM: 1 ký tự HOA)\n * \"D là điểm đối xứng của H qua đường thẳng d\" → reflectLine (through='d')\n *\n * name (điểm ảnh) = ký tự HOA đứng trước \"đối xứng\" (dạng A) hoặc lời dẫn\n * \"Gọi/Lấy …\" (dạng B). of = điểm gốc (X). through = Z, phân loại bằng\n * classifyThrough. Không trích đủ name / of / through hợp lệ → BỎ QUA clause\n * (đừng bịa tên) để pipeline escalate AI.\n */\nexport const reflectionRule: LanguageRule = {\n id: 'reflection',\n priority: 55,\n languages: ['vi', 'en'],\n patterns: [REFLECT, REFLECT_EN_PRE],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!REFLECT.test(c.text) && !REFLECT_EN_PRE.test(c.text)) continue;\n\n // Phân phối \"P, Q lần lượt đối xứng A qua L1, L2\" — xử lý TRƯỚC (NAME_BEFORE\n // sẽ chỉ bắt được P). Cả 2 trục phân loại bằng classifyThrough.\n const dm = DISTRIB.exec(c.text);\n if (dm) {\n const [n1, n2, ofPt, raw1, raw2] = [\n normalizePointName(dm[1]),\n normalizePointName(dm[2]),\n normalizePointName(dm[3]),\n dm[4],\n dm[5],\n ];\n const t1 = classifyThrough(raw1);\n const t2 = classifyThrough(raw2);\n if (t1 && t2) {\n const mk = (nm: string, t: { kind: 'point' | 'line'; value: string }) =>\n t.kind === 'point'\n ? { kind: 'reflectPoint', of: ofPt, through: t.value }\n : { kind: 'reflectLine', of: ofPt, through: t.value };\n out.push({\n ruleId: 'reflection',\n clauseIds: [c.id],\n intents: [addPoint(n1, mk(n1, t1)), addPoint(n2, mk(n2, t2))],\n });\n continue;\n }\n }\n\n let name: string | undefined;\n let of: string | undefined;\n let throughRaw: string | undefined;\n\n const before = NAME_BEFORE.exec(c.text);\n if (before) {\n name = normalizePointName(before[1]);\n of = normalizePointName(before[2]);\n throughRaw = before[3];\n } else {\n const after = NAME_AFTER.exec(c.text);\n if (after) {\n // Không có tên đứng trước → lấy từ lời dẫn (\"Gọi D là …\").\n name = extractPointName(c.text);\n of = normalizePointName(after[1]);\n throughRaw = after[2];\n } else {\n // --- EN (issue #46 group B) — chỉ chạy khi cả 2 dạng VN fail. ---\n const en = REFLECT_EN.exec(c.text);\n if (en) {\n name = normalizePointName(en[1]);\n of = normalizePointName(en[2]);\n throughRaw = en[3];\n }\n }\n }\n\n if (!name || !of || !throughRaw) continue;\n\n const through = classifyThrough(throughRaw);\n if (!through) continue;\n\n const constraint =\n through.kind === 'point'\n ? { kind: 'reflectPoint', of, through: through.value }\n : { kind: 'reflectLine', of, through: through.value };\n\n out.push({\n ruleId: 'reflection',\n clauseIds: [c.id],\n intents: [addPoint(name, constraint)],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/pointAtDistance.ts\n//\n// Constraint METRIC: điểm trên tia kéo dài, cách mốc một khoảng cho trước.\n// C = through + d · unit(through − from) (xem spec 2026-06-06-point-at-distance)\n//\n// Phrasing phủ:\n// - \"trên tia đối của tia BA, lấy (điểm)? C sao cho BC = R\"\n// tia đối của tia BA = tia từ B ngược hướng A ⇒ hướng A→B kéo dài.\n// ⇒ from = A, through = B, điểm mới C nằm NGOÀI B.\n// - \"kéo dài AB (về phía B) lấy C sao cho BC = R\"\n// ⇒ from = A, through = B.\n// - EN (issue #46 group B):\n// \"On ray XY extended beyond Y, take D such that YD = …\" ⇒ from=X, through=Y.\n// \"Extend XY beyond Y to D such that YD = …\" ⇒ from=X, through=Y.\n// \"On the opposite ray of ray XY, take D such that XD …\" ⇒ from=Y, through=X.\n//\n// Hướng suy từ thứ tự token (from→through), KHÔNG cần field thừa. Điểm mốc đo\n// khoảng cách (through) trùng đỉnh đầu của cụm \"YZ = ...\" (Y = through, Z = tên\n// điểm mới). Ta dùng chính cặp này để chốt hướng + nguồn distance.\n//\n// distance (3 nguồn — discriminated union):\n// \"= R\" / \"= bán kính\" / \"= bán kính (O)\" → {kind:'circleRadius', circle}\n// \"= AB\" / \"= MN\" (2 ký tự HOA) → {kind:'segmentLength', p1, p2}\n// \"= 3\" / \"= 2,5\" / \"= 2 cm\" → {kind:'literal', value}\n//\n// GOTCHA \\b: \\b của JS dựa ASCII word-char nên KHÔNG khớp quanh ký tự Việt.\n// Mọi regex chứa ký tự Việt dùng cờ 'u' + lookaround \\p{L}.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// LƯU Ý: KHÔNG dùng cờ 'i' — nó làm [A-Z] khớp cả chữ thường, hỏng việc trích\n// tên điểm (đỉnh là CHỮ HOA). Clause có thể bắt đầu bằng chữ HOA (\"Kéo dài…\",\n// \"Trên tia đối…\") nên chữ cái đầu từ-khoá tiếng Việt dùng alternation [Kk]/[Tt].\n// --- Prefilter (toàn đề) ------------------------------------------------------\nconst KEYWORD = /(?:[Kk]éo\\s*dài|tia\\s*đối)/u;\n\n// --- Trigger trên clause ------------------------------------------------------\n// \"trên tia đối của tia BA\" → cặp [B, A] (B = gốc tia, A = hướng cũ). Hướng kéo\n// dài là tia đối ⇒ from = A, through = B.\nconst TIA_DOI =\n /tia\\s*đối\\s+của\\s+tia\\s+([A-Z])([A-Z])(?![A-Z])/u;\n// \"kéo dài AB\" → cặp [A, B]. Mặc định lấy điểm về phía B (đỉnh cuối) ⇒ from = A,\n// through = B. (\"về phía A\" hiếm + cần re-map; defer → bỏ qua để escalate.)\nconst KEO_DAI =\n /[Kk]éo\\s*dài\\s+(?:(?:đoạn|cạnh|tia)\\s+)?([A-Z])([A-Z])(?![A-Z])/u;\n\n// \"lấy (điểm)? C sao cho\" / \"lấy C\" / \"lấy C′\" → tên điểm mới (CAPTURE prime).\n// Issue #46 nhóm A: prime (' U+0027 / ′ U+2032) là PHẦN của tên — giữ lại để\n// \"C′\" ≠ đỉnh \"C\" (tránh addPoint dedup drop → escalate). Group 2 = prime char.\nconst TAKE_POINT =\n /lấy\\s+(?:điểm\\s+)?([A-Z])(['′]?)(?![A-Z])/u;\n\n// Normalize prime về 1 dạng: ′ (U+2032) → ' (U+0027). NameZ/serialize NAME_REGEX\n// cho phép ' nhưng KHÔNG cho phép ′ → chuẩn hoá để name \"C'\" chảy qua DSL/render\n// (label) không cần đổi schema. Trả về tên đầy đủ (chữ + prime đã normalize).\nfunction normalizePointName(letter: string, prime: string): string {\n return prime ? `${letter}'` : letter;\n}\n\n// \"về phía X\": hướng kéo dài. Mặc định through = đỉnh cuối cụm. Nếu \"về phía X\"\n// mà X KHÁC through (vd \"kéo dài AB về phía A\") → hướng đảo, rule không xử lý\n// đúng (defer) → skip để escalate.\nconst VE_PHIA = /về\\s+phía\\s+([A-Z])(?![A-Za-z])/u;\n\n// === EN (issue #46 group B) ==================================================\n// Additive — KHÔNG đụng building block VN ở trên. Nhãn STRICT [A-Z] (KHÔNG cờ\n// 'i' — sẽ nuốt chữ thường); first-letter flex của verb bằng [Ee]/[Tt]/[Mm]/…\n//\n// EN prefilter (runRules tests `patterns` against whole problem, IGNORING the\n// `languages` field — so an EN regex is REQUIRED here for EN-only problems to\n// reach match()). Broad but match() validates precisely → safe.\nconst PREFILTER_EN = /beyond|opposite\\s+ray/i;\n\n// \"ray XY extended beyond Z\" → ray X→Y extended past Z. from=X, through=Y;\n// require Z===Y (you extend past the FAR endpoint). Comma before \"extended\" ok.\nconst RAY_EXTENDED_EN =\n /ray\\s+([A-Z])([A-Z])(?![A-Z])\\s*,?\\s*extended\\s+beyond\\s+([A-Z])(?![A-Z])/u;\n// \"extend(ed)? (segment|line|side)? XY beyond Z\" (no \"ray\"). from=X, through=Y;\n// require Z===Y.\nconst EXTEND_SEG_EN =\n /[Ee]xtend(?:ed)?\\s+(?:segment\\s+|line\\s+|side\\s+)?([A-Z])([A-Z])(?![A-Z])\\s+beyond\\s+([A-Z])(?![A-Z])/u;\n// \"opposite ray of ray XY\" → mirror VN tia đối: from=Y(2nd), through=X(1st).\nconst OPPOSITE_RAY_EN =\n /opposite\\s+ray\\s+of\\s+ray\\s+([A-Z])([A-Z])(?![A-Z])/u;\n\n// New-point name (EN). \"take/mark/choose/pick D\" or \"to D\" (phrasing \"extend AB\n// beyond B TO D\"). Lookbehind (?<![A-Za-z]) stops \"to\" matching inside words\n// (into, photo). NO `i` flag — capture is [A-Z]; first-letter flex per verb.\n// group 1 = letter, group 2 = prime (mirror VN TAKE_POINT).\nconst TAKE_POINT_EN =\n /(?<![A-Za-z])(?:[Tt]ake|[Mm]ark|[Cc]hoose|[Pp]ick|to)\\s+(?:a\\s+|the\\s+)?(?:point\\s+)?([A-Z])(['′]?)(?![A-Z])/u;\n\n// Cụm chốt mốc + khoảng cách: \"BC = R\" / \"BC = AB\" / \"BC = 3\" / \"BC = 2,5 cm\".\n// Đỉnh đầu (m[1]) = mốc đo (through); đỉnh sau (m[2]) = điểm mới (Z); m[3] = prime\n// của điểm mới (CAPTURE — phải khớp tên điểm mới ở TAKE_POINT). Issue #46 nhóm A:\n// điểm mới có thể mang dấu phẩy/prime (\"BC′ = R\"); giữ prime để chốt mốc đúng.\n// Phần sau dấu \"=\" (m[4]) gom thô để parse riêng (radius / segment / số). KHÔNG\n// kết thúc trên ',' — dấu phẩy có thể là phân tách thập phân (\"2,5\"); clause đã\n// được segmentClauses tách trên dấu chấm/'; nên gom tới hết clause là an toàn.\nconst DIST_CLAUSE =\n /(?:sao\\s+cho\\s+)?([A-Z])([A-Z])(['′]?)(?![A-Z])\\s*=\\s*(.+?)\\s*(?:[.;]|$)/u;\n\n// --- Distance parsing ---------------------------------------------------------\nconst RADIUS_WORD = /(?<!\\p{L})(?:R|bán\\s*kính)(?!\\p{L})/u;\nconst CIRCLE_OF_RADIUS = /bán\\s*kính\\s*(?:\\(\\s*)?([A-Z])\\s*\\)?/u;\nconst SEGMENT_PAIR = /^\\s*([A-Z])([A-Z])(?![A-Z])\\s*$/u;\nconst NUMBER = /(\\d+(?:[.,]\\d+)?)/u;\n\n// Tâm đường tròn trong đề: \"(O;\" / \"(O)\" / \"đường tròn tâm O\" → tên circle.\nconst CIRCLE_NAME_PAREN = /\\(\\s*([A-Z])\\s*[;,)]/u;\nconst CIRCLE_NAME_WORDS = /đường\\s*tròn\\s*(?:tâm\\s+)?([A-Z])(?![A-Z])/u;\n\nfunction parseNum(raw: string): number {\n return Number(raw.replace(',', '.'));\n}\n\n/** Tên circle để gắn radius. Suy từ đề (ctx.problem); mặc định 'O'. */\nfunction resolveCircleName(problem: string): string {\n const w = CIRCLE_NAME_WORDS.exec(problem);\n if (w) return w[1];\n const p = CIRCLE_NAME_PAREN.exec(problem);\n if (p) return p[1];\n return 'O';\n}\n\ntype DistanceBase =\n | { kind: 'circleRadius'; circle: string }\n | { kind: 'segmentLength'; p1: string; p2: string }\n | { kind: 'literal'; value: number };\n\ntype Distance = DistanceBase & { scale?: number; offset?: number };\n\n// --- Hệ số/bội/offset (Issue #46 nhóm C) -------------------------------------\n// Tách \"<scale>·base ± offset\". scale = số đứng TRƯỚC base (qua dấu nhân ·/./×/*\n// hoặc dán liền \"2AB\"/\"2R\" hoặc cách \"2 AB\"). offset = \"± số\" đứng SAU base.\n// \"2R\" → scale 2, base R\n// \"2·AB\" → scale 2, base AB\n// \"R + 1\" → base R, offset +1\n// \"2R + 1\" → scale 2, base R, offset +1\n// base có thể là R/bán kính, cặp đỉnh (AB), hoặc số literal.\n//\n// Hệ số đứng trước base: \"2\", \"2·\", \"2.\", \"2×\", \"2*\", \"2 \" (số rồi base).\nconst COEF_PREFIX = /^(\\d+(?:[.,]\\d+)?)\\s*[·.×*]?\\s*(?=[A-Z]|bán)/u;\n// Offset đứng cuối: \"± số\" (chỉ số literal, không nhân thêm đại lượng).\nconst OFFSET_SUFFIX = /([+-])\\s*(\\d+(?:[.,]\\d+)?)\\s*$/u;\n// Dấu nhân CHỈ giữa 2 đại lượng (vd \"R·AB\", \"AB·MN\"): tích 2 đại lượng → mơ hồ.\n// Phát hiện: có dấu nhân mà 2 BÊN đều KHÔNG phải số → reject.\nconst MUL_TWO_QUANTITIES = /[A-Z](?:\\s*['′])?\\s*[·×*]\\s*[A-Z]/u;\n\n/** Parse phần sau dấu \"=\" → DistanceSpec hoặc undefined (không nhận dạng được). */\nfunction parseDistance(raw: string, problem: string): Distance | undefined {\n let text = raw.trim();\n\n // 0. TỪ CHỐI ngay các biểu thức KHÔNG xử lý được:\n if (/\\//u.test(text)) return undefined; // chia: \"AB/2\", \"1/2 AB\" → defer\n if (/\\blần\\b/u.test(text)) return undefined; // \"2 lần bán kính\" → defer\n if (MUL_TWO_QUANTITIES.test(text)) return undefined; // tích 2 đại lượng \"R·AB\"\n // '-' đứng đầu (giá trị âm trực tiếp \"-3\") → defer. ('-' offset xử lý ở dưới.)\n if (/^-/u.test(text)) return undefined;\n\n // 1. Tách offset \"± số\" ở cuối (literal). Không nhân thêm đại lượng.\n let offset: number | undefined;\n const off = OFFSET_SUFFIX.exec(text);\n if (off) {\n const sign = off[1] === '-' ? -1 : 1;\n offset = sign * parseNum(off[2]);\n text = text.slice(0, off.index).trim();\n }\n // Sau khi bóc offset, KHÔNG còn được phép có toán tử +/- (vd \"1 + 2 + R\" lạ).\n if (/[+]/u.test(text)) return undefined;\n if (/-\\s*\\d/u.test(text)) return undefined;\n\n // 2. Tách hệ số (scale) đứng trước base. Chỉ nhận khi PHÍA SAU là base\n // (đỉnh HOA / \"bán\"). \"3\" đơn lẻ KHÔNG khớp (→ literal value).\n let scale: number | undefined;\n const coef = COEF_PREFIX.exec(text);\n if (coef) {\n scale = parseNum(coef[1]);\n if (!(Number.isFinite(scale) && scale > 0)) return undefined;\n text = text.slice(coef[0].length).trim();\n }\n\n // Còn sót dấu nhân lẻ (vd \"·R\" do tách lỗi) → mơ hồ.\n if (/[·×*]/u.test(text)) return undefined;\n\n const withCoef = (base: DistanceBase): Distance => {\n const d: Distance = { ...base };\n if (scale !== undefined) d.scale = scale;\n if (offset !== undefined) d.offset = offset;\n return d;\n };\n\n // 3. base = bán kính: \"R\" / \"bán kính\" / \"bán kính (O)\".\n if (RADIUS_WORD.test(text)) {\n const co = CIRCLE_OF_RADIUS.exec(text);\n const circle = co ? co[1] : resolveCircleName(problem);\n return withCoef({ kind: 'circleRadius', circle });\n }\n // 4. base = đoạn = 2 ký tự HOA liền (\"AB\", \"MN\").\n const seg = SEGMENT_PAIR.exec(text);\n if (seg) return withCoef({ kind: 'segmentLength', p1: seg[1], p2: seg[2] });\n // 5. base = số literal (board units). \"2 cm\" → 2 (cm-mapping defer).\n // Lưu ý: nếu đã tách scale thì KHÔNG còn base số (scale·số vô nghĩa) → defer.\n if (scale === undefined) {\n const num = NUMBER.exec(text);\n if (num) {\n const value = parseNum(num[1]);\n if (Number.isFinite(value) && value > 0) return withCoef({ kind: 'literal', value });\n }\n }\n return undefined;\n}\n\n/**\n * \"kéo dài AB lấy C sao cho BC = R\" / \"trên tia đối của tia BA, lấy C sao cho\n * BC = R\" → add-point C kind:pointAtDistance. Hướng (from→through) suy từ token\n * cặp + mốc đo (đỉnh đầu cụm \"YZ = …\"). Không parse đủ (thiếu tên điểm mới /\n * distance không nhận dạng / mốc không khớp) → bỏ qua để escalate AI.\n *\n * EN (issue #46 group B) — mirror VN, chỉ chạy khi VN không xác định được hướng:\n * \"ray XY extended beyond Y, take D such that YD = …\" → from=X, through=Y\n * \"extend XY beyond Y to D such that YD = …\" → from=X, through=Y\n * \"opposite ray of ray XY, take D such that XD = …\" → from=Y, through=X\n */\nexport const pointAtDistanceRule: LanguageRule = {\n id: 'pointAtDistance',\n priority: 55,\n languages: ['vi', 'en'],\n patterns: [KEYWORD, PREFILTER_EN],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n let from: string | undefined;\n let through: string | undefined;\n let name: string | undefined;\n let isEn = false;\n\n // --- Hướng VN (from → through) ---\n const doi = TIA_DOI.exec(c.text);\n if (doi) {\n // tia đối của tia BA: B = gốc, A = hướng cũ ⇒ kéo dài về B ⇒ from=A, through=B.\n from = doi[2];\n through = doi[1];\n } else {\n const kd = KEO_DAI.exec(c.text);\n if (kd) {\n // kéo dài AB (về phía B mặc định) ⇒ from=A, through=B.\n from = kd[1];\n through = kd[2];\n }\n }\n\n if (from && through) {\n // VN name (GIỮ prime, normalize ′→').\n const take = TAKE_POINT.exec(c.text);\n name = take ? normalizePointName(take[1], take[2]) : undefined;\n } else {\n // --- EN direction (additive; chỉ khi VN không xác định được hướng) ---\n const opp = OPPOSITE_RAY_EN.exec(c.text);\n const ray = RAY_EXTENDED_EN.exec(c.text);\n const ext = EXTEND_SEG_EN.exec(c.text);\n if (opp) {\n // opposite ray of ray XY → mirror VN tia đối: from=Y, through=X.\n from = opp[2];\n through = opp[1];\n } else if (ray && ray[3] === ray[2]) {\n // ray XY extended beyond Z (Z must = Y): from=X, through=Y.\n from = ray[1];\n through = ray[2];\n } else if (ext && ext[3] === ext[2]) {\n // extend XY beyond Z (Z must = Y): from=X, through=Y.\n from = ext[1];\n through = ext[2];\n }\n if (from && through) {\n isEn = true;\n const takeEn = TAKE_POINT_EN.exec(c.text);\n name = takeEn ? normalizePointName(takeEn[1], takeEn[2]) : undefined;\n }\n }\n\n if (!from || !through || !name) continue;\n\n // VE_PHIA: chỉ VN (EN không có \"về phía\"). Giữ outcome VN byte-identical.\n if (!isEn) {\n const vp = VE_PHIA.exec(c.text);\n if (vp && vp[1] !== through) continue;\n }\n\n // --- Mốc đo + khoảng cách (\"YZ = …\") — language-agnostic (DIST_CLAUSE) ---\n const dc = DIST_CLAUSE.exec(c.text);\n if (!dc) continue;\n const anchor = dc[1]; // Y = mốc đo (phải trùng through; đỉnh đơn)\n const newPt = normalizePointName(dc[2], dc[3]); // Z = điểm mới (phải trùng name)\n // Mốc đo phải là through; đỉnh sau là điểm mới ta vừa lấy (so theo tên đã\n // normalize ⇒ \"BC′\" khớp điểm \"C'\", \"BD′\" KHÔNG khớp điểm \"C'\").\n if (anchor !== through || newPt !== name) continue;\n\n const distance = parseDistance(dc[4], ctx.problem);\n if (!distance) continue;\n\n out.push({\n ruleId: 'pointAtDistance',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'pointAtDistance', from, through, distance })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/eulerLine.ts\n//\n// Đường thẳng Euler (issue #47, construct 1): đường thẳng đi qua 3 tâm tam giác\n// THẲNG HÀNG — trọng tâm G, trực tâm H, tâm đường tròn ngoại tiếp O. KHÔNG phải\n// kind DSL riêng — compose từ 3 tâm (centroid/orthocenter/circumcenter, đã có)\n// + kind tổng quát `lineThrough([G,H,O])`.\n//\n// Fail-safe (escalate, KHÔNG dựng sai):\n// - \"đường tròn Euler\" (đường tròn 9 điểm) → KHÔNG khớp (regex chỉ nhận\n// \"đường (thẳng) Euler\", không có \"tròn\").\n// - Tam giác đều (\"đều\") → G≡H≡O suy biến, đường Euler không xác định → bỏ qua.\n// - Không có tam giác / >1 tam giác (nhập nhằng) → bỏ qua.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\n// \"đường thẳng Euler\" / \"đường Euler\" — \"thẳng\" optional. KHÔNG khớp \"đường tròn\n// Euler\" (vì \"tròn\" KHÔNG phải nhánh optional \"thẳng\"). \\p{L} lookaround vì \\b\n// không khớp quanh ký tự Việt.\nconst EULER_LINE_KW = /(?<!\\p{L})đường\\s+(?:thẳng\\s+)?[Ee]uler(?!\\p{L})/u;\n\n// Tam giác (global): quét mọi tam giác nêu trong đề.\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\n// Tam giác đều → 3 tâm trùng → đường Euler suy biến.\nconst EQUILATERAL_KW = /(?<!\\p{L})đều(?!\\p{L})/u;\n\n/** Bộ 3 đỉnh duy nhất toàn đề; undefined nếu 0 hoặc >1 tam giác phân biệt. */\nfunction uniqueTriangle(problem: string): [string, string, string] | undefined {\n TRI_G.lastIndex = 0;\n const tris: string[][] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) {\n tris.push([m[1], m[2], m[3]]);\n }\n const distinct = new Set(tris.map((t) => t.join('')));\n if (distinct.size !== 1) return undefined;\n const t = tris[0];\n return [t[0], t[1], t[2]];\n}\n\nexport const eulerLineRule: LanguageRule = {\n id: 'eulerLine',\n priority: 68,\n languages: ['vi'],\n patterns: [EULER_LINE_KW],\n match(ctx) {\n // Suy biến tam giác đều → escalate (G≡H≡O → đường Euler không xác định).\n if (EQUILATERAL_KW.test(ctx.problem)) return [];\n\n const tri = uniqueTriangle(ctx.problem);\n if (!tri) return []; // 0 hoặc >1 tam giác → nhập nhằng → escalate.\n const [A, B, C] = tri;\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!EULER_LINE_KW.test(c.text)) continue;\n out.push({\n ruleId: 'eulerLine',\n clauseIds: [c.id],\n intents: [\n addPoint('G', { kind: 'centroid', of: [A, B, C] }),\n addPoint('H', { kind: 'orthocenter', of: [A, B, C] }),\n addPoint('O', { kind: 'circumcenter', of: [A, B, C] }),\n drawLine('euler' + A + B + C, 'lineThrough', { points: ['G', 'H', 'O'] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/radicalAxis.ts\n//\n// Trục đẳng phương 2 đường tròn (issue #47, construct 2): đường ⊥ đường nối tâm\n// O₁O₂, mọi điểm trên nó có lũy thừa (power) bằng nhau với 2 đường tròn. KHÔNG\n// phải kind point — compose từ kind tổng quát `radicalAxis(circle1, circle2)`\n// (tham chiếu 2 CIRCLE đã được circleRadius dựng theo center letter).\n//\n// Fail-safe (escalate, KHÔNG dựng sai):\n// - Đồng tâm \"(O;3) và (O;5)\" → {O} (1 center phân biệt) → bỏ qua (suy biến,\n// trục không xác định).\n// - 0 hoặc 1 đường tròn có bán kính → không đủ 2 → bỏ qua.\n// - >2 đường tròn → nhập nhằng (cặp nào?) → bỏ qua.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawLine } from './_shared';\n\n// \"trục đẳng phương\" / \"đẳng phương\" — \"trục\" optional. \\p{L} lookaround vì \\b\n// không khớp quanh ký tự Việt.\nconst RADICAL_KW = /(?<!\\p{L})(?:trục\\s+)?đẳng\\s*phương(?!\\p{L})/u;\n\n// Đường tròn CÓ BÁN KÍNH (số hoặc ký hiệu R/r) — khớp những gì circleRadius\n// dựng qua centerRadius. \"(O; 3)\" / \"(I, 2.5)\" / \"(O; R)\". Global: nhiều đường\n// tròn / đề. Group 1 = center letter.\nconst CIRCLE_R_G = /\\(\\s*([A-Z])\\s*[;,]\\s*(?:\\d|[Rr])/gu;\n\n/** Các center letter phân biệt của đường tròn-có-bán-kính nêu trong đề. */\nfunction circleCentersWithRadius(problem: string): string[] {\n CIRCLE_R_G.lastIndex = 0;\n const centers = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = CIRCLE_R_G.exec(problem)) !== null) {\n centers.add(m[1]);\n }\n return [...centers];\n}\n\nexport const radicalAxisRule: LanguageRule = {\n id: 'radicalAxis',\n priority: 66,\n languages: ['vi'],\n patterns: [RADICAL_KW],\n match(ctx) {\n const centers = circleCentersWithRadius(ctx.problem);\n // Cần ĐÚNG 2 đường tròn phân biệt. Đồng tâm → 1 center → escalate. >2 → mơ hồ.\n if (centers.length !== 2) return [];\n const [c1, c2] = centers;\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!RADICAL_KW.test(c.text)) continue;\n out.push({\n ruleId: 'radicalAxis',\n clauseIds: [c.id],\n intents: [drawLine('rad' + c1 + c2, 'radicalAxis', { circle1: c1, circle2: c2 })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/simson.ts\n//\n// Đường thẳng Simson (issue #47, construct 3): P trên đường tròn ngoại tiếp tam\n// giác ABC → 3 chân vuông góc hạ từ P xuống 3 cạnh (BC, CA, AB) THẲNG HÀNG\n// (định lý Simson). KHÔNG kind DSL riêng — compose:\n// - P = onCircle (glider trên đường tròn ngoại tiếp, theta cố định 0.7).\n// - 3 chân = perpFoot (chiếu trực giao xuống đường vô hạn BC/CA/AB).\n// - đường Simson = lineThrough([chân1, chân2, chân3]).\n//\n// Fail-safe (escalate, KHÔNG dựng sai):\n// - Không có đường tròn ngoại tiếp khai báo → KHÔNG đặt được P → bỏ qua.\n// - 0 hoặc >1 tam giác phân biệt (nhập nhằng) → bỏ qua.\n// - P trùng đỉnh (Simson của A) → 3 chân suy biến → bỏ qua.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\n// \"Simson\" — danh từ riêng. \\b không khớp quanh ký tự ASCII letter ổn, nhưng\n// dùng lookaround [A-Za-z] để chắc chắn không khớp trong từ khác.\nconst SIMSON_KW = /(?<![A-Za-z])[Ss]imson(?![A-Za-z])/u;\n\n// Tam giác (global): quét mọi tam giác nêu trong đề.\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\n// Tên tâm đường tròn ngoại tiếp: \"(O)\" — dạng ngoặc 1 chữ HOA.\nconst CIRCLE_CENTER = /\\(\\s*([A-Z])\\s*\\)/u;\n\n// P của Simson: \"Simson của (điểm) P\".\nconst SIMSON_OF = /[Ss]imson\\s+của\\s+(?:điểm\\s+)?([A-Z])(?![A-Za-z])/u;\n\n/** Bộ 3 đỉnh duy nhất toàn đề; undefined nếu 0 hoặc >1 tam giác phân biệt. */\nfunction uniqueTriangle(problem: string): [string, string, string] | undefined {\n TRI_G.lastIndex = 0;\n const tris: string[][] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) {\n tris.push([m[1], m[2], m[3]]);\n }\n const distinct = new Set(tris.map((t) => t.join('')));\n if (distinct.size !== 1) return undefined;\n const t = tris[0];\n return [t[0], t[1], t[2]];\n}\n\nexport const simsonRule: LanguageRule = {\n id: 'simson',\n priority: 64,\n languages: ['vi'],\n patterns: [SIMSON_KW],\n match(ctx) {\n const tri = uniqueTriangle(ctx.problem);\n if (!tri) return []; // 0 hoặc >1 tam giác → nhập nhằng → escalate.\n const [A, B, C] = tri;\n\n // Đường tròn ngoại tiếp PHẢI được khai báo (vd \"(O)\") — circleTriangle dựng\n // circle tên theo chữ trong \"(O)\". Thiếu → KHÔNG đặt được P → escalate.\n const cm = CIRCLE_CENTER.exec(ctx.problem);\n if (!cm) return [];\n const O = cm[1];\n\n // P của Simson.\n const pm = SIMSON_OF.exec(ctx.problem);\n if (!pm) return []; // không xác định được P → escalate.\n const P = pm[1];\n\n // Suy biến: P là 1 đỉnh tam giác → 3 chân trùng → đường Simson suy biến.\n if (P === A || P === B || P === C) return [];\n\n const f1 = 'S' + A + B + C + '1';\n const f2 = 'S' + A + B + C + '2';\n const f3 = 'S' + A + B + C + '3';\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!SIMSON_KW.test(c.text)) continue;\n out.push({\n ruleId: 'simson',\n clauseIds: [c.id],\n intents: [\n addPoint(P, { kind: 'onCircle', circle: O, theta: 0.7 }),\n addPoint(f1, { kind: 'perpFoot', from: P, onLine: B + C }),\n addPoint(f2, { kind: 'perpFoot', from: P, onLine: C + A }),\n addPoint(f3, { kind: 'perpFoot', from: P, onLine: A + B }),\n drawLine('simson' + P, 'lineThrough', { points: [f1, f2, f3] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/ninePoint.ts\n//\n// Đường tròn chín điểm / đường tròn Euler (issue #47, construct 4): đường tròn qua\n// 3 trung điểm cạnh (= cũng qua 3 chân đường cao + 3 trung điểm đỉnh-trực tâm;\n// bán kính R/2). Dựng = circle3 qua 3 TRUNG ĐIỂM CẠNH — TRÁNH radius-scaling.\n// Compose midpoint×3 + circle3, KHÔNG kind DSL mới.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle } from './_shared';\n\n// \"đường tròn chín điểm\" / \"đường tròn Euler\" / \"chín điểm\". KHÔNG khớp \"đường\n// thẳng Euler\" (yêu cầu \"tròn\" trước Euler — đó là đường thẳng Euler, construct 1).\nconst NINE_KW = /(?<!\\p{L})(?:đường\\s*tròn\\s+Euler|(?:đường\\s*tròn\\s+)?chín\\s*điểm)(?!\\p{L})/u;\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])/gu;\n\nfunction uniqueTriangle(problem: string): [string, string, string] | undefined {\n TRI_G.lastIndex = 0;\n const tris: string[][] = [];\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(problem)) !== null) tris.push([m[1], m[2], m[3]]);\n const distinct = new Set(tris.map((t) => t.join('')));\n if (distinct.size !== 1) return undefined;\n const t = tris[0];\n return [t[0], t[1], t[2]];\n}\n\nexport const ninePointRule: LanguageRule = {\n id: 'ninePoint',\n priority: 63,\n languages: ['vi'],\n patterns: [NINE_KW],\n match(ctx) {\n const tri = uniqueTriangle(ctx.problem);\n if (!tri) return []; // 0 hoặc >1 tam giác → escalate.\n const [A, B, C] = tri;\n const mAB = 'M' + A + B, mBC = 'M' + B + C, mCA = 'M' + C + A;\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n if (!NINE_KW.test(c.text)) continue;\n out.push({\n ruleId: 'ninePoint',\n clauseIds: [c.id],\n intents: [\n addPoint(mAB, { kind: 'midpoint', of: A + B }),\n addPoint(mBC, { kind: 'midpoint', of: B + C }),\n addPoint(mCA, { kind: 'midpoint', of: C + A }),\n drawCircle('N9', 'through3', { points: [mAB, mBC, mCA] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/diameterCirclePairwise.ts\n//\n// Đề \"đường tròn đường kính đôi một cắt nhau lần thứ hai\" (whole-problem construct):\n//\n// Cho đường tròn (O) và ba dây cung AB, AC, AD bất kì. Các đường tròn đường\n// kính AB, AC, AD đôi một cắt nhau lần thứ hai tại M, N, P.\n//\n// Bản chất: (đ.kính AX)∩(đ.kính AY) lần 2 = chân vuông góc hạ từ A xuống XY\n// (∠ nhìn AX,AY = 90°). M,N,P = 3 chân Simson của A với ΔBCD. Đề gốc chỉ là\n// GIẢ THIẾT → hình tối giản: (O)+O, A/B/C/D, dây AX, 3 đường tròn đường kính,\n// M/N/P (giao điểm thứ hai, loại điểm chung A).\n//\n// Fail-safe (escalate, KHÔNG dựng sai): thiếu tâm \"(O)\"; <2 đường kính chung\n// apex; đầu mút/kết quả trùng; số tên kết quả ≠ số đường kính.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, drawCircle, DUONG_KW } from './_shared';\n\n// Tâm đường tròn: \"(O)\" — ngoặc 1 chữ HOA.\nconst CIRCLE_CENTER = /\\(\\s*([A-Z])\\s*\\)/u;\n// Prefilter: phải có \"đường kính\" + dấu hiệu \"đôi một\"/\"cắt nhau\".\nconst KW_DIAMETER = new RegExp(DUONG_KW + '\\\\s*kính', 'u');\nconst KW_PAIRWISE = /đôi một|cắt nhau/u;\n\n// Góc đặt điểm (radian) — apex trên cao, các đầu mút còn lại rải cung dưới ở\n// vị trí TỔNG QUÁT (tránh suy biến chân vuông góc trùng nhau).\nconst APEX_THETA = 2.0;\nconst OTHER_THETAS = [5.5, 4.0, 0.6, 3.3, 1.1, 5.0] as const;\n\ninterface Parsed {\n center: string;\n apex: string;\n others: string[];\n results: string[];\n}\n\nfunction parse(problem: string): Parsed | undefined {\n const cm = CIRCLE_CENTER.exec(problem);\n if (!cm) return undefined;\n const center = cm[1];\n\n // Vùng sau \"đường kính\" tới khi gặp \"đôi một\"/\"cắt nhau\" (cùng câu).\n const dm = new RegExp(DUONG_KW + '\\\\s*kính\\\\s+([^.;\\n]*)', 'u').exec(problem);\n if (!dm) return undefined;\n let region = dm[1];\n const cut = region.search(/đôi một|cắt nhau/u);\n if (cut >= 0) region = region.slice(0, cut);\n const pairs = region.match(/[A-Z][A-Z]/g) ?? [];\n if (pairs.length < 2) return undefined;\n\n // apex = chữ xuất hiện trong MỌI cặp.\n const counts = new Map<string, number>();\n for (const pr of pairs) {\n counts.set(pr[0], (counts.get(pr[0]) ?? 0) + 1);\n counts.set(pr[1], (counts.get(pr[1]) ?? 0) + 1);\n }\n const apexEntries = [...counts].filter(([, n]) => n === pairs.length);\n if (apexEntries.length !== 1) return undefined; // 0 → không chung; >1 → nhập nhằng\n const apex = apexEntries[0][0];\n const others = pairs.map((pr) => (pr[0] === apex ? pr[1] : pr[0]));\n if (new Set(others).size !== others.length) return undefined; // đầu mút trùng\n if (others.includes(apex)) return undefined;\n\n // Tên kết quả sau \"tại\": các chữ HOA đơn lẻ (M, N, P, ...).\n const rm = /\\btại\\s+([A-Z][^.;\\n]*)/u.exec(problem);\n if (!rm) return undefined;\n const results = rm[1].match(/\\b[A-Z]\\b/g) ?? [];\n // \"đôi một cắt nhau\" của n đường kính chung apex = TẤT CẢ C(n,2) cặp → C(n,2)\n // giao điểm. Số tên kết quả phải khớp đúng (n=3 → 3; n=4 → 6; ...).\n const numPairs = (others.length * (others.length - 1)) / 2;\n if (results.length !== numPairs) return undefined;\n if (new Set(results).size !== results.length) return undefined;\n\n return { center, apex, others, results };\n}\n\nexport const diameterCirclePairwiseRule: LanguageRule = {\n id: 'diameter-circle-pairwise',\n priority: 66,\n languages: ['vi'],\n patterns: [KW_DIAMETER],\n match(ctx) {\n if (!KW_PAIRWISE.test(ctx.problem)) return [];\n const p = parse(ctx.problem);\n if (!p) return [];\n const { center, apex, others, results } = p;\n\n const circOf = (other: string) => `k${apex}${other}`;\n const oCircle = `k${center}`; // tên entity đường tròn (O) (khác điểm tâm O)\n\n // Tất cả cặp (i<j) theo thứ tự từ điển — \"đôi một\" = mọi cặp đường kính.\n const allPairs: Array<[number, number]> = [];\n for (let i = 0; i < others.length; i++)\n for (let j = i + 1; j < others.length; j++) allPairs.push([i, j]);\n\n const intents = [\n // (O): tâm `center` (free) + bán kính cố định.\n drawCircle(oCircle, 'centerRadius', { center, radius: 4 }),\n // apex + các đầu mút = glider trên (O), vị trí tổng quát.\n addPoint(apex, { kind: 'onCircle', circle: oCircle, theta: APEX_THETA }),\n ...others.map((o, i) =>\n addPoint(o, { kind: 'onCircle', circle: oCircle, theta: OTHER_THETAS[i % OTHER_THETAS.length] }),\n ),\n // Dây cung apex–đầu mút.\n ...others.map((o) => connect(apex, o, 'segment')),\n // Đường tròn đường kính apex–đầu mút.\n ...others.map((o) => drawCircle(circOf(o), 'diameter', { endpoints: [apex, o] })),\n // Giao điểm thứ hai của TỪNG cặp đường tròn đường kính, loại điểm chung apex.\n ...results.map((r, k) =>\n addPoint(r, {\n kind: 'circleSecondIntersection',\n c1: circOf(others[allPairs[k][0]]),\n c2: circOf(others[allPairs[k][1]]),\n exclude: apex,\n }),\n ),\n ];\n\n const out: RuleMatch[] = [{\n ruleId: 'diameter-circle-pairwise',\n // Whole-problem construct: claim mọi clause để coverage gate đầy đủ.\n clauseIds: ctx.clauses.map((c) => c.id),\n intents,\n }];\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/angleBisectorFoot.ts\n//\n// Chân đường phân giác (trong/ngoài) hạ từ một đỉnh xuống cạnh đối:\n// \"D là chân đường phân giác từ A\" → onLine = cạnh đối A (suy từ tam giác)\n// \"D là chân đường phân giác trong kẻ từ A đến BC\" → onLine = BC (nêu rõ)\n// \"D là chân phân giác góc A\" → onLine = cạnh đối A\n// \"D là chân đường phân giác ngoài từ A\" → externalAngleBisectorFoot\n// → add-point D {kind:'angleBisectorFoot', from:'A', onLine:'BC'} (builder dựng\n// tia phân giác ∠(onLine[0])-from-(onLine[1]) ∩ đoạn onLine).\n//\n// Phân biệt (KHÔNG chồng rule khác):\n// - cevian (\"phân giác AD\" — đỉnh+chân dạng cặp HOA NGAY sau \"phân giác\"): rule\n// này BẮT BUỘC chữ \"chân\" mở đầu cụm → cevian không khớp.\n// - perpFoot (\"chân đường vuông góc / cao\"): keyword khác (\"vuông góc\"/\"cao\").\n// - angleBisectorAngle (\"phân giác góc A\" — vẽ tia VISIBLE, không foot): rule\n// đó tự né khi có \"chân\" đứng trước (guard CHAN_BEFORE bên angleBisectorAngle).\n//\n// Cần TAM GIÁC để suy cạnh đối khi đề KHÔNG nêu cạnh (\"đến BC\"); nêu rõ thì dùng\n// luôn. Tên chân (HOA) bind cục bộ qua \"X là\" NGAY TRƯỚC cụm. Thiếu tên / không\n// suy được cạnh đối → bỏ qua clause (escalate AI thay vì đoán sai).\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt (\"đ\",\"ề\",\"ạ\"…).\n// Regex chứa ký tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// Tam giác toàn đề (suy cạnh đối). Bổ ngữ \"vuông|cân|đều|nhọn|tù\" optional.\nconst TRI = /tam\\s*giác(?:\\s+(?:vuông|cân|đều|nhọn|tù))?\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\n\n// onLine token: tên đường 1 ký tự HOA HOẶC cặp đỉnh 2 ký tự HOA. Tiền tố tuỳ chọn.\nconst LINE = '(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{1,2})(?![A-Z])';\n// Giới từ dẫn tới cạnh đáy.\nconst PREP_TO = '(?:đến|tới|xuống|trên|ra)';\n// Đỉnh: \"từ (đỉnh)? X\" | \"của góc X\" | \"góc X\" | \"tại (đỉnh)? X\" | \"đỉnh X\".\nconst VERTEX =\n '(?:từ\\\\s+(?:đỉnh\\\\s+)?|của\\\\s+góc\\\\s+|góc\\\\s+|tại\\\\s+(?:đỉnh\\\\s+)?|đỉnh\\\\s+)([A-Z])(?![A-Z])';\n\n// \"chân (của)? (đường|tia)? phân giác (trong|ngoài)? (hạ|kẻ|vẽ|dựng)? VERTEX (PREP_TO LINE)?\".\n// group1 = trong|ngoài (optional); group2 = vertex; group3 = onLine (optional).\nconst CORE = new RegExp(\n 'chân\\\\s+(?:của\\\\s+)?(?:đường\\\\s*|tia\\\\s+)?phân\\\\s*giác\\\\s+(?:(trong|ngoài)\\\\s+)?' +\n '(?:(?:hạ|kẻ|vẽ|dựng)\\\\s+)?' +\n VERTEX +\n `(?:\\\\s+${PREP_TO}\\\\s+${LINE})?`,\n 'gu',\n);\n\n// Tên chân đứng TRƯỚC: \"X là \" NGAY TRƯỚC cụm \"chân … phân giác\".\nconst NAME_BEFORE = /([A-Z])(?:['′]?)\\s+là\\s+$/u;\n\n// Prefilter toàn đề.\nconst PREFILTER = /chân\\s+(?:của\\s+)?(?:đường\\s*|tia\\s+)?phân\\s*giác/u;\n\n/** Cạnh đối diện đỉnh V trong tam giác = 2 đỉnh còn lại, join token (vd \"BC\"). */\nfunction opposite(tri: readonly string[], vertex: string): string | undefined {\n const rest = tri.filter((v) => v !== vertex);\n return rest.length === 2 ? rest[0] + rest[1] : undefined;\n}\n\n/**\n * Mỗi clause → 0..n add-point angleBisectorFoot / externalAngleBisectorFoot.\n * onLine ưu tiên cạnh nêu rõ (\"đến BC\"); else suy cạnh đối từ tam giác. Tên chân\n * bind cục bộ. Thiếu tên / không suy được cạnh → bỏ qua (escalate).\n */\nexport const angleBisectorFootRule: LanguageRule = {\n id: 'angleBisectorFoot',\n priority: 63,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const triM = TRI.exec(ctx.problem);\n const tri = triM ? [triM[1], triM[2], triM[3]] : null;\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n CORE.lastIndex = 0;\n for (const m of c.text.matchAll(CORE)) {\n const external = m[1] === 'ngoài';\n const vertex = m[2];\n let onLine: string | undefined = m[3]; // cạnh nêu rõ (optional)\n if (!onLine) {\n if (!tri || !tri.includes(vertex)) continue; // không suy được cạnh đối → escalate\n onLine = opposite(tri, vertex);\n }\n if (!onLine) continue; // không có cạnh (nêu rõ/suy ra) → escalate\n // Tên chân: \"X là\" NGAY TRƯỚC cụm; không có → escalate (đừng bịa).\n const nm = NAME_BEFORE.exec(c.text.slice(0, m.index));\n if (!nm) continue;\n const name = nm[1];\n if (onLine.includes(name)) continue; // chân trùng đầu mút cạnh đáy → degenerate\n const kind = external ? 'externalAngleBisectorFoot' : 'angleBisectorFoot';\n out.push({\n ruleId: 'angleBisectorFoot',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind, from: vertex, onLine })],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/intersection.ts\n//\n// Giao điểm GENERIC của 2 đường thẳng/đoạn cho bởi CẶP ĐỈNH (2 ký tự HOA):\n// \"D là giao điểm của AB và CE\" → tên TRƯỚC (\"X là …\")\n// \"AM cắt CN tại K\" → tên SAU (\"… tại D\")\n// \"AC và BD cắt nhau tại O\" → tên SAU, dạng \"cắt nhau\"\n// → add-point D {kind:'intersection', of:['AB','CE']} (builder ensure 2 segment\n// rồi lấy giao). Mỗi ref = 1 đường qua 2 điểm đã có; thiếu điểm → transpile-fail\n// → escalate (fail-safe).\n//\n// CHỈ nhận ref CẶP ĐỈNH \"AB\" (2 ký tự HOA). KHÔNG nhận:\n// - giao 2 ĐƯỜNG TRÒN \"(O) và (O')\" → kind circleIntersection (rule khác/defer);\n// ref \"(O)\" có ngoặc nên [A-Z]{2} không khớp → tự loại.\n// - line∩circle \"AB cắt (O) tại M\" → secondIntersection (defer); \"(O)\" không\n// phải cặp đỉnh → tự loại.\n// - \"đôi một cắt nhau\" (diameterCirclePairwise) → \"đôi một\" chen giữa cặp đỉnh\n// và \"cắt nhau\" phá khớp dạng C; dạng dùng dấu phẩy (không \"và\") cũng không khớp.\n//\n// Guard degenerate (fail-safe — thà escalate còn hơn dựng điểm vô nghĩa):\n// - 4 đầu mút phải PHÂN BIỆT: chia sẻ đỉnh → 2 đường gặp tại đỉnh chung (không\n// phải điểm mới) → bỏ qua.\n// - tên điểm cần dựng KHÔNG được nằm trong ref (định nghĩa vòng) → bỏ qua.\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt. Regex chứa ký\n// tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, DUONG_KW } from './_shared';\n\n// Ref = cặp đỉnh \"AB\" (đúng 2 ký tự HOA, cho phép khoảng trắng ở giữa \"A B\", neo (?![A-Z]) chặn cụm 3+).\n// Tiền tố \"đường thẳng|đoạn|tia|cạnh\" optional.\nconst REF =\n '(?:' +\n DUONG_KW +\n '\\\\s*thẳng\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+|tia\\\\s+|cạnh\\\\s+)?([A-Z]\\\\s*[A-Z])(?![A-Z])';\nconst CONN = '(?:và|với)';\n\n// A: \"giao điểm (của)? REF1 (và|với) REF2\" — tên đứng TRƯỚC qua \"X là\". \"của\"\n// lặp 0..2 (OCR đôi khi nhân đôi \"của của\").\nconst GIAO_DIEM = new RegExp(`giao\\\\s*điểm\\\\s+(?:của\\\\s+){0,2}${REF}\\\\s*${CONN}\\\\s*${REF}`, 'gu');\n// A2: \"giao điểm (của)? REF1 (và|với) REF2 là Z\" — tên đứng SAU (\"… là M\").\nconst GIAO_LA = new RegExp(`giao\\\\s*điểm\\\\s+(?:của\\\\s+){0,2}${REF}\\\\s*${CONN}\\\\s*${REF}\\\\s+là\\\\s+([A-Z])(?![A-Z])`, 'gu');\n// B: \"REF1 (kéo dài)? cắt REF2 (kéo dài)? (tại|ở) (điểm)? D\" — tên SAU (vao10:\n// \"BE kéo dài cắt AD ở M\", \"AE và BC kéo dài cắt nhau tại D\").\nconst CAT_TAI = new RegExp(`${REF}\\\\s+(?:kéo\\\\s+dài\\\\s+)?cắt\\\\s+${REF}\\\\s+(?:kéo\\\\s+dài\\\\s+)?(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])`, 'gu');\n// C: \"REF1 (và|với) REF2 (cắt|giao) nhau tại D\" — tên SAU. REF2 NGAY trước \"cắt\n// nhau\" → \"đôi một\" (diameterCirclePairwise) chen vào sẽ phá khớp.\n// CONN gồm dấu phẩy: \"AB, CD cắt nhau tại E\" (Câu 13). \"đôi một\" vẫn bị loại vì\n// nó chen giữa REF2 và \"cắt nhau\" → REF2 không liền \"cắt nhau\".\nconst CAT_NHAU = new RegExp(\n `${REF}\\\\s*(?:,|và|với)\\\\s*${REF}\\\\s+(?:của\\\\s+tam\\\\s*giác\\\\s+[A-Z]{3}\\\\s+)?(?:kéo\\\\s+dài\\\\s+)?(?:cắt|giao)\\\\s+nhau\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n// C2: \"AB, CD … vuông góc với nhau (tại|ở) I\" → I = AB ∩ CD (hai dây ⊥ NHAU gặp\n// ở I — httcd:68 \"hai dây AB, CD bằng nhau và vuông góc với nhau tại I\"). Blob\n// `[^.]{0,30}?` cho \"bằng nhau và\" xen. CHỈ áp cho clause có \"dây\" (tránh\n// \"đường kính … vuông góc tại O\" — O=tâm, perpDiameters lo).\nconst CAT_PERP_NHAU = new RegExp(\n `${REF}\\\\s*(?:,|và)\\\\s*${REF}(?![A-Z])[^.]{0,30}?vuông\\\\s*góc\\\\s+với\\\\s+nhau\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n// D: \"E, F lần lượt là giao điểm của AB và CD, của AD và BC\" → zip 2 tên với 2 cặp.\nconst DISTRIB_TWO = new RegExp(\n `([A-Z])\\\\s*,\\\\s*([A-Z])\\\\s+lần\\\\s*lượt\\\\s+là\\\\s+giao\\\\s*điểm\\\\s+của\\\\s+${REF}\\\\s*${CONN}\\\\s*${REF}\\\\s*,\\\\s*của\\\\s+${REF}\\\\s*${CONN}\\\\s*${REF}`,\n 'gu',\n);\n// E: 1 đường ∩ 2 đường — \"MA cắt DB, DC (theo thứ tự|lần lượt)? tại X, Z\"\n// → X=MA∩DB, Z=MA∩DC. groups: 1=line, 2=ref1, 3=ref2, 4=name1, 5=name2.\nconst CAT_ONE_TWO = new RegExp(\n `${REF}\\\\s+cắt\\\\s+${REF}\\\\s*(?:,|và)\\\\s*${REF}\\\\s+(?:theo\\\\s+thứ\\\\s+tự\\\\s+|lần\\\\s*lượt\\\\s+)?tại\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*(?:tại\\\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n// F: 2 đường ∩ 1 đường — \"TC, TB (lần lượt|theo thứ tự)? cắt EF tại P, Q\"\n// → P=TC∩EF, Q=TB∩EF. groups: 1=ref1, 2=ref2, 3=sharedLine, 4=name1, 5=name2.\nconst CAT_TWO_ONE = new RegExp(\n `${REF}\\\\s*(?:,|và)\\\\s*${REF}\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?cắt\\\\s+${REF}\\\\s+tại\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n// F-ray: 2 đường ∩ 1 ĐƯỜNG ĐẶT TÊN — tia tiếp tuyến \"Bx\" / đường thẳng \"d\"\n// \"Các tia AC, AD cắt Bx tại E, F\" (vao10:12) → E=AC∩Bx, F=AD∩Bx.\n// Shape-name giữ as-is (resolveSegmentRef không tách): \"Bx\" do tangent-ray vẽ,\n// \"d\" do parallelPerp/tangentLineNamedAtPoint vẽ. Token thường neo (?![\\p{L}\\d])\n// nên \"cắt nhau\"/\"cắt đường\" không bị nuốt ('n','đ' có chữ theo sau).\n// groups: 1=ref1 2=ref2 3=shape 4=name1 5=name2.\nconst CAT_TWO_ONE_RAY = new RegExp(\n `${REF}\\\\s*(?:,|và)\\\\s*${REF}\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?cắt\\\\s+(?:đường\\\\s*thẳng\\\\s+|tia\\\\s+)?([A-Z][a-z]|[a-z])(?![\\\\p{L}\\\\d])\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?tại\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n// B-ray đơn: \"tia AF cắt (tia)? (tiếp tuyến)? Bx … tại D\" (vao10:18 — mô tả\n// \"của nửa đường tròn (O)\" chen giữa ray và \"tại\", gap bounded không vượt ,;.).\n// groups: 1=ref1 2=shape 3=name.\nconst CAT_ONE_RAY = new RegExp(\n `${REF}\\\\s+cắt\\\\s+(?:tia\\\\s+)?(?:tiếp\\\\s*tuyến\\\\s+)?(?:đường\\\\s*thẳng\\\\s+)?([A-Z][a-z]|[a-z])(?![\\\\p{L}\\\\d])[^.;,]{0,40}?(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// F2: \"giao điểm của R1 (,|và) R2 với R3 (lần lượt|theo thứ tự)? là M và N\" →\n// M=R1∩R3, N=R2∩R3 (2 đường giao 1 đường chung, tên SAU, dạng \"giao điểm\n// của\"). Bài 29 (\"CF,DE với AB\"), Bài 122 (\"PB và BC với AD\").\n// groups: 1=ref1 2=ref2 3=shared 4=name1 5=name2.\nconst GIAO_TWO_ONE_LA = new RegExp(\n `giao\\\\s*điểm\\\\s+(?:của\\\\s+)?${REF}\\\\s*(?:,|và)\\\\s*${REF}\\\\s+với\\\\s+${REF}\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?là\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// F3 (ZIP): \"R1, R2 lần lượt cắt R3, R4 tại M, N\" → M=R1∩R3, N=R2∩R4 (zip\n// 1-1, KHÔNG dùng chung đường). \"lần lượt/theo thứ tự\" BẮT BUỘC để chắc zip.\n// Bài 99: \"Các đường thẳng BO,CO lần lượt cắt các đoạn thẳng AC,AB tại M,N\".\n// groups: 1=ref1 2=ref2 3=ref3 4=ref4 5=name1 6=name2.\nconst CAT_ZIP = new RegExp(\n `${REF}\\\\s*,\\\\s*${REF}\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)cắt\\\\s+(?:các\\\\s+)?(?:đoạn(?:\\\\s+thẳng)?\\\\s+|cạnh\\\\s+|${DUONG_KW}\\\\s*thẳng\\\\s+)?${REF}\\\\s*,\\\\s*${REF}\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// Tên điểm đứng TRƯỚC (pattern A): \"X là \" NGAY TRƯỚC \"giao điểm\".\nconst NAME_BEFORE = /([A-Z])(?:['′]?)\\s+là\\s+$/u;\n\n// G: phân phối N CẶP — \"X, Y, Z lần lượt là giao (điểm)? của (các)? cặp (đường\n// thẳng)? (R1a, R1b), (R2a, R2b), …\" / \"… AC và BD; AB và CD; …\". Zip tên↔cặp.\n// Brokard/Pappus-family (giao của 3-4 cặp đường thẳng).\nconst NAMES_LIST = '((?:[A-Z]\\\\s*,\\\\s*)+[A-Z])(?![A-Z])';\nconst DISTRIB_PAIRS = new RegExp(\n NAMES_LIST +\n '\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?là\\\\s+giao\\\\s*(?:điểm)?\\\\s+(?:của\\\\s+)?(?:các\\\\s+)?cặp\\\\s+(?:đường\\\\s*thẳng\\\\s+)?([^.]+)',\n 'u',\n);\n// Cặp bên trong blob: \"(R1, R2)\" hoặc \"R1 và R2\" — quét toàn cục, optional ngoặc.\nconst PAIR_IN_BLOB = new RegExp(`\\\\(?\\\\s*([A-Z]\\\\s*[A-Z])\\\\s*(?:,|${CONN})\\\\s*([A-Z]\\\\s*[A-Z])\\\\s*\\\\)?`, 'gu');\n\n// H: ký hiệu ∩ — \"X = REF1 ∩ REF2\", HỖ TRỢ điểm CÓ CHỈ SỐ (A1, A', B1C1):\n// \"A1 = BC ∩ AP\", \"A2 = BC ∩ B1C1\". PT = HOA + (số|prime) optional. Cặp =\n// 2 PT liền (greedy → \"B1C1\"→B1,C1). builder resolveSegmentRef tách cặp\n// subscript qua splitKnownPair. Tên = 1 PT trước \"=\".\nconst PT = \"[A-Z](?:[0-9]|['′])?\";\nconst CAP_SYMBOL = new RegExp(\n `(${PT})\\\\s*=\\\\s*(${PT})\\\\s*(${PT})\\\\s*∩\\\\s*(${PT})\\\\s*(${PT})(?!${PT})`,\n 'gu',\n);\n\n// I (fallback): \"Z là giao điểm của (hai)? (tia)? REF1 (,|và|với) REF2\" với đầu\n// mút CÓ PRIME (\"M'A\") và/hoặc separator DẤU PHẨY — 2 trường hợp GIAO_DIEM (chỉ\n// và|với, ref 2 HOA) bỏ lỡ. Vd \"S là giao điểm của hai tia BM, M'A\" (d80:10).\n// CHẠY CUỐI per-clause (sau mọi pattern khác) + seen-dedup → thuần additive.\nconst PTP = \"[A-Z](?:['′])?\";\nconst REFP = `(?:đường\\\\s*thẳng\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+|tia\\\\s+|cạnh\\\\s+)?(${PTP}\\\\s*${PTP})(?![A-Za-z])`;\nconst GIAO_PRIMED = new RegExp(\n `giao\\\\s*điểm\\\\s+(?:của\\\\s+)?(?:hai\\\\s+)?(?:tia\\\\s+|đường\\\\s*thẳng\\\\s+|đoạn\\\\s+|cạnh\\\\s+)?${REFP}\\\\s*(?:,|và|với)\\\\s*${REFP}`,\n 'gu',\n);\n// \"REF1, REF2 cắt nhau tại Z\" với đầu mút CÓ PRIME (\"EF, B'C' cắt nhau tại K\").\n// Tên SAU. group1=ref1, 2=ref2, 3=tên.\nconst CAT_NHAU_PRIMED = new RegExp(\n `${REFP}\\\\s*(?:,|và|với)\\\\s*${REFP}\\\\s+(?:cắt|giao)\\\\s+nhau\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\nfunction splitPrimedPair(tok: string): [string, string] {\n const m = /^([A-Z](?:['′])?)([A-Z](?:['′])?)$/u.exec(tok.replace(/\\s+/g, ''));\n if (!m) return ['', ''];\n return [m[1].replace('′', \"'\"), m[2].replace('′', \"'\")];\n}\n\n// Prefilter toàn đề.\nconst PREFILTER = /giao\\s*điểm|cắt|giao\\s+nhau|giao\\s+của|∩|vuông\\s*góc\\s+với\\s+nhau/u;\n\n/**\n * Build intent intersection nếu hợp lệ: 4 đầu mút phân biệt (không chia sẻ đỉnh)\n * + tên không nằm trong ref. Ngược lại trả null (escalate).\n */\nfunction makeIntent(name: string, ref1: string, ref2: string): IntentT | null {\n ref1 = ref1.replace(/\\s+/g, '');\n ref2 = ref2.replace(/\\s+/g, '');\n const ends = [ref1[0], ref1[1], ref2[0], ref2[1]];\n if (new Set(ends).size !== 4) return null; // chia sẻ đỉnh / ref trùng → degenerate\n if (ends.includes(name)) return null; // ref chứa chính điểm cần dựng → vô nghĩa\n return addPoint(name, { kind: 'intersection', of: [ref1, ref2] });\n}\n\n/** Như makeIntent nhưng 4 đầu mút TƯỜNG MINH (cho điểm có chỉ số: B1, A'…). */\nfunction makeIntentEnds(name: string, e1: string, e2: string, e3: string, e4: string): IntentT | null {\n const ends = [e1, e2, e3, e4];\n if (new Set(ends).size !== 4) return null;\n if (ends.includes(name)) return null;\n return addPoint(name, { kind: 'intersection', of: [e1 + e2, e3 + e4] });\n}\n\nexport const intersectionRule: LanguageRule = {\n id: 'intersection',\n // THẤP HƠN mọi rule tạo điểm (midpoint=50 thấp nhất, perpFoot/cevian/center…\n // đều ≥50): intentsToDsl xử lý intent THEO THỨ TỰ priority DESC (không topo-sort)\n // → các điểm đầu mút (vd M,N trung điểm trong \"AM cắt CN tại K\") phải được dựng\n // TRƯỚC khi intersection tham chiếu chúng. Đặt 45 (>connect 40) để chạy sau cùng.\n priority: 45,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const seen = new Set<string>(); // tên đã claim trong clause (tránh trùng tên)\n const emit = (name: string, ref1: string, ref2: string) => {\n if (seen.has(name)) return;\n const intent = makeIntent(name, ref1, ref2);\n if (!intent) return;\n seen.add(name);\n out.push({ ruleId: 'intersection', clauseIds: [c.id], intents: [intent] });\n };\n\n DISTRIB_TWO.lastIndex = 0;\n for (const m of c.text.matchAll(DISTRIB_TWO)) {\n emit(m[1], m[3], m[4]);\n emit(m[2], m[5], m[6]);\n }\n\n // H: ký hiệu ∩ — \"X = e1e2 ∩ e3e4\" (hỗ trợ chỉ số). Dùng emit-by-ends để\n // không index ref[0]/ref[1] (sai với \"B1C1\").\n CAP_SYMBOL.lastIndex = 0;\n for (const m of c.text.matchAll(CAP_SYMBOL)) {\n const name = m[1];\n if (seen.has(name)) continue;\n const intent = makeIntentEnds(name, m[2], m[3], m[4], m[5]);\n if (!intent) continue;\n seen.add(name);\n out.push({ ruleId: 'intersection', clauseIds: [c.id], intents: [intent] });\n }\n\n // E: 1 đường ∩ 2 đường (\"MA cắt DB, DC tại X, Z\").\n CAT_ONE_TWO.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_ONE_TWO)) {\n emit(m[4], m[1], m[2]);\n emit(m[5], m[1], m[3]);\n }\n // F: 2 đường ∩ 1 đường (\"TC, TB cắt EF tại P, Q\").\n CAT_TWO_ONE.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_TWO_ONE)) {\n emit(m[4], m[1], m[3]);\n emit(m[5], m[2], m[3]);\n }\n // F-ray: 2 đường ∩ 1 đường đặt tên (\"Các tia AC, AD cắt Bx tại E, F\").\n // Guard riêng (không qua makeIntent — ref 2 là shape-name, không phải cặp đỉnh).\n const emitShape = (name: string, pairRef: string, shape: string) => {\n if (seen.has(name)) return;\n const pair = pairRef.replace(/\\s+/g, '');\n if (pair.length !== 2 || pair[0] === pair[1] || pair.includes(name)) return;\n if (shape === name) return;\n seen.add(name);\n out.push({\n ruleId: 'intersection',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'intersection', of: [pair, shape] })],\n });\n };\n CAT_TWO_ONE_RAY.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_TWO_ONE_RAY)) {\n emitShape(m[4], m[1], m[3]);\n emitShape(m[5], m[2], m[3]);\n }\n // B-ray đơn: \"tia AF cắt tia tiếp tuyến Bx … tại D\".\n CAT_ONE_RAY.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_ONE_RAY)) {\n emitShape(m[3], m[1], m[2]);\n }\n // F2: \"giao điểm của R1 (,|và) R2 với R3 lần lượt là M và N\".\n GIAO_TWO_ONE_LA.lastIndex = 0;\n for (const m of c.text.matchAll(GIAO_TWO_ONE_LA)) {\n emit(m[4], m[1], m[3]);\n emit(m[5], m[2], m[3]);\n }\n // F3 (ZIP): \"R1, R2 lần lượt cắt R3, R4 tại M, N\" → M=R1∩R3, N=R2∩R4.\n CAT_ZIP.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_ZIP)) {\n emit(m[5], m[1], m[3]);\n emit(m[6], m[2], m[4]);\n }\n\n // A2: tên SAU — \"giao điểm của REF1 và REF2 là Z\" (ưu tiên trước A để\n // không bị NAME_BEFORE bắt nhầm lời dẫn \"Gọi\" đứng trước).\n GIAO_LA.lastIndex = 0;\n for (const m of c.text.matchAll(GIAO_LA)) emit(m[3], m[1], m[2]);\n // A: tên TRƯỚC — \"X là giao điểm của REF1 và REF2\".\n GIAO_DIEM.lastIndex = 0;\n for (const m of c.text.matchAll(GIAO_DIEM)) {\n const nm = NAME_BEFORE.exec(c.text.slice(0, m.index));\n if (nm) emit(nm[1], m[1], m[2]);\n }\n // B: \"REF1 cắt REF2 tại D\".\n CAT_TAI.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_TAI)) emit(m[3], m[1], m[2]);\n // C: \"REF1 và REF2 cắt nhau tại D\".\n CAT_NHAU.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_NHAU)) emit(m[3], m[1], m[2]);\n\n // C2: \"hai dây AB, CD … vuông góc với nhau tại I\" → I=AB∩CD (chỉ clause \"dây\").\n if (/dây/u.test(c.text)) {\n CAT_PERP_NHAU.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_PERP_NHAU)) emit(m[3], m[1], m[2]);\n }\n\n // I (fallback): primed/comma — \"Z là giao điểm của hai tia BM, M'A\". Tên\n // ĐỨNG TRƯỚC. Chỉ điểm chưa được pattern trên claim (seen-dedup).\n GIAO_PRIMED.lastIndex = 0;\n for (const m of c.text.matchAll(GIAO_PRIMED)) {\n const nm = NAME_BEFORE.exec(c.text.slice(0, m.index));\n if (!nm) continue;\n const name = nm[1];\n if (seen.has(name)) continue;\n const [a, b] = splitPrimedPair(m[1]);\n const [d, e] = splitPrimedPair(m[2]);\n if (!a || !b || !d || !e) continue;\n const ends = [a, b, d, e];\n if (new Set(ends).size !== 4 || ends.includes(name)) continue;\n seen.add(name);\n out.push({\n ruleId: 'intersection',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'intersection', of: [a + b, d + e] })],\n });\n }\n\n // J (fallback): primed \"cắt nhau\" — \"EF, B'C' cắt nhau tại K\". Tên SAU.\n CAT_NHAU_PRIMED.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_NHAU_PRIMED)) {\n const name = m[3];\n if (seen.has(name)) continue;\n const [a, b] = splitPrimedPair(m[1]);\n const [d, e] = splitPrimedPair(m[2]);\n if (!a || !b || !d || !e) continue;\n const ends = [a, b, d, e];\n if (new Set(ends).size !== 4 || ends.includes(name)) continue;\n seen.add(name);\n out.push({\n ruleId: 'intersection',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'intersection', of: [a + b, d + e] })],\n });\n }\n }\n\n // G: phân phối N cặp — quét TOÀN ĐỀ (segmentClauses cắt ';' nên blob\n // \"AC và BD; AB và CD; AD và BC\" bị tách; cặp 2,3 ở clause khác). Claim\n // clause chứa danh sách tên (\"lần lượt là giao\").\n const dp = DISTRIB_PAIRS.exec(ctx.problem);\n if (dp) {\n const names = dp[1].split(',').map((s) => s.trim()).filter(Boolean);\n const pairs: Array<[string, string]> = [];\n PAIR_IN_BLOB.lastIndex = 0;\n for (const pm of dp[2].matchAll(PAIR_IN_BLOB)) pairs.push([pm[1], pm[2]]);\n // Zip 1-1: số tên = số cặp (≥2). Lệch → bỏ (escalate, không đoán lệch).\n if (names.length >= 2 && names.length === pairs.length) {\n // Clause chứa danh sách tên + \"giao của ... cặp\" (để coverage claim).\n const owner = ctx.clauses.find(\n (c) => c.text.includes(names[0]) && /giao\\s*(?:điểm)?\\s+(?:của\\s+)?(?:các\\s+)?cặp/u.test(c.text),\n );\n const seenG = new Set<string>();\n for (let i = 0; i < names.length; i++) {\n const intent = makeIntent(names[i], pairs[i][0], pairs[i][1]);\n if (!intent || seenG.has(names[i])) continue;\n seenG.add(names[i]);\n out.push({ ruleId: 'intersection', clauseIds: owner ? [owner.id] : [], intents: [intent] });\n }\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/chord.ts\n//\n// Dây cung của đường tròn (chord):\n// \"Cho đường tròn (O), dây AB\" → circle O + A,B ∈ (O) + đoạn AB\n// \"đường tròn tâm O. Dây cung MN\" → circle O + M,N ∈ (O) + đoạn MN\n// \"AB là dây của (O)\" → reverse\n// → drawCircle(O, centerRadius default) + onCircle A,B + connect A-B (dây).\n//\n// \"(O)\" KHÔNG có bán kính (circleRadius cố ý BỎ QUA \"(O)\" trơ). Dây cần MỘT đường\n// tròn để minh hoạ → emit circleCR tâm O bán kính CANONICAL (SYMBOLIC_RADIUS), y\n// như cách xử lý \"(O; R)\" ký hiệu. 2 đầu mút dây là glider onCircle (theta phân\n// biệt) → nằm ĐÚNG trên đường tròn; đoạn nối = dây.\n//\n// Nếu đường tròn O đã được rule khác (circleRadius) dựng với bán kính cụ thể →\n// addShape idempotent theo TÊN + circleRadius priority cao hơn ⇒ định nghĩa cụ\n// thể THẮNG, circle ở đây bị bỏ (không chồng). onCircle/connect vẫn dùng O đó.\n//\n// Circle emit TRƯỚC (RuleMatch đầu) để onCircle tham chiếu O đã tồn tại (transpile\n// xử lý theo thứ tự). Claim cả clause khai báo đường tròn để coverage không sót.\n//\n// Thiếu đường tròn / đầu mút dây trùng tâm / cặp trùng → bỏ qua (escalate).\n//\n// GOTCHA \\b: \\b của JS theo ASCII nên KHÔNG khớp quanh ký tự Việt. Regex chứa ký\n// tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { Clause } from '../deterministic/coverage';\nimport { addPoint, connect, drawCircle, CIRCLE_KW } from './_shared';\nimport { SYMBOLIC_RADIUS } from './circleRadius';\n\n// Tên đường tròn toàn đề: \"đường tròn (tâm) O\" / \"(O)\".\n// Hỗ trợ cả tên chữ (alpha, omega...).\nconst CIRCLE_WORDS = new RegExp(CIRCLE_KW + '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([^\\\\s;,).:]+)(?![A-Z])', 'u');\nconst CIRCLE_PAREN = /\\(\\s*([^\\\\s;,).:]+)\\s*\\)/u;\n\n// \"dây (cung)? AB\" (forward) / \"AB là (một)? dây (cung)?\" (reverse). Cặp đỉnh 2\n// ký tự HOA liền, neo (?![A-Z]) chặn cụm 3+.\n// [Dd]ây: \"Dây\" HOA đầu câu (sau dấu '.') cũng khớp; nhãn cặp đỉnh vẫn STRICT HOA.\nconst CHORD_FWD = /[Dd]ây\\s+(?:cung\\s+)?([A-Z])([A-Z])(?![A-Z])/gu;\nconst CHORD_REV = /([A-Z])([A-Z])(?![A-Z])\\s+là\\s+(?:một\\s+)?dây(?:\\s+cung)?(?!\\p{L})/gu;\n\n// \"(vẽ)? hai dây CD,EF\" — HAI dây liệt kê: 2 cặp đỉnh HOA ngăn cách dấu phẩy sau\n// \"hai dây\". CHORD_FWD chỉ bắt cặp NGAY sau \"dây\" (CD) nên bỏ sót cặp thứ hai (EF\n// sau dấu phẩy). Bắt riêng để cả 4 đầu mút thành glider onCircle. Bỏ qua phần\n// \"cùng đi qua I\" (I là điểm trên dây AB, rule khác xử lý).\n// Guard `(?!\\s+cắt\\s+nhau)`: \"hai dây MN và BK CẮT NHAU ở E\" mô tả GIAO của 2 dây\n// Đà CÓ (M,N,B,K dựng trước) — KHÔNG khai báo dây mới (vao10:226: B=đầu đường kính\n// → onCircle gây CYCLE). Chỉ khớp khi 2 dây là MỚI (\"vẽ … song song\", \"cùng đi qua\").\nconst CHORD_TWO =\n /(?:vẽ\\s+)?(?:hai|các)\\s+dây\\s+(?:cung\\s+)?([A-Z])([A-Z])(?![A-Z])\\s*(?:,|và)\\s*([A-Z])([A-Z])(?![A-Z])(?!\\s+cắt\\s+nhau)/gu;\n\n// Glider angle cho 2 đầu mút dây ĐẦU TIÊN (radian) — phân biệt để A≠B, dây trải\n// phần trên. Dây thứ k (k≥1) tịnh tiến theta thêm k·THETA_STEP để KHÔNG trùng\n// điểm khi nhiều dây trên cùng đường tròn.\nconst THETA_A = 2.3;\nconst THETA_B = 0.7;\nconst THETA_STEP = 0.9;\n\n// Prefilter toàn đề (\"Dây\" HOA đầu câu cũng khớp).\nconst PREFILTER = /[Dd]ây/u;\n\n/** Escape regex metachar — tên đường tròn từ OCR bẩn có thể chứa \"(\", \"*\"… */\nfunction escapeRe(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Clause id chứa khai báo đường tròn (CIRCLE_WORDS hoặc \"(O)\"). */\nfunction findCircleClauseId(clauses: readonly Clause[], circle: string): number | undefined {\n const frag = new RegExp(CIRCLE_KW + `|\\\\(\\\\s*${escapeRe(circle)}\\\\s*\\\\)`, 'u');\n for (const c of clauses) if (frag.test(c.text)) return c.id;\n return undefined;\n}\n\n/**\n * Resolve tên đường tròn từ toàn đề; undefined nếu không có.\n */\nfunction resolveCircle(problem: string): string | undefined {\n const w = CIRCLE_WORDS.exec(problem);\n if (w) return w[1];\n const p = CIRCLE_PAREN.exec(problem);\n if (p) return p[1];\n return undefined;\n}\n\nexport const chordRule: LanguageRule = {\n id: 'chord',\n // Dưới circleRadius (75) — nếu circle O có bán kính cụ thể, định nghĩa đó thắng.\n // 71: TRÊN externalPoint (68) + tangentNamedFromExt (50) để đường tròn nền\n // (do dây định nghĩa) build TRƯỚC điểm ngoài / tiếp điểm tham chiếu nó (Bài 8:\n // \"(O) và dây AB. Lấy C ngoài. Kẻ tiếp tuyến CP, CQ\"). DƯỚI circleRadius (75)\n // để bán kính SỐ cụ thể vẫn thắng (idempotent theo tên).\n priority: 71,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = resolveCircle(ctx.problem);\n if (!circle) return []; // không có đường tròn → escalate\n\n // Gom các dây hợp lệ.\n interface Chord {\n clauseId: number;\n a: string;\n b: string;\n }\n const chords: Chord[] = [];\n const seen = new Set<string>(); // \"a|b\" (chuẩn hoá thứ tự) tránh trùng\n for (const c of ctx.clauses) {\n const pushChord = (clauseId: number, a: string, b: string) => {\n if (a === b) return; // cặp trùng → degenerate\n if (a === circle || b === circle) return; // đầu mút trùng tâm → degenerate\n const key = [a, b].sort().join('|');\n if (seen.has(key)) return;\n seen.add(key);\n chords.push({ clauseId, a, b });\n };\n // \"hai dây CD,EF\" / \"hai dây AB và CD vuông góc với nhau\" — khai báo TƯỜNG\n // MINH 2 dây (\"hai|các dây X,Y\") → 4 đầu mút glider. Chạy KỂ CẢ khi clause có\n // \"vuông góc\" (2 dây ⊥ NHAU ≠ perpChordThroughPoint — httcd:65/68).\n CHORD_TWO.lastIndex = 0;\n for (const m of c.text.matchAll(CHORD_TWO)) {\n pushChord(c.id, m[1], m[2]);\n pushChord(c.id, m[3], m[4]);\n }\n // GUARD (chỉ dây ĐƠN fwd/rev): dây cung VUÔNG GÓC (qua điểm, ⊥ đoạn) →\n // perpChordThroughPoint sở hữu (D,E là giao của đường ⊥ với đường tròn SẴN CÓ).\n if (/vuông\\s*góc|⊥/u.test(c.text)) continue;\n const collect = (re: RegExp) => {\n re.lastIndex = 0;\n for (const m of c.text.matchAll(re)) pushChord(c.id, m[1], m[2]);\n };\n collect(CHORD_FWD);\n collect(CHORD_REV);\n }\n if (chords.length === 0) return []; // không trích được dây → escalate\n\n const out: RuleMatch[] = [];\n // 1) Đường tròn (centerRadius default) — TRƯỚC, claim clause khai báo đường\n // tròn để coverage không sót clause \"Cho đường tròn (O)\".\n const circleClauseId = findCircleClauseId(ctx.clauses, circle);\n out.push({\n ruleId: 'chord',\n clauseIds: circleClauseId === undefined ? [] : [circleClauseId],\n intents: [drawCircle(circle, 'centerRadius', { center: circle, radius: SYMBOLIC_RADIUS })],\n });\n // 2) Mỗi dây: 2 đầu mút glider onCircle (theta phân biệt) + đoạn nối. Dây thứ\n // k tịnh tiến theta thêm k·THETA_STEP → nhiều dây KHÔNG trùng điểm (dây đầu\n // giữ 2.3/0.7 như cũ ⇒ hành vi 1-dây không đổi).\n chords.forEach((ch, k) => {\n const offset = k * THETA_STEP;\n out.push({\n ruleId: 'chord',\n clauseIds: [ch.clauseId],\n intents: [\n addPoint(ch.a, { kind: 'onCircle', circle, theta: THETA_A + offset }),\n addPoint(ch.b, { kind: 'onCircle', circle, theta: THETA_B + offset }),\n connect(ch.a, ch.b, 'segment'),\n ],\n });\n });\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/incircleTangency.ts\n//\n// Tiếp điểm của đường tròn nội tiếp với các cạnh tam giác:\n// \"Đường tròn (I) nội tiếp tam giác ABC tiếp xúc với các cạnh BC, CA, AB\n// tại các điểm D, E, G\"\n// → D/E/G = tangencyPoint(circle I, onLine BC/CA/AB).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle } from './_shared';\nimport type { IntentT } from '../intent';\nimport type { Clause } from '../deterministic/coverage';\n\nconst PREFILTER = /tiếp\\s*xúc|tiếp\\s*điểm/u;\n\n// \"tiếp điểm của (đường tròn)? (I) với (các cạnh)? BC,CA,AB lần lượt là D,E,F\"\n// (tên ĐẶT SAU \"là\") + dạng đảo \"tiếp điểm của BC,CA,AB với (đường tròn)? (I)\n// lần lượt là D,E,F\". circle = tâm trong ngoặc. Bài 76, 91.\nconst TANGENT_NAMED_FWD = /tiếp\\s*điểm\\s+(?:của\\s+)?(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])\\s*\\)\\s+với\\s+(?:các\\s+)?(?:(?:cạnh|đoạn)\\s+)?([A-Z]{2}(?:\\s*(?:,|và)\\s*[A-Z]{2})*)\\s+(?:lần\\s*lượt\\s+|theo\\s+thứ\\s+tự\\s+)?là\\s+(?:các\\s+)?(?:điểm\\s+)?([A-Z](?:\\s*(?:,|và)\\s*[A-Z])*)(?![A-Za-z])/iu;\nconst TANGENT_NAMED_REV = /tiếp\\s*điểm\\s+(?:của\\s+)?(?:các\\s+)?(?:(?:cạnh|đoạn)\\s+)?([A-Z]{2}(?:\\s*(?:,|và)\\s*[A-Z]{2})*)\\s+với\\s+(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])\\s*\\)\\s+(?:lần\\s*lượt\\s+|theo\\s+thứ\\s+tự\\s+)?là\\s+(?:các\\s+)?(?:điểm\\s+)?([A-Z](?:\\s*(?:,|và)\\s*[A-Z])*)(?![A-Za-z])/iu;\n\n// Vertices SAU \"tam giác\" optional — \"(I) nội tiếp tam giác tiếp xúc …\" (đỉnh suy\n// từ các cạnh tiếp xúc) cũng hợp lệ.\nconst INCIRCLE_IN_CLAUSE = /đường\\s*tròn\\s*(?:\\(\\s*([A-Z])\\s*\\)|tâm\\s+([A-Z]))?\\s*nội\\s*tiếp\\s+tam\\s*giác(?:\\s+([A-Z])([A-Z])([A-Z])(?![A-Z]))?/iu;\n\n// \"cạnh|đoạn\" optional: \"tiếp xúc với AB, AC, BC lần lượt tại D, E, F\" (Bài 18)\n// không nêu chữ \"cạnh\". Separator danh sách = \",\" HOẶC \"và\" (\"AB, AC lần lượt\n// tại D và E\" — VD12, tiếp xúc 2 cạnh). splitCsv tách cả \"và\".\n// Tiền tố đếm \"các|ba|hai|bốn\" trước \"cạnh\"/\"điểm\" (\"ba cạnh BC,CA và AB\",\n// \"tại ba điểm D,E và F\" — Bài 57).\nconst SIDE_POINT_LIST = /tiếp\\s*xúc\\s+(?:với\\s+)?(?:các\\s+|ba\\s+|hai\\s+|bốn\\s+)?(?:(?:cạnh|đoạn)\\s+)?([A-Z]{2}(?:\\s*(?:,|và)\\s*[A-Z]{2})*)\\s+(?:lần\\s*lượt\\s+|tương\\s*ứng\\s+)?tại\\s+(?:các\\s+|ba\\s+|hai\\s+|bốn\\s+)?(?:điểm\\s+)?([A-Z]'?(?:\\s*(?:,|và)\\s*[A-Z]'?)*)(?![A-Za-z])/iu;\n\n// Dạng ĐẢO (Bài 11): \"Cạnh AB, BC, CA tiếp xúc với đường tròn (O) tại D, E, F\".\n// Cạnh đứng TRƯỚC \"tiếp xúc\"; đường tròn (O) là đường tròn NỘI TIẾP (tiếp xúc cả\n// 3 cạnh) — không rule nào khác dựng nên rule này tự emit circle inscribedIn.\nconst REVERSED_SIDE_POINT = /(?:các\\s+)?(?:cạnh|đoạn)\\s+([A-Z]{2}(?:\\s*(?:,|và)\\s*[A-Z]{2})*)\\s+tiếp\\s*xúc\\s+(?:với\\s+)?(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])\\s*\\)\\s+(?:lần\\s*lượt\\s+|tương\\s*ứng\\s+)?tại\\s+(?:các\\s+)?(?:điểm\\s+)?([A-Z]'?(?:\\s*(?:,|và)\\s*[A-Z]'?)*)(?![A-Za-z])/iu;\n\nfunction splitCsv(blob: string): string[] {\n // Blob do capture đảm bảo chỉ gồm tên HOA + separator (,/và) → split thẳng.\n // KHÔNG dùng \\bvà\\b: 'à' non-word theo ASCII nên \\b sau 'à' chết trước space.\n return blob\n .split(/,|và/iu)\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\nfunction normalizeSpaces(text: string): string {\n return text.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction logicalChunks(problem: string, clauses: readonly Clause[]): Array<{ text: string; clauseIds: number[] }> {\n return problem\n .split(/[.;]+/u)\n .map((text) => normalizeSpaces(text))\n .filter(Boolean)\n .map((text) => ({\n text,\n clauseIds: clauses\n .filter((c) => text.includes(normalizeSpaces(c.text)))\n .map((c) => c.id),\n }));\n}\n\n// \"đường tròn nội tiếp (I)\" / \"đường tròn nội tiếp I\" — tên tâm ĐỨNG SAU \"nội\n// tiếp\" (tam giác đứng TRƯỚC \"đường tròn\": \"tam giác ABC, đường tròn nội tiếp\n// (I) tiếp xúc …\"). Phân biệt với INCIRCLE_IN_CLAUSE (tên giữa \"đường tròn\" và\n// \"nội tiếp\" + \"tam giác\" theo sau). Bare ([A-Z]) neo (?![A-Za-z]) để chỉ nhận 1\n// chữ tâm, KHÔNG nuốt \"ABC\" (3 đỉnh viết liền).\n// KHÔNG cờ 'i' ([A-Z] dưới 'i' nuốt chữ thường); [Đđ] để \"Đường\" đầu câu vẫn khớp.\nconst INCIRCLE_NAME_AFTER = /[Đđ]ường\\s*tròn\\s+nội\\s*tiếp\\s+(?:\\(\\s*([A-Z])\\s*\\)|([A-Z])(?![A-Za-z]))/u;\n\nfunction parseIncircleName(text: string): string | undefined {\n const m = INCIRCLE_IN_CLAUSE.exec(text);\n if (m) return m[1] ?? m[2] ?? 'O';\n const m2 = INCIRCLE_NAME_AFTER.exec(text);\n if (m2) return m2[1] ?? m2[2] ?? 'O';\n return undefined;\n}\n\n// \"Đường tròn (X) (…)? tiếp xúc …\" — tên đường tròn ĐỨNG TRƯỚC \"tiếp xúc\" trong\n// chunk. Dùng khi đề nêu \"(tam giác) ngoại tiếp (X)\" ở chỗ khác (không \"(X) nội\n// tiếp tam giác\") nên parseIncircleName miss. Chỉ tin là incircle khi tiếp xúc\n// ĐỦ 3 cạnh (3 đỉnh phân biệt) — caller kiểm.\nconst FORWARD_CIRCLE = /đường\\s*tròn\\s*\\(\\s*([A-Z])\\s*\\)[^.]*?tiếp\\s*xúc/iu;\n\nfunction parseTangencies(text: string, circle: string): IntentT[] {\n const m = SIDE_POINT_LIST.exec(text);\n if (!m) return [];\n\n const sides = splitCsv(m[1]);\n const names = splitCsv(m[2]);\n if (sides.length === 0 || sides.length !== names.length) return [];\n\n return names.map((name, i) => (\n addPoint(name, { kind: 'tangencyPoint', circle, onLine: sides[i] })\n ));\n}\n\nexport const incircleTangencyRule: LanguageRule = {\n id: 'incircleTangency',\n priority: 71,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const chunk of logicalChunks(ctx.problem, ctx.clauses)) {\n // \"tiếp điểm của (I) với BC,CA,AB lần lượt là D,E,F\" (tên SAU \"là\") + đảo.\n const tn = TANGENT_NAMED_FWD.exec(chunk.text) ?? TANGENT_NAMED_REV.exec(chunk.text);\n if (tn) {\n const fwd = TANGENT_NAMED_FWD.test(chunk.text);\n const circle = fwd ? tn[1] : tn[2];\n const sides = splitCsv(fwd ? tn[2] : tn[1]);\n const names = splitCsv(tn[3]);\n if (sides.length >= 1 && sides.length === names.length) {\n const verts = [...new Set(sides.join('').split(''))];\n const intents: IntentT[] = [];\n if (verts.length === 3) intents.push(drawCircle(circle, 'inscribedIn', { triangle: verts }));\n for (let i = 0; i < names.length; i++) {\n intents.push(addPoint(names[i], { kind: 'tangencyPoint', circle, onLine: sides[i] }));\n }\n out.push({ ruleId: 'incircleTangency', clauseIds: chunk.clauseIds, intents });\n continue;\n }\n }\n\n // Dạng ĐẢO trước: \"Cạnh ... tiếp xúc với đường tròn (O) tại ...\" — circle là\n // đường tròn nội tiếp, tự dựng inscribedIn + tiếp điểm.\n const rev = REVERSED_SIDE_POINT.exec(chunk.text);\n if (rev) {\n const sides = splitCsv(rev[1]);\n const circle = rev[2];\n const names = splitCsv(rev[3]);\n if (sides.length >= 1 && sides.length === names.length) {\n const verts = [...new Set(sides.join('').split(''))];\n const intents: IntentT[] = [];\n // Tiếp xúc đủ 3 cạnh → là đường tròn nội tiếp tam giác (3 đỉnh).\n if (verts.length === 3) {\n intents.push(drawCircle(circle, 'inscribedIn', { triangle: verts }));\n }\n for (let i = 0; i < names.length; i++) {\n intents.push(addPoint(names[i], { kind: 'tangencyPoint', circle, onLine: sides[i] }));\n }\n out.push({ ruleId: 'incircleTangency', clauseIds: chunk.clauseIds, intents });\n continue;\n }\n }\n\n let circle = parseIncircleName(chunk.text);\n if (!circle) {\n // Fallback: \"Đường tròn (X) tiếp xúc <đủ 3 cạnh>\" (đề nêu \"ngoại tiếp (X)\"\n // ở chỗ khác → parseIncircleName miss). Chỉ nhận khi 3 đỉnh phân biệt.\n const fm = FORWARD_CIRCLE.exec(chunk.text);\n const sp = SIDE_POINT_LIST.exec(chunk.text);\n if (fm && sp) {\n const verts = [...new Set(splitCsv(sp[1]).join('').split(''))];\n if (verts.length === 3) circle = fm[1];\n }\n if (!circle) continue;\n }\n\n const tangencies = parseTangencies(chunk.text, circle);\n if (tangencies.length === 0) continue;\n\n // Nếu tiếp xúc đủ 3 cạnh → tự dựng đường tròn nội tiếp (circleTriangle có\n // thể đã bỏ lỡ khi \"nội tiếp tam giác\" KHÔNG nêu đỉnh liền kề). Dedup theo\n // tên: nếu circle đã có (circleTriangle emit) thì intentsToDsl bỏ trùng.\n const m = SIDE_POINT_LIST.exec(chunk.text);\n const sides = m ? splitCsv(m[1]) : [];\n const verts = [...new Set(sides.join('').split(''))];\n const intents: IntentT[] =\n verts.length === 3\n ? [drawCircle(circle, 'inscribedIn', { triangle: verts }), ...tangencies]\n : tangencies;\n\n out.push({ ruleId: 'incircleTangency', clauseIds: chunk.clauseIds, intents });\n }\n return out;\n },\n};\n","import type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, drawCircle, drawShape, CIRCLE_KW, DUONG_KW } from './_shared';\n\nconst TRI = /tam\\s*giác(?:[^A-Z.;\\n]*)\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/u;\nconst ALTITUDES = /các\\s+đường\\s*cao\\s+([A-Z])([A-Z])\\s*,\\s*([A-Z])([A-Z])(?![A-Z])/u;\nconst DIAMETER_INTERSECTION = new RegExp(\n CIRCLE_KW +\n '\\\\s+' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])\\\\s+và\\\\s+' +\n CIRCLE_KW +\n '\\\\s+' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])[^.;\\n]*?tại\\\\s+các\\\\s+điểm\\\\s+([A-Z])\\\\s*,\\\\s*([A-Z])(?![A-Z])',\n 'u',\n);\nconst SEGMENT_CIRCLE = new RegExp(\n '[Đđ]oạn\\\\s+thẳng\\\\s+([A-Z])([A-Z])\\\\s+cắt\\\\s+' +\n CIRCLE_KW +\n '\\\\s+' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])\\\\s+tại\\\\s+điểm\\\\s+([A-Z])(?![A-Z])',\n 'gu',\n);\nconst LINE_LINE =\n /[Cc]ác\\s+đường\\s+thẳng\\s+([A-Z])([A-Z])\\s+và\\s+([A-Z])([A-Z])\\s+cắt\\s+nhau\\s+tại\\s+([A-Z])(?![A-Z])/u;\n\nfunction opposite(triangle: readonly string[], apex: string): string | undefined {\n const rest = triangle.filter((v) => v !== apex);\n return rest.length === 2 ? rest[0] + rest[1] : undefined;\n}\n\nexport const altitudeDiameterCirclesRule: LanguageRule = {\n id: 'altitude-diameter-circles',\n priority: 67,\n languages: ['vi'],\n patterns: [new RegExp(DUONG_KW + '\\\\s*cao', 'u'), new RegExp(DUONG_KW + '\\\\s*kính', 'u')],\n match(ctx) {\n const tri = TRI.exec(ctx.problem);\n const alts = ALTITUDES.exec(ctx.problem);\n const circles = DIAMETER_INTERSECTION.exec(ctx.problem);\n if (!tri || !alts || !circles) return [];\n\n const triangle = [tri[1], tri[2], tri[3]] as const;\n const altPairs = [\n [alts[1], alts[2]],\n [alts[3], alts[4]],\n ] as const;\n\n const altitudeIntents = [];\n for (const [apex, foot] of altPairs) {\n if (!triangle.includes(apex) || triangle.includes(foot)) return [];\n const opp = opposite(triangle, apex);\n if (!opp) return [];\n altitudeIntents.push(\n addPoint(foot, { kind: 'perpFoot', from: apex, onLine: opp }),\n connect(apex, foot, 'segment'),\n );\n }\n\n const dia1 = circles[1] + circles[2];\n const dia2 = circles[3] + circles[4];\n const known = new Set(altPairs.map(([a, f]) => `${a}${f}`));\n if (!known.has(dia1) || !known.has(dia2) || dia1 === dia2) return [];\n\n const c1 = `k${dia1}`;\n const c2 = `k${dia2}`;\n const x = circles[5];\n const y = circles[6];\n if (x === y) return [];\n\n const segCircles = [...ctx.problem.matchAll(SEGMENT_CIRCLE)];\n const extraPointIntents = [];\n for (const m of segCircles) {\n const line = `${m[1]}${m[2]}`;\n const dia = `${m[3]}${m[4]}`;\n const point = m[5];\n if (line === dia || point === line[0] || point === line[1]) return [];\n const circle = dia === dia1 ? c1 : dia === dia2 ? c2 : undefined;\n if (!circle) return [];\n extraPointIntents.push(\n addPoint(point, { kind: 'intersection', of: [line, circle], branch: 0 }),\n );\n }\n\n const lineLine = LINE_LINE.exec(ctx.problem);\n if (lineLine) {\n extraPointIntents.push(\n addPoint(lineLine[5], {\n kind: 'intersection',\n of: [`${lineLine[1]}${lineLine[2]}`, `${lineLine[3]}${lineLine[4]}`],\n }),\n );\n }\n\n const intents = [\n drawShape('triangle', [...triangle], 'any'),\n ...altitudeIntents,\n drawCircle(c1, 'diameter', { endpoints: [dia1[0], dia1[1]] }),\n drawCircle(c2, 'diameter', { endpoints: [dia2[0], dia2[1]] }),\n addPoint(x, { kind: 'circleIntersection', c1, c2, which: 0 }),\n addPoint(y, { kind: 'circleIntersection', c1, c2, which: 1 }),\n ...extraPointIntents,\n ];\n\n const out: RuleMatch[] = [{\n ruleId: 'altitude-diameter-circles',\n clauseIds: ctx.clauses.map((c) => c.id),\n intents,\n }];\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/diameterCircleCutsSides.ts\n//\n// \"Đường tròn đường kính BC cắt AB, AC tại M và N\" — đường tròn đường kính một\n// cạnh cắt hai cạnh kề tại các điểm phái sinh (phân phối 1-1):\n//\n// Cho tam giác ABC nhọn, đường tròn đường kính BC cắt AB, AC tại M và N.\n//\n// Bản chất: đường tròn đường kính PQ đi qua P, Q. Cạnh AB (chứa B ∈ đường kính)\n// cắt đường tròn tại B và một điểm thứ hai M (= chân đường cao hạ từ C, ∠BMC=90°\n// Thales). Vì luôn biết điểm chung (đỉnh dùng chung giữa cạnh và đường kính), ta\n// dựng M bằng `secondIntersection` (JSXGraph otherintersection loại điểm chung) —\n// robust hơn `intersection`+branch (không phụ thuộc thứ tự index JSXGraph).\n//\n// Phân phối: \"cắt L1, L2 tại X, Y\" → zip L1↔X, L2↔Y (kèm biến thể \"lần lượt\",\n// nối \"và\", tiền tố \"cạnh\"/\"các cạnh\"). Đường tròn KHÔNG tự dựng tam giác (triangle\n// rule lo) — chỉ emit đường tròn + các giao điểm.\n//\n// Fail-safe (escalate, thà thiếu hơn dựng sai):\n// - số cạnh ≠ số điểm → bỏ qua.\n// - cạnh không chia sẻ ĐÚNG 1 đỉnh với đường kính (0 → không biết điểm chung;\n// 2 → cạnh trùng đường kính, suy biến) → bỏ qua.\n// - tên điểm trùng đỉnh cạnh/đường kính (định nghĩa vòng) → bỏ qua.\n//\n// GOTCHA \\b: \\b của JS theo ASCII. Vùng tên điểm (\"M và N\", \"M, N\") các chữ HOA\n// luôn cách bởi dấu cách/phẩy nên \\b[A-Z]\\b an toàn; vẫn dùng cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawCircle, CIRCLE_KW, DUONG_KW } from './_shared';\n\n// Anchor \"đường tròn đường kính PQ cắt <cạnh…> (lần lượt)? tại <điểm…>\".\n// lineRegion lazy tới \"tại\" đầu tiên; pointRegion tới hết clause (không . ; \\n).\n// Global: một clause có thể chứa NHIỀU \"đường tròn đường kính … cắt … tại …\"\n// (vd Bài 13: hai nửa đường tròn). pointRegion bắt CHẶT (chỉ HOA + ,/và) để\n// không nuốt sang construct kế trong cùng clause.\nconst PATTERN = new RegExp(\n // Chỉ-báo đường tròn: \"đường tròn (tâm X|(X))?\" HOẶC \"(X)\" trần (httcd:2 \"(O)\n // đường kính BC\" — KHÔNG có chữ \"đường tròn\"). Bắt buộc có 1 trong 2.\n '(?:' +\n CIRCLE_KW + '\\\\s+(?:(?:\\\\(\\\\s*[A-Z]\\\\s*\\\\)|tâm\\\\s+[A-Z])\\\\s+)?' +\n '|\\\\(\\\\s*[A-Z]\\\\s*\\\\)\\\\s+' +\n ')' +\n DUONG_KW +\n // optional phẩy + đại từ \"nó\" giữa diameter và \"cắt\" (vao10:81 \"AH, cắt…\").\n // \"theo thứ tự\" = \"lần lượt\". Anchor điểm = \"tại\" (dạng \"ở\" tách sang\n // PATTERN_O vì lazy-region dừng ở \"ở\" đầu tiên có thể nuốt thiếu — vao10:155).\n '\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s*,?\\\\s*(?:nó\\\\s+)?\\\\s*cắt\\\\s+([^.;\\\\n]*?)\\\\s+(?:(?:lần\\\\s*lượt|theo\\\\s+thứ\\\\s+tự)\\\\s+)?tại\\\\s+([A-Z](?!\\\\p{L})(?:\\\\s*(?:,|và)\\\\s*[A-Z](?!\\\\p{L}))*)',\n 'gu',\n);\n\n// Phân phối anchor \"ở\" — YÊU CẦU ≥2 điểm (\"ở D và E\") để KHÔNG nuốt dạng xen\n// \"cắt BC ở N và cắt (O) tại D\" (1 điểm sau \"ở\", phần \"cắt (O)\" là giao 2 đường\n// tròn — rule khác/escalate lo). httcd:2 \"(O) đường kính BC, nó cắt các cạnh\n// AB, AC theo thứ tự ở D và E\". groups: 1=d0 2=d1 3=lineRegion 4=points(≥2).\nconst PATTERN_O = new RegExp(\n '(?:' +\n CIRCLE_KW + '\\\\s+(?:(?:\\\\(\\\\s*[A-Z]\\\\s*\\\\)|tâm\\\\s+[A-Z])\\\\s+)?' +\n '|\\\\(\\\\s*[A-Z]\\\\s*\\\\)\\\\s+' +\n ')' +\n DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s*,?\\\\s*(?:nó\\\\s+)?\\\\s*cắt\\\\s+([^.;\\\\n]*?)\\\\s+(?:(?:lần\\\\s*lượt|theo\\\\s+thứ\\\\s+tự)\\\\s+)?ở\\\\s+([A-Z](?!\\\\p{L})(?:\\\\s*(?:,|và)\\\\s*[A-Z](?!\\\\p{L}))+)',\n 'gu',\n);\n\n// Dạng XEN KẼ: \"đường tròn đường kính BC cắt AB ở N và cắt AC ở M\" (lặp \"cắt L\n// ở/tại P\", KHÔNG phải \"cắt L1,L2 tại P1,P2\"). groups: d0 d1 | L1 P1 | L2 P2.\nconst PATTERN_INTERLEAVED = new RegExp(\n CIRCLE_KW + '\\\\s+(?:(?:\\\\(\\\\s*[A-Z]\\\\s*\\\\)|tâm\\\\s+[A-Z])\\\\s+)?' + DUONG_KW +\n '\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+cắt\\\\s+([A-Z]{2})(?![A-Z])\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])' +\n '\\\\s+và\\\\s+cắt\\\\s+([A-Z]{2})(?![A-Z])\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])',\n 'gu',\n);\n\nconst PREFILTER = new RegExp(DUONG_KW + '\\\\s*kính', 'u');\n\n/** Đỉnh chung DUY NHẤT giữa cạnh \"AB\" và đường kính \"BC\" (vd \"B\"). */\nfunction sharedVertex(line: string, dia: string): string | undefined {\n const shared = [line[0], line[1]].filter((ch) => dia.includes(ch));\n return shared.length === 1 ? shared[0] : undefined;\n}\n\nexport const diameterCircleCutsSidesRule: LanguageRule = {\n // THẤP HƠN triangle (100): cần A,B,C dựng trước khi secondIntersection tham\n // chiếu cạnh/đỉnh. Đặt 66 (cùng họ diameterCirclePairwise) — đủ thấp so với 100.\n id: 'diameter-circle-cuts-sides',\n priority: 66,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n PATTERN.lastIndex = 0;\n PATTERN_O.lastIndex = 0;\n for (const m of [...c.text.matchAll(PATTERN), ...c.text.matchAll(PATTERN_O)]) {\n const d0 = m[1];\n const d1 = m[2];\n const dia = d0 + d1; // \"BC\"\n const lines = m[3].match(/[A-Z][A-Z](?![A-Z])/gu) ?? [];\n const points = m[4].match(/\\b[A-Z]\\b/gu) ?? [];\n\n // Phân phối 1-1: cần ≥1 cạnh và số cạnh == số điểm.\n if (lines.length === 0 || lines.length !== points.length) continue;\n\n const circle = `k${dia}`;\n const intents: IntentT[] = [\n drawCircle(circle, 'diameter', { endpoints: [d0, d1] }),\n ];\n\n let ok = true;\n const seen = new Set<string>();\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const pt = points[i];\n const other = sharedVertex(line, dia);\n // Cần đúng 1 đỉnh chung (điểm đã biết trên cả cạnh lẫn đường tròn).\n if (!other) { ok = false; break; }\n // Tên điểm phải MỚI, không trùng đỉnh cạnh/đường kính.\n if (line.includes(pt) || dia.includes(pt) || seen.has(pt)) { ok = false; break; }\n seen.add(pt);\n intents.push(addPoint(pt, { kind: 'secondIntersection', line, circle, other }));\n }\n if (!ok) continue;\n\n out.push({ ruleId: 'diameter-circle-cuts-sides', clauseIds: [c.id], intents });\n }\n\n // Dạng xen kẽ \"cắt L1 ở P1 và cắt L2 ở P2\".\n PATTERN_INTERLEAVED.lastIndex = 0;\n for (const m of c.text.matchAll(PATTERN_INTERLEAVED)) {\n const dia = m[1] + m[2];\n const circle = `k${dia}`;\n const pairs: Array<[string, string]> = [[m[3], m[4]], [m[5], m[6]]];\n const intents: IntentT[] = [drawCircle(circle, 'diameter', { endpoints: [m[1], m[2]] })];\n let ok = true;\n const seen = new Set<string>();\n for (const [line, pt] of pairs) {\n const other = sharedVertex(line, dia);\n if (!other || line.includes(pt) || dia.includes(pt) || seen.has(pt)) { ok = false; break; }\n seen.add(pt);\n intents.push(addPoint(pt, { kind: 'secondIntersection', line, circle, other }));\n }\n if (ok) out.push({ ruleId: 'diameter-circle-cuts-sides', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleDiameter.ts\n//\n// Standalone circle with a named diameter:\n// \"Cho đường tròn (O) đường kính AB\" → A,B free; O midpoint AB; circle O_c diameter AB\n// \"Cho nửa đường tròn (O) đường kính AB\" → same construction for now (full support circle)\n// \"Cho (O;R) đường kính AB\" → same, radius symbol ignored because diameter fixes circle\n//\n// This deliberately does NOT parse \"đường tròn đường kính BC cắt AB tại M\" because\n// diameterCircleCutsSides owns that richer construct.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, drawCircle, DUONG_KW, CIRCLE_KW } from './_shared';\n\nconst DIAMETER_KW = new RegExp(DUONG_KW + '\\\\s*kính', 'u');\n\n// \"hai đường kính AB và CD vuông góc với nhau\" — HAI đường kính vuông góc của\n// CÙNG một đường tròn. perpDiameters rule sở hữu (4 điểm onCircle), KHÔNG dựng\n// đường tròn đường kính rời. Guard bỏ qua khi gặp dạng này.\nconst TWO_PERP_DIAMETERS = new RegExp(\n 'hai\\\\s+' + DUONG_KW + '\\\\s*kính[^.]{0,40}?vuông\\\\s*góc',\n 'u',\n);\n// Tên tâm: 1 chữ HOA + tuỳ chọn prime (') hoặc chỉ số (\"O'\", \"O1\", \"O2\"). Đề\n// olympiad hay có 2-3 đường tròn (O), (O'), (O₁) → cần bắt prime/subscript, nếu\n// không \"(O') đường kính BC\" không khớp (paren branch kẹt ở ký tự ') → bỏ sót\n// đường tròn thứ hai (phang:6). circleDiameter dựng circle \"O'_c\" + center \"O'\".\nconst CTR = String.raw`[A-Z](?:['′]|\\d{1,2})?`;\n// Tên tâm: \"(O)\"/\"(O;R)\" | \"tâm O\" | \"tâm (O)\" (ngoặc quanh tâm sau \"tâm\" —\n// mohinh:26 \"đường tròn tâm (O)\") | BARE \"nửa đường tròn O đường kính AB\" (vao10\n// — paren rơi vào ô bảng; lookahead \"đường kính\" để không nuốt HOA khác).\nconst CIRCLE_NAME = String.raw`(?:${CIRCLE_KW}|nửa\\s+${CIRCLE_KW})\\s*(?:\\(\\s*(${CTR})(?:\\s*[;,]\\s*[Rr])?\\s*\\)|tâm\\s+\\(?\\s*(${CTR})\\s*\\)?|([A-Z])(?=\\s+[đĐ]ư[ờơ]ng\\s*kính))?`;\n\nconst WORDS = new RegExp(\n CIRCLE_NAME + String.raw`[^.;\\n]{0,40}?` + DUONG_KW + String.raw`\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])`,\n 'gu',\n);\n// \"(O;R) đường kính AB\" / \"(O,R) có đường kính BC\" / \"(O;R), đường kính AB\" —\n// \"có\"/phẩy xen giữa (vao10).\nconst COMPACT = new RegExp(\n String.raw`\\(\\s*(${CTR})\\s*[;,]\\s*[Rr]\\s*\\)\\s*,?\\s*(?:có\\s+)?` + DUONG_KW + String.raw`\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])`,\n 'gu',\n);\n// \"Cho (O) đường kính AC\" — paren bare KHÔNG chữ \"đường tròn\", mở đầu bằng\n// \"Cho\" (đường tròn nền GIVEN — vao10 139/180). Full construction như WORDS.\nconst GIVEN_BARE = new RegExp(\n String.raw`[Cc]ho\\s+\\(\\s*(${CTR})\\s*\\)\\s*,?\\s*(?:có\\s+)?` + DUONG_KW + String.raw`\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])`,\n 'gu',\n);\n// Bare paren \"(I) đường kính AH\" — KHÔNG chữ \"đường tròn\" đứng trước (vao10:61\n// \"Vẽ (I) đường kính AH và (K) đường kính BH\"). CHỈ nhận khi CẢ 2 đầu mút đã\n// xuất hiện TRƯỚC match (đường tròn phụ dựng trên đoạn có sẵn) → emit tâm\n// midpoint + đường tròn, KHÔNG free/connect (đầu mút thuộc hình đã dựng).\nconst BARE_PAREN = new RegExp(\n String.raw`\\(\\s*(${CTR})\\s*\\)\\s*(?:có\\s+)?` + DUONG_KW + String.raw`\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])`,\n 'gu',\n);\n\ninterface Parsed {\n center: string;\n a: string;\n b: string;\n}\n\nfunction parseAll(text: string): Parsed[] {\n const out: Parsed[] = [];\n WORDS.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = WORDS.exec(text)) !== null) {\n const center = m[1] ?? m[2] ?? m[3];\n const a = m[4];\n const b = m[5];\n if (!center || center === a || center === b || a === b) continue;\n out.push({ center, a, b });\n }\n\n COMPACT.lastIndex = 0;\n while ((m = COMPACT.exec(text)) !== null) {\n const center = m[1];\n const a = m[2];\n const b = m[3];\n if (!center || center === a || center === b || a === b) continue;\n out.push({ center, a, b });\n }\n\n const seen = new Set<string>();\n return out.filter((p) => {\n const key = `${p.center}|${p.a}${p.b}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nfunction intentsFor(p: Parsed) {\n return [\n addPoint(p.a, { kind: 'free' }),\n addPoint(p.b, { kind: 'free' }),\n addPoint(p.center, { kind: 'midpoint', of: `${p.a}${p.b}` }),\n connect(p.a, p.b, 'segment'),\n drawCircle(`${p.center}_c`, 'diameter', { endpoints: [p.a, p.b] }),\n ];\n}\n\nexport const circleDiameterRule: LanguageRule = {\n id: 'circle-diameter',\n priority: 67,\n languages: ['vi'],\n patterns: [DIAMETER_KW],\n match(ctx) {\n // \"hai đường kính ... vuông góc\" → perpDiameters sở hữu; KHÔNG dựng đường tròn\n // đường kính rời (sẽ chồng + sai: đường tròn này có 2 đường kính, không phải\n // đường tròn ĐƯỜNG KÍNH AB).\n if (TWO_PERP_DIAMETERS.test(ctx.problem)) return [];\n const out: RuleMatch[] = [];\n const whole = parseAll(ctx.problem);\n const compact = whole.filter((p) => ctx.problem.includes(`(${p.center};`) || ctx.problem.includes(`(${p.center},`));\n if (compact.length > 0) {\n for (const p of compact) {\n const claim = ctx.clauses\n .filter((c) => DIAMETER_KW.test(c.text) || c.text.includes(`(${p.center}`))\n .map((c) => c.id);\n out.push({\n ruleId: 'circle-diameter',\n clauseIds: claim.length > 0 ? claim : ctx.clauses.map((c) => c.id),\n intents: intentsFor(p),\n });\n }\n }\n\n const emitted = new Set(compact.map((p) => `${p.center}|${p.a}${p.b}`));\n for (const c of ctx.clauses) {\n const parsed = parseAll(c.text);\n for (const p of parsed) {\n const key = `${p.center}|${p.a}${p.b}`;\n if (emitted.has(key)) continue;\n emitted.add(key);\n out.push({\n ruleId: 'circle-diameter',\n clauseIds: [c.id],\n intents: intentsFor(p),\n });\n }\n }\n\n // \"Cho (O) đường kính AC\" — đường tròn nền GIVEN, full construction.\n GIVEN_BARE.lastIndex = 0;\n let gm: RegExpExecArray | null;\n while ((gm = GIVEN_BARE.exec(ctx.problem)) !== null) {\n const p = { center: gm[1], a: gm[2], b: gm[3] };\n if (!p.center || p.center === p.a || p.center === p.b || p.a === p.b) continue;\n const key = `${p.center}|${p.a}${p.b}`;\n if (emitted.has(key)) continue;\n emitted.add(key);\n const matched = gm[0];\n const claim = ctx.clauses.filter((c) => c.text.includes(matched.replace(/^[Cc]ho\\s+/u, ''))).map((c) => c.id);\n out.push({\n ruleId: 'circle-diameter',\n clauseIds: claim.length > 0 ? claim : [ctx.clauses[0]?.id ?? 0],\n intents: intentsFor(p),\n });\n }\n\n // Bare paren \"(I) đường kính AH\" — đầu mút phải Đà xuất hiện trước match\n // (lookbehind chỉ loại chữ thường, đồng quy ước với diameterEndpoint).\n BARE_PAREN.lastIndex = 0;\n let bm: RegExpExecArray | null;\n while ((bm = BARE_PAREN.exec(ctx.problem)) !== null) {\n const center = bm[1];\n const a = bm[2];\n const b = bm[3];\n if (!center || center === a || center === b || a === b) continue;\n const key = `${center}|${a}${b}`;\n if (emitted.has(key)) continue;\n const before = ctx.problem.slice(0, bm.index);\n const known = (p: string) => new RegExp(`(?<![a-z])${p}(?![a-z])`, 'u').test(before);\n if (!known(a) || !known(b)) continue;\n emitted.add(key);\n const matched = bm[0];\n const claim = ctx.clauses.filter((c) => c.text.includes(matched)).map((c) => c.id);\n out.push({\n ruleId: 'circle-diameter',\n clauseIds: claim.length > 0 ? claim : [ctx.clauses[0]?.id ?? 0],\n intents: [\n addPoint(center, { kind: 'midpoint', of: `${a}${b}` }),\n drawCircle(`${center}_c`, 'diameter', { endpoints: [a, b] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/onCirclePoint.ts\n//\n// Points declared on a named circle/semicircle:\n// \"Điểm M nằm trên nửa đường tròn\" after \"(O) đường kính AB\" → M on O_c\n// \"Lấy điểm F thuộc cung AC nhỏ\" with a unique \"(O)\" circle → F on O_c/O\n//\n// This rule is intentionally conservative: it needs one unambiguous circle name\n// in the whole problem, and it does not try to model arc bounds yet.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\nconst PREFILTER = /(?:nằm|thuộc|lấy\\s+điểm|trên\\s+(?:nửa\\s+)?(?:đường\\s*tròn|cung))/iu;\nconst NAMED_CIRCLE = /(?:nửa\\s+)?đường\\s*tròn\\s*(?:tâm\\s+)?\\(?\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)?/u;\nconst COMPACT_CIRCLE = /\\(\\s*([A-Z])\\s*[;,]\\s*[Rr]\\s*\\)/u;\n// \"<Name> thuộc/nằm trên/là (một) điểm trên cung (nhỏ|lớn)? <pair>\" — chấp nhận\n// tính từ cung ĐỨNG TRƯỚC cặp đỉnh (\"cung lớn AB\") lẫn sau (\"cung AB nhỏ\").\n// Hậu tố circle/cung: \"cung (nhỏ|lớn)? AB\" | \"(nửa)? đường tròn\" | \"(O)\" bare\n// paren (1 ký tự HOA — \"thuộc (O)\" cực phổ biến khi đề đã đặt tên đường tròn).\nconst ON_SUFFIX =\n '(?:cung\\\\s+(?:nhỏ\\\\s+|lớn\\\\s+)?[A-Z]{2}(?:\\\\s*(?:nhỏ|lớn))?|(?:nửa\\\\s+)?đường\\\\s*tròn|\\\\(\\\\s*[A-Z]\\\\s*\\\\))';\nconst POINT_ON = new RegExp(\n // \"nằm\" optional → bắt \"M (bất kì)? trên (nửa)? đường tròn\" / \"điểm A trên (O)\"\n // (chỉ \"trên\" trần, không \"nằm trên\"). ON_SUFFIX neo circle/cung nên \"trên\"\n // trần vẫn an toàn (không nuốt \"trên đoạn/tia\").\n //\n // Nhánh \"là (một)? điểm …\" chấp nhận giới từ kết là \"trên\" HOẶC \"thuộc\"\n // (\"Gọi E là một điểm bất kì thuộc cung nhỏ BC\" — hinh9 #108). ON_SUFFIX vẫn\n // neo circle/cung nên \"thuộc\" trần không nuốt \"thuộc cạnh/đoạn\".\n `(?:[Đđ]iểm\\\\s+)?([A-Z])(?:\\\\s+[^.]{0,12}?)?\\\\s+(?:(?:nằm\\\\s+)?trên|thuộc|là\\\\s+(?:một\\\\s+)?điểm\\\\s+(?:[^.A-Z]{0,16}?\\\\s+)?(?:(?:nằm\\\\s+)?trên|thuộc))\\\\s+${ON_SUFFIX}`,\n 'u',\n);\nconst TAKE_ON = new RegExp(\n `[Ll]ấy\\\\s+điểm\\\\s+([A-Z])[^.]{0,20}?(?:trên|thuộc)\\\\s+(?:cung|(?:nửa\\\\s+)?đường\\\\s*tròn|\\\\(\\\\s*[A-Z]\\\\s*\\\\))`,\n 'u',\n);\n// Đảo \"Trên (nửa)? đường tròn lấy điểm X\" (KHÔNG \"(X)\", không \"cung\") → X onCircle\n// trên circle toàn-đề. TAKE_ON_REV cần \"(X)\"; TAKE_ON_CUNG cần \"cung\"; đây phủ\n// dạng trần \"Trên đường tròn lấy điểm D\" (phang:14).\nconst TAKE_ON_DUONGTRON =\n /[Tt]rên\\s+(?:nửa\\s+)?đường\\s*tròn\\s+lấy\\s+(?:một\\s+)?điểm\\s+([A-Z])(?![A-Z])/u;\n// Đảo trên CUNG (không paren): \"Trên cung BC lấy điểm M\" → M onCircle. KHÁC\n// TAKE_ON_REV (cần \"(X)\"): ở đây cung nêu bằng cặp đỉnh; circle = toàn đề.\nconst TAKE_ON_CUNG = /[Tt]rên\\s+cung\\s+(?:nhỏ\\s+|lớn\\s+)?[A-Z]{2}(?:\\s*(?:nhỏ|lớn))?[^.]{0,16}?lấy\\s+điểm\\s+([A-Z])(?![A-Z])/u;\n// Đảo: \"Trên (nửa)? đường tròn (X) lấy điểm P\" — clause TỰ nêu circle (X). Bắt\n// CẢ circle lẫn điểm để không nhầm sang circle toàn-đề khác. group1=center,\n// group2=point. Center emit THÔ (resolveCircleNames map X→X_c nếu cần).\nconst TAKE_ON_REV =\n /[Tt]rên\\s+(?:nửa\\s+)?(?:đường\\s*tròn|cung)\\s*\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)[^.]{0,16}?lấy\\s+điểm\\s+([A-Z])(?![A-Z])/u;\n// Distributive 2 điểm (Bài 9): \"(lấy)? hai điểm C và D thuộc (nửa)? đường tròn\"\n// → 2 điểm onCircle với theta KHÁC nhau. group1=điểm 1 (C), group2=điểm 2 (D).\n// `hai\\s*điểm`: OCR hay dính \"haiđiểm\" (httcd:191). \"bất kì/kỳ\" optional xen giữa\n// tên thứ hai và \"thuộc\".\nconst TWO_ON =\n /(?:lấy\\s+)?hai\\s*điểm\\s+([A-Z])(?![A-Za-z])\\s+và\\s+([A-Z])(?![A-Za-z])(?:\\s+bất\\s*k[ìiyỳ])?\\s+thuộc\\s+(?:nửa\\s+)?(?:đường\\s*tròn|cung)/u;\n// \"(Các)? điểm E, F thuộc cung BC …\" — 2 điểm phân phối ngăn bởi dấu phẩy.\nconst TWO_ON_COMMA =\n /(?:[CcNn]ác\\s+|[Nn]hững\\s+)?điểm\\s+([A-Z])(?![A-Za-z])\\s*,\\s*([A-Z])(?![A-Za-z])\\s+thuộc\\s+(?:nửa\\s+)?(?:đường\\s*tròn|cung)/u;\n// \"M, N là hai điểm thuộc cung nhỏ BC …\" / \"C,D là các điểm nằm trên (O)\"\n// (vao10:12) — tên ĐỨNG TRƯỚC \"là (hai|các) điểm thuộc/nằm trên\". Hậu tố nhận\n// thêm \"(X)\" paren bare vì đề hay viết \"nằm trên (O)\" không chữ \"đường tròn\".\nconst TWO_ON_NAMES =\n /([A-Z])(?![A-Za-z])\\s*,\\s*([A-Z])(?![A-Za-z])\\s+là\\s+(?:hai|các)\\s+điểm\\s+(?:thuộc|nằm\\s+trên|trên)\\s+(?:(?:nửa\\s+)?(?:đường\\s*tròn|cung)|\\(\\s*[A-Z]\\s*\\))/u;\n// ĐẢO 2 điểm trên CUNG: \"Trên cung (lớn|nhỏ)? AB lấy hai điểm C, D\" / \"C và D\"\n// (hinh9:19, vao10:202). Cung nêu bằng cặp đỉnh; circle = toàn đề. group1, group2\n// = 2 điểm.\nconst TWO_ON_CUNG_REV =\n /[Tt]rên\\s+cung\\s+(?:nhỏ\\s+|lớn\\s+)?[A-Z]{2}(?:\\s*(?:nhỏ|lớn))?\\s+lấy\\s+hai\\s+điểm\\s+([A-Z])(?![A-Za-z])\\s*(?:,|và)\\s*([A-Z])(?![A-Za-z])/u;\n\n// Bare \"(O)\" (1 ký tự HOA trong ngoặc) — fallback khi không có tiền tố \"đường\n// tròn\". Dùng cuối cùng vì rộng (mọi \"(X)\").\nconst BARE_CIRCLE = /\\(\\s*([A-Z])\\s*\\)/u;\n\n// Đường tròn đường kính KHÔNG tên tâm: \"(nửa)? đường tròn đường kính XY\" →\n// diameterCircleSecant đặt tên \"kXY\". Dùng làm fallback khi không có tâm nêu tên.\nconst UNNAMED_DIAMETER = /(?:nửa\\s+)?đường\\s*tròn\\s+đường\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])/u;\n\nfunction resolveCircle(problem: string): string | undefined {\n const m = NAMED_CIRCLE.exec(problem) ?? COMPACT_CIRCLE.exec(problem) ?? BARE_CIRCLE.exec(problem);\n if (!m) {\n // Không có tâm đặt tên → thử đường tròn đường kính vô danh duy nhất (\"kXY\").\n const dm = UNNAMED_DIAMETER.exec(problem);\n return dm ? `k${dm[1]}${dm[2]}` : undefined;\n }\n const center = m[1];\n // circleDiameterRule names its support circle \"<center>_c\" (đường tròn ĐƯỜNG\n // KÍNH có tên tâm). Chỉ thêm \"_c\" khi \"đường kính\" gắn với CHÍNH center NÀY —\n // KHÔNG phải \"đường kính\" của 1 đường tròn KHÁC trong đề. Vd phang:17:\n // circumcircle \"(O)\" (circleTriangle đặt tên \"O\") + 1 đường tròn đường kính MP\n // rời → onCircle phải trỏ \"O\", KHÔNG \"O_c\". Nếu là circle bán kính/qua-3-điểm\n // (tên thô \"O\"), resolveCircleNames sẽ map \"O\"→\"O_c\" khi cần (có collision).\n const c = center.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const diameterOfThisCenter =\n new RegExp(`(?:\\\\(\\\\s*${c}\\\\s*[;,)]|tâm\\\\s+${c}(?![A-Za-z]))[^.]{0,25}?đường\\\\s*kính`, 'u').test(problem) ||\n new RegExp(`đường\\\\s*kính[^.]{0,25}?\\\\(\\\\s*${c}\\\\s*\\\\)`, 'u').test(problem);\n return diameterOfThisCenter ? `${center}_c` : center;\n}\n\nexport const onCirclePointRule: LanguageRule = {\n id: 'on-circle-point',\n priority: 64,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = resolveCircle(ctx.problem);\n const out: RuleMatch[] = [];\n let theta = 1.2;\n for (const c of ctx.clauses) {\n // Đảo trước: clause tự nêu circle (X) → dùng circle ĐÓ (thô), tránh nhầm\n // circle toàn-đề. Khớp rồi thì bỏ qua forward patterns cho clause này.\n const rev = TAKE_ON_REV.exec(c.text);\n if (rev) {\n const name = rev[2];\n if (name.length === 1) {\n out.push({\n ruleId: 'on-circle-point',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'onCircle', circle: rev[1], theta })],\n });\n theta += 0.8;\n }\n continue;\n }\n if (!circle) continue; // forward patterns cần circle toàn-đề\n // Distributive 2 điểm: \"lấy hai điểm C và D thuộc nửa đường tròn\" — 2 điểm\n // onCircle theta khác nhau trên circle toàn-đề.\n const two =\n TWO_ON.exec(c.text) ??\n TWO_ON_COMMA.exec(c.text) ??\n TWO_ON_NAMES.exec(c.text) ??\n TWO_ON_CUNG_REV.exec(c.text);\n if (two && two[1].length === 1 && two[2].length === 1) {\n out.push({\n ruleId: 'on-circle-point',\n clauseIds: [c.id],\n intents: [\n addPoint(two[1], { kind: 'onCircle', circle, theta }),\n addPoint(two[2], { kind: 'onCircle', circle, theta: theta + 0.8 }),\n ],\n });\n theta += 1.6;\n continue;\n }\n const m =\n POINT_ON.exec(c.text) ??\n TAKE_ON.exec(c.text) ??\n TAKE_ON_CUNG.exec(c.text) ??\n TAKE_ON_DUONGTRON.exec(c.text);\n if (!m) continue;\n const name = m[1];\n if (name.length !== 1) continue;\n out.push({\n ruleId: 'on-circle-point',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'onCircle', circle, theta })],\n });\n theta += 0.8;\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentAt.ts\n//\n// Tangent lines at points on a named circle:\n// \"Tiếp tuyến tại M cắt tiếp tuyến tại A và B của đường tròn (O) lần lượt tại C và D\"\n// → tangents tM/tA/tB + C=tM∩tA, D=tM∩tB\n//\n// Simple single tangent declarations are also emitted as visible tangent lines.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /[Tt]iếp\\s*tuyến\\s+(?:với\\s+|của\\s+)?(?:đường\\s*tròn\\s*)?(?:\\([^)]*\\)\\s*)?tại/u;\nconst CIRCLE_REF = /đường\\s*tròn\\s*\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)|\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)/u;\n\nconst DISTRIB = /[Tt]iếp\\s*tuyến\\s+tại\\s+([A-Z])\\s+cắt\\s+tiếp\\s*tuyến\\s+tại\\s+([A-Z])\\s+và\\s+([A-Z])[^.]{0,60}?lần\\s*lượt\\s+tại\\s+([A-Z])\\s+và\\s+([A-Z])/u;\n// \"Tiếp tuyến tại B, C (của (O))? cắt nhau tại T\" → tB, tC, T = tB∩tC.\nconst TWO_MEET =\n /[Tt]iếp\\s*tuyến\\s+(?:với\\s+|của\\s+)?(?:đường\\s*tròn\\s*)?(?:\\(\\s*[A-Z]['′]?\\s*\\)\\s*)?tại\\s+([A-Z])\\s*(?:,|và)\\s*([A-Z])(?![A-Z])[^.]{0,30}?cắt\\s+nhau\\s+(?:ở|tại)\\s+([A-Z])(?![A-Z])/u;\nconst SINGLE = /[Tt]iếp\\s*tuyến\\s+tại\\s+(?:điểm\\s+)?([A-Z])(?:\\s+với|\\s+của|\\s+đường|\\s*$)/u;\n\nfunction circleName(problem: string): string | undefined {\n const m = CIRCLE_REF.exec(problem);\n const center = m?.[1] ?? m?.[2];\n if (!center) return undefined;\n return /đường\\s*kính/u.test(problem) ? `${center}_c` : center;\n}\n\nfunction tName(point: string): string {\n return `t${point}`;\n}\n\nexport const tangentAtRule: LanguageRule = {\n id: 'tangent-at',\n priority: 63,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = circleName(ctx.problem);\n if (!circle) return [];\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const d = DISTRIB.exec(c.text);\n if (d) {\n const base = d[1];\n const p1 = d[2];\n const p2 = d[3];\n const x1 = d[4];\n const x2 = d[5];\n out.push({\n ruleId: 'tangent-at',\n clauseIds: [c.id],\n intents: [\n drawLine(tName(base), 'tangentAt', { through: base, circle }),\n drawLine(tName(p1), 'tangentAt', { through: p1, circle }),\n drawLine(tName(p2), 'tangentAt', { through: p2, circle }),\n addPoint(x1, { kind: 'intersection', of: [tName(base), tName(p1)] }),\n addPoint(x2, { kind: 'intersection', of: [tName(base), tName(p2)] }),\n ],\n });\n continue;\n }\n\n const tm = TWO_MEET.exec(c.text);\n if (tm) {\n const [b, cc, t] = [tm[1], tm[2], tm[3]];\n if (b !== cc && t !== b && t !== cc) {\n out.push({\n ruleId: 'tangent-at',\n clauseIds: [c.id],\n intents: [\n drawLine(tName(b), 'tangentAt', { through: b, circle }),\n drawLine(tName(cc), 'tangentAt', { through: cc, circle }),\n addPoint(t, { kind: 'intersection', of: [tName(b), tName(cc)] }),\n ],\n });\n continue;\n }\n }\n\n const s = SINGLE.exec(c.text);\n if (!s) continue;\n const through = s[1];\n out.push({\n ruleId: 'tangent-at',\n clauseIds: [c.id],\n intents: [drawLine(tName(through), 'tangentAt', { through, circle })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/onSegmentPoint.ts\n//\n// Điểm tự do trên đoạn/cạnh/bán kính:\n// \"Trên cạnh AC lấy điểm M\" → M onSegment AC\n// \"điểm E thuộc cạnh BC\" → E onSegment BC\n// \"D nằm giữa A và B\" → D onSegment AB\n//\n// Rule này cố ý không giải metric (AC=10, CB=40, AD=2DB). Mục tiêu là dựng điểm\n// đúng constraint trên segment để các construct sau có ref hợp lệ; t mặc định do\n// builder chọn.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// \"thuộc <2 HOA>\" (vd \"D thuộc AC\") cũng kích hoạt — KHÔNG bắt buộc chữ \"cạnh\".\n// \"thuộc (O)\"/\"thuộc cung\" KHÔNG khớp ([A-Z]{2} cần 2 HOA liền, paren/'cung' loại)\n// → onCirclePoint lo. match() vẫn validate SEG nên prefilter rộng vô hại.\n// \"[Tt]rên\\s+[A-Z]{2}\" cho dạng đoạn-trước \"trên BC, CA, AB … lấy điểm M, N, E\"\n// (cạnh nêu trần bằng cặp đỉnh, không chữ \"cạnh/đoạn\"). match() vẫn validate nên\n// prefilter rộng vô hại.\n// \"đường kính AB\" là 1 ĐOẠN (đường kính của đường tròn) → cho phép \"trên đường\n// kính AB lấy điểm C\" (phang:14). Thêm vào prefix đoạn-loại.\nconst PREFILTER = /(?:thuộc\\s+(?:các\\s+|hai\\s+|ba\\s+)?(?:cạnh|đoạn|đáy|tia|bán\\s*kính|đường\\s*kính|dây|[A-Z]{2})|[Tt]rên\\s+(?:các\\s+|hai\\s+|ba\\s+)?(?:cạnh|đoạn|đáy|tia|bán\\s*kính|đường\\s*kính|đường\\s*thẳng|dây|[A-Z]{2})|(?:di\\s*chuyển|di\\s*động)\\s+trên|nằm\\s+giữa)/u;\n\n// \"Trên đường thẳng d (lấy)? (một)? (điểm)? M\" — đường ĐẶT TÊN chữ thường (d, d1).\n// resolveSegmentRef thấy shape \"d\" (tangentLineNamedAtPoint dựng) → glider trên d.\n// Token tên đường = 1 chữ thường + tối đa 1 chữ số, NEO (?!\\p{L}) để KHÔNG nuốt\n// từ tiếng Việt \"vuông\"/\"song\"… (\"đường thẳng vuông góc\" → \"v\"+(?!\\p{L}) thất bại\n// vì sau \"v\" là \"u\" (chữ) — không khớp; tránh bịa đoạn \"vu\").\nconst ON_NAMED_LINE = new RegExp(\n String.raw`[Tt]rên\\s+đường\\s*thẳng\\s+([a-z][0-9]?)(?!\\p{L})[^.]{0,20}?(?:lấy\\s+)?(?:một\\s+)?(?:điểm\\s+)?([A-Z](?:['′])?)(?![A-Z])`,\n 'gu',\n);\n\nconst SEG = '([A-Z]{2})(?![A-Z])';\nconst POINT = \"([A-Z](?:['′])?)(?![A-Z])\";\n\n// \"Trên cạnh AC lấy điểm M\" / \"Trên đoạn thẳng OB lấy điểm H\" / \"trên đáy CD …\".\nconst ON_SEG_THEN_POINT = new RegExp(\n String.raw`[Tt]rên\\s+(?:cạnh|đáy|đoạn(?:\\s+thẳng)?|bán\\s*kính|đường\\s*kính|dây\\s*(?:cung)?)\\s+${SEG}[^.]{0,30}?(?:lấy\\s+)?(?:một\\s+)?(?:điểm\\s+)?${POINT}`,\n 'gu',\n);\n\n// \"Trên (cạnh|đáy)? AC lấy (các)? điểm D, E (, F)\" — NHIỀU điểm CÙNG đoạn AC\n// (toán 8: \"Trên cạnh AC lấy các điểm D,E sao cho AD=DE=EC\"). group1=seg,\n// group2=blob tên. Chạy TRƯỚC metric-skip (đặt điểm free dù có \"sao cho =\").\nconst ON_SEG_MULTI_POINT = new RegExp(\n String.raw`[Tt]rên\\s+(?:cạnh\\s+|đáy\\s+|đoạn(?:\\s+thẳng)?\\s+)?${SEG}\\s+(?:lấy\\s+)?(?:các\\s+)?(?:điểm\\s+)?((?:[A-Z](?:['′])?\\s*,\\s*)+[A-Z](?:['′])?)(?![A-Z])`,\n 'gu',\n);\n\n// \"điểm E thuộc cạnh BC\" / \"C thuộc đoạn thẳng AB\" / \"Điểm D thuộc AC\" (không\n// chữ \"cạnh\"). Prefix \"cạnh|đoạn|…\" optional; SEG = cặp HOA [A-Z]{2} nên \"thuộc\n// (O)\"/\"thuộc cung BC\" KHÔNG khớp (paren/'cung' chữ thường) → onCirclePoint lo.\nconst POINT_THUOC_SEG = new RegExp(\n String.raw`(?:điểm\\s+)?${POINT}\\s+(?:là\\s+(?:một\\s+)?điểm\\s+(?:bất\\s*k[iìyỳ]\\s+)?)?thuộc\\s+(?:(?:cạnh|đoạn(?:\\s+thẳng)?|bán\\s*kính|dây\\s*(?:cung)?)\\s+)?${SEG}`,\n 'gu',\n);\n\n// \"điểm N thuộc tia AM\" — điểm trên TIA (2 đầu mút HOA). CHẠY TRƯỚC metric-skip\n// (đặt free dù \"sao cho AN=BM\" — metric chỉ tinh chỉnh; httcd:128). Tách khỏi\n// POINT_THUOC_SEG vì cần né \"tia đối của tia AB\" (oppositeRayPoint lo): SEG sau\n// \"tia \" phải là cặp HOA NGAY (≠ \"đối\").\nconst POINT_THUOC_TIA = new RegExp(\n String.raw`(?:điểm\\s+)?${POINT}\\s+(?:là\\s+(?:một\\s+)?điểm\\s+(?:bất\\s*k[iìyỳ]\\s+)?)?thuộc\\s+tia\\s+${SEG}`,\n 'gu',\n);\n\n// \"M là (một)? điểm (bất kì)? trên (cạnh|đoạn|đáy)? AD\" — tên ĐỨNG TRƯỚC + \"là\n// điểm trên\" (KHÔNG \"thuộc\", KHÔNG động từ chuyển động — son123:9). CHẠY TRƯỚC\n// metric-skip (\"sao cho ∠=30°\"). SEG=[A-Z]{2} + prefix loại \"tia/cung/đường tròn\"\n// (onCirclePoint/oppositeRay lo).\nconst POINT_ON_SEG_DECL = new RegExp(\n String.raw`${POINT}\\s+là\\s+(?:một\\s+)?điểm\\s+(?:bất\\s*k[iìyỳ]\\s+)?trên\\s+(?:cạnh\\s+|đáy\\s+|đoạn(?:\\s+thẳng)?\\s+)?${SEG}`,\n 'gu',\n);\n\n// \"Điểm P di chuyển trên cạnh AC\" / \"P di động trên đoạn BC\" / \"Lấy P trên cạnh\n// AC\" — điểm ĐỨNG TRƯỚC + động từ chuyển động (di chuyển/thay đổi/di động/nằm)\n// optional + \"trên (cạnh) SEG\". Điểm 1-DOF (di động) vẫn dựng 1 vị trí đại diện.\n// KHÔNG nhận \"trên cung\" (onCircle lo) — chỉ cạnh/đoạn/đường thẳng/bán kính.\nconst POINT_MOVE_SEG = new RegExp(\n String.raw`(?:điểm\\s+)?${POINT}\\s+(?:là\\s+(?:một\\s+)?điểm\\s+)?(?:di\\s*chuyển|thay\\s*đổi|di\\s*động|chuyển\\s*động|nằm)\\s+trên\\s+(?:cạnh\\s+|đoạn(?:\\s+thẳng)?\\s+|đường\\s*thẳng\\s+|bán\\s*kính\\s+|đường\\s*kính\\s+)?${SEG}`,\n 'gu',\n);\n\n// \"D nằm giữa A và B\" / \"một điểm D nằm giữa A và B\" / \"M là (một)? điểm nằm\n// giữa A và B\" (tên đứng TRƯỚC \"là điểm\" — httcd:67, vao10:219).\nconst BETWEEN = new RegExp(\n String.raw`(?:một\\s+)?(?:điểm\\s+)?${POINT}\\s+(?:là\\s+(?:một\\s+)?điểm\\s+)?nằm\\s+giữa\\s+(?:hai\\s+điểm\\s+)?([A-Z])\\s+và\\s+([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// Distributive CÙNG đoạn: \"(Các)? điểm M, N thuộc BC\" → M,N đều onSegment BC.\nconst TWO_SAME_SEG = new RegExp(\n String.raw`(?:[CcNn]ác\\s+|[Nn]hững\\s+)?điểm\\s+([A-Z])\\s*,\\s*([A-Z])(?![A-Z])\\s+thuộc\\s+(?:cạnh\\s+|đoạn(?:\\s+thẳng)?\\s+)?${SEG}`,\n 'gu',\n);\n// Distributive ZIP: \"(các)? điểm P, Q (theo thứ tự|lần lượt)? thuộc AC, AB\"\n// → P↔AC, Q↔AB. (Cần \"theo thứ tự\"/\"lần lượt\" để chắc là zip, không phải cùng đoạn.)\nconst ZIP_SEG = new RegExp(\n String.raw`(?:[CcNn]ác\\s+|[Nn]hững\\s+)?điểm\\s+([A-Z])\\s*,\\s*([A-Z])(?![A-Z])\\s+(?:theo\\s+thứ\\s+tự|lần\\s*lượt)\\s+thuộc\\s+(?:các\\s+)?(?:cạnh\\s+|đoạn\\s+|tia\\s+)?${SEG}\\s*,\\s*${SEG}`,\n 'gu',\n);\n// Distributive ĐOẠN-TRƯỚC: \"trên BC, CA, AB (thứ tự|lần lượt)? lấy (các)? điểm\n// M, N, E\" → zip SEG_i ↔ point_i (N≥2). Đề hay nêu cạnh TRƯỚC rồi tên điểm SAU.\n// CHẠY kể cả khi clause có \"sao cho …=…\" (metric chỉ TINH CHỈNH vị trí; đặt điểm\n// free trên cạnh là đủ cho hình). group1 = blob đoạn, group2 = blob tên điểm.\nconst SEGS_THEN_POINTS = new RegExp(\n String.raw`[Tt]rên\\s+(?:các\\s+)?(?:cạnh\\s+|đoạn(?:\\s+thẳng)?\\s+|đáy\\s+|bán\\s*kính\\s+)?((?:[A-Z]{2}\\s*,\\s*)+[A-Z]{2})(?![A-Z])(?:\\s+của\\s+(?:tam\\s*giác\\s+|tứ\\s*giác\\s+)?[A-Z]{2,4})?\\s+(?:(?:theo\\s+)?thứ\\s+tự\\s+|lần\\s*lượt\\s+)?lấy\\s+(?:các\\s+)?điểm\\s+((?:[A-Z]\\s*,\\s*)+[A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// \"Trên đoạn BH lấy điểm M và trên đoạn CH lấy điểm N\" — 2 điểm trên 2 đoạn KHÁC\n// nối \"và\". Distributive coordinated → CHẠY TRƯỚC metric-skip (đặt free dù \"sao\n// cho ∠=90°\"). Chỉ cạnh/đáy/đoạn (KHÔNG tia → tránh đụng pointAtDistance). KHÔNG\n// khớp đơn lẻ \"Trên cạnh AB lấy điểm D sao cho AD=2DB\" (cần vế \"và … lấy\" thứ 2).\nconst TWO_SEG_LAY = new RegExp(\n String.raw`[Tt]rên\\s+(?:cạnh|đáy|đoạn(?:\\s+thẳng)?)\\s+${SEG}\\s+(?:lấy\\s+)?(?:một\\s+)?(?:điểm\\s+)?${POINT}\\s+và\\s+(?:trên\\s+)?(?:cạnh|đáy|đoạn(?:\\s+thẳng)?)\\s+${SEG}\\s+(?:lấy\\s+)?(?:một\\s+)?(?:điểm\\s+)?${POINT}`,\n 'gu',\n);\n\nfunction normalizePoint(name: string): string {\n return name.replace('′', \"'\");\n}\n\nfunction validOnSegment(name: string, segment: string): boolean {\n return /^[A-Z]['′]?$/u.test(name) && /^[A-Z]{2}$/u.test(segment) && !segment.includes(name[0]);\n}\n\nfunction hasMetricConstraint(text: string): boolean {\n return /sao\\s+cho[^.]{0,40}(?:=|>|<)/u.test(text);\n}\n\nexport const onSegmentPointRule: LanguageRule = {\n id: 'on-segment-point',\n priority: 62,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents = [];\n\n // Distributive đoạn-trước CHẠY TRƯỚC metric-skip (vẽ điểm free trên cạnh dù\n // có \"sao cho …=…\"). \"trên BC, CA, AB … lấy điểm M, N, E\" → zip 1-1.\n SEGS_THEN_POINTS.lastIndex = 0;\n for (const m of c.text.matchAll(SEGS_THEN_POINTS)) {\n const segs = m[1].split(',').map((s) => s.trim());\n const pts = m[2].split(',').map((s) => normalizePoint(s.trim()));\n if (segs.length === pts.length && segs.length >= 2) {\n const seenD = new Set<string>();\n for (let i = 0; i < segs.length; i++) {\n if (seenD.has(pts[i])) continue;\n if (validOnSegment(pts[i], segs[i])) {\n seenD.add(pts[i]);\n intents.push(addPoint(pts[i], { kind: 'onSegment', of: segs[i] }));\n }\n }\n }\n }\n\n // Coordinated \"Trên đoạn BH lấy điểm M và trên đoạn CH lấy điểm N\" → M∈BH,\n // N∈CH. Pre-metric (đặt free dù \"sao cho ∠=90°\"). group 1/3 = đoạn, 2/4 = tên.\n TWO_SEG_LAY.lastIndex = 0;\n for (const m of c.text.matchAll(TWO_SEG_LAY)) {\n for (const [pt, seg] of [[m[2], m[1]], [m[4], m[3]]] as Array<[string, string]>) {\n const n = normalizePoint(pt);\n if (validOnSegment(n, seg)) intents.push(addPoint(n, { kind: 'onSegment', of: seg }));\n }\n }\n\n // \"Trên cạnh AC lấy các điểm D, E (, F)\" — nhiều điểm CÙNG đoạn, TRƯỚC\n // metric-skip (toán8: \"lấy các điểm D,E sao cho AD=DE=EC\").\n ON_SEG_MULTI_POINT.lastIndex = 0;\n for (const m of c.text.matchAll(ON_SEG_MULTI_POINT)) {\n const seg = m[1];\n const names = m[2].split(',').map((x) => normalizePoint(x.trim())).filter(Boolean);\n if (names.length < 2) continue;\n for (const n of names) if (validOnSegment(n, seg)) intents.push(addPoint(n, { kind: 'onSegment', of: seg }));\n }\n\n // ZIP distributive \"P, Q lần lượt thuộc (tia|cạnh) AC, AB\" CHẠY TRƯỚC\n // metric-skip (đặt điểm free trên cạnh/tia dù có \"sao cho …=…\" — Bài 47).\n const zipConsumed: Array<[number, number]> = [];\n ZIP_SEG.lastIndex = 0;\n for (const m of c.text.matchAll(ZIP_SEG)) {\n const [n1, n2, s1, s2] = [normalizePoint(m[1]), normalizePoint(m[2]), m[3], m[4]];\n if (validOnSegment(n1, s1) && validOnSegment(n2, s2)) {\n intents.push(addPoint(n1, { kind: 'onSegment', of: s1 }));\n intents.push(addPoint(n2, { kind: 'onSegment', of: s2 }));\n zipConsumed.push([m.index ?? 0, (m.index ?? 0) + m[0].length]);\n }\n }\n\n // \"điểm N thuộc tia AM\" → onSegment AM, CHẠY TRƯỚC metric-skip (httcd:128\n // \"… sao cho AN=BM\" — đặt N free; metric chỉ tinh chỉnh).\n POINT_THUOC_TIA.lastIndex = 0;\n for (const m of c.text.matchAll(POINT_THUOC_TIA)) {\n const name = normalizePoint(m[1]);\n const segment = m[2];\n if (validOnSegment(name, segment)) {\n intents.push(addPoint(name, { kind: 'onSegment', of: segment }));\n }\n }\n\n // \"M là (một)? điểm trên cạnh AD\" — pre-metric (son123:9 \"sao cho ∠=30°\").\n POINT_ON_SEG_DECL.lastIndex = 0;\n for (const m of c.text.matchAll(POINT_ON_SEG_DECL)) {\n const name = normalizePoint(m[1]);\n const segment = m[2];\n if (validOnSegment(name, segment)) {\n intents.push(addPoint(name, { kind: 'onSegment', of: segment }));\n }\n }\n\n // Còn lại CỐ Ý bỏ qua clause có ràng buộc metric (vd \"sao cho AD=2DB\") để\n // không đoán sai vị trí — distributive ở trên đã dựng điểm free đủ cho hình.\n if (hasMetricConstraint(c.text)) {\n if (intents.length > 0) out.push({ ruleId: 'on-segment-point', clauseIds: [c.id], intents });\n continue;\n }\n\n // Điểm trên đường ĐẶT TÊN chữ thường (\"Trên đường thẳng d lấy điểm M\").\n ON_NAMED_LINE.lastIndex = 0;\n for (const m of c.text.matchAll(ON_NAMED_LINE)) {\n const line = m[1];\n const name = normalizePoint(m[2]);\n if (/^[A-Z]['′]?$/u.test(name)) intents.push(addPoint(name, { kind: 'onSegment', of: line }));\n }\n\n ON_SEG_THEN_POINT.lastIndex = 0;\n for (const m of c.text.matchAll(ON_SEG_THEN_POINT)) {\n const segment = m[1];\n const name = normalizePoint(m[2]);\n if (validOnSegment(name, segment)) {\n intents.push(addPoint(name, { kind: 'onSegment', of: segment }));\n }\n }\n\n // (ZIP đã chạy trước metric-skip ở trên — zipConsumed dùng cho TWO_SAME_SEG.)\n // \"Các điểm M, N thuộc BC\" — cùng đoạn (bỏ span đã khớp ZIP).\n TWO_SAME_SEG.lastIndex = 0;\n for (const m of c.text.matchAll(TWO_SAME_SEG)) {\n if (zipConsumed.some(([a, b]) => (m.index ?? 0) >= a && (m.index ?? 0) < b)) continue;\n const [n1, n2, seg] = [normalizePoint(m[1]), normalizePoint(m[2]), m[3]];\n if (validOnSegment(n1, seg) && validOnSegment(n2, seg)) {\n intents.push(addPoint(n1, { kind: 'onSegment', of: seg }));\n intents.push(addPoint(n2, { kind: 'onSegment', of: seg }));\n }\n }\n\n POINT_THUOC_SEG.lastIndex = 0;\n for (const m of c.text.matchAll(POINT_THUOC_SEG)) {\n const name = normalizePoint(m[1]);\n const segment = m[2];\n if (validOnSegment(name, segment)) {\n intents.push(addPoint(name, { kind: 'onSegment', of: segment }));\n }\n }\n\n // \"Điểm P di chuyển/di động/nằm trên cạnh AC\" — điểm trước + động từ.\n POINT_MOVE_SEG.lastIndex = 0;\n for (const m of c.text.matchAll(POINT_MOVE_SEG)) {\n const name = normalizePoint(m[1]);\n const segment = m[2];\n if (validOnSegment(name, segment)) {\n intents.push(addPoint(name, { kind: 'onSegment', of: segment }));\n }\n }\n\n // \"cắt … (tại|ở) D và E (D nằm giữa A và E)\": D,E là GIAO ĐIỂM cát tuyến\n // (secant/lineCircleIntersection dựng), \"nằm giữa\" chỉ là thứ tự → onSegment\n // sẽ tạo phụ thuộc vòng (D onSegment AE, E = secondIntersection AD). Bỏ\n // toàn bộ BETWEEN trong clause có \"cắt … tại/ở\".\n const cutContext = /cắt[^.]{0,40}?(?:tại|ở)\\s+[A-Z]/u.test(c.text);\n BETWEEN.lastIndex = 0;\n for (const m of cutContext ? [] : c.text.matchAll(BETWEEN)) {\n // \"sao cho X nằm giữa Y và Z\" = ĐIỀU KIỆN thứ tự trên điểm Đà có (vd đỉnh\n // hình, hoặc giao điểm vừa dựng) — KHÔNG dựng onSegment (sẽ tạo phụ thuộc\n // vòng nếu Y/Z lại phái sinh từ X). Chỉ nhận \"nằm giữa\" khi GIỚI THIỆU điểm mới.\n const before = c.text.slice(0, m.index ?? 0);\n if (/sao\\s+cho\\s*$/u.test(before) || /sao\\s+cho\\b/u.test(before)) continue;\n const name = normalizePoint(m[1]);\n const segment = `${m[2]}${m[3]}`;\n if (validOnSegment(name, segment)) {\n intents.push(addPoint(name, { kind: 'onSegment', of: segment }));\n }\n }\n\n if (intents.length > 0) out.push({ ruleId: 'on-segment-point', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/lineCircleIntersection.ts\n//\n// Giao đường thẳng/đoạn với đường tròn:\n// \"CM cắt (O) tại N\" → N = secondIntersection(CM, O), other=C\n// \"AD, BE, CF cắt đường tròn (O) lần lượt tại M, N, P\"\n// → M/N/P là giao thứ hai, loại A/B/C tương ứng.\n//\n// `other` lấy là chữ đầu của line token XY. Đây đúng cho các đề phổ biến\n// \"đường cao AD cắt lại ngoại tiếp tại M\", \"CM cắt (O) tại N\"; dạng cần loại\n// chữ thứ hai sẽ phải có rule riêng/fail-safe sau.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, CIRCLE_KW } from './_shared';\n\n// 3 nhánh: cắt-rồi-paren | giao điểm thứ hai | \"cắt AB và (O)\" (LINE_AND_CIRCLE\n// vao10:28 — paren đứng sau \"và\", nhánh 1 không khớp) | \"giao điểm thứ hai …\n// với đường tròn\" TRẦN không paren (vao10:254).\nconst PREFILTER = /cắt\\s+(?:lại\\s+)?(?:(?:nửa\\s+)?đường\\s*tròn\\s*)?\\(|cắt\\s+(?:lại\\s+)?(?:nửa\\s+)?đường\\s*tròn\\s+(?:ở|tại)|cắt\\s+[A-Z]{2}\\s+và\\s+\\(|giao\\s*điểm\\s+(?:thứ\\s+hai\\s+)?(?:của\\s+|khác\\s+[A-Z]\\s+của\\s+)?(?:đường\\s*thẳng\\s+)?[A-Z]{2}\\s+(?:và|với)\\s+(?:(?:nửa\\s+)?đường\\s*tròn|\\(|ngoại\\s*tiếp\\s+tam\\s*giác)/u;\n// \"(O)\" + compact \"(O;R)\"/\"(O,R)\" — vao10:127 \"Tia CI cắt đường tròn (O;R) tại E\".\n// \"nửa\" optional — vao10:18 \"giao điểm thứ hai của DC với NỬA đường tròn (O)\".\nconst CIRCLE = String.raw`(?:(?:nửa\\s+)?đường\\s*tròn\\s*)?\\(\\s*([A-Z])(?:['′]?)\\s*(?:[;,]\\s*[Rr]\\s*)?\\)`;\n// Circle GIỮ prime trong tên tâm (O'): cần cho \"(O')\" — đường tròn đường kính\n// đặt tên \"O'_c\" (circleDiameter). emit raw \"O'\" → resolveCircleNames map \"O'_c\".\nconst CIRCLE_P = String.raw`(?:(?:nửa\\s+)?đường\\s*tròn\\s*)?\\(\\s*([A-Z](?:['′])?)\\s*(?:[;,]\\s*[Rr]\\s*)?\\)`;\n\n// \"<XY> vuông góc <L> (tại I)? … cắt (nửa)? đường tròn (O') (ở|tại) F\" → đường\n// vuông góc XY cắt đường tròn (O') tại F (2 nhánh, lấy branch 0). XY có thể là\n// \"EI\" (E onCircle + I chân vuông góc) — cả 2 điểm dựng trước, line ref hợp lệ.\nconst PERP_CUTS_CIRCLE = new RegExp(\n String.raw`([A-Z])([A-Z])(?![A-Z])\\s+(?:vuông\\s*góc|⊥)\\s+(?:với\\s+)?[A-Z]{2}(?![A-Z])(?:\\s+tại\\s+[A-Z])?` +\n String.raw`[^.]{0,30}?cắt\\s+` + CIRCLE_P + String.raw`\\s+(?:ở|tại)\\s+(?:điểm\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n\nconst TRIPLE_DISTRIB = new RegExp(\n String.raw`([A-Z]{2})\\s*,\\s*([A-Z]{2})\\s*,\\s*([A-Z]{2})(?![A-Z])[^.]{0,80}?cắt\\s+` +\n CIRCLE +\n String.raw`[^.]{0,40}?lần\\s*lượt\\s+(?:ở|tại)\\s+([A-Z])\\s*,\\s*([A-Z])\\s*,\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// 2 đường ∩ đường tròn, phân phối: \"BE,CF … cắt (O) lần lượt tại M và N\" (vao10:77\n// \"Các đường cao BE,CF cắt nhau tại H, cắt đường tròn (O;R) lần lượt tại M và N\" —\n// \"cắt nhau tại H,\" xen giữa; lazy-region + CIRCLE-paren tự bỏ qua \"cắt nhau\").\n// Guard CHỈ 2 đường + CHỈ 2 điểm (lookahead phủ định ngăn nuốt dạng 3 của TRIPLE).\nconst DOUBLE_DISTRIB = new RegExp(\n String.raw`([A-Z]{2})\\s*(?:,|và)\\s*([A-Z]{2})(?![A-Z])(?!\\s*(?:,|và)\\s*[A-Z]{2})[^.]{0,80}?cắt\\s+` +\n CIRCLE +\n String.raw`[^.]{0,40}?lần\\s*lượt\\s+(?:ở|tại)\\s+([A-Z])\\s*(?:,|và)\\s*([A-Z])(?![A-Z])(?!\\s*(?:,|và)\\s*[A-Z])`,\n 'gu',\n);\n\n// \"XY cắt (O) (ở|tại) (điểm (thứ hai)?)? Z (khác W)?\" — \"điểm thứ hai\" + \"khác W\"\n// optional. `khác W` (nếu có) là điểm chung cần loại (other); else mặc định\n// chữ đầu của line (đầu mút nằm trên đường tròn).\nconst SINGLE = new RegExp(\n String.raw`([A-Z]{2})(?![A-Z])\\s+cắt\\s+(?:lại\\s+)?` + CIRCLE +\n String.raw`\\s+(?:ở|tại)\\s+(?:điểm\\s+(?:thứ\\s+hai\\s+)?)?(?:là\\s+)?([A-Z])(?![A-Z])(?:\\s+khác\\s+([A-Z])(?![A-Z]))?`,\n 'gu',\n);\n\n// \"XY cắt (O) tại HAI điểm M, N\" — CẢ HAI giao của đường với đường tròn (branch\n// 0/1). Khác SINGLE (1 giao thứ hai khi biết điểm chung): ở đây 2 đầu mút đều\n// chưa nằm trên (O) nên dùng intersection lineCircle 2 nhánh.\nconst BOTH = new RegExp(\n String.raw`([A-Z]{2})(?![A-Z])\\s+cắt\\s+` + CIRCLE +\n String.raw`\\s+(?:ở|tại)\\s+(?:hai\\s+|các\\s+)?điểm\\s+(?:phân\\s*biệt\\s+)?([A-Z])\\s*(?:,|và)\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// \"XY cắt AB và (O) lần lượt tại H và I\" (vao10:28 \"OM cắt AB và (O) lần lượt\n// tại H và I\") — 1 đường cắt 1 ĐƯỜNG + 1 ĐƯỜNG TRÒN phân phối: H=XY∩AB\n// (intersection thường), I=XY∩(O) (intersection lineCircle branch 0 — cả 2 đầu\n// mút XY đều không trên đường tròn nên không dùng secondIntersection).\n// groups: 1=line 2=line2 3=circle 4=name1 5=name2.\nconst LINE_AND_CIRCLE = new RegExp(\n String.raw`([A-Z]{2})(?![A-Z])\\s+cắt\\s+([A-Z]{2})(?![A-Z])\\s+và\\s+` + CIRCLE +\n String.raw`\\s+(?:lần\\s*lượt\\s+|theo\\s+thứ\\s+tự\\s+)?(?:tại|ở)\\s+([A-Z])\\s*(?:,|và)\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// \"XY (kéo dài)? cắt (lại)? (nửa)? đường tròn (ở|tại) (điểm (thứ hai)?)? Z\" —\n// đường tròn TRẦN (không paren, httcd:42 \"BN cắt đường tròn ở C\"). 1 đầu mút XY\n// trên đường tròn (đầu line) → Z = giao thứ hai. circle resolve toàn đề.\nconst SINGLE_BARE = new RegExp(\n String.raw`([A-Z]{2})(?![A-Z])\\s+(?:kéo\\s+dài\\s+)?cắt\\s+(?:lại\\s+)?(?:nửa\\s+)?đường\\s*tròn(?!\\s*\\()\\s+(?:ở|tại)\\s+(?:điểm\\s+(?:thứ\\s+hai\\s+)?)?(?:là\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// \"(đường thẳng)? AO cắt (O), (O′) lần lượt (ở|tại) C và D\" (vao10:174,\n// son123:107) — 1 đường cắt HAI đường tròn (giao của 2 circle tự do). A (đầu line)\n// nằm trên CẢ 2 đường tròn (là 1 giao điểm) → C,D đều là secondIntersection, mỗi\n// điểm với circle tương ứng, other = đầu line. Line giữ prime (\"AO′\").\n// groups: 1=line(prime optional) 2=circle1 3=circle2 4=name1 5=name2.\nconst LINE_TWO_CIRCLES = new RegExp(\n String.raw`(?:đường\\s*thẳng\\s+)?([A-Z][A-Z](?:['′])?)(?![A-Z])\\s+cắt\\s+` +\n CIRCLE_P + String.raw`\\s*(?:,|và)\\s*` + CIRCLE_P +\n String.raw`\\s+(?:lần\\s*lượt\\s+|theo\\s+thứ\\s+tự\\s+)?(?:ở|tại)\\s+([A-Z])(?![A-Z])\\s*(?:,|và)\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// Đường tròn LÀM CHỦ NGỮ: \"(O) cắt XY (ở|tại) Z\" (vao10:157 \"(O) cắt AC tại E\").\n// Đảo của SINGLE (line chủ ngữ). 1 đầu mút XY nằm trên (O) → Z = giao thứ hai,\n// other = đầu line (mặc định line[0]). groups: 1=circle 2=line 3=name.\nconst CIRCLE_SUBJECT = new RegExp(\n CIRCLE + String.raw`\\s+cắt\\s+(?:lại\\s+)?([A-Z]{2})(?![A-Z])\\s+(?:ở|tại)\\s+(?:điểm\\s+(?:thứ\\s+hai\\s+)?)?(?:là\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// \"giao điểm của XY và (O) là R (khác W)?\" — dạng \"Gọi giao điểm của NQ và (O)\n// là R khác N\". Ref đầu = line (cặp đỉnh), ref sau = circle \"(O)\".\nconst GIAO_CIRCLE = new RegExp(\n String.raw`giao\\s*điểm\\s+(?:thứ\\s+hai\\s+)?(?:của\\s+)?([A-Z]{2})(?![A-Z])\\s+(?:và|với)\\s+` + CIRCLE +\n String.raw`\\s+là\\s+([A-Z])(?![A-Z])(?:\\s+khác\\s+([A-Z])(?![A-Z]))?`,\n 'gu',\n);\n\n// \"X là giao điểm thứ hai của XY (và|với) (O)\" — tên TRƯỚC, \"thứ hai\", KHÔNG\n// \"khác\" (Bài 114: \"I là giao điểm thứ hai của KA với (O)\"). other = đầu mút\n// line nằm trên đường tròn: ưu tiên chữ THỨ HAI (đỉnh tam giác/điểm-trên-(O)\n// thường đứng sau, vd KA→A, AH→H?) — mặc định line[1] cho dạng này.\nconst NAME_2ND_CUA = new RegExp(\n String.raw`([A-Z])(?![A-Z])\\s+là\\s+giao\\s*điểm\\s+thứ\\s+hai\\s+của\\s+([A-Z]{2})(?![A-Z])\\s+(?:và|với)\\s+` + CIRCLE,\n 'gu',\n);\n\n// \"I là giao điểm thứ hai của (đường thẳng)? CE với đường tròn\" — đường tròn\n// TRẦN không paren (vao10:254); circle resolve từ toàn đề. other = line[0]\n// (dạng này đầu mút TRÊN đường tròn thường đứng trước: \"CE\" với C tiếp điểm).\nconst NAME_2ND_BARE = new RegExp(\n String.raw`([A-Z])(?![A-Z])\\s+là\\s+giao\\s*điểm\\s+thứ\\s+hai\\s+của\\s+(?:đường\\s*thẳng\\s+)?([A-Z]{2})(?![A-Z])\\s+(?:và|với)\\s+(?:nửa\\s+)?đường\\s*tròn(?!\\s*\\()`,\n 'gu',\n);\n// Resolve circle toàn đề cho NAME_2ND_BARE: \"(O)\"/\"(O;R)\" hoặc \"đường tròn (tâm)? O\".\nconst RESOLVE_CIRCLE_BARE =\n /\\(\\s*([A-Z])(?:['′]?)\\s*(?:[;,]\\s*[Rr]\\s*)?\\)|đường\\s*tròn\\s+(?:tâm\\s+)?([A-Z])(?![A-Za-z])/u;\n\n// Distributive \"E,F lần lượt là giao điểm thứ hai của AM,AN với (O)\" → E=2nd(AM,O),\n// F=2nd(AN,O). 2 line cùng circle. groups: 1=n1 2=n2 3=line1 4=line2 5=circle.\nconst DISTRIB_2ND = new RegExp(\n String.raw`([A-Z])\\s*,\\s*([A-Z])(?![A-Z])\\s+(?:lần\\s*lượt\\s+|theo\\s+thứ\\s+tự\\s+)?là\\s+giao\\s*điểm\\s+thứ\\s+hai\\s+của\\s+([A-Z]{2})\\s*,\\s*([A-Z]{2})(?![A-Z])\\s+(?:và|với)\\s+` + CIRCLE,\n 'gu',\n);\n\n// Tên ĐỨNG TRƯỚC + \"khác\" TRƯỚC \"của\": \"K là giao điểm (thứ hai)? khác A của AY\n// và (O)\" (VD8). g1=name, g2=other(khác), g3=line, g4|g5=circle.\nconst NAME_KHAC_CUA = new RegExp(\n String.raw`([A-Z])(?![A-Z])\\s+là\\s+giao\\s*điểm\\s+(?:thứ\\s+hai\\s+)?khác\\s+([A-Z])(?![A-Z])\\s+của\\s+([A-Z]{2})(?![A-Z])\\s+(?:và|với)\\s+` + CIRCLE,\n 'gu',\n);\n\n// Đường tròn MÔ TẢ (KHÔNG \"(O)\"): \"giao điểm thứ hai của <LINE> (và|với) (nửa)?\n// đường tròn ngoại tiếp tam giác XYZ là (điểm)? P (khác Q)?\" (hinh9 #66).\n// circleTriangle dựng circumcircle này KHÔNG khai báo tâm → tên mặc định \"O\"\n// (intentFor: center || 'O'). Vì cụm \"đường tròn ngoại tiếp tam giác XYZ\" ở đây\n// KHÔNG có token tâm \"(X)\"/\"tâm X\" chen giữa → resolve circle ref = \"O\".\n// Tên P đứng SAU, \"khác Q\" optional (Q = điểm chung cần loại; else default line[0]).\nconst NAME_2ND_CIRCUM = new RegExp(\n String.raw`giao\\s*điểm\\s+thứ\\s+hai\\s+của\\s+([A-Z]{2})(?![A-Z])\\s+(?:và|với)\\s+` +\n String.raw`(?:nửa\\s+)?` + CIRCLE_KW +\n String.raw`\\s+ngoại\\s*tiếp\\s+tam\\s*giác\\s+[A-Z]{3}(?![A-Z])` +\n String.raw`\\s+là\\s+(?:điểm\\s+)?([A-Z])(?![A-Z])(?:\\s+khác\\s+([A-Z])(?![A-Z]))?`,\n 'gu',\n);\n\nfunction secondIntersection(name: string, line: string, circle: string, other?: string) {\n return addPoint(name, { kind: 'secondIntersection', line, circle, other: other ?? line[0] });\n}\n\nfunction valid(name: string, line: string): boolean {\n return /^[A-Z]$/u.test(name) && /^[A-Z]{2}$/u.test(line) && !line.includes(name);\n}\n\nexport const lineCircleIntersectionRule: LanguageRule = {\n id: 'line-circle-intersection',\n priority: 47,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents = [];\n\n TRIPLE_DISTRIB.lastIndex = 0;\n for (const m of c.text.matchAll(TRIPLE_DISTRIB)) {\n const circle = m[4];\n const pairs: Array<[string, string]> = [[m[1], m[5]], [m[2], m[6]], [m[3], m[7]]];\n if (pairs.every(([line, name]) => valid(name, line))) {\n intents.push(...pairs.map(([line, name]) => secondIntersection(name, line, circle)));\n }\n }\n\n DOUBLE_DISTRIB.lastIndex = 0;\n for (const m of c.text.matchAll(DOUBLE_DISTRIB)) {\n const circle = m[3];\n const pairs: Array<[string, string]> = [[m[1], m[4]], [m[2], m[5]]];\n if (pairs.every(([line, name]) => valid(name, line))) {\n intents.push(...pairs.map(([line, name]) => secondIntersection(name, line, circle)));\n }\n }\n\n SINGLE.lastIndex = 0;\n for (const m of c.text.matchAll(SINGLE)) {\n const line = m[1];\n const circle = m[2];\n const name = m[3];\n const other = m[4]; // \"khác W\" (optional) → điểm chung cần loại\n if (valid(name, line)) intents.push(secondIntersection(name, line, circle, other));\n }\n\n LINE_AND_CIRCLE.lastIndex = 0;\n for (const m of c.text.matchAll(LINE_AND_CIRCLE)) {\n const [line, line2, circle, n1, n2] = [m[1], m[2], m[3], m[4], m[5]];\n if (n1 === n2 || line.includes(n1) || line2.includes(n1) || line.includes(n2)) continue;\n intents.push(\n addPoint(n1, { kind: 'intersection', of: [line, line2] }),\n addPoint(n2, { kind: 'intersection', of: [line, circle], branch: 0 }),\n );\n }\n\n BOTH.lastIndex = 0;\n for (const m of c.text.matchAll(BOTH)) {\n const line = m[1];\n const circle = m[2];\n const [x, y] = [m[3], m[4]];\n if (x === y || line.includes(x) || line.includes(y)) continue;\n intents.push(\n addPoint(x, { kind: 'intersection', of: [line, circle], branch: 0 }),\n addPoint(y, { kind: 'intersection', of: [line, circle], branch: 1 }),\n );\n }\n\n // \"I là giao điểm thứ hai của CE với đường tròn\" TRẦN — circle toàn đề.\n NAME_2ND_BARE.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_2ND_BARE)) {\n const rc = RESOLVE_CIRCLE_BARE.exec(ctx.problem);\n const circle = rc?.[1] ?? rc?.[2];\n if (!circle || !valid(m[1], m[2])) continue;\n intents.push(secondIntersection(m[1], m[2], circle, m[2][0]));\n }\n\n // \"X là giao điểm thứ hai của XY (và|với) (O)\" — name trước, other=line[1].\n NAME_2ND_CUA.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_2ND_CUA)) {\n const [name, line, circle] = [m[1], m[2], m[3]];\n if (valid(name, line)) intents.push(secondIntersection(name, line, circle, line[1]));\n }\n\n // \"E,F lần lượt là giao điểm thứ hai của AM,AN với (O)\" — 2 line cùng circle.\n DISTRIB_2ND.lastIndex = 0;\n for (const m of c.text.matchAll(DISTRIB_2ND)) {\n const [n1, n2, l1, l2, circle] = [m[1], m[2], m[3], m[4], m[5]];\n if (valid(n1, l1)) intents.push(secondIntersection(n1, l1, circle));\n if (valid(n2, l2)) intents.push(secondIntersection(n2, l2, circle));\n }\n\n // \"AO cắt (O), (O′) lần lượt ở C và D\" — 1 đường, 2 đường tròn.\n LINE_TWO_CIRCLES.lastIndex = 0;\n for (const m of c.text.matchAll(LINE_TWO_CIRCLES)) {\n const line = m[1].replace(/′/g, \"'\");\n const [circle1, circle2, n1, n2] = [m[2].replace(/′/g, \"'\"), m[3].replace(/′/g, \"'\"), m[4], m[5]];\n const other = line[0]; // đầu line nằm trên cả 2 đường tròn (1 giao điểm)\n if (n1 === n2 || line.includes(n1) || line.includes(n2)) continue;\n if (circle1 === circle2) continue;\n intents.push(\n addPoint(n1, { kind: 'secondIntersection', line, circle: circle1, other }),\n addPoint(n2, { kind: 'secondIntersection', line, circle: circle2, other }),\n );\n }\n\n // \"XY cắt đường tròn TRẦN (ở|tại) Z\" — circle resolve toàn đề.\n SINGLE_BARE.lastIndex = 0;\n for (const m of c.text.matchAll(SINGLE_BARE)) {\n const rc = RESOLVE_CIRCLE_BARE.exec(ctx.problem);\n const circle = rc?.[1] ?? rc?.[2];\n const [line, name] = [m[1], m[2]];\n if (circle && valid(name, line)) intents.push(secondIntersection(name, line, circle, line[0]));\n }\n\n // \"(O) cắt XY tại Z\" — đường tròn chủ ngữ (đảo SINGLE).\n CIRCLE_SUBJECT.lastIndex = 0;\n for (const m of c.text.matchAll(CIRCLE_SUBJECT)) {\n const [circle, line, name] = [m[1], m[2], m[3]];\n if (valid(name, line)) intents.push(secondIntersection(name, line, circle));\n }\n\n GIAO_CIRCLE.lastIndex = 0;\n for (const m of c.text.matchAll(GIAO_CIRCLE)) {\n const line = m[1];\n const circle = m[2];\n const name = m[3];\n const other = m[4];\n if (valid(name, line)) intents.push(secondIntersection(name, line, circle, other));\n }\n\n // \"K là giao điểm khác A của AY và (O)\" — tên trước, \"khác\" trước \"của\".\n NAME_KHAC_CUA.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_KHAC_CUA)) {\n const name = m[1];\n const other = m[2];\n const line = m[3];\n const circle = m[4];\n if (valid(name, line)) intents.push(secondIntersection(name, line, circle, other));\n }\n\n // \"giao điểm thứ hai của AI và đường tròn ngoại tiếp tam giác ABC là điểm P\n // khác A\" — circle MÔ TẢ (không \"(O)\"), resolve = \"O\" (tên circleTriangle dùng\n // cho circumcircle không khai báo tâm). other = \"khác Q\" (nếu có), else line[0].\n NAME_2ND_CIRCUM.lastIndex = 0;\n for (const m of c.text.matchAll(NAME_2ND_CIRCUM)) {\n const line = m[1];\n const name = m[2];\n const other = m[3]; // \"khác Q\" optional\n if (valid(name, line)) intents.push(secondIntersection(name, line, 'O', other));\n }\n\n // \"EI ⊥ BC … cắt (nửa)? đường tròn (O') ở F\" → F = giao đường vuông góc với\n // đường tròn (2 nhánh, branch 0). circle raw (giữ prime) → resolveCircleNames map.\n PERP_CUTS_CIRCLE.lastIndex = 0;\n for (const m of c.text.matchAll(PERP_CUTS_CIRCLE)) {\n const line = m[1] + m[2];\n const circle = m[3];\n const name = m[4];\n if (line.includes(name)) continue;\n intents.push(addPoint(name, { kind: 'intersection', of: [line, circle], branch: 0 }));\n }\n\n if (intents.length > 0) out.push({ ruleId: 'line-circle-intersection', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/incenterNamedTriangle.ts\n//\n// Tâm đường tròn NỘI TIẾP (incenter) cho tam giác NÊU TƯỜNG MINH trong clause —\n// hai dạng mà rule `centers` punt:\n//\n// 1. PHÂN PHỐI (distributive):\n// \"I, K (tương ứng|lần lượt) là tâm (các) (đường tròn) nội tiếp\n// tam giác ABH và (tam giác) ACH\"\n// → I = incenter(A,B,H), K = incenter(A,C,H). Zip 1-1 hai tên với hai\n// tam giác theo thứ tự xuất hiện.\n//\n// 2. ĐƠN, tam giác tường minh TRONG clause:\n// \"I là tâm (các) (đường tròn) nội tiếp tam giác ABH\"\n// → I = incenter(A,B,H). Vì tam giác nêu ngay trong clause nên KHÔNG nhập\n// nhằng dù toàn đề có nhiều tam giác — đây là chỗ `centers` bỏ qua.\n//\n// Ràng buộc an toàn (escalate thay vì đoán):\n// - Tam giác phải là ĐÚNG 3 ký tự HOA, phân biệt, nêu trong clause.\n// - Dạng phân phối: số tên == số tam giác (zip 1-1) thì mới emit.\n// - Không bịa tên / không fallback tam giác toàn đề (để `centers` lo dạng đó).\n//\n// Intent trùng với `centers` (nếu có) đều bị dedup downstream theo JSON → vô hại.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\nimport { CIRCLE_KW } from './_shared';\n\n// \"nội tiếp\" — không khớp quanh ký tự Việt nên dùng lookaround \\p{L}.\nconst INSCRIBE_KW = /(?<!\\p{L})nội\\s*tiếp(?!\\p{L})/u;\n// \"ngoại tiếp\" — clause có cụm này là circumcenter, KHÔNG phải việc của rule này.\nconst CIRCUM_KW = /(?<!\\p{L})ngoại\\s*tiếp(?!\\p{L})/u;\n\n// Cụm từ khoá \"tâm (các)? (đường tròn)? nội tiếp\" — tới trước danh sách tam giác.\nconst CENTER_INSCRIBE =\n new RegExp(\n `tâm\\\\s+(?:các\\\\s+)?(?:${CIRCLE_KW}\\\\s+)?nội\\\\s*tiếp`,\n 'u',\n );\n\n// Một tam giác: \"tam giác ABH\" → ['A','B','H']. Quét toàn cục trong đoạn.\nconst TRI_G = /tam giác\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\nfunction trianglesIn(text: string): string[][] {\n const out: string[][] = [];\n TRI_G.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(text)) !== null) {\n out.push([m[1], m[2], m[3]]);\n }\n return out;\n}\n\n/** Tam giác hợp lệ = đúng 3 ký tự HOA phân biệt. */\nfunction validTri(tri: string[]): boolean {\n return tri.length === 3 && new Set(tri).size === 3;\n}\n\n// Danh sách tên điểm đứng TRƯỚC cụm \"(tương ứng|lần lượt)? là tâm ... nội tiếp\".\n// Dạng phân phối: \"I, K tương ứng là …\" → ['I','K']. Dạng đơn: \"I là …\" → ['I'].\nconst NAMES_BEFORE =\n /(?<!\\p{L})([A-Z](?:\\s*,\\s*[A-Z])*)\\s+(?:tương\\s+ứng\\s+|lần\\s+lượt\\s+)?là\\s+tâm(?!\\p{L})/u;\n\nfunction namesBefore(text: string): string[] | undefined {\n const m = NAMES_BEFORE.exec(text);\n if (!m) return undefined;\n const names = m[1]\n .split(',')\n .map((s) => s.trim())\n .filter((s) => /^[A-Z]$/u.test(s));\n return names.length > 0 ? names : undefined;\n}\n\n/**\n * Incenter cho tam giác tường minh trong clause (dạng phân phối + đơn). Mỗi\n * clause sinh tối đa min(số tên, số tam giác) intent (zip 1-1). Bỏ qua nếu\n * thiếu tên / thiếu tam giác / tam giác không hợp lệ.\n */\nexport const incenterNamedTriangleRule: LanguageRule = {\n id: 'incenterNamedTriangle',\n priority: 70,\n languages: ['vi'],\n patterns: [INSCRIBE_KW],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // Chỉ xử lý clause nói về \"tâm … nội tiếp\"; bỏ \"ngoại tiếp\" (circumcenter).\n if (CIRCUM_KW.test(c.text)) continue;\n if (!CENTER_INSCRIBE.test(c.text)) continue;\n\n const names = namesBefore(c.text);\n if (!names) continue;\n\n // Tam giác đứng SAU cụm từ khoá nội tiếp (vùng \"tam giác ABH và tam giác ACH\").\n const kw = CENTER_INSCRIBE.exec(c.text);\n const tail = kw ? c.text.slice(kw.index + kw[0].length) : c.text;\n const tris = trianglesIn(tail).filter(validTri);\n if (tris.length === 0) continue;\n\n // Zip 1-1 tên ↔ tam giác theo thứ tự. Số lượng phải khớp để không đoán mù:\n // - 1 tên + 1 tam giác (dạng đơn) → OK.\n // - n tên + n tam giác (phân phối) → OK.\n // Lệch số → bỏ qua (escalate).\n if (names.length !== tris.length) continue;\n\n const intents = names.map((name, idx) =>\n addPoint(name, { kind: 'incenter', of: tris[idx] }),\n );\n out.push({ ruleId: 'incenterNamedTriangle', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpThroughCutsLines.ts\n//\n// Đường thẳng QUA 1 điểm (song song / vuông góc với 1 đường) RỒI CẮT hai đường\n// khác tại hai điểm đặt tên:\n// \"Qua B kẻ đường thẳng vuông góc với DE, đường thẳng này cắt các đường thẳng\n// DE và DC theo thứ tự ở H và K\"\n// → draw-line prpB (perpThrough B→DE) [trùng parallelPerp → dedup]\n// H = giao(prpB, DE); K = giao(prpB, DC)\n//\n// parallelPerp chỉ dựng được đường thẳng, KHÔNG dựng giao điểm ⇒ \"ở H và K\" bị\n// bỏ → coverage/guard escalate. Rule này phủ TRỌN câu (đường + 2 giao) để render\n// được. Tên line theo CÙNG quy ước parallelPerp ('prp'/'par' + điểm qua) nên\n// intent draw-line trùng JSON và bị dedup, không tạo 2 đường.\n//\n// GOTCHA \\b: dùng (?!\\p{L}) + cờ 'u' quanh ký tự Việt.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\n// group1 = điểm qua; group2 = kind; group3+4 = đường tham chiếu;\n// group5+6, group7+8 = hai đường bị cắt; group9, group10 = hai giao điểm.\nconst RE = new RegExp(\n '(?:Qua|qua|Từ|từ)\\\\s+(?:điểm\\\\s+)?([A-Z])(?:[\\'′]?)(?!\\\\p{L})' +\n '[^.]{0,24}?(song\\\\s*song|vuông\\\\s*góc)\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?' +\n '([A-Z])([A-Z])(?!\\\\p{L})' +\n '[^.]{0,40}?cắt\\\\s+(?:các\\\\s+)?(?:đường\\\\s*thẳng\\\\s+)?([A-Z])([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])([A-Z])(?![A-Z])' +\n '[^.]{0,30}?(?:ở|tại)\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\nconst PREFILTER =\n /(?:Qua|qua|Từ|từ)\\s+(?:điểm\\s+)?[A-Z][^.]{0,24}?(?:song\\s*song|vuông\\s*góc)[^.]{0,80}?cắt/u;\n\n// SINGLE: \"(Một đường thẳng (đi)? )?(Qua|Từ) (điểm)? P ... (vuông góc|song song)\n// với L1 ... cắt L2 (ở|tại) Q\" — CHỈ 1 đường bị cắt, 1 giao điểm. Bài 30\n// (\"Kẻ đường thẳng qua D vuông góc OD, cắt AB ở K\"), Bài 33 (\"Một đường thẳng đi\n// qua điểm D, vuông góc với OD và cắt BC tại E\").\n// groups: 1=qua P, 2=kind, 3+4=L1, 5+6=L2, 7=giao Q.\n// group 5 = chân TÙY CHỌN trên đường ⊥ (\"tại E\" giữa L1 và \"cắt\"); group6+7=L2;\n// group8=giao. Chân chỉ khớp khi tên đứng RIÊNG (?![A-Za-z]) → KHÔNG bắt \"Evà\"\n// dính (giữ nguyên hành vi cũ với OCR-glue, tránh regress).\nconst RE_SINGLE = new RegExp(\n '(?:Qua|qua|Từ|từ)\\\\s+(?:điểm\\\\s+)?([A-Z])(?:[\\'′]?)(?!\\\\p{L})' +\n '[^.]{0,30}?(song\\\\s*song|vuông\\\\s*góc)\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+|đường\\\\s*thẳng\\\\s+)?' +\n '([A-Z])([A-Z])(?!\\\\p{L})' +\n '(?:\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Za-z]))?' +\n '[^.]{0,30}?cắt\\\\s+(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z])([A-Z])(?!\\\\p{L})\\\\s+(?:ở|tại)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])',\n 'gu',\n);\n\nexport const perpThroughCutsLinesRule: LanguageRule = {\n id: 'perpThroughCutsLines',\n priority: 50,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n let twoCut = false;\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n twoCut = true;\n const through = m[1];\n const isParallel = /song/.test(m[2]);\n const to = m[3] + m[4];\n const line1 = m[5] + m[6];\n const line2 = m[7] + m[8];\n const h = m[9];\n const k = m[10];\n if (isParallel && to.includes(through)) continue; // degenerate\n if (h === k) continue;\n const kind = isParallel ? 'parallelThrough' : 'perpThrough';\n const name = (isParallel ? 'par' : 'prp') + through;\n out.push({\n ruleId: 'perpThroughCutsLines',\n clauseIds: [c.id],\n intents: [\n drawLine(name, kind, { through, to }),\n addPoint(h, { kind: 'intersection', of: [name, line1] }),\n addPoint(k, { kind: 'intersection', of: [name, line2] }),\n ],\n });\n }\n\n // SINGLE-cut (chỉ khi clause KHÔNG khớp dạng 2-cut → tránh nhân đôi).\n if (twoCut) continue;\n RE_SINGLE.lastIndex = 0;\n for (const m of c.text.matchAll(RE_SINGLE)) {\n const through = m[1];\n const isParallel = /song/.test(m[2]);\n const to = m[3] + m[4];\n const foot = m[5]; // chân trên đường ⊥ (tùy chọn)\n const l2 = m[6] + m[7];\n const q = m[8];\n if (isParallel && to.includes(through)) continue;\n if (l2.includes(q) || through === q) continue;\n const kind = isParallel ? 'parallelThrough' : 'perpThrough';\n const name = (isParallel ? 'par' : 'prp') + through;\n const intents = [drawLine(name, kind, { through, to })];\n // Chân E = giao đường ⊥ với đường-tham-chiếu (to). Bỏ nếu trùng q/đầu mút.\n if (foot && foot !== q && !to.includes(foot) && foot !== through) {\n intents.push(addPoint(foot, { kind: 'intersection', of: [name, to] }));\n }\n intents.push(addPoint(q, { kind: 'intersection', of: [name, l2] }));\n out.push({ ruleId: 'perpThroughCutsLines', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentRay.ts\n//\n// Tiếp tuyến TẠI đầu mút đường kính, ĐẶT TÊN bằng token tia (Ax/Bx/By):\n// \"Kẻ tiếp tuyến Ax\" (Bài 7 — (O;R) đường kính AB)\n// \"Kẻ tiếp tuyến Bx\" (Bài 9 — nửa đường tròn đường kính AB)\n// \"Từ A và B kẻ hai tiếp tuyến Ax, By\"\n//\n// Tiếp tuyến tại đầu mút A của đường kính AB = tiếp tuyến của đường tròn TẠI A.\n// → draw-line kind tangentAt {through:<endpoint>, circle:'O'} đặt tên theo token\n// tia (Ax). Endpoint nằm TRÊN đường tròn nên tangentAt hợp lệ.\n//\n// Circle ref emit THÔ là chữ tâm \"O\" — resolveCircleNames map \"O\"→\"O_c\" (vì\n// circleDiameter đặt circle \"O_c\" + point \"O\"; base \"O\" không phải circle thật).\n//\n// GOTCHA \\b: regex chứa ký tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { drawLine } from './_shared';\n\n// Prefilter: phải có \"tiếp tuyến\" + 1 token tia (chữ HOA + x/y/z/t thường).\nconst PREFILTER = /tiếp\\s*tuyến\\s+[A-Z][xyzt](?![A-Za-z])/u;\n\n// Đường tròn đường kính: \"(O; R) đường kính AB\" / \"(O) đường kính AB\" / \"tâm O\n// đường kính AB\". Lấy tâm O + 2 đầu mút đường kính (A,B) để validate token tia\n// neo đúng đầu mút. circleDiameter dựng circle \"O_c\" + point O cho cả hai cách\n// viết tâm (ngoặc lẫn \"tâm O\"); resolveCircleNames map \"O\"→\"O_c\".\nconst CIRCLE_CENTER = /\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)|tâm\\s+([A-Z])(?![A-Za-z])/u;\nconst DIAMETER_ENDS = /đường\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])/u;\n\n// Token tia \"Ax\" = 1 chữ HOA (đầu mút) + 1 chữ thường x/y/z/t.\n// \"tiếp tuyến <list>\" — bắt CỤM ngay sau \"tiếp tuyến(s)\" rồi quét mọi token tia\n// trong cụm (xử lý cả dạng đơn \"tiếp tuyến Ax\" lẫn liệt kê \"tiếp tuyến Ax, By\").\nconst AFTER_TANGENT = /tiếp\\s*tuyến\\s+((?:[A-Z][xyzt](?![A-Za-z])\\s*[,và\\s]*)+)/gu;\nconst RAY_TOKEN = /([A-Z])([xyzt])(?![A-Za-z])/gu;\n\nexport const tangentRayRule: LanguageRule = {\n id: 'tangent-ray',\n // Cao hơn point-on-ray (55) + intersect-ray (48): token tia phải được dựng\n // TRƯỚC khi điểm-trên-tia / giao-với-tia tham chiếu nó (intentsToDsl xử lý\n // theo priority DESC, không topo-sort).\n priority: 63,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const cm = CIRCLE_CENTER.exec(ctx.problem);\n const dm = DIAMETER_ENDS.exec(ctx.problem);\n // Cần đường tròn ĐƯỜNG KÍNH (có tâm + 2 đầu mút) — chỉ những đầu mút này\n // mới hợp lệ làm điểm tiếp xúc của tiếp tuyến tại đầu mút.\n if (!dm) return [];\n // \"(O)\" → cm[1]; \"tâm O\" → cm[2]; KHÔNG tên tâm → đường tròn đường kính vô\n // danh \"kXY\" (diameterCircleSecant đặt tên vậy). Tiếp tuyến tại đầu mút A của\n // đường kính AB = tiếp tuyến tại A của đường tròn đó.\n const center = cm ? (cm[1] ?? cm[2]) : `k${dm[1]}${dm[2]}`;\n const ends = new Set([dm[1], dm[2]]);\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents: IntentT[] = [];\n const seen = new Set<string>();\n AFTER_TANGENT.lastIndex = 0;\n for (const grp of c.text.matchAll(AFTER_TANGENT)) {\n RAY_TOKEN.lastIndex = 0;\n for (const m of grp[1].matchAll(RAY_TOKEN)) {\n const endpoint = m[1];\n const token = `${m[1]}${m[2]}`;\n if (!ends.has(endpoint)) continue; // tia không neo đầu mút đường kính → bỏ\n if (seen.has(token)) continue;\n seen.add(token);\n intents.push(\n drawLine(token, 'tangentAt', { through: endpoint, circle: center }),\n );\n }\n }\n if (intents.length > 0) {\n out.push({ ruleId: 'tangent-ray', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/pointOnTangentRay.ts\n//\n// Điểm nằm TRÊN một tiếp tuyến Đà ĐẶT TÊN (token tia Ax/Bx/By):\n// \"Kẻ tiếp tuyến Ax và lấy trên tiếp tuyến đó một điểm P\" (Bài 7)\n// \"lấy trên Ax một điểm P\" (gọi thẳng tên tia)\n//\n// → add-point P {kind:'onSegment', of:'Ax'} — builder resolveSegmentRef thấy\n// shape 'Ax' đã có (do tangentRay dựng trước, priority cao hơn) → glider trên\n// đường tiếp tuyến. \"tiếp tuyến đó\" = anaphora trỏ tia đặt tên gần nhất.\n//\n// GOTCHA \\b: regex chứa ký tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint } from './_shared';\n\n// Token tiếp tuyến đặt tên: \"tiếp tuyến Ax\". Dùng để biết tia gần nhất (anaphora).\nconst NAMED_TANGENT = /tiếp\\s*tuyến\\s+([A-Z][xyzt])(?![A-Za-z])/gu;\n\n// Prefilter: bất kỳ tiếp tuyến đặt tên \"<Ray>\" nào (match() lọc tiếp). Đủ để bắt\n// cả forward (\"lấy trên Ax\") lẫn reverse (\"Trên tia Ax lấy điểm M\").\nconst PREFILTER = /tiếp\\s*tuyến\\s+[A-Z][xyzt]/u;\n\n// \"lấy trên tiếp tuyến đó (một)? điểm P\" — anaphora (tia gần nhất).\nconst TAKE_ON_THAT =\n /lấy\\s+trên\\s+tiếp\\s*tuyến\\s+(?:đó|ấy|này)\\s+(?:một\\s+)?điểm\\s+([A-Z])(?![A-Za-z])/u;\n// \"lấy trên Ax (một)? điểm P\" — gọi thẳng token tia.\nconst TAKE_ON_RAY =\n /lấy\\s+trên\\s+([A-Z][xyzt])(?![A-Za-z])[^.]{0,16}?điểm\\s+([A-Z])(?![A-Za-z])/u;\n// Reverse: \"Trên (tia)? Ax lấy (một)? điểm M\" (group1=ray, group2=point).\nconst REV_TAKE_ON_RAY =\n /[Tt]rên\\s+(?:tia\\s+)?([A-Z][xyzt])(?![A-Za-z])\\s+lấy\\s+(?:một\\s+)?điểm\\s+([A-Z])(?![A-Za-z])/u;\n// \"(điểm)? M trên Ax\" — \"Từ điểm M trên Ax kẻ …\" (group1=point, group2=ray).\nconst ON_RAY =\n /điểm\\s+([A-Z])(?![A-Za-z])\\s+trên\\s+([A-Z][xyzt])(?![A-Za-z])/u;\n\nexport const pointOnTangentRayRule: LanguageRule = {\n id: 'point-on-tangent-ray',\n // Dưới tangent-ray (63) để tia đã dựng; trên intersect-ray (48).\n priority: 55,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n // Tập tia tiếp tuyến Đà đặt tên toàn đề (tangentRay dựng các tia này). Reverse\n // form chỉ emit khi ray ∈ tập này → tránh onSegment của shape chưa dựng\n // (transpile-fail). \"Trên tia Bx\" mà Bx không phải tiếp tuyến → bỏ qua.\n const namedRays = new Set<string>();\n for (const m of ctx.problem.matchAll(NAMED_TANGENT)) namedRays.add(m[1]);\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const intents: IntentT[] = [];\n\n // Dạng gọi thẳng tên tia \"lấy trên Ax điểm P\".\n const direct = TAKE_ON_RAY.exec(c.text);\n if (direct) {\n intents.push(addPoint(direct[2], { kind: 'onSegment', of: direct[1] }));\n } else {\n // Dạng anaphora \"lấy trên tiếp tuyến đó điểm P\" → bind tia đặt tên gần\n // nhất TRƯỚC vị trí \"lấy trên\".\n const anaph = TAKE_ON_THAT.exec(c.text);\n if (anaph) {\n const before = c.text.slice(0, anaph.index);\n let ray: string | undefined;\n NAMED_TANGENT.lastIndex = 0;\n for (const m of before.matchAll(NAMED_TANGENT)) ray = m[1];\n if (ray) intents.push(addPoint(anaph[1], { kind: 'onSegment', of: ray }));\n }\n }\n\n // Reverse \"Trên tia Ax lấy điểm M\" / \"điểm M trên Ax\" — chỉ khi Ax là tiếp\n // tuyến đặt tên toàn đề (đã dựng). Không trùng forward (forward dùng \"lấy\n // trên\").\n if (intents.length === 0) {\n const rev = REV_TAKE_ON_RAY.exec(c.text) ?? ON_RAY.exec(c.text);\n if (rev) {\n // REV_TAKE: g1=ray g2=point. ON_RAY: g1=point g2=ray. Token tia có dạng\n // [A-Z][xyzt]; điểm là [A-Z] đơn → phân biệt bằng dạng token.\n const rayTok = /^[A-Z][xyzt]$/.test(rev[1]) ? rev[1] : rev[2];\n const ptTok = rayTok === rev[1] ? rev[2] : rev[1];\n if (namedRays.has(rayTok) && /^[A-Z]$/.test(ptTok)) {\n intents.push(addPoint(ptTok, { kind: 'onSegment', of: rayTok }));\n }\n }\n }\n\n if (intents.length > 0) {\n out.push({ ruleId: 'point-on-tangent-ray', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/pointOnTangentAt.ts\n//\n// Điểm lấy TRÊN tiếp tuyến TẠI một điểm trên đường tròn (tiếp tuyến KHÔNG đặt tên\n// kiểu tia Ax — mà mô tả bằng \"tiếp tuyến tại A\"):\n// \"Trên tiếp tuyến của đường tròn (O) tại A lấy điểm M\" (vao10:17)\n// \"Trên tiếp tuyến tại C của (O) lấy một điểm P\"\n//\n// → drawLine('tA', 'tangentAt', {through:A, circle}) + addPoint(M, onSegment 'tA')\n// Tạo CẢ tiếp tuyến (như tangentAt) LẪN điểm tự do M trượt trên nó. M là gốc\n// của nhiều phái sinh downstream (\"Từ M vẽ tiếp tuyến thứ hai\", \"MB cắt (O)\") →\n// phủ clause này mở khoá cả chuỗi.\n//\n// KHÁC pointOnTangentRay (tia Đà đặt tên Ax do tangentRay dựng): ở đây tiếp tuyến\n// chưa tồn tại, rule tự dựng line tên \"t<điểm>\".\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /[Tt]rên\\s+tiếp\\s*tuyến/u;\nconst CIRCLE_REF =\n /đường\\s*tròn\\s*(?:tâm\\s+)?\\(?\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)?|\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)/u;\n\n// \"Trên tiếp tuyến (của (đường tròn)? (O))? tại A (của (O))? lấy (một)? điểm M\"\n// - \"của (O)\" có thể đứng TRƯỚC \"tại A\" (\"tiếp tuyến của (O) tại A\") hoặc SAU\n// (\"tiếp tuyến tại A của (O)\") — blob `[^.]{0,30}?` nuốt cụm xen giữa.\n// group1 = điểm tiếp xúc (A); group2 = điểm lấy (M).\nconst TAKE_ON_TANGENT_AT = new RegExp(\n '[Tt]rên\\\\s+tiếp\\\\s*tuyến\\\\s+[^.]{0,30}?tại\\\\s+([A-Z])(?![A-Za-z])' +\n '[^.]{0,30}?lấy\\\\s+(?:một\\\\s+)?điểm\\\\s+([A-Z])(?![A-Za-z])',\n 'u',\n);\n\nfunction circleName(problem: string): string | undefined {\n const m = CIRCLE_REF.exec(problem);\n const center = m?.[1] ?? m?.[2];\n if (!center) return undefined;\n return /đường\\s*kính/u.test(problem) ? `${center}_c` : center;\n}\n\nexport const pointOnTangentAtRule: LanguageRule = {\n // Dưới tangent-at (63) / tangent-ray (63); rule này TỰ dựng line nên thứ tự nội\n // bộ (drawLine trước addPoint) đảm bảo onSegment tham chiếu được line.\n id: 'point-on-tangent-at',\n priority: 56,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = circleName(ctx.problem);\n if (!circle) return [];\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = TAKE_ON_TANGENT_AT.exec(c.text);\n if (!m) continue;\n const [touch, point] = [m[1], m[2]];\n if (touch === point) continue;\n const line = `t${touch}`;\n out.push({\n ruleId: 'point-on-tangent-at',\n clauseIds: [c.id],\n intents: [\n drawLine(line, 'tangentAt', { through: touch, circle }),\n addPoint(point, { kind: 'onSegment', of: line }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/intersectRay.ts\n//\n// Hai đường/tia cắt một TIA ĐẶT TÊN (token tia Bx/Ax/By), zip 1-1 ra 2 giao điểm:\n// \"Các tia AC và AD cắt Bx lần lượt ở E, F\" (Bài 9)\n// \"Tia AC và AD cắt Bx lần lượt tại E và F\"\n//\n// → E = AC ∩ Bx, F = AD ∩ Bx. Mỗi giao = add-point intersection of:[Lk, Ray].\n// builder resolveSegmentRef: \"AC\" → segment 2 đỉnh; \"Bx\" → shape draw-line đã\n// có (tangentRay dựng trước, priority cao hơn). Token tia (Bx) KHÔNG phải cặp\n// đỉnh nên generic intersection rule bỏ qua → cần rule riêng này.\n//\n// GOTCHA \\b: regex chứa ký tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint } from './_shared';\n\n// L = cặp đỉnh \"AC\" (2 chữ HOA). Ray = token tia \"Bx\" (1 HOA + x/y/z/t).\nconst LINE = '([A-Z][A-Z])(?![A-Z])';\nconst RAY = '([A-Z][xyzt])(?![A-Za-z])';\nconst NAME = '([A-Z])(?![A-Za-z])';\n\n// \"(các)? tia? L1 và L2 (lần lượt)? cắt <Ray> (lần lượt)? (ở|tại) P1 (,|và) P2\"\nconst PATTERN = new RegExp(\n String.raw`(?:[Cc]ác\\s+)?(?:tia\\s+)?${LINE}\\s+và\\s+${LINE}\\s+(?:lần\\s*lượt\\s+)?cắt\\s+${RAY}\\s+(?:lần\\s*lượt\\s+)?(?:ở|tại)\\s+${NAME}\\s*(?:,|và)\\s*${NAME}`,\n 'u',\n);\n\nconst PREFILTER = /cắt\\s+[A-Z][xyzt](?![A-Za-z])/u;\n\nexport const intersectRayRule: LanguageRule = {\n id: 'intersect-ray',\n // Thấp nhất trong cụm tia: tia (63) + điểm-trên-tia (55) phải dựng trước; giao\n // điểm tham chiếu cả tia LẪN các cạnh AC/AD. Trên connect (40).\n priority: 48,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = PATTERN.exec(c.text);\n if (!m) continue;\n const l1 = m[1];\n const l2 = m[2];\n const ray = m[3];\n const p1 = m[4];\n const p2 = m[5];\n // Guard fail-safe: 2 tên giao phân biệt, không trùng nhau, không nằm trong tia.\n if (p1 === p2) continue;\n const intents: IntentT[] = [\n addPoint(p1, { kind: 'intersection', of: [l1, ray] }),\n addPoint(p2, { kind: 'intersection', of: [l2, ray] }),\n ];\n out.push({ ruleId: 'intersect-ray', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentFromPointAt.ts\n//\n// Tiếp tuyến TỪ điểm ngoài, tiếp xúc đường tròn TẠI một tiếp điểm ĐẶT TÊN:\n// \"từ P kẻ tiếp tuyến tiếp xúc với (O) tại M\" (Bài 7)\n// \"Từ P kẻ tiếp tuyến tiếp xúc đường tròn (O) tại M\"\n//\n// → 1 tiếp tuyến từ P (which:'first') + tiếp điểm M (tangentPoint which 0).\n//\n// TÁCH RIÊNG khỏi tangentFromExt (priority 65) vì điểm ngoài `from` ở đây có thể\n// là điểm PHÁI SINH dựng muộn (vd P = điểm-trên-tiếp-tuyến, priority 55). Đặt\n// priority THẤP HƠN point-on-tangent-ray (55) để P được dựng TRƯỚC khi tiếp\n// tuyến/tiếp điểm tham chiếu (intentsToDsl xử lý theo priority DESC, không\n// topo-sort) — nếu không sẽ transpile-fail (UNKNOWN_REF P).\n//\n// Circle ref emit THÔ (\"O\") — resolveCircleNames map \"O\"→\"O_c\" (tangentPoint +\n// draw-line.circle đều được rewrite) khi đường tròn là circleDiameter \"O_c\".\n//\n// GOTCHA \\b: regex chứa ký tự Việt dùng cờ 'u' + lookaround (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /tiếp\\s*tuyến\\s+tiếp\\s*xúc/u;\n\n// \"(với|tới|đến) (đường tròn)? (X)\" hoặc \"đường tròn (X)\" → circle (1 chữ tâm).\nconst CIRCLE_TARGET = String.raw`(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])(?:['′]?)\\s*\\)`;\n\n// \"[Tt]ừ P ... (kẻ|vẽ) (một)? tiếp tuyến tiếp xúc (với|tới|đến)? <circle> tại M\".\nconst PATTERN = new RegExp(\n String.raw`(?<!\\p{L})[Tt]ừ\\s+(?:điểm\\s+)?([A-Z])(?:['′]?)(?!\\p{L})[^.]{0,30}?(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:một\\s+)?tiếp\\s*tuyến\\s+tiếp\\s*xúc\\s+(?:với\\s+|tới\\s+|đến\\s+)?` +\n CIRCLE_TARGET +\n String.raw`\\s+tại\\s+([A-Z])(?![A-Za-z])`,\n 'u',\n);\n\nexport const tangentFromPointAtRule: LanguageRule = {\n id: 'tangent-from-point-at',\n // Dưới point-on-tangent-ray (55): điểm ngoài (P) có thể dựng ở priority 55.\n priority: 50,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = PATTERN.exec(c.text);\n if (!m) continue;\n const from = m[1];\n const circle = m[2];\n const tp = m[3];\n if (!circle || tp === from) continue;\n const intents: IntentT[] = [\n drawLine('t', 'tangentFromExt', { from, circle, which: 'first' }),\n addPoint(tp, { kind: 'tangentPoint', from, circle, which: 0 }),\n ];\n out.push({ ruleId: 'tangent-from-point-at', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpLineTakePoint.ts\n//\n// \"Trên đường thẳng vuông góc với <XY> tại <H>, lấy một điểm <M> (ở ngoài đường\n// tròn)?\" — dựng đường vuông góc với XY tại H (perpThrough) RỒI đặt điểm M trên\n// đường đó.\n//\n// Trên đường thẳng vuông góc với OB tại H, lấy một điểm M ở ngoài đường tròn\n// → draw-line prpH (perpThrough H→OB)\n// M = onSegment(prpH) (onSegment builder tự promote line non-segment →\n// DSL onLine vì prpH là 'perpendicular' line-like)\n//\n// parallelPerp YÊU CẦU tiền tố \"Qua/Từ <P>\" — ở đây vắng (\"trên đường thẳng\n// vuông góc với OB tại H\") nên parallelPerp KHÔNG fire; rule này tự emit đường\n// vuông góc + điểm trên đó để phủ trọn câu.\n//\n// Tên đường: 'prp' + điểm-tại (CÙNG quy ước parallelPerp 'prp'+through) → nếu có\n// rule khác dựng cùng đường thì JSON trùng và dedup.\n//\n// GOTCHA \\b: dùng (?!\\p{L})/(?<!\\p{L}) + cờ 'u' quanh ký tự Việt.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine, DUONG_KW } from './_shared';\n\n// group1+2 = cặp đỉnh đường tham chiếu (vd OB); group3 = điểm \"tại\";\n// group4 = điểm lấy trên đường vuông góc.\nconst RE = new RegExp(\n DUONG_KW +\n '\\\\s*thẳng\\\\s+vuông\\\\s*góc\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?' +\n '([A-Z])([A-Z])(?![A-Z])\\\\s+tại\\\\s+([A-Z])(?![A-Z])' +\n '[^.;]{0,40}?(?:lấy|Lấy)\\\\s+(?:một\\\\s+)?(?:điểm\\\\s+)?([A-Z])(?![A-Z])',\n 'gu',\n);\n\nconst PREFILTER = new RegExp(\n DUONG_KW + '\\\\s*thẳng\\\\s+vuông\\\\s*góc[^.;]{0,60}?(?:lấy|Lấy)',\n 'u',\n);\n\nexport const perpLineTakePointRule: LanguageRule = {\n id: 'perpLineTakePoint',\n // Cao hơn pairSecondIntersection (46) vì C/D có thể tham chiếu MA/MB ⇒ M phải\n // dựng trước. Đặt 56.\n priority: 56,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const to = m[1] + m[2];\n const at = m[3];\n const pt = m[4];\n // Tên điểm lấy không được trùng đầu mút đường tham chiếu / điểm \"tại\".\n if (to.includes(pt) || pt === at) continue;\n const line = 'prp' + at;\n out.push({\n ruleId: 'perpLineTakePoint',\n clauseIds: [c.id],\n intents: [\n drawLine(line, 'perpThrough', { through: at, to }),\n addPoint(pt, { kind: 'onSegment', of: line }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/pairSecondIntersection.ts\n//\n// CẶP giao thứ hai trên một đường tròn (phân phối 1-1):\n// \"L1, L2 (lần lượt|thứ tự)? cắt (đường tròn)? (\\(O\\))? tại P1, P2\"\n// (nối \"và\" hoặc \",\"). L1,L2 là line token 2 chữ HOA.\n// → P1 = secondIntersection(L1, circle, other1)\n// P2 = secondIntersection(L2, circle, other2)\n//\n// Bài 16: \"Các đường thẳng CD, AE lần lượt cắt đường tròn tại F, G.\" (vô danh)\n// Bài 18: \"MA và MB thứ tự cắt đường tròn (O) tại C và D.\" ((O))\n//\n// CIRCLE RESOLUTION:\n// - Nếu clause/đề nêu \"(X)\" → dùng tâm X (emit RAW 'X'; resolveCircleNames\n// map 'O'→'O_c' nếu cần).\n// - Nếu đường tròn VÔ DANH (\"đường tròn\" không \"(X)\") → resolve về đường tròn\n// đường-kính DUY NHẤT trong đề: scan \"(nửa)? đường tròn đường kính XY\" →\n// đường tròn tên `kXY` (do diameterCircleCutsSides dựng). 0 hoặc >1 ứng viên\n// → BỎ QUA (escalate, không đoán).\n//\n// `other` (điểm chung đã biết để loại): trong 2 chữ của line, chọn chữ là\n// circle-member. circle-member = đầu mút đường kính (B,D với kBD; A,B với O_c)\n// CỘNG điểm đã khai báo qua \"cắt … tại X\" trên đường tròn đó (vd E của Bài 16).\n// Bài 16: \"CD\"→D (đầu kính), \"AE\"→E (giao trước). Bài 18: \"MA\"→A, \"MB\"→B.\n// Nếu không chữ nào là circle-member → fallback chữ THỨ HAI của line (điểm ngoài\n// thường viết trước). Hình vẫn render đúng (P nằm trên line∩circle); `other` chỉ\n// định hướng chọn nhánh nào trong 2 giao.\n//\n// KHÔNG đụng lineCircleIntersection (SINGLE \"XY cắt (O) tại Z\" + TRIPLE distrib):\n// rule này CHỈ dạng CẶP. Trùng intent (cùng JSON) thì dedup downstream OK.\n//\n// GOTCHA \\b: dùng (?!\\p{L})/(?<!\\p{L}) + cờ 'u' quanh ký tự Việt.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, CIRCLE_KW, DUONG_KW } from './_shared';\n\n// CẶP: hai line token, \"lần lượt|thứ tự\"?, \"cắt\", \"(đường tròn)?\", \"(X)?\",\n// \"tại|ở\", hai điểm.\nconst PAIR = new RegExp(\n '([A-Z]{2})(?![A-Z])\\\\s*(?:,|và)\\\\s*([A-Z]{2})(?![A-Z])' +\n '[^.;]{0,24}?(?:lần\\\\s*lượt\\\\s+|thứ\\\\s*tự\\\\s+)?cắt\\\\s+' +\n '(?:' + CIRCLE_KW + '\\\\s*)?' +\n '(?:\\\\(\\\\s*([A-Z])(?:[\\'′]?)\\\\s*\\\\)\\\\s*)?' +\n '(?:lần\\\\s*lượt\\\\s+|thứ\\\\s*tự\\\\s+)?(?:tại|ở)\\\\s+' +\n '([A-Z])(?![A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\nconst PREFILTER = /[A-Z]{2}\\s*(?:,|và)\\s*[A-Z]{2}[^.;]{0,40}?cắt/u;\n\n// \"đường tròn đường kính XY\" → endpoints (scan toàn đề).\nconst DIAMETER = new RegExp(\n CIRCLE_KW + '\\\\s+' + DUONG_KW + '\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// \"cắt <gì đó> tại X\" — điểm giao đã khai báo trên (một) đường tròn.\nconst PRIOR_CUT = /cắt\\s+[^.;]{0,30}?(?:tại|ở)\\s+([A-Z])(?![A-Z])/gu;\n\ninterface Resolved {\n circle: string;\n members: Set<string>;\n}\n\n/** Resolve đường tròn vô danh → kXY duy nhất + thu thập circle-member. */\nfunction resolveUnnamed(problem: string): Resolved | undefined {\n DIAMETER.lastIndex = 0;\n const dias = [...problem.matchAll(DIAMETER)];\n if (dias.length !== 1) return undefined; // 0 hoặc >1 → ambiguous → escalate\n const d0 = dias[0][1];\n const d1 = dias[0][2];\n const members = new Set<string>([d0, d1]);\n // điểm giao đã khai báo trên đường tròn (vd \"cắt BC tại E\").\n PRIOR_CUT.lastIndex = 0;\n for (const m of problem.matchAll(PRIOR_CUT)) members.add(m[1]);\n return { circle: `k${d0}${d1}`, members };\n}\n\n/** Circle-member với đường tròn ĐẶT TÊN \"(X)\": đầu mút đường kính X + giao trước. */\nfunction resolveNamed(problem: string, center: string): Set<string> {\n const members = new Set<string>();\n // đường kính của (X): \"đường tròn (X) đường kính AB\" / \"(X) đường kính AB\".\n const DIA_NAMED = new RegExp(\n '\\\\(\\\\s*' + center + '(?:[\\'′]?)\\\\s*\\\\)\\\\s*' + DUONG_KW + '\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])',\n 'gu',\n );\n for (const m of problem.matchAll(DIA_NAMED)) {\n members.add(m[1]);\n members.add(m[2]);\n }\n PRIOR_CUT.lastIndex = 0;\n for (const m of problem.matchAll(PRIOR_CUT)) members.add(m[1]);\n return members;\n}\n\n/** Chọn `other`: chữ là circle-member; else fallback chữ thứ hai của line. */\nfunction pickOther(line: string, members: Set<string>): string {\n if (members.has(line[0]) && !members.has(line[1])) return line[0];\n if (members.has(line[1]) && !members.has(line[0])) return line[1];\n if (members.has(line[0]) && members.has(line[1])) return line[0];\n return line[1]; // điểm ngoài thường viết trước → đầu mút trên đường tròn là chữ 2\n}\n\nfunction valid(name: string, line: string): boolean {\n return /^[A-Z]$/u.test(name) && /^[A-Z]{2}$/u.test(line) && !line.includes(name);\n}\n\nexport const pairSecondIntersectionRule: LanguageRule = {\n id: 'pairSecondIntersection',\n priority: 46,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n PAIR.lastIndex = 0;\n for (const m of c.text.matchAll(PAIR)) {\n const line1 = m[1];\n const line2 = m[2];\n const center = m[3]; // có thể undefined (vô danh)\n const p1 = m[4];\n const p2 = m[5];\n if (!valid(p1, line1) || !valid(p2, line2)) continue;\n if (p1 === p2) continue;\n\n let circle: string;\n let members: Set<string>;\n if (center) {\n circle = center;\n members = resolveNamed(ctx.problem, center);\n } else {\n const r = resolveUnnamed(ctx.problem);\n if (!r) continue; // ambiguous → escalate\n circle = r.circle;\n members = r.members;\n }\n\n const intents: IntentT[] = [\n addPoint(p1, {\n kind: 'secondIntersection',\n line: line1,\n circle,\n other: pickOther(line1, members),\n }),\n addPoint(p2, {\n kind: 'secondIntersection',\n line: line2,\n circle,\n other: pickOther(line2, members),\n }),\n ];\n out.push({ ruleId: 'pairSecondIntersection', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleCenterRadiusSegment.ts\n//\n// Đường tròn TÂM <X> bán kính = ĐOẠN <XY> (bán kính cho bằng tên đoạn, không số):\n// \"Vẽ đường tròn tâm A bán kính AH\"\n// → circle TÂM A đi qua H (|AH| là bán kính) → centerThrough {center:'A', through:'H'}\n//\n// \"Gọi HD là đường kính của đường tròn (A; AH)\" — D = điểm đối tâm của H qua A\n// (D = 2A − H), tức reflectPoint của H qua điểm A. (circleRadius / circleDiameter\n// KHÔNG khớp \"(A; AH)\" vì AH không phải số / ký hiệu [Rr].)\n//\n// \"Tiếp tuyến của đường tròn tại D cắt CA ở E\"\n// → tangent tại D tới đường tròn (tangentAt) + E = giao(tiếp tuyến, CA).\n//\n// Đây là construct \"đường tròn tâm A bán kính AH\" điển hình của đề hình học lớp 9\n// (tam giác vuông + đường cao + đường tròn quanh chân/đỉnh). circleRadius rule CHỈ\n// nhận bán kính SỐ hoặc ký hiệu [Rr]; \"bán kính AH\" (đoạn) rơi vào rule này.\n//\n// Circle name = THÔ chữ tâm (vd 'A'); resolveCircleNames đổi 'A'→'A_c' khi A cũng\n// là điểm (đỉnh tam giác) — center A đã tồn tại nên KHÔNG inject thêm.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + lookaround (?!\\p{L}), KHÔNG \\b ASCII.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle, drawLine, CIRCLE_KW } from './_shared';\n\n// \"(đường tròn) tâm <X> bán kính <X><Y>\" — bán kính là ĐOẠN (2 chữ HOA), chữ đầu\n// trùng tâm. Loại bán kính số (\\d) / ký hiệu [Rr] (circleRadius sở hữu).\nconst CENTER_RADIUS_SEG = new RegExp(\n CIRCLE_KW +\n '\\\\s*(?:\\\\(\\\\s*)?(?:tâm\\\\s+)?([A-Z])(?:\\\\s*\\\\))?\\\\s*bán\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])',\n 'u',\n);\n\n// \"Gọi <H><D> là đường kính của đường tròn (<center>; ...)\" — đầu mút thứ hai (D)\n// là điểm đối tâm của đầu mút thứ nhất (H) qua TÂM center (D = reflectPoint H qua center).\n// Lưu ý segmentClauses cắt tại ';' nên clause chỉ còn \"... đường tròn (A\".\nconst DIAMETER_OF_CIRCLE = new RegExp(\n '([A-Z])([A-Z])(?![A-Z])\\\\s+là\\\\s+' +\n '[Đđ]ư[ờơ]ng\\\\s*kính\\\\s+của\\\\s+' +\n CIRCLE_KW +\n '\\\\s*\\\\(\\\\s*([A-Z])(?![A-Z])',\n 'u',\n);\n\n// \"Tiếp tuyến của đường tròn tại <D> cắt <C><A> ở/tại <E>\"\nconst TANGENT_AT_CUTS = new RegExp(\n '[Tt]iếp\\\\s*tuyến\\\\s+của\\\\s+' +\n CIRCLE_KW +\n '\\\\s+tại\\\\s+([A-Z])(?![A-Z])\\\\s+cắt\\\\s+([A-Z])([A-Z])(?![A-Z])\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])',\n 'u',\n);\n\nconst PREFILTER = new RegExp(\n CIRCLE_KW + '[^.]{0,16}?bán\\\\s*kính\\\\s+[A-Z]{2}|' +\n '[A-Z]{2}\\\\s+là\\\\s+[Đđ]ư[ờơ]ng\\\\s*kính|' +\n '[Tt]iếp\\\\s*tuyến\\\\s+của\\\\s+' + CIRCLE_KW + '\\\\s+tại',\n 'u',\n);\n\nexport const circleCenterRadiusSegmentRule: LanguageRule = {\n id: 'circle-center-radius-segment',\n // Trên circleRadius (75) để \"bán kính AH\" được rule này lo trước; nhưng vì\n // circleRadius bỏ qua bán-kính-đoạn nên thực tế không tranh chấp. Đặt 76.\n priority: 76,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n\n // Tâm circle suy từ clause \"tâm <X> bán kính <XY>\" (dùng để map tangentAt).\n let circleCenter: string | undefined;\n\n for (const c of ctx.clauses) {\n // 1) Đường tròn tâm X bán kính XY (đoạn) → centerThrough.\n const cr = CENTER_RADIUS_SEG.exec(c.text);\n if (cr) {\n const center = cr[1];\n const a = cr[2];\n const b = cr[3];\n // bán kính = đoạn xuất phát từ tâm: chữ đầu PHẢI là tâm, qua đầu kia.\n if (a === center && b !== center) {\n circleCenter = center;\n out.push({\n ruleId: 'circle-center-radius-segment',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'centerThrough', { center, through: b })],\n });\n }\n }\n\n // 2) \"<H><D> là đường kính của đường tròn (center)\" → D đối tâm H qua center.\n const dm = DIAMETER_OF_CIRCLE.exec(c.text);\n if (dm) {\n const h = dm[1];\n const d = dm[2];\n const center = dm[3];\n if (h !== d && d !== center) {\n out.push({\n ruleId: 'circle-center-radius-segment',\n clauseIds: [c.id],\n intents: [addPoint(d, { kind: 'reflectPoint', of: h, through: center })],\n });\n }\n }\n\n // 3) \"Tiếp tuyến của đường tròn tại D cắt CA ở E\".\n const tg = TANGENT_AT_CUTS.exec(c.text);\n if (tg) {\n const at = tg[1];\n const line = tg[2] + tg[3];\n const e = tg[4];\n // circle ref = tâm THÔ (resolveCircleNames map → _c nếu cần).\n const circle = circleCenter ?? at; // fallback: dùng chính điểm tiếp xúc? không — cần tâm\n if (circleCenter && at !== e && !line.includes(e)) {\n const tName = `t${at}`;\n out.push({\n ruleId: 'circle-center-radius-segment',\n clauseIds: [c.id],\n intents: [\n drawLine(tName, 'tangentAt', { through: at, circle }),\n addPoint(e, { kind: 'intersection', of: [tName, line] }),\n ],\n });\n }\n }\n }\n\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpDiameters.ts\n//\n// Đường tròn có HAI ĐƯỜNG KÍNH VUÔNG GÓC:\n// \"Cho đường tròn (O) bán kính R có hai đường kính AB và CD vuông góc với nhau\"\n// → đường tròn O (centerRadius, tâm O) + 4 điểm trên đường tròn:\n// A=0°, B=180° (1 đường kính); C=90°, D=270° (đường kính vuông góc).\n// Đặt 4 điểm onCircle ở 0/π/π·½/π·1.5 ⇒ AB ⊥ CD theo cách dựng.\n//\n// Circle name = THÔ 'O'; resolveCircleNames đổi 'O'→'O_c' vì O cũng là tâm/điểm.\n// Tâm O cần tồn tại như point — emit add-point O free (resolveCircleNames cũng tự\n// inject cho centerRadius khi center===name, nhưng explicit cho chắc + xác định thứ tự).\n//\n// Đây là construct TOÀN-MỆNH-ĐỀ (whole-clause); claim clause để circleDiameter\n// (vốn khớp \"đường kính AB\") KHÔNG dựng đường tròn đường kính rời — circleDiameter\n// có guard riêng bỏ qua dạng \"hai đường kính ... vuông góc\".\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle, CIRCLE_KW, DUONG_KW } from './_shared';\nimport { SYMBOLIC_RADIUS } from './circleRadius';\n\n// Tên đường tròn: \"đường tròn (O)\" / \"(O;R)\" bare (vao10:72 \"Cho (O), hai đường\n// kính…\") / \"đường tròn tâm O\". 2 group: paren-center | tâm-center.\nconst CIRC =\n '(?:' + CIRCLE_KW + '\\\\s*)?\\\\(\\\\s*([A-Z])(?:\\\\s*[;,]\\\\s*[Rr])?\\\\s*\\\\)' +\n '|' + CIRCLE_KW + '\\\\s+tâm\\\\s+([A-Z])(?![A-Za-z])';\n// Cặp đường kính: \"AB và CD\" / \"AB, CD\" / \"AB;CD\" (vao10:73 — ';' giữa cặp làm\n// segmentClauses tách clause, nhưng RE chạy trên ctx.problem nên vẫn khớp).\nconst PAIR =\n '([A-Z])([A-Z])(?![A-Z])\\\\s*(?:[,;]\\\\s*|và\\\\s+)([A-Z])([A-Z])(?![A-Z])';\n\n// Thứ tự 1 — tên TRƯỚC tính từ: \"(O) … hai đường kính AB và CD … vuông góc\".\nconst RE_NAMES_FIRST = new RegExp(\n '(?:' + CIRC + ')[^.]{0,40}?hai\\\\s+' + DUONG_KW + '\\\\s*kính\\\\s+(?:là\\\\s+)?' +\n PAIR + '[^.]{0,20}?vuông\\\\s*góc',\n 'u',\n);\n// Thứ tự 2 — tính từ TRƯỚC tên (vao10:127): \"(O;R) có hai đường kính vuông góc\n// (với nhau)? (là)? AB và CD\".\nconst RE_ADJ_FIRST = new RegExp(\n '(?:' + CIRC + ')[^.]{0,40}?hai\\\\s+' + DUONG_KW +\n '\\\\s*kính\\\\s+vuông\\\\s*góc(?:\\\\s+với\\\\s+nhau)?\\\\s*(?:là\\\\s+)?\\\\s*' + PAIR,\n 'u',\n);\n\n// Ký hiệu ⊥ vừa là separator vừa là khẳng định ⊥: \"hai đường kính AB ⊥ CD\" (vao10:71).\nconst RE_PERP_SYM = new RegExp(\n '(?:' + CIRC + ')[^.]{0,40}?hai\\\\s+' + DUONG_KW +\n '\\\\s*kính\\\\s+(?:là\\\\s+)?([A-Z])([A-Z])(?![A-Z])\\\\s*⊥\\\\s*([A-Z])([A-Z])(?![A-Z])',\n 'u',\n);\n\nconst PREFILTER = new RegExp('hai\\\\s+' + DUONG_KW + '\\\\s*kính[^.]{0,40}?(?:vuông\\\\s*góc|⊥)', 'u');\n\n// Góc đặt 4 đầu mút: AB trục ngang (0,π), CD trục dọc (π/2, 3π/2) ⇒ AB⊥CD.\nconst THETA_A = 0;\nconst THETA_B = Math.PI;\nconst THETA_C = Math.PI / 2;\nconst THETA_D = (3 * Math.PI) / 2;\n\nexport const perpDiametersRule: LanguageRule = {\n id: 'perp-diameters',\n // Trên circleDiameter (67) để chạy trước; circleDiameter cũng tự guard bỏ dạng này.\n priority: 70,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const m = RE_NAMES_FIRST.exec(ctx.problem) ?? RE_ADJ_FIRST.exec(ctx.problem) ?? RE_PERP_SYM.exec(ctx.problem);\n if (!m) return [];\n const center = m[1] ?? m[2];\n const a = m[3];\n const b = m[4];\n const cc = m[5];\n const d = m[6];\n // 5 tên phải phân biệt nhau.\n const names = [center, a, b, cc, d];\n if (new Set(names).size !== names.length) return [];\n\n // Claim clause chứa \"đường kính ... vuông góc\". Thêm clause ĐUÔI khi cặp 2\n // bị split tại ';' (\"…AB\" | \"CD vuông góc với nhau\" — vao10:73): đuôi chứa\n // đúng cặp thứ hai + \"vuông góc\".\n const claim = ctx.clauses\n .filter(\n (c) =>\n PREFILTER.test(c.text) ||\n /hai\\s+đư[ờơ]ng\\s*kính/u.test(c.text) ||\n (c.text.includes(cc + d) && /vuông\\s*góc/u.test(c.text)),\n )\n .map((c) => c.id);\n\n return [\n {\n ruleId: 'perp-diameters',\n clauseIds: claim.length > 0 ? claim : [ctx.clauses[0]?.id ?? 0],\n intents: [\n addPoint(center, { kind: 'free' }),\n drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS }),\n addPoint(a, { kind: 'onCircle', circle: center, theta: THETA_A }),\n addPoint(b, { kind: 'onCircle', circle: center, theta: THETA_B }),\n addPoint(cc, { kind: 'onCircle', circle: center, theta: THETA_C }),\n addPoint(d, { kind: 'onCircle', circle: center, theta: THETA_D }),\n ],\n },\n ];\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpLineCutsTangent.ts\n//\n// \"Đường thẳng vuông góc với <AB> tại <M> cắt tiếp tuyến tại <N> của đường tròn ở <P>\"\n// → draw-line prpM (perpThrough qua M, vuông góc AB)\n// + tiếp tuyến tN tại N của đường tròn (tangentAt)\n// + P = giao(prpM, tN).\n//\n// parallelPerp KHÔNG khớp (không mở đầu \"Qua/Từ\"); tangentAt khớp \"tiếp tuyến tại N\"\n// nhưng KHÔNG dựng giao P. Rule này phủ TRỌN clause.\n//\n// Circle ref = THÔ chữ tâm; resolveCircleNames map → '_c' nếu cần. Tên tiếp tuyến\n// 'tN' khớp quy ước tangentAt ('t' + điểm) → intent draw-line cùng tên dedup\n// (addShape idempotent), không tạo 2 tiếp tuyến.\n//\n// Thứ tự (intentsToDsl xử lý priority DESC): N phải có TRƯỚC tN và P; M trước prpM.\n// Đặt priority cao (65) để chạy trước tangentAt (63), nhưng N/M do rule khác tạo\n// (lineCircleIntersection 47 / onSegment) — intentsToDsl loop theo priority nên\n// các điểm đó add SAU; tuy vậy add-point P chỉ cần prpM & tN là SHAPE (đã add ở\n// cùng match này, trước P trong mảng intents) — điểm M/N chỉ là tham số dựng line,\n// builder line dung sai forward-ref điểm? KHÔNG — line cần điểm tồn tại. Vì thế\n// priority phải THẤP hơn rule tạo M, N. Đặt 44 (dưới lineCircleIntersection 47,\n// onSegmentPoint). Xem ghi chú priority trong registry.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine, CIRCLE_KW, DUONG_KW } from './_shared';\n\n// \"Đường thẳng vuông góc với <X><Y> tại <M> cắt tiếp tuyến tại <N> của đường tròn ở/tại <P>\"\nconst RE = new RegExp(\n DUONG_KW +\n '\\\\s*thẳng\\\\s+vuông\\\\s*góc\\\\s+(?:với\\\\s+)?([A-Z])([A-Z])(?![A-Z])\\\\s+tại\\\\s+([A-Z])(?![A-Z])' +\n '[^.]{0,20}?cắt\\\\s+tiếp\\\\s*tuyến\\\\s+tại\\\\s+([A-Z])(?![A-Z])' +\n '(?:\\\\s+của\\\\s+' +\n CIRCLE_KW +\n ')?\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])',\n 'u',\n);\n\n// Tâm đường tròn từ toàn đề (\"(O)\" / \"(O; R)\").\nconst CIRCLE_REF = /(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)/u;\n\nconst PREFILTER = new RegExp(\n DUONG_KW + '\\\\s*thẳng\\\\s+vuông\\\\s*góc[^.]{0,40}?cắt\\\\s+tiếp\\\\s*tuyến',\n 'u',\n);\n\nexport const perpLineCutsTangentRule: LanguageRule = {\n id: 'perp-line-cuts-tangent',\n // Dưới các rule tạo điểm M (onSegment ~?), N (lineCircleIntersection 47) để N,M\n // tồn tại trước khi rule này dựng line tham chiếu chúng. Đặt 44.\n priority: 44,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const cm = CIRCLE_REF.exec(ctx.problem);\n const center = cm?.[1];\n if (!center) return [];\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = RE.exec(c.text);\n if (!m) continue;\n const to = m[1] + m[2];\n const mPt = m[3];\n const nPt = m[4];\n const p = m[5];\n // Tên phân biệt + M không nằm trong đường tham chiếu là endpoint trùng? cho phép.\n if (mPt === nPt || mPt === p || nPt === p) continue;\n const prpName = `prp${mPt}`;\n const tName = `t${nPt}`;\n out.push({\n ruleId: 'perp-line-cuts-tangent',\n clauseIds: [c.id],\n intents: [\n drawLine(prpName, 'perpThrough', { through: mPt, to }),\n drawLine(tName, 'tangentAt', { through: nPt, circle: center }),\n addPoint(p, { kind: 'intersection', of: [prpName, tName] }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpChordThroughPoint.ts\n//\n// Dây cung VUÔNG GÓC kẻ qua một điểm, của đường tròn ĐƯỜNG KÍNH có sẵn:\n// \"Qua M kẻ dây cung DE vuông góc với AB\"\n// → đường ⊥ qua M tới AB (prpM) + D,E = giao(prpM, đường tròn (O)) 2 nhánh + đoạn DE.\n//\n// Đây KHÁC chord.ts (\"dây AB\" → 2 glider tự do trên đường tròn minh hoạ): ở đây dây\n// được RÀNG BUỘC ⊥ với một đoạn và đi qua một điểm cho trước, nên 2 đầu mút D,E là\n// GIAO ĐIỂM của đường vuông góc với đường tròn Đà TỒN TẠI trong đề (đường tròn đường\n// kính, do circleDiameter dựng tên \"<tâm>_c\"). chord.ts đã có guard bỏ qua dây có\n// \"vuông góc\" để rule này sở hữu.\n//\n// Tên đường tròn: tìm \"(O) ... đường kính XY\" trong đề → tâm O → circle \"O_c\". Emit\n// ref TRỰC TIẾP \"O_c\" (resolveCircleNames KHÔNG rewrite circle-ref trong constraint\n// 'intersection', nên KHÔNG dựa vào rewrite O→O_c — phải đặt tên đã-resolve sẵn).\n//\n// Priority CAO (70) > perpFoot(65) > intersection(45): \"kẻ BI vuông góc với CD tại I\"\n// (perpFoot) tham chiếu D, nên D phải được dựng TRƯỚC (intentsToDsl chạy priority DESC,\n// KHÔNG topo-sort).\n//\n// GOTCHA \\b: regex chứa ký tự Việt dùng cờ 'u' + lookaround, KHÔNG \\b.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, drawLine, DUONG_KW, CIRCLE_KW } from './_shared';\n\n// \"(O) ... đường kính XY\" → tâm O. (nửa) đường tròn (tâm)? (O hoặc tâm O) ... đường kính.\nconst DIAMETER_CIRCLE = new RegExp(\n String.raw`(?:${CIRCLE_KW}|nửa\\s+${CIRCLE_KW})\\s*(?:\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)|tâm\\s+([A-Z]))[^.;\\n]{0,40}?` +\n DUONG_KW +\n String.raw`\\s*kính\\s+[A-Z][A-Z](?![A-Z])`,\n 'u',\n);\n\n// \"Qua|Từ <P> kẻ|vẽ|dựng dây (cung)? <D><E> vuông góc với <X><Y>\"\n// g1=through point | g2,g3=chord endpoints | g4=segment the chord ⊥ to (2-char)\nconst PERP_CHORD = new RegExp(\n String.raw`(?:Qua|Từ)\\s+([A-Z])(?![A-Z])\\s+(?:kẻ|vẽ|dựng|vạch)\\s+dây(?:\\s+cung)?\\s+([A-Z])([A-Z])(?![A-Z])\\s+(?:⊥|vuông\\s*góc(?:\\s+với)?)\\s+(?:với\\s+)?(?:đường\\s*thẳng\\s+|cạnh\\s+|đoạn\\s+)?([A-Z]{2})(?![A-Z])`,\n 'gu',\n);\n\n/** Tâm đường tròn đường kính trong đề → undefined nếu không có. */\nfunction diameterCircleCenter(problem: string): string | undefined {\n const m = DIAMETER_CIRCLE.exec(problem);\n if (!m) return undefined;\n return m[1] ?? m[2];\n}\n\nconst PREFILTER = /dây/u;\n\nexport const perpChordThroughPointRule: LanguageRule = {\n id: 'perp-chord-through-point',\n priority: 70,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const center = diameterCircleCenter(ctx.problem);\n if (!center) return []; // không có đường tròn đường kính → để chord/escalate lo\n const circle = `${center}_c`;\n\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n PERP_CHORD.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = PERP_CHORD.exec(c.text)) !== null) {\n const through = m[1];\n const d = m[2];\n const e = m[3];\n const perpTo = m[4];\n if (d === e) continue; // dây suy biến\n // tên đường ⊥ duy nhất theo điểm qua (prp<through>); intersection ref dùng tên này.\n const line = `prp${through}`;\n out.push({\n ruleId: 'perp-chord-through-point',\n clauseIds: [c.id],\n intents: [\n drawLine(line, 'perpThrough', { through, to: perpTo }),\n addPoint(d, { kind: 'intersection', of: [line, circle], branch: 0 }),\n addPoint(e, { kind: 'intersection', of: [line, circle], branch: 1 }),\n connect(d, e, 'segment'),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/polygonInscribedCircle.ts\n//\n// \"hình vuông / hình chữ nhật ABCD nội tiếp (đường tròn)? (O)\" → đường tròn\n// ngoại tiếp đa giác = circle qua 3 đỉnh đầu (đa giác này CYCLIC theo dựng hình:\n// vuông + chữ nhật luôn nội tiếp được, 3 đỉnh xác định đường tròn, đỉnh 4 tự nằm\n// trên). drawCircle('O', through3, [A,B,C]). resolveCircleNameCollisions sẽ\n// inject tâm O (circumcenter) + đổi tên circle O→O_c nếu O bị dùng như point.\n//\n// CHỈ nhận hình vuông / chữ nhật (cyclic-by-construction). KHÔNG nhận \"tứ giác\"\n// / \"hình bình hành\" chung (không cyclic theo dựng hình mặc định → through3 sẽ\n// sai) → để escalate / rule khác.\n//\n// \\b không khớp ký tự Việt → lookaround \\p{L} + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawCircle } from './_shared';\n\nconst PREFILTER = /(?:hình\\s+vuông|hình\\s+chữ\\s+nhật)[^.]{0,40}?nội\\s*tiếp/u;\n\n// \"(hình vuông|hình chữ nhật) ABCD ... nội tiếp (đường tròn)? ( (O) | tâm O )\".\nconst POLY_INSCRIBED = new RegExp(\n '(?:hình\\\\s+vuông|hình\\\\s+chữ\\\\s+nhật)\\\\s+([A-Z])([A-Z])([A-Z])([A-Z])(?![A-Z])' +\n '[^.]{0,30}?nội\\\\s*tiếp\\\\s+(?:trong\\\\s+)?(?:đường\\\\s*tròn\\\\s*)?(?:\\\\(\\\\s*([A-Z])\\\\s*\\\\)|tâm\\\\s+([A-Z]))',\n 'u',\n);\n\nexport const polygonInscribedCircleRule: LanguageRule = {\n id: 'polygon-inscribed-circle',\n priority: 66,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = POLY_INSCRIBED.exec(c.text);\n if (!m) continue;\n const verts = [m[1], m[2], m[3], m[4]];\n const center = m[5] ?? m[6];\n if (!center) continue;\n // through3 dùng 3 đỉnh đầu — đa giác cyclic nên đỉnh 4 tự nằm trên.\n out.push({\n ruleId: 'polygon-inscribed-circle',\n clauseIds: [c.id],\n intents: [drawCircle(center, 'through3', { points: verts.slice(0, 3) })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpAtPointCutsLine.ts\n//\n// \"Đường (thẳng)? vuông góc/song song với <L1> tại <P> cắt <L2> (ở|tại) <Q>\"\n// \"Đường vuông góc với AB tại B cắt CD ở I\"\n// → draw-line prpB (perpThrough B→AB); Q = giao(prpB, L2).\n//\n// KHÁC perpThroughCutsLines (dạng \"Qua P kẻ … cắt 2 đường tại H,K\"): ở đây mệnh\n// đề mở bằng \"Đường … với L1 tại P\" và CHỈ cắt 1 đường (1 giao điểm). Tên đường\n// theo cùng quy ước parallelPerp ('prp'/'par'+P) để dedup nếu trùng.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\n// group1+2 = đường tham chiếu (L1), 3 = kind, 4 = điểm qua (P), 5+6 = đường bị\n// cắt (L2), 7 = giao điểm (Q).\nconst RE = new RegExp(\n 'Đường\\\\s*(?:thẳng\\\\s+)?(vuông\\\\s*góc|song\\\\s*song)\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+|đường\\\\s*thẳng\\\\s+)?' +\n '([A-Z])([A-Z])(?!\\\\p{L})\\\\s+tại\\\\s+([A-Z])(?!\\\\p{L})' +\n '[^.]{0,24}?cắt\\\\s+(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z])([A-Z])(?!\\\\p{L})\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// Biến thể cắt ĐƯỜNG TRÒN: \"Đường vuông góc với AB tại C cắt (nửa)? đường tròn\n// (O) (ở|tại) E\" → E = giao đường vuông góc với đường tròn (branch 0). circle\n// raw (resolveCircleNames map \"_c\"). group1+2=L1, 3=qua P, 4=tâm O, 5=giao E.\nconst RE_CIRCLE = new RegExp(\n 'Đường\\\\s*(?:thẳng\\\\s+)?vuông\\\\s*góc\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+|đường\\\\s*thẳng\\\\s+)?' +\n '([A-Z])([A-Z])(?!\\\\p{L})\\\\s+tại\\\\s+([A-Z])(?!\\\\p{L})' +\n \"[^.]{0,24}?cắt\\\\s+(?:nửa\\\\s+)?đường\\\\s*tròn\\\\s*\\\\(\\\\s*([A-Z](?:['′])?)\\\\s*\\\\)\\\\s+(?:ở|tại)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])\",\n 'gu',\n);\n\nconst PREFILTER = /Đường\\s*(?:thẳng\\s+)?(?:vuông\\s*góc|song\\s*song)[^.]{0,40}?tại\\s+[A-Z][^.]{0,24}?cắt/u;\n\nexport const perpAtPointCutsLineRule: LanguageRule = {\n id: 'perpAtPointCutsLine',\n priority: 50,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const isParallel = /song/.test(m[1]);\n const l1 = m[2] + m[3];\n const through = m[4];\n const l2 = m[5] + m[6];\n const q = m[7];\n // degenerate: điểm qua không thuộc L1 thì ⊥ vẫn hợp lệ; nhưng L2 chứa Q\n // (giao trùng đầu mút) hoặc qua điểm = giao → bỏ.\n if (l2.includes(q) || through === q) continue;\n const kind = isParallel ? 'parallelThrough' : 'perpThrough';\n const name = (isParallel ? 'par' : 'prp') + through;\n out.push({\n ruleId: 'perpAtPointCutsLine',\n clauseIds: [c.id],\n intents: [\n drawLine(name, kind, { through, to: l1 }),\n addPoint(q, { kind: 'intersection', of: [name, l2] }),\n ],\n });\n }\n\n // Cắt ĐƯỜNG TRÒN: \"Đường vuông góc với AB tại C cắt (nửa)? đường tròn (O) tại E\".\n RE_CIRCLE.lastIndex = 0;\n for (const m of c.text.matchAll(RE_CIRCLE)) {\n const l1 = m[1] + m[2];\n const through = m[3];\n const circle = m[4];\n const e = m[5];\n if (l1.includes(e) || through === e) continue;\n const name = `prp${through}`;\n out.push({\n ruleId: 'perpAtPointCutsLine',\n clauseIds: [c.id],\n intents: [\n drawLine(name, 'perpThrough', { through, to: l1 }),\n addPoint(e, { kind: 'intersection', of: [name, circle], branch: 0 }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentAtCutsLines.ts\n//\n// \"Tiếp tuyến của (O) tại C cắt AD, AB lần lượt tại P, Q\"\n// → draw-line tC (tangentAt C của đường tròn) + P=tC∩AD, Q=tC∩AB.\n//\n// Bổ sung tangentAt (vốn chỉ bắt \"tiếp tuyến TẠI X …\", bỏ lỡ \"tiếp tuyến CỦA\n// (O) tại X cắt …\"). Chấp nhận cả 2 thứ tự \"của (O) tại C\" và \"tại C của (O)\".\n// Đường tròn lấy từ toàn đề (1 \"(O)\"/\"tâm O\" duy nhất).\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /[Tt]iếp\\s*tuyến[^.]{0,30}?tại\\s+[A-Z][^.]{0,40}?cắt|Qua\\s+(?:điểm\\s+)?[A-Z][^.]{0,40}?tiếp\\s*tuyến[^.]{0,20}?cắt/u;\nconst CIRCLE_REF = /đường\\s*tròn\\s*(?:tâm\\s+)?\\(?\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)?/u;\nconst UNNAMED_DIAMETER = /(?:nửa\\s+)?đường\\s*tròn\\s+đường\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])/u;\n\n// \"Qua (điểm)? M … (kẻ)? tiếp tuyến (thứ ba)? cắt (các tiếp tuyến)? Ax, By (lần\n// lượt)? (ở|tại) C, D\" → tiếp tuyến TẠI M (M trên đường tròn) cắt 2 tia → C,D.\n// group1=M(tiếp điểm), 2+3=2 đường/tia bị cắt, 4+5=2 giao điểm.\nconst QUA_RE = new RegExp(\n 'Qua\\\\s+(?:điểm\\\\s+)?([A-Z])(?!\\\\p{L})[^.]{0,40}?tiếp\\\\s*tuyến\\\\s+(?:thứ\\\\s+(?:ba|3|hai|2)\\\\s+)?cắt\\\\s+' +\n '(?:các\\\\s+)?(?:(?:các\\\\s+)?tiếp\\\\s*tuyến\\\\s+|đường\\\\s*thẳng\\\\s+|cạnh\\\\s+)?' +\n '([A-Z](?:[A-Z]|[xyzt]))\\\\s*(?:,|và)\\\\s*([A-Z](?:[A-Z]|[xyzt]))(?!\\\\p{L})\\\\s+(?:lần\\\\s*lượt\\\\s+)?(?:ở|tại)\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// SINGLE: \"Tiếp tuyến tại A (của (O))? cắt (tia)? BC tại D\" → 1 đường + 1 giao.\n// group1=tiếp điểm, group2=đường bị cắt (1-2 ký tự), group3=giao điểm.\nconst SINGLE_RE = new RegExp(\n '[Tt]iếp\\\\s*tuyến\\\\s+(?:của\\\\s+[^.]{0,14}?\\\\s+)?tại\\\\s+(?:điểm\\\\s+)?([A-Z])(?!\\\\p{L})' +\n '(?:\\\\s+của\\\\s+[^.]{0,14}?)?\\\\s+cắt\\\\s+(?:tia\\\\s+|đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?' +\n '([A-Z]{1,2})(?![A-Z])\\\\s+(?:tại|ở)\\\\s+([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// group1 = tangent point, 2+3 = 2 đường bị cắt, 4+5 = 2 giao điểm.\nconst RE = new RegExp(\n '[Tt]iếp\\\\s*tuyến\\\\s+(?:của\\\\s+[^.]{0,14}?\\\\s+)?tại\\\\s+(?:điểm\\\\s+)?([A-Z])(?!\\\\p{L})' +\n '(?:\\\\s+của\\\\s+[^.]{0,14}?)?\\\\s+cắt\\\\s+(?:các\\\\s+)?(?:(?:các\\\\s+)?tiếp\\\\s*tuyến\\\\s+|đường\\\\s*thẳng\\\\s+|cạnh\\\\s+)?' +\n // Đường bị cắt: cặp đỉnh \"AD\" HOẶC token tia đã đặt tên \"Ax\"/\"By\" (1 HOA +\n // x/y/z/t). tangentRay dựng tia Ax,By (priority 63>62) trước → giao hợp lệ.\n '([A-Z](?:[A-Z]|[xyzt]))\\\\s*(?:,|và)\\\\s*([A-Z](?:[A-Z]|[xyzt]))(?!\\\\p{L})\\\\s+(?:lần\\\\s*lượt\\\\s+)?(?:tại|ở)\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\nfunction circleName(problem: string): string | undefined {\n const m = CIRCLE_REF.exec(problem);\n if (m) return /đường\\s*kính/u.test(problem) ? `${m[1]}_c` : m[1];\n // Không tâm đặt tên → đường tròn đường kính vô danh \"kXY\" (diameterCircleSecant).\n const dm = UNNAMED_DIAMETER.exec(problem);\n return dm ? `k${dm[1]}${dm[2]}` : undefined;\n}\n\nexport const tangentAtCutsLinesRule: LanguageRule = {\n id: 'tangentAtCutsLines',\n priority: 62,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = circleName(ctx.problem);\n if (!circle) return [];\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n let matchedTwo = false;\n\n // \"Qua điểm M … tiếp tuyến thứ ba cắt Ax, By ở C, D\" → tiếp tuyến tại M.\n QUA_RE.lastIndex = 0;\n for (const m of c.text.matchAll(QUA_RE)) {\n const at = m[1];\n const [l1, l2, p, q] = [m[2], m[3], m[4], m[5]];\n if (p === q || at === p || at === q) continue;\n matchedTwo = true;\n const t = `t${at}`;\n out.push({\n ruleId: 'tangentAtCutsLines',\n clauseIds: [c.id],\n intents: [\n drawLine(t, 'tangentAt', { through: at, circle }),\n addPoint(p, { kind: 'intersection', of: [t, l1] }),\n addPoint(q, { kind: 'intersection', of: [t, l2] }),\n ],\n });\n }\n\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n matchedTwo = true;\n const at = m[1];\n const l1 = m[2];\n const l2 = m[3];\n const p = m[4];\n const q = m[5];\n if (p === q) continue;\n const t = `t${at}`;\n out.push({\n ruleId: 'tangentAtCutsLines',\n clauseIds: [c.id],\n intents: [\n drawLine(t, 'tangentAt', { through: at, circle }),\n addPoint(p, { kind: 'intersection', of: [t, l1] }),\n addPoint(q, { kind: 'intersection', of: [t, l2] }),\n ],\n });\n }\n // SINGLE chỉ khi clause KHÔNG khớp dạng 2-đường (tránh double-emit).\n if (matchedTwo) continue;\n SINGLE_RE.lastIndex = 0;\n for (const m of c.text.matchAll(SINGLE_RE)) {\n const at = m[1];\n const line = m[2];\n const z = m[3];\n if (line.includes(z) || line.includes(at)) continue;\n const t = `t${at}`;\n out.push({\n ruleId: 'tangentAtCutsLines',\n clauseIds: [c.id],\n intents: [\n drawLine(t, 'tangentAt', { through: at, circle }),\n addPoint(z, { kind: 'intersection', of: [t, line] }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/diameterEndpoint.ts\n//\n// \"Gọi AD là đường kính của (O)\" / \"AD là đường kính đường tròn (O)\"\n// → D = điểm xuyên tâm đối của A qua tâm O (reflectPoint of A through O).\n// A đã nằm trên (O) (đỉnh/điểm cũ) ⇒ D = đầu mút kia của đường kính.\n// Dạng ĐỘNG TỪ (vao10): \"kẻ/vẽ/dựng đường kính AD (cắt BC tại H)\" — không có\n// \"là\", tâm suy từ đề; đầu mút đầu phải Đà xuất hiện trước match.\n//\n// CHỈ kích hoạt khi 1 trong 2 đầu mút đã là điểm nêu trước (đỉnh tam giác…) và\n// đầu kia là điểm MỚI cần dựng. Tâm lấy từ \"(O)\"/\"tâm O\" trong clause/đề.\n// KHÁC circleDiameter (\"đường tròn đường kính AB\" — dựng đường tròn MỚI): ở đây\n// \"AD là đường kính CỦA (O)\" — (O) đã có, chỉ cần đầu mút đối tâm.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// group1+2 = cặp đầu mút đường kính (AD), 3 = tâm O.\nconst RE = new RegExp(\n '([A-Z])([A-Z])(?![A-Z])\\\\s+là\\\\s+đường\\\\s*kính\\\\s+(?:của\\\\s+)?(?:đường\\\\s*tròn\\\\s*)?(?:tâm\\\\s+)?\\\\(?\\\\s*([A-Z])\\\\s*\\\\)?',\n 'gu',\n);\n\n// Dạng động từ: groups 1=đầu mút cũ 2=đầu mút mới (có thể prime \"CC'\").\nconst RE_VERB = new RegExp(\n \"(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\\\s+(?:[^.;,]{0,24}?và\\\\s+)?đường\\\\s*kính\\\\s+([A-Z])([A-Z]['′]?)(?![A-Za-z'′])\",\n 'gu',\n);\n// Tâm từ đề: \"(O)\" / \"(O;R)\" / \"(O,R)\" / \"tâm O\" — match ĐẦU TIÊN (đường tròn\n// nền). reflectPoint.through trỏ POINT tâm (resolveCircleNames inject scene\n// point cho circumcenter/midpoint nên tên tâm là điểm thật).\nconst RESOLVE_CENTER = /\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr0-9][^)]*)?\\s*\\)|tâm\\s+([A-Z])(?![A-Za-z])/u;\n\nconst PREFILTER = /[A-Z]{2}\\s+là\\s+đường\\s*kính|(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+(?:[^.;,]{0,24}?và\\s+)?đường\\s*kính/u;\n\nexport const diameterEndpointRule: LanguageRule = {\n id: 'diameterEndpoint',\n priority: 56,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n const emitted = new Set<string>();\n // Tập tên điểm \"đã biết\" thô: đỉnh tam giác/điểm xuất hiện trước. Heuristic\n // đơn giản: đầu mút đầu (A) coi là điểm cũ (gốc), đầu sau (D) là điểm mới.\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const a = m[1];\n const d = m[2];\n const center = m[3];\n if (a === d || center === a || center === d) continue;\n // D = xuyên tâm đối của A qua O.\n emitted.add(d);\n out.push({\n ruleId: 'diameterEndpoint',\n clauseIds: [c.id],\n intents: [addPoint(d, { kind: 'reflectPoint', of: a, through: center })],\n });\n }\n }\n const cm = RESOLVE_CENTER.exec(ctx.problem);\n const center = cm?.[1] ?? cm?.[2];\n if (!center) return out;\n for (const c of ctx.clauses) {\n RE_VERB.lastIndex = 0;\n for (const m of c.text.matchAll(RE_VERB)) {\n const a = m[1];\n const d = m[2].replace(/′/g, \"'\");\n if (a === d || center === a || center === d || emitted.has(d)) continue;\n // Đầu mút đầu phải Đà xuất hiện trước match trong đề (\"kẻ đường kính\n // MN\" qua điểm tuỳ ý — cả 2 mút mới — KHÔNG thuộc rule này). Lookbehind\n // chỉ loại chữ THƯỜNG: \"C\" trong \"ABC\" (sau B hoa) vẫn là điểm đã biết.\n const before = ctx.problem.slice(0, ctx.problem.indexOf(m[0]));\n if (!new RegExp(`(?<![a-z])${a}(?![a-z])`, 'u').test(before)) continue;\n emitted.add(d);\n out.push({\n ruleId: 'diameterEndpoint',\n clauseIds: [c.id],\n intents: [addPoint(d, { kind: 'reflectPoint', of: a, through: center })],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleThroughTwoCutsSides.ts\n//\n// \"Đường tròn (I) (luôn)? (đi)? qua B và C cắt AB, AC (lần lượt)? tại M, N\"\n// → tâm I = điểm tự do trên TRUNG TRỰC của BC (⇒ đường tròn qua cả B lẫn C),\n// đường tròn I_c = centerThrough(I, B), M = giao thứ hai (AB, I_c) loại B,\n// N = giao thứ hai (AC, I_c) loại C.\n//\n// Đường tròn qua 2 điểm có 1 bậc tự do (tâm chạy trên trung trực) — mô hình bằng\n// onPerpBisector + centerThrough để kéo vẫn đi qua đúng B, C.\n//\n// Mỗi cạnh bị cắt PHẢI chứa đúng 1 trong 2 điểm-qua (B hoặc C) để xác định điểm\n// chung loại trừ (other) cho giao thứ hai. Lệch → bỏ qua (escalate fail-safe).\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle } from './_shared';\n\nconst PREFILTER = /[Đđ]ường\\s*tròn\\s*\\(?[A-Z]\\)?[^.]{0,30}?(?:đi\\s+)?qua\\s+[A-Z][^.]{0,30}?cắt/u;\n\n// group1 = tâm I, 2+3 = 2 điểm qua (B,C), 4+5 = 2 cạnh (AB,AC), 6+7 = 2 giao (M,N).\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s*\\\\(\\\\s*([A-Z])\\\\s*\\\\)\\\\s*(?:luôn\\\\s+)?(?:đi\\\\s+)?qua\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s+([A-Z])(?!\\\\p{L})' +\n '[^.]{0,20}?cắt\\\\s+(?:các\\\\s+(?:cạnh|đoạn)\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{2})\\\\s*(?:,|và)\\\\s*([A-Z]{2})(?!\\\\p{L})' +\n '\\\\s+(?:lần\\\\s*lượt\\\\s+)?(?:ở|tại)\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\n/** Điểm-qua (B hoặc C) nằm trên cạnh `side` để làm `other` cho giao thứ hai. */\nfunction commonPoint(side: string, p1: string, p2: string): string | undefined {\n const onP1 = side.includes(p1);\n const onP2 = side.includes(p2);\n if (onP1 && !onP2) return p1;\n if (onP2 && !onP1) return p2;\n return undefined; // 0 hoặc 2 → không xác định → escalate\n}\n\nexport const circleThroughTwoCutsSidesRule: LanguageRule = {\n id: 'circleThroughTwoCutsSides',\n priority: 58,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const center = m[1];\n const b = m[2];\n const cc = m[3];\n const side1 = m[4];\n const side2 = m[5];\n const n1 = m[6];\n const n2 = m[7];\n if (b === cc || n1 === n2) continue;\n const other1 = commonPoint(side1, b, cc);\n const other2 = commonPoint(side2, b, cc);\n if (!other1 || !other2) continue;\n const circ = `${center}_c`;\n out.push({\n ruleId: 'circleThroughTwoCutsSides',\n clauseIds: [c.id],\n intents: [\n addPoint(center, { kind: 'onPerpBisector', p1: b, p2: cc }),\n drawCircle(circ, 'centerThrough', { center, through: b }),\n addPoint(n1, { kind: 'secondIntersection', line: side1, circle: circ, other: other1 }),\n addPoint(n2, { kind: 'secondIntersection', line: side2, circle: circ, other: other2 }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circumcircleNamedDistrib.ts\n//\n// \"K, L lần lượt là (đường tròn)? ngoại tiếp (các)? tam giác BQF, CQE\"\n// → drawCircle K through3(B,Q,F), drawCircle L through3(C,Q,E).\n//\n// circleTriangle xử lý \"đường tròn (K) ngoại tiếp tam giác BQF\" (1 cái); rule này\n// lo dạng PHÂN PHỐI đặt tên đường tròn ngoại tiếp 2 tam giác.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawCircle } from './_shared';\n\nconst PREFILTER = /lần\\s*lượt\\s+là\\s+(?:đường\\s*tròn\\s+)?ngoại\\s*tiếp/u;\n\n// group1+2 = 2 tên đường tròn, 3..5 = đỉnh tam giác 1, 6..8 = đỉnh tam giác 2.\nconst RE = new RegExp(\n '([A-Z])\\\\s*,\\\\s*([A-Z])\\\\s+lần\\\\s*lượt\\\\s+là\\\\s+(?:đường\\\\s*tròn\\\\s+)?ngoại\\\\s*tiếp\\\\s+(?:các\\\\s+)?tam\\\\s*giác\\\\s+' +\n '([A-Z])([A-Z])([A-Z])(?![A-Z])\\\\s*,\\\\s*(?:tam\\\\s*giác\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])',\n 'u',\n);\n\nexport const circumcircleNamedDistribRule: LanguageRule = {\n id: 'circumcircleNamedDistrib',\n priority: 67,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = RE.exec(c.text);\n if (!m) continue;\n const n1 = m[1];\n const n2 = m[2];\n const tri1 = [m[3], m[4], m[5]];\n const tri2 = [m[6], m[7], m[8]];\n if (n1 === n2) continue;\n out.push({\n ruleId: 'circumcircleNamedDistrib',\n clauseIds: [c.id],\n intents: [\n drawCircle(n1, 'through3', { points: tri1 }),\n drawCircle(n2, 'through3', { points: tri2 }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circumcirclePairMeet.ts\n//\n// \"Đường tròn ngoại tiếp tam giác AME và đường tròn ngoại tiếp tam giác ANF\n// cắt nhau tại Q khác A\"\n// → 2 đường tròn ngoại tiếp (tên synth) + Q = giao thứ hai 2 đường tròn\n// (circleSecondIntersection, loại điểm chung \"khác A\").\n//\n// Tên đường tròn synth `w<verts>` (vô danh trong đề) — không đụng circle khác.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawCircle, addPoint } from './_shared';\n\nconst PREFILTER = /[Đđ]ường\\s*tròn\\s+ngoại\\s*tiếp\\s+(?:các\\s+)?tam\\s*giác\\s+[A-Z]{3}\\s*(?:,|\\s+(?:và|cắt)\\s+(?:lại\\s+)?đường\\s*tròn\\s+ngoại\\s*tiếp\\s+tam\\s*giác)/u;\n\n// Dạng \"X cắt Y tại Q\": \"(đường tròn ngoại tiếp tam giác T1) cắt (đường tròn\n// ngoại tiếp tam giác T2) (tại|ở) Q (khác W)?\" — KHÔNG có \"và … cắt nhau\"\n// (Bài 24/25: \"...tam giác BEI cắt đường tròn ngoại tiếp tam giác CDI tại K khác I\").\nconst RE_CAT = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s+ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z]{3})(?![A-Z])\\\\s+cắt\\\\s+(?:lại\\\\s+)?' +\n '[Đđ]ường\\\\s*tròn\\\\s+ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z]{3})(?![A-Z])\\\\s+' +\n '(?:tại|ở)\\\\s+(?:điểm\\\\s+(?:thứ\\\\s+hai\\\\s+)?)?(?:là\\\\s+)?([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+([A-Z])(?![A-Z]))?',\n 'u',\n);\n\n// Dạng NÉN: \"đường tròn ngoại tiếp tam giác AEM, AFN cắt nhau tại P khác A\"\n// (một \"đường tròn ngoại tiếp\" + 2 tam giác ngăn phẩy).\nconst RE_COMPACT = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s+ngoại\\\\s*tiếp\\\\s+(?:các\\\\s+)?tam\\\\s*giác\\\\s+([A-Z]{3})(?![A-Z])\\\\s*,\\\\s*([A-Z]{3})(?![A-Z])\\\\s+' +\n 'cắt\\\\s+nhau\\\\s+(?:tại|ở)\\\\s+([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+([A-Z])(?![A-Z]))?',\n 'u',\n);\n\n// group1 = tam giác 1 (3 đỉnh), 2 = tam giác 2, 3 = giao điểm, 4 = điểm loại (khác A).\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s+ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z]{3})(?![A-Z])\\\\s+và\\\\s+' +\n '[Đđ]ường\\\\s*tròn\\\\s+ngoại\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z]{3})(?![A-Z])\\\\s+' +\n 'cắt\\\\s+nhau\\\\s+(?:tại|ở)\\\\s+([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+([A-Z])(?![A-Z]))?',\n 'u',\n);\n\n// Ký hiệu paren circumcircle \"(ABC)\" = đường tròn qua 3 đỉnh. 2 dạng:\n// LA: \"giao điểm (thứ hai)? của (đường tròn)? (ABC) và (ADE) là F (khác W)?\"\n// BEFORE: \"F là giao điểm (thứ hai)? của (đường tròn)? (ABC) và (ADE)\"\n// group1=tri1 2=tri2 3=name 4=khác (LA) | BEFORE: 1=name 2=tri1 3=tri2.\nconst PAR = '(?:đường\\\\s*tròn\\\\s+)?\\\\(\\\\s*([A-Z]{3})\\\\s*\\\\)';\nconst RE_PAREN_LA = new RegExp(\n `giao\\\\s*điểm\\\\s+(?:thứ\\\\s+hai\\\\s+)?(?:của\\\\s+)?${PAR}\\\\s+và\\\\s+${PAR}\\\\s+là\\\\s+([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+([A-Z])(?![A-Z]))?`,\n 'u',\n);\nconst RE_PAREN_BEFORE = new RegExp(\n `([A-Z])(?![A-Z])\\\\s+là\\\\s+giao\\\\s*điểm\\\\s+(?:thứ\\\\s+hai\\\\s+)?(?:của\\\\s+)?${PAR}\\\\s+và\\\\s+${PAR}`,\n 'u',\n);\n\nexport const circumcirclePairMeetRule: LanguageRule = {\n id: 'circumcirclePairMeet',\n priority: 59,\n languages: ['vi'],\n patterns: [PREFILTER, new RegExp(`${PAR}\\\\s+và\\\\s+${PAR}`, 'u')],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // Paren circumcircle \"(ABC) và (ADE)\" — tách trước (tri = 3 chữ trong ngoặc).\n const pl = RE_PAREN_LA.exec(c.text);\n const pb = pl ? null : RE_PAREN_BEFORE.exec(c.text);\n if (pl || pb) {\n const t1 = (pl ? pl[1] : pb![2]);\n const t2 = (pl ? pl[2] : pb![3]);\n const q = pl ? pl[3] : pb![1];\n const tri1 = t1.split(''), tri2 = t2.split('');\n const shared = (pl && pl[4]) || tri1.find((v) => tri2.includes(v));\n if (shared && !tri1.includes(q) && !tri2.includes(q)) {\n out.push({\n ruleId: 'circumcirclePairMeet',\n clauseIds: [c.id],\n intents: [\n drawCircle(`w${t1}`, 'through3', { points: tri1 }),\n drawCircle(`w${t2}`, 'through3', { points: tri2 }),\n addPoint(q, { kind: 'circleSecondIntersection', c1: `w${t1}`, c2: `w${t2}`, exclude: shared }),\n ],\n });\n continue;\n }\n }\n const m = RE.exec(c.text) ?? RE_CAT.exec(c.text) ?? RE_COMPACT.exec(c.text);\n if (!m) continue;\n const tri1 = m[1].split('');\n const tri2 = m[2].split('');\n const q = m[3];\n // Điểm chung để loại: \"khác A\" tường minh, else đỉnh chung của 2 tam giác.\n const shared = m[4] ?? tri1.find((v) => tri2.includes(v));\n if (!shared) continue;\n const w1 = `w${m[1]}`;\n const w2 = `w${m[2]}`;\n out.push({\n ruleId: 'circumcirclePairMeet',\n clauseIds: [c.id],\n intents: [\n drawCircle(w1, 'through3', { points: tri1 }),\n drawCircle(w2, 'through3', { points: tri2 }),\n addPoint(q, { kind: 'circleSecondIntersection', c1: w1, c2: w2, exclude: shared }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentCircleAtPoint.ts\n//\n// \"Đường tròn (K) qua A và tiếp xúc với BC tại D (lần lượt)? cắt AC, AB tại E, F\"\n// → đường tròn tâm K TIẾP XÚC đường BC TẠI D + đi QUA A.\n// Tâm K = giao của ⊥BC-tại-D (bán kính KD ⊥ tiếp tuyến) và trung-trực AD\n// (KA = KD). circle = centerThrough(K, D). E,F = giao thứ hai với AC, AB\n// (loại A — A nằm trên đường tròn + trên 2 cạnh).\n//\n// Dựng tâm bằng primitive sẵn có: perpThrough + perpBisector (draw-line) + intersection.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine, drawCircle } from './_shared';\n\nconst PREFILTER = /[Đđ]ường\\s*tròn\\s*\\(?[A-Z]\\)?[^.]{0,40}?tiếp\\s*xúc[^.]{0,20}?tại\\s+[A-Z]/u;\n\n// group1=tâm K, 2=điểm qua A, 3=đường tiếp xúc BC, 4=tiếp điểm D,\n// 5+6 = 2 cạnh bị cắt, 7+8 = 2 giao điểm.\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s*\\\\(\\\\s*([A-Z])\\\\s*\\\\)\\\\s*(?:đi\\\\s+)?qua\\\\s+([A-Z])\\\\s+(?:và\\\\s+)?tiếp\\\\s*xúc\\\\s+(?:với\\\\s+)?' +\n '(?:cạnh\\\\s+|đường\\\\s*thẳng\\\\s+)?([A-Z]{2})\\\\s+tại\\\\s+([A-Z])(?!\\\\p{L})' +\n '[^.]{0,24}?cắt\\\\s+(?:các\\\\s+(?:cạnh|đoạn)\\\\s+|cạnh\\\\s+)?([A-Z]{2})\\\\s*(?:,|và)\\\\s*([A-Z]{2})(?!\\\\p{L})' +\n '\\\\s+(?:lần\\\\s*lượt\\\\s+)?(?:ở|tại)\\\\s+([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// Pattern B (Câu 21): \"Đường tròn (K) đi qua C, T tiếp xúc AB có tâm K thuộc BC\"\n// → tâm K cách đều C, T (trên đường tròn) ⇒ K ∈ trung-trực(C,T); K ∈ BC.\n// K = trung-trực(C,T) ∩ BC; circle = centerThrough(K, C). Tiếp xúc AB tự\n// thoả theo dựng hình (đề đảm bảo). group1=K, 2=C, 3=T, 4=đường chứa tâm.\nconst RE_THROUGH2_CENTER_ON = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s*\\\\(\\\\s*([A-Z])\\\\s*\\\\)\\\\s*(?:đi\\\\s+)?qua\\\\s+([A-Z])\\\\s*,\\\\s*([A-Z])(?!\\\\p{L})' +\n '[^.]{0,40}?tâm\\\\s+[A-Z]\\\\s+thuộc\\\\s+([A-Z]{2})(?![A-Z])',\n 'gu',\n);\n\nexport const tangentCircleAtPointRule: LanguageRule = {\n id: 'tangentCircleAtPoint',\n priority: 60,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const k = m[1];\n const through = m[2];\n const tanLine = m[3];\n const at = m[4];\n const side1 = m[5];\n const side2 = m[6];\n const p1 = m[7];\n const p2 = m[8];\n if (at === through || p1 === p2) continue;\n const circ = `${k}_c`;\n const perp = `${k}_perp`; // ⊥ tiếp tuyến tại tiếp điểm\n const pb = `${k}_pb`; // trung trực (through, at)\n out.push({\n ruleId: 'tangentCircleAtPoint',\n clauseIds: [c.id],\n intents: [\n drawLine(perp, 'perpThrough', { through: at, to: tanLine }),\n drawLine(pb, 'perpBisector', { p1: through, p2: at }),\n addPoint(k, { kind: 'intersection', of: [perp, pb] }),\n drawCircle(circ, 'centerThrough', { center: k, through: at }),\n addPoint(p1, { kind: 'secondIntersection', line: side1, circle: circ, other: through }),\n addPoint(p2, { kind: 'secondIntersection', line: side2, circle: circ, other: through }),\n ],\n });\n }\n\n // Pattern B: qua 2 điểm, tâm trên đường M (tiếp xúc tự thoả).\n RE_THROUGH2_CENTER_ON.lastIndex = 0;\n for (const m of c.text.matchAll(RE_THROUGH2_CENTER_ON)) {\n const k = m[1];\n const x = m[2];\n const y = m[3];\n const centerLine = m[4];\n if (x === y) continue;\n const circ = `${k}_c`;\n const pb = `${k}_pb`;\n out.push({\n ruleId: 'tangentCircleAtPoint',\n clauseIds: [c.id],\n intents: [\n drawLine(pb, 'perpBisector', { p1: x, p2: y }),\n addPoint(k, { kind: 'intersection', of: [pb, centerLine] }),\n drawCircle(circ, 'centerThrough', { center: k, through: x }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/externalBisectorCutsLines.ts\n//\n// \"Đường thẳng chứa phân giác ngoài của góc BHC cắt AB, AC lần lượt tại M, N\"\n// → phân giác NGOÀI ∠BHC = đường ⊥ phân giác TRONG tại đỉnh H.\n// M = giao(phân-giác-ngoài, AB); N = giao(…, AC).\n//\n// Dựng: angleBisector(B,H,C) [trong] → perpThrough(H, đó) [ngoài] → 2 giao.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /phân\\s*giác\\s+ngoài\\s+(?:của\\s+)?góc\\s+[A-Z]{3}[^.]{0,30}?cắt/u;\n\n// group1..3 = đỉnh góc (vertex = giữa), 4+5 = 2 đường bị cắt, 6+7 = 2 giao điểm.\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*thẳng\\\\s+(?:chứa\\\\s+)?phân\\\\s*giác\\\\s+ngoài\\\\s+(?:của\\\\s+)?góc\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])' +\n '[^.]{0,20}?cắt\\\\s+(?:các\\\\s+(?:cạnh|đường\\\\s*thẳng)\\\\s+)?([A-Z]{2})\\\\s*(?:,|và)\\\\s*([A-Z]{2})(?!\\\\p{L})' +\n '\\\\s+(?:lần\\\\s*lượt\\\\s+)?(?:ở|tại)\\\\s+(?:các\\\\s+điểm\\\\s+)?([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\nexport const externalBisectorCutsLinesRule: LanguageRule = {\n id: 'externalBisectorCutsLines',\n priority: 57,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const [p1, vertex, p2] = [m[1], m[2], m[3]];\n const l1 = m[4];\n const l2 = m[5];\n const n1 = m[6];\n const n2 = m[7];\n if (n1 === n2) continue;\n const bis = `bisIn${vertex}`; // phân giác trong ∠p1·vertex·p2\n const ext = `bisOut${vertex}`; // phân giác ngoài = ⊥ phân giác trong tại vertex\n out.push({\n ruleId: 'externalBisectorCutsLines',\n clauseIds: [c.id],\n intents: [\n drawLine(bis, 'angleBisector', { p1, vertex, p2 }),\n drawLine(ext, 'perpThrough', { through: vertex, to: bis }),\n addPoint(n1, { kind: 'intersection', of: [ext, l1] }),\n addPoint(n2, { kind: 'intersection', of: [ext, l2] }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentTwoSidesCircle.ts\n//\n// \"Đường tròn K tiếp xúc với CA, AB lần lượt tại E, F và tiếp xúc trong với (O)\n// tại S\" — đường tròn MIXTILINEAR nội tiếp ứng đỉnh A:\n// - K = tâm mixtilinear (of = [đỉnh chung, đỉnh khác cạnh1, đỉnh khác cạnh2]).\n// - S = tiếp điểm với đường tròn ngoại tiếp (O).\n// - E = chân ⊥ từ K xuống cạnh1 (tiếp điểm), F = chân ⊥ xuống cạnh2.\n// - circle K_c = centerThrough(K, E).\n//\n// Đỉnh A = chữ CHUNG của 2 cạnh tiếp xúc (CA ∩ AB = A). 2 cạnh phải chia sẻ đúng\n// 1 đỉnh → else bỏ qua (escalate).\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle } from './_shared';\n\nconst PREFILTER = /[Đđ]ường\\s*tròn[^.]{0,30}?tiếp\\s*xúc[^.]{0,40}?tiếp\\s*xúc\\s+trong/u;\n\n// group1=K, 2=cạnh1, 3=cạnh2, 4=E, 5=F, 6=S.\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s*\\\\(?\\\\s*([A-Z])\\\\s*\\\\)?\\\\s+tiếp\\\\s*xúc\\\\s+(?:với\\\\s+)?(?:các\\\\s+cạnh\\\\s+|cạnh\\\\s+)?' +\n '([A-Z]{2})\\\\s*,\\\\s*([A-Z]{2})(?!\\\\p{L})\\\\s+(?:lần\\\\s*lượt\\\\s+)?(?:ở|tại)\\\\s+([A-Z])\\\\s*,\\\\s*([A-Z])(?!\\\\p{L})' +\n '\\\\s+và\\\\s+tiếp\\\\s*xúc\\\\s+trong\\\\s+(?:với\\\\s+)?\\\\(?\\\\s*[A-Z]\\\\s*\\\\)?\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])',\n 'gu',\n);\n\n/** Đỉnh chung của 2 cạnh \"CA\",\"AB\" (vd \"A\"); undefined nếu 0 hoặc 2 chung. */\nfunction commonVertex(s1: string, s2: string): string | undefined {\n const shared = [...s1].filter((ch) => s2.includes(ch));\n return shared.length === 1 ? shared[0] : undefined;\n}\n\nexport const tangentTwoSidesCircleRule: LanguageRule = {\n id: 'tangentTwoSidesCircle',\n priority: 61,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const k = m[1];\n const side1 = m[2];\n const side2 = m[3];\n const e = m[4];\n const f = m[5];\n const s = m[6];\n const apex = commonVertex(side1, side2);\n if (!apex || e === f) continue;\n const o1 = [...side1].find((ch) => ch !== apex)!; // đỉnh khác trên cạnh1\n const o2 = [...side2].find((ch) => ch !== apex)!;\n const of: [string, string, string] = [apex, o1, o2];\n const circ = `${k}_c`;\n out.push({\n ruleId: 'tangentTwoSidesCircle',\n clauseIds: [c.id],\n intents: [\n addPoint(k, { kind: 'mixtilinearPoint', of, which: 'center' }),\n addPoint(s, { kind: 'mixtilinearPoint', of, which: 'touch' }),\n addPoint(e, { kind: 'perpFoot', from: k, onLine: side1 }),\n addPoint(f, { kind: 'perpFoot', from: k, onLine: side2 }),\n drawCircle(circ, 'centerThrough', { center: k, through: e }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/interiorPoint.ts\n//\n// Điểm TỰ DO bên trong một hình:\n// \"P là một điểm nằm trong tam giác ABC\" → addPoint(P, {kind:'free'})\n// \"Lấy điểm M nằm bên trong tứ giác ABCD\"\n//\n// Điểm tự do (kéo được) — chỉ để UNBLOCK các construct phái sinh (vd PA, trung\n// trực ∩ PA). KHÔNG kích hoạt khi clause CŨNG nói \"trên đường tròn/cung\" (onCircle\n// giữ điểm đó — priority cao hơn + addPoint idempotent, nhưng guard để khỏi claim thừa).\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'. Priority THẤP (sau onCircle…).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\nconst PREFILTER = /(?:nằm\\s+)?(?:bên\\s+)?trong\\s+(?:tam\\s*giác|tứ\\s*giác|hình|mặt\\s*phẳng)/u;\n// \"trong tam giác/tứ giác/hình ABCD\" HOẶC \"trong mặt phẳng (chứa) tam giác ABC\"\n// (điểm thuộc mặt phẳng tam giác = điểm tự do gần tam giác → unblock construct).\nconst RE =\n /(?:[Gg]ọi\\s+|[Ll]ấy\\s+)?(?:điểm\\s+)?([A-Z])(?!\\p{L})\\s+(?:là\\s+)?(?:một\\s+)?điểm\\s+(?:nằm\\s+)?(?:bên\\s+)?trong\\s+(?:mặt\\s*phẳng\\s+(?:chứa\\s+)?)?(?:tam\\s*giác|tứ\\s*giác|hình\\s+\\S+)\\s+[A-Z]{3,4}(?![A-Z])/u;\n\n// Dạng tên-SAU-\"điểm\" + đỉnh hình KHÔNG lặp: \"(một)? điểm O nằm (bên)? trong\n// (hình chữ nhật|tam giác|…)\" (Bài 5: \"và một điểm O nằm trong hình chữ nhật\").\n// Hình đã được dựng ở chỗ khác (quad/triangle) → O là điểm tự do bên trong.\nconst RE2 =\n /(?:một\\s+)?[Đđ]iểm\\s+([A-Z])(?!\\p{L})\\s+nằm\\s+(?:bên\\s+)?trong\\s+(?:tam\\s*giác|tứ\\s*giác|hình(?:\\s+(?:chữ\\s*nhật|vuông|thoi|bình\\s*hành|thang|\\S+))?)(?:\\s+[A-Z]{3,4}(?![A-Z]))?/u;\n\nexport const interiorPointRule: LanguageRule = {\n id: 'interiorPoint',\n priority: 30,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // onCircle/onSegment giữ điểm nếu clause nêu \"trên (đường tròn|cung|…)\".\n if (/trên\\s+(?:đường\\s*tròn|cung|nửa|\\()/u.test(c.text)) continue;\n const m = RE.exec(c.text) ?? RE2.exec(c.text);\n if (!m) continue;\n out.push({\n ruleId: 'interiorPoint',\n clauseIds: [c.id],\n intents: [addPoint(m[1], { kind: 'free' })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/parallelCutsTangentAt.ts\n//\n// \"Đường thẳng qua E song song với AC cắt tiếp tuyến tại C của (O) tại M\"\n// → đường ∥ AC qua E ∩ tiếp tuyến tại C của (O) = M.\n// parallelThrough(E, AC) + tangentAt(C, O) + M = giao.\n//\n// Đường tròn lấy từ toàn đề (\"(O)\"). \\b không khớp ký tự Việt → (?!\\p{L}) + 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /[Đđ]ường\\s*thẳng\\s+qua\\s+[A-Z][^.]{0,40}?tiếp\\s*tuyến\\s+tại\\s+[A-Z]/u;\nconst CIRCLE_REF = /đường\\s*tròn\\s*\\(\\s*([A-Z])\\s*\\)|\\(\\s*([A-Z])\\s*\\)/u;\n\n// group1=điểm qua E, 2=loại (song/vuông), 3=đường tham chiếu AC, 4=tiếp điểm C, 5=giao M.\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*thẳng\\\\s+qua\\\\s+([A-Z])(?!\\\\p{L})\\\\s+(song\\\\s*song|vuông\\\\s*góc)\\\\s+(?:với\\\\s+)?' +\n '([A-Z]{2})(?!\\\\p{L})\\\\s+cắt\\\\s+tiếp\\\\s*tuyến\\\\s+tại\\\\s+([A-Z])(?!\\\\p{L})' +\n '(?:\\\\s+của\\\\s+[^.]{0,12}?)?\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])',\n 'gu',\n);\n\nfunction circleName(problem: string): string | undefined {\n const m = CIRCLE_REF.exec(problem);\n return m ? (m[1] ?? m[2]) : undefined;\n}\n\nexport const parallelCutsTangentAtRule: LanguageRule = {\n id: 'parallelCutsTangentAt',\n priority: 52,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = circleName(ctx.problem);\n if (!circle) return [];\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const through = m[1];\n const isParallel = /song/.test(m[2]);\n const refLine = m[3];\n const at = m[4];\n const meet = m[5];\n const lineName = (isParallel ? 'par' : 'prp') + through;\n const tName = `t${at}`;\n out.push({\n ruleId: 'parallelCutsTangentAt',\n clauseIds: [c.id],\n intents: [\n drawLine(lineName, isParallel ? 'parallelThrough' : 'perpThrough', { through, to: refLine }),\n drawLine(tName, 'tangentAt', { through: at, circle }),\n addPoint(meet, { kind: 'intersection', of: [lineName, tName] }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/inExCircleTangentBC.ts\n//\n// Tâm + tiếp điểm trên 1 cạnh của đường tròn NỘI tiếp / BÀNG tiếp:\n// \"Đường tròn nội tiếp tam giác ABC có tâm I tiếp xúc với BC tại D\"\n// → I = incenter(ABC); D = perpFoot(I, BC) (tiếp điểm = chân ⊥ từ tâm).\n// \"Đường tròn bàng tiếp góc A của tam giác ABC có tâm J tiếp xúc với BC tại E\"\n// → J = excenter(ABC, đối A); E = perpFoot(J, BC).\n//\n// Chỉ dựng ĐIỂM (tâm + tiếp điểm) — đủ cho construct phái sinh (AE, DI, …). Đường\n// tròn vẽ (nếu cần) do circleTriangle lo riêng.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\nconst PREFILTER = /[Đđ]ường\\s*tròn\\s+(?:nội|bàng)\\s*tiếp[^.]{0,60}?tâm\\s+[A-Z][^.]{0,30}?tiếp\\s*xúc/u;\n\nconst TANGENT_TAIL = '\\\\s*,?\\\\s*tiếp\\\\s*xúc\\\\s+(?:với\\\\s+)?(?:cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?([A-Z]{2})(?!\\\\p{L})\\\\s+(?:ở|tại)\\\\s+([A-Z])(?![A-Z])';\n// Nội tiếp: group1=tam giác(3 đỉnh), 2=tâm I, 3=cạnh BC, 4=tiếp điểm D.\nconst INCIRCLE = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s+nội\\\\s*tiếp\\\\s+tam\\\\s*giác\\\\s+([A-Z]{3})(?![A-Z])[^.]{0,20}?tâm\\\\s+([A-Z])(?!\\\\p{L})' + TANGENT_TAIL,\n 'u',\n);\n// Bàng tiếp: group1=góc đối(A), 2=tam giác, 3=tâm J, 4=cạnh, 5=tiếp điểm E.\nconst EXCIRCLE = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s+bàng\\\\s*tiếp\\\\s+góc\\\\s+([A-Z])(?!\\\\p{L})\\\\s+(?:của\\\\s+)?tam\\\\s*giác\\\\s+([A-Z]{3})(?![A-Z])[^.]{0,20}?tâm\\\\s+([A-Z])(?!\\\\p{L})' + TANGENT_TAIL,\n 'u',\n);\n\nexport const inExCircleTangentBCRule: LanguageRule = {\n id: 'inExCircleTangentBC',\n priority: 69,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const im = INCIRCLE.exec(c.text);\n if (im) {\n const tri = im[1].split('') as [string, string, string];\n const center = im[2];\n const side = im[3];\n const touch = im[4];\n out.push({\n ruleId: 'inExCircleTangentBC',\n clauseIds: [c.id],\n intents: [\n addPoint(center, { kind: 'incenter', of: tri }),\n addPoint(touch, { kind: 'perpFoot', from: center, onLine: side }),\n ],\n });\n }\n const em = EXCIRCLE.exec(c.text);\n if (em) {\n const opp = em[1];\n const tri = em[2].split('') as [string, string, string];\n const center = em[3];\n const side = em[4];\n const touch = em[5];\n if (!tri.includes(opp)) continue;\n out.push({\n ruleId: 'inExCircleTangentBC',\n clauseIds: [c.id],\n intents: [\n addPoint(center, { kind: 'excenter', of: tri, opposite: opp }),\n addPoint(touch, { kind: 'perpFoot', from: center, onLine: side }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentPointsFromExt.ts\n//\n// \"Từ A kẻ tới đường tròn ngoại tiếp tam giác BIC các tiếp tuyến AP, AQ\n// (P, Q là các tiếp điểm)\" — 2 tiếp tuyến từ điểm NGOÀI A, 2 tiếp điểm P, Q.\n// → P = tangentPoint(A, circle, which=0); Q = tangentPoint(A, circle, which=1)\n// + đoạn AP, AQ.\n//\n// Tiếp tuyến đặt tên \"AP\",\"AQ\" (chữ đầu = điểm ngoài A, chữ sau = tiếp điểm).\n// Circle: \"(X)\" tường minh, else đường tròn (ngoại|nội) tiếp tam giác → tên mặc\n// định 'O' (circleTriangle dùng 'O' khi không nêu tâm).\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect } from './_shared';\n\nconst PREFILTER = /[Tt]ừ\\s+(?:điểm\\s+)?[A-Z][^.]{0,60}?tiếp\\s*tuyến\\s+[A-Z]{2}\\s*,\\s*[A-Z]{2}/u;\n\n// group1=điểm ngoài A, 2+3=tiếp tuyến 1 (AP), 4+5=tiếp tuyến 2 (AQ).\nconst RE = new RegExp(\n '[Tt]ừ\\\\s+(?:điểm\\\\s+)?([A-Z])(?!\\\\p{L})[^.]{0,60}?tiếp\\\\s*tuyến\\\\s+([A-Z])([A-Z])\\\\s*,\\\\s*([A-Z])([A-Z])(?!\\\\p{L})',\n 'gu',\n);\nconst PAREN_CIRCLE = /\\(\\s*([A-Z])\\s*\\)/u;\n\nexport const tangentPointsFromExtRule: LanguageRule = {\n id: 'tangentPointsFromExt',\n priority: 50,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const from = m[1];\n // 2 tiếp tuyến phải cùng bắt đầu bằng điểm ngoài; tiếp điểm = chữ thứ 2.\n if (m[2] !== from || m[4] !== from) continue;\n const p = m[3];\n const q = m[5];\n if (p === q) continue;\n // Circle: \"(X)\" trong clause, else mặc định 'O' (circleTriangle default).\n const par = PAREN_CIRCLE.exec(c.text);\n const circle = par ? par[1] : 'O';\n out.push({\n ruleId: 'tangentPointsFromExt',\n clauseIds: [c.id],\n intents: [\n addPoint(p, { kind: 'tangentPoint', from, circle, which: 0 }),\n addPoint(q, { kind: 'tangentPoint', from, circle, which: 1 }),\n connect(from, p, 'segment'),\n connect(from, q, 'segment'),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleExternalPoint.ts\n//\n// Mở đầu đề CỰC PHỔ BIẾN (tiếp tuyến từ điểm ngoài):\n// \"Cho đường tròn (O) và điểm A (nằm)? (ở)? ngoài (đường tròn)?\"\n// → drawCircle(O) bán kính canonical + addPoint(A, externalToCircle O).\n//\n// circleRadius CỐ Ý bỏ \"(O)\" TRƠ (không bán kính/đi qua) vì mơ hồ. Nhưng khi đề\n// nêu KÈM \"điểm A ngoài (O)\" thì đường tròn LÀ hình nền (phải vẽ) và A là điểm\n// ngoài để kẻ tiếp tuyến/cát tuyến. Rule này claim cả cụm trong 1 clause → vẽ\n// circle + A một lần, UNBLOCK tangentPointsFromExt / secant / intersection OA∩BC.\n//\n// externalPoint.ts xử dạng \"Lấy/Gọi điểm A ngoài (O)\" (chỉ điểm, dựa circleRadius\n// vẽ circle). Ở đây circle KHÔNG có bán kính nên externalPoint không đủ → rule\n// riêng tự emit cả circle.\n//\n// GOTCHA \\b: ký tự Việt \"ngoài\"/\"đường\" → cờ 'u', không \\b.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle } from './_shared';\nimport { SYMBOLIC_RADIUS } from './circleRadius';\n\n// \"đường tròn (O) ... và (có)? điểm A (nằm/ở)? ngoài\". group1=tâm O, group2=A.\n// [^.A-Z]{0,8}? giữa \"(O)\" và \"và/điểm\" cho phép \"; R)\" hoặc khoảng trắng; chặn\n// nhảy dấu chấm / nhãn HOA khác.\n// \"đường tròn\" optional — vao10 259/268 \"Cho (O) và điểm A nằm ngoài (O)\" viết\n// paren trần; \"một điểm\" cũng gặp.\nconst VN_FORM = new RegExp(\n String.raw`(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)[^.A-Z]{0,8}?(?:và\\s+)?(?:có\\s+)?(?:một\\s+)?điểm\\s+([A-Z])(?:['′]?)[^.A-Z]{0,14}?(?:nằm\\s+|ở\\s+)?ngoài`,\n 'u',\n);\n\n// Dạng ĐẢO — điểm trước, đường tròn sau (vao10:28 \"Cho điểm M nằm ngoài đường\n// tròn tâm O\"; vao10:31 \"một điểm A nằm ngoài đường tròn\" — tâm vắng, resolve\n// từ đề). group1=điểm, group2=tâm (optional — '.' chặn \\s* nên không nuốt chữ\n// HOA mở câu sau).\nconst VN_REV = new RegExp(\n String.raw`điểm\\s+([A-Z])(?:['′]?)\\s+(?:nằm\\s+|ở\\s+)?ngoài\\s+đường\\s*tròn\\s*(?:tâm\\s+)?\\(?\\s*([A-Z])?`,\n 'u',\n);\n// Resolve tâm từ toàn đề khi VN_REV không có tâm sau \"ngoài đường tròn\":\n// \"đường tròn (tâm)? O\" / \"(O)\" / \"(O;R)\".\nconst RESOLVE_CENTER =\n /đường\\s*tròn\\s*(?:\\(\\s*)?(?:tâm\\s+)?([A-Z])(?![A-Za-z])|\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)/u;\n\n// Điểm ngoài qua METRIC (không chữ \"ngoài\"): \"(O; 3cm) và điểm A có OA = 6 cm\"\n// → 6 > 3 ⇒ A ngoài (O). group1=tâm, group2=R, group3=điểm, group4=cặp đo (OA),\n// group5=khoảng cách d. Chỉ external khi cặp-đo = {tâm, điểm} và d > R.\nconst VN_METRIC = new RegExp(\n String.raw`\\(\\s*([A-Z])\\s*[;,]\\s*(\\d+(?:[.,]\\d+)?)\\s*cm\\s*\\)[^.A-Z]{0,12}?(?:và\\s+)?(?:có\\s+)?điểm\\s+([A-Z])(?:['′]?)[^.]{0,12}?([A-Z]{2})\\s*=\\s*(\\d+(?:[.,]\\d+)?)`,\n 'u',\n);\n\n// EN mirror: \"circle (O) and (a)? point A (lies|lying)? outside\".\nconst EN_FORM = new RegExp(\n String.raw`(?:[Cc]ircle\\s*)?\\(\\s*([A-Z])(?:\\s*[;,]\\s*[Rr])?\\s*\\)[^.A-Z]{0,8}?and\\s+(?:a\\s+)?point\\s+([A-Z])(?:['′]?)[^.A-Z]{0,18}?outside`,\n 'u',\n);\n\nexport const circleExternalPointRule: LanguageRule = {\n id: 'circleExternalPoint',\n priority: 70,\n languages: ['vi', 'en'],\n patterns: [/ngoài/u, /[Oo]utside/u, /điểm\\s+[A-Z][^.]{0,12}?[A-Z]{2}\\s*=\\s*\\d/u],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = VN_FORM.exec(c.text) ?? EN_FORM.exec(c.text);\n let center: string | undefined;\n let ext: string | undefined;\n if (m) {\n center = m[1];\n ext = m[2];\n } else if (VN_METRIC.test(c.text)) {\n const mm = VN_METRIC.exec(c.text)!;\n const [ctr, r, pt, pair, d] = [mm[1], mm[2], mm[3], mm[4], mm[5]];\n // cặp đo phải gồm tâm + điểm; d > R ⇒ ngoài.\n const norm = (s: string) => parseFloat(s.replace(',', '.'));\n if (pair.includes(ctr) && pair.includes(pt) && norm(d) > norm(r)) {\n center = ctr;\n ext = pt;\n }\n } else {\n const rv = VN_REV.exec(c.text);\n if (!rv) continue;\n ext = rv[1];\n // Tâm sau \"ngoài đường tròn\" nếu có, else resolve từ toàn đề.\n const rc = rv[2] ? undefined : RESOLVE_CENTER.exec(ctx.problem);\n center = rv[2] ?? rc?.[1] ?? rc?.[2];\n }\n if (!center || !ext || center === ext) continue;\n out.push({\n ruleId: 'circleExternalPoint',\n clauseIds: [c.id],\n intents: [\n drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS }),\n addPoint(ext, { kind: 'externalToCircle', circle: center }),\n ],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentNamedFromExt.ts\n//\n// Tiếp tuyến TỪ điểm ngoài, tiếp điểm CÓ TÊN — dạng \"Kẻ/Vẽ\" (KHÁC\n// tangentPointsFromExt dùng \"Từ A …\"). Điểm ngoài = chữ ĐẦU của cặp đỉnh:\n// \"Kẻ (các/hai)? tiếp tuyến AB, AC\" → A ngoài, B,C tiếp điểm (which 0/1).\n// \"Kẻ tiếp tuyến CD\" → C ngoài, D tiếp điểm (which 0).\n// 2 tiếp tuyến đơn cùng điểm ngoài (vd \"tiếp tuyến AB\" … \"tiếp tuyến AE\")\n// → B which 0, E which 1 (đếm theo thứ tự xuất hiện / điểm ngoài).\n//\n// Mỗi tiếp điểm → addPoint(tangentPoint, {from, circle, which}) + đoạn from→điểm.\n// Điểm ngoài (chữ đầu) phải Đà được dựng bởi rule khác (circleExternalPoint /\n// externalPoint / onSegment); rule này KHÔNG tự dựng nó. Circle = \"(X)\" duy nhất\n// trong đề (emit thô; resolveCircleNameCollisions chuẩn hoá base→_c nếu cần).\n//\n// Phân biệt:\n// - \"tiếp tuyến TẠI A\" (tangentAt) → \"tại\" CHỮ THƯỜNG, cặp [A-Z]{2} không khớp.\n// - \"tiếp tuyến từ A đến (O)\" (tangentFromExt, drawLine) → không cặp HOA sau\n// \"tiếp tuyến\" (là \"từ\").\n// - \"tiếp tuyến Ax, By\" (tia tiếp tuyến) → x,y CHỮ THƯỜNG → không khớp.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u', lookaround \\p{L} thay \\b.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect } from './_shared';\n\nconst PREFILTER =\n /(?:[Kk]ẻ|[Vv]ẽ)\\s+(?:các\\s+|hai\\s+|2\\s+)?tiếp\\s*tuyến\\s+(?:thứ\\s+\\S+\\s+)?[A-Z]{2}|[Cc]ác\\s+tiếp\\s*tuyến\\s+với/u;\n\n// 2 tiếp tuyến: \"Kẻ (các/hai/2)? tiếp tuyến XY, XZ\" / \"XY và XZ\" (vao10).\n// g1g2 = cặp 1, g3g4 = cặp 2.\nconst TWO = new RegExp(\n '(?:[Kk]ẻ|[Vv]ẽ)\\\\s+(?:các\\\\s+|hai\\\\s+|2\\\\s+)?tiếp\\\\s*tuyến\\\\s+([A-Z])([A-Z])\\\\s*(?:,\\\\s*|và\\\\s+)([A-Z])([A-Z])(?!\\\\p{L})',\n 'gu',\n);\n// 1 tiếp tuyến: \"Kẻ tiếp tuyến XY\" / \"vẽ tiếp tuyến thứ hai XY\" (qualifier thứ\n// tự optional — vao10:17). g1=ngoài, g2=tiếp điểm.\nconst ONE = new RegExp(\n '(?:[Kk]ẻ|[Vv]ẽ)\\\\s+tiếp\\\\s*tuyến\\\\s+(?:thứ\\\\s+(?:nhất|hai|nhì|ba|\\\\d+)\\\\s+)?([A-Z])([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// \"Các tiếp tuyến với đường tròn kẻ từ A tiếp xúc (với đường tròn)? tại B,C\"\n// (vao10) — điểm ngoài nêu sau \"kẻ từ\", tiếp điểm sau \"tại\".\nconst FROM_TOUCH = new RegExp(\n '[Cc]ác\\\\s+tiếp\\\\s*tuyến\\\\s+với\\\\s+đường\\\\s*tròn\\\\s+kẻ\\\\s+từ\\\\s+([A-Z])(?!\\\\p{L})' +\n '[^.;]{0,40}?tại\\\\s+([A-Z])\\\\s*(?:,\\\\s*|và\\\\s+)([A-Z])(?!\\\\p{L})',\n 'gu',\n);\n\n// Appositive đặt tên tiếp điểm: \"(với)? P và Q là (các|hai|2)? tiếp điểm\" —\n// claim-only khi P,Q đều đã được emit là tangentPoint (không thông tin mới).\nconst TOUCH_APPOS = new RegExp(\n '^(?:với\\\\s+)?([A-Z])\\\\s*(?:,\\\\s*|và\\\\s+)([A-Z])\\\\s+là\\\\s+(?:các\\\\s+|hai\\\\s+|2\\\\s+)?tiếp\\\\s*điểm',\n 'u',\n);\n\nconst PAREN_CIRCLE = /\\(\\s*([A-Z])\\s*\\)/u;\n\nexport const tangentNamedFromExtRule: LanguageRule = {\n id: 'tangentNamedFromExt',\n priority: 50,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const par = PAREN_CIRCLE.exec(ctx.problem);\n const circle = par ? par[1] : 'O';\n const out: RuleMatch[] = [];\n const twoClauses = new Set<number>();\n // đếm số tiếp điểm đã gán theo từng điểm ngoài (gán which 0 rồi 1).\n const whichOf = new Map<string, 0 | 1>();\n\n // --- 2 tiếp tuyến (ưu tiên: tránh ONE bắt lại cặp đầu) ---\n for (const c of ctx.clauses) {\n TWO.lastIndex = 0;\n for (const m of c.text.matchAll(TWO)) {\n const ext = m[1];\n if (m[3] !== ext) continue; // 2 cặp phải cùng điểm ngoài\n const p = m[2];\n const q = m[4];\n if (p === q || p === ext || q === ext) continue;\n twoClauses.add(c.id);\n whichOf.set(ext, 1); // đã dùng which 0+1\n out.push({\n ruleId: 'tangentNamedFromExt',\n clauseIds: [c.id],\n intents: [\n addPoint(p, { kind: 'tangentPoint', from: ext, circle, which: 0 }),\n addPoint(q, { kind: 'tangentPoint', from: ext, circle, which: 1 }),\n connect(ext, p, 'segment'),\n connect(ext, q, 'segment'),\n ],\n });\n }\n }\n\n // --- \"Các tiếp tuyến với đường tròn kẻ từ A … tại B,C\" (vao10) ---\n for (const c of ctx.clauses) {\n if (twoClauses.has(c.id)) continue;\n FROM_TOUCH.lastIndex = 0;\n for (const m of c.text.matchAll(FROM_TOUCH)) {\n const ext = m[1];\n const p = m[2];\n const q = m[3];\n if (p === q || p === ext || q === ext) continue;\n twoClauses.add(c.id);\n whichOf.set(ext, 1);\n out.push({\n ruleId: 'tangentNamedFromExt',\n clauseIds: [c.id],\n intents: [\n addPoint(p, { kind: 'tangentPoint', from: ext, circle, which: 0 }),\n addPoint(q, { kind: 'tangentPoint', from: ext, circle, which: 1 }),\n connect(ext, p, 'segment'),\n connect(ext, q, 'segment'),\n ],\n });\n }\n }\n\n // --- 1 tiếp tuyến (bỏ clause đã khớp 2-tiếp-tuyến) ---\n for (const c of ctx.clauses) {\n if (twoClauses.has(c.id)) continue;\n ONE.lastIndex = 0;\n for (const m of c.text.matchAll(ONE)) {\n const ext = m[1];\n const p = m[2];\n if (p === ext) continue;\n const prev = whichOf.get(ext);\n const which: 0 | 1 = prev === undefined ? 0 : prev === 0 ? 1 : 1;\n if (prev === 1) continue; // điểm ngoài đã có 2 tiếp tuyến → bỏ (chỉ 2)\n whichOf.set(ext, which);\n out.push({\n ruleId: 'tangentNamedFromExt',\n clauseIds: [c.id],\n intents: [\n addPoint(p, { kind: 'tangentPoint', from: ext, circle, which }),\n connect(ext, p, 'segment'),\n ],\n });\n }\n }\n\n // --- Appositive \"với P và Q là hai tiếp điểm\": claim-only nếu cả 2 tên đã\n // được emit là tangentPoint trong các match trên (không thông tin mới).\n const touchNames = new Set(\n out.flatMap((m) =>\n m.intents\n .filter((i: any) => i.op === 'add-point' && i.constraint?.kind === 'tangentPoint')\n .map((i: any) => i.name as string),\n ),\n );\n for (const c of ctx.clauses) {\n const m = TOUCH_APPOS.exec(c.text);\n if (m && touchNames.has(m[1]) && touchNames.has(m[2])) {\n out.push({ ruleId: 'tangentNamedFromExt', clauseIds: [c.id], intents: [] });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/secant.ts\n//\n// Cát tuyến từ điểm NGOÀI: đường thẳng qua điểm ngoài A cắt đường tròn tại 2\n// điểm (gần→xa). Mô hình hoá để A, D, E THẲNG HÀNG:\n// D = onCircle(circle, theta) (giao gần, glider)\n// E = secondIntersection(line=\"AD\", circle, other=D) (giao xa, trên đúng tia AD)\n// + đoạn A→E (chứa D).\n//\n// Dạng nhận:\n// \"cát tuyến ADE\" → ext=A, gần=D, xa=E (token 3 chữ).\n// \"cát tuyến ACD tới/với đường tròn\" → ext=A, gần=C, xa=D.\n// \"(Một) đường thẳng (d) (đi) qua A cắt (đường tròn|(O)) tại D và E\" → A,D,E.\n//\n// Circle: \"(X)\" duy nhất toàn đề (emit thô; resolver chuẩn hoá base→_c). Điểm\n// ngoài A phải do rule khác dựng (circleExternalPoint/externalPoint).\n//\n// Priority 58: DƯỚI circleExternalPoint(70)/externalPoint(68) (A + circle build\n// trước) nhưng TRÊN midpoint(50)/intersection(45) (D,E build trước \"H trung điểm\n// DE\" / \"giao điểm … DE\"). GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect } from './_shared';\n\n// Token \"cát tuyến AXY\" — A ngoài, X gần, Y xa.\nconst CAT_TUYEN = /cát\\s*tuyến\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n// \"qua A cắt (đường tròn|(O)) (tại|ở) D (và|,) E\".\nconst LINE_THROUGH = new RegExp(\n String.raw`[Qq]ua\\s+(?:điểm\\s+)?([A-Z])(?!\\p{L})[^.]{0,30}?cắt\\s+(?:đường\\s*tròn\\s*)?(?:\\(\\s*([A-Z])\\s*\\)\\s*)?(?:tại|ở)\\s+(?:hai\\s+|2\\s+)?(?:điểm\\s+)?([A-Z])\\s*(?:và|,)\\s*([A-Z])(?![A-Z])`,\n 'gu',\n);\nconst PAREN_CIRCLE = /\\(\\s*([A-Z])\\s*\\)/u;\n\nconst PREFILTER = /cát\\s*tuyến|[Qq]ua\\s+(?:điểm\\s+)?[A-Z][^.]{0,30}?cắt/u;\n\nfunction secantIntents(ext: string, near: string, far: string, circle: string, theta: number) {\n // đầu mút phân biệt + không trùng điểm ngoài.\n if (new Set([ext, near, far]).size !== 3) return null;\n const line = ext + near; // 2 chữ HOA cho secondIntersection\n return [\n addPoint(near, { kind: 'onCircle', circle, theta }),\n addPoint(far, { kind: 'secondIntersection', line, circle, other: near }),\n connect(ext, far, 'segment'),\n ];\n}\n\nexport const secantRule: LanguageRule = {\n id: 'secant',\n priority: 58,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const par = PAREN_CIRCLE.exec(ctx.problem);\n const fallbackCircle = par ? par[1] : 'O';\n const out: RuleMatch[] = [];\n let theta = 2.4;\n for (const c of ctx.clauses) {\n CAT_TUYEN.lastIndex = 0;\n for (const m of c.text.matchAll(CAT_TUYEN)) {\n const intents = secantIntents(m[1], m[2], m[3], fallbackCircle, theta);\n if (intents) {\n out.push({ ruleId: 'secant', clauseIds: [c.id], intents });\n theta += 0.7;\n }\n }\n LINE_THROUGH.lastIndex = 0;\n for (const m of c.text.matchAll(LINE_THROUGH)) {\n const circle = m[2] ?? fallbackCircle;\n const intents = secantIntents(m[1], m[3], m[4], circle, theta);\n if (intents) {\n out.push({ ruleId: 'secant', clauseIds: [c.id], intents });\n theta += 0.7;\n }\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/oppositeRayPoint.ts\n//\n// Điểm trên TIA ĐỐI: \"Trên tia đối của tia AB lấy điểm C\" → C nằm trên tia đối\n// của tia AB (xuất phát A, hướng NGƯỢC B) = trên đường BA kéo dài QUA A.\n// → C = pointAtDistance(from=B, through=A, literal) (C vượt qua A, xa B).\n//\n// \"tia AB\" = tia gốc A hướng B. Tia ĐỐI = gốc A hướng ngược B. Điểm C trên tia\n// đối ⇒ C bên kia A so với B ⇒ pointAtDistance từ B qua A kéo dài. Khoảng cách\n// không nêu (\"lấy điểm C\" tuỳ ý) → literal canonical (chỉ để minh hoạ vị trí).\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// \"Trên tia đối của tia AB lấy điểm C\" — g1g2 = tia AB (A gốc, B hướng), g3 = C.\nconst RE = new RegExp(\n String.raw`[Tt]rên\\s+tia\\s+đối\\s+(?:của\\s+)?tia\\s+([A-Z])([A-Z])(?![A-Z])[^.]{0,20}?lấy\\s+(?:một\\s+)?(?:điểm\\s+)?([A-Z])(?![A-Z])`,\n 'gu',\n);\n\n// Khoảng cách canonical (board units) — vị trí C trên tia đối không nêu metric.\n// Dạng tên-TRƯỚC (vao10): \"Lấy điểm A trên tia đối của tia CB\" — g1=tên, g2g3=tia.\nconst RE_NAME_FIRST = new RegExp(\n String.raw`[Ll]ấy\\s+(?:điểm\\s+)?([A-Z])(?![A-Z])\\s+trên\\s+tia\\s+đối\\s+(?:của\\s+)?tia\\s+([A-Z])([A-Z])(?![A-Z])`,\n 'gu',\n);\n\nconst CANON = 2.5;\n\nexport const oppositeRayPointRule: LanguageRule = {\n id: 'oppositeRayPoint',\n priority: 56,\n languages: ['vi'],\n patterns: [/tia\\s+đối/u],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const a = m[1]; // gốc tia\n const b = m[2]; // hướng tia\n const name = m[3];\n if (new Set([a, b, name]).size !== 3) continue;\n out.push({\n ruleId: 'oppositeRayPoint',\n clauseIds: [c.id],\n // tia AB gốc A → tia đối gốc A ngược B → C vượt A so với B:\n // pointAtDistance(from=B, through=A) đặt C sau A trên tia B→A.\n intents: [\n addPoint(name, {\n kind: 'pointAtDistance',\n from: b,\n through: a,\n distance: { kind: 'literal', value: CANON },\n }),\n ],\n });\n }\n RE_NAME_FIRST.lastIndex = 0;\n for (const m of c.text.matchAll(RE_NAME_FIRST)) {\n const name = m[1];\n const a = m[2]; // gốc tia\n const b = m[3]; // hướng tia\n if (new Set([a, b, name]).size !== 3) continue;\n out.push({\n ruleId: 'oppositeRayPoint',\n clauseIds: [c.id],\n intents: [\n addPoint(name, {\n kind: 'pointAtDistance',\n from: b,\n through: a,\n distance: { kind: 'literal', value: CANON },\n }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpChordAtFoot.ts\n//\n// Dây vuông góc với một đường (thường là đường kính). HAI nhánh theo việc đầu\n// mút thứ nhất đã được đề nhắc TRƯỚC clause hay chưa:\n//\n// (A) Đầu mút neo Đà có (\"Kẻ dây DE ⊥ AB tại H\" — D là tiếp điểm/điểm dựng trước):\n// → E = reflectLine(D qua AB) (E đối xứng D qua AB → cũng trên đường tròn\n// khi AB là đường kính)\n// H = perpFoot(D trên AB) (chân vuông góc = giao DE với AB)\n// + đoạn DE (dây).\n//\n// (B) KHÔNG đầu mút nào có trước + dây ⊥ đường COLLINEAR với đường kính tại H\n// (vao10 61/94/126: \"(O;R) đường kính AB. Điểm H thuộc OA. Kẻ dây CD ⊥ AB\n// tại H\"): H là điểm DẪN (đã/được dựng trên đường kính), 2 đầu mút = giao\n// đường-⊥-tại-H với đường tròn:\n// H = onSegment(T) (first-wins nhường nếu rule khác đã dựng H)\n// pc<H> = perpThrough(H, T) (đường ⊥ T tại H)\n// C = rightAngleViewing(X, Y, pc<H>) (X,Y = 2 đầu đường kính — Thales:\n// giao pc<H> với đường tròn đường kính XY, đúng đường tròn của dây)\n// D = reflectLine(C qua T) + đoạn CD.\n// Điều kiện: đề có \"đường kính XY\"; mọi chữ của T ∈ {X, Y, tâm} (T collinear\n// đường kính). Thiếu điều kiện → rơi về nhánh (A) như cũ (fail-safe escalate).\n//\n// KHÁC perpChordThroughPoint (\"Qua M kẻ dây DE ⊥ AB\" — chord qua điểm cho trước).\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'; ⊥ hoặc \"vuông góc với\".\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect, drawLine } from './_shared';\n\n// \"(Kẻ)? dây (cung)? DE (⊥|vuông góc với) AB (tại H)?\" — g1g2=dây DE, g3=đường\n// AB (1-2 ký tự), g4=H (optional, chân).\nconst RE = new RegExp(\n String.raw`(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)?\\s*[Dd]ây\\s*(?:cung\\s+)?([A-Z])([A-Z])(?![A-Z])\\s*(?:⊥|vuông\\s*góc(?:\\s+với)?)\\s+(?:đường\\s*thẳng\\s+|cạnh\\s+|đoạn\\s+)?([A-Z]{1,2})(?![A-Z])(?:\\s+tại\\s+(?:điểm\\s+)?([A-Z])(?![A-Z]))?`,\n 'gu',\n);\n\n// \"đường kính XY\" trong toàn đề (lấy cặp ĐẦU TIÊN — đường kính chính của (O)).\nconst DIAMETER = /đường\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])/u;\n// Tâm đường tròn đặt tên: \"(O\" / \"tâm O\".\nconst CENTER = /\\(\\s*([A-Z])\\s*[;,)]|tâm\\s+([A-Z])(?![A-Za-z])/u;\n\n/** Đầu mút d đã được đề nhắc TRƯỚC vị trí match (token HOA đứng riêng)? */\nfunction appearsBefore(problem: string, chordText: string, d: string): boolean {\n const pos = problem.indexOf(chordText);\n if (pos < 0) return true; // không định vị được → conservative: coi như đã có (nhánh A)\n return new RegExp(`(?<![A-Za-z])${d}(?![a-z])`, 'u').test(problem.slice(0, pos));\n}\n\nexport const perpChordAtFootRule: LanguageRule = {\n id: 'perpChordAtFoot',\n priority: 49,\n languages: ['vi'],\n patterns: [/[Dd]ây[^.]{0,12}?(?:⊥|vuông\\s*góc)/u],\n match(ctx) {\n const out: RuleMatch[] = [];\n const diam = DIAMETER.exec(ctx.problem);\n const ctrM = CENTER.exec(ctx.problem);\n const center = ctrM ? (ctrM[1] ?? ctrM[2]) : undefined;\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const d = m[1]; // đầu mút thứ nhất\n const e = m[2]; // đầu mút thứ hai (suy ra)\n const line = m[3];\n const h = m[4];\n if (new Set([d, e]).size !== 2 || line.includes(d) || line.includes(e)) continue;\n\n // Nhánh (B): cả 2 đầu mút mới + có chân H + T collinear đường kính.\n const diamLetters = diam ? [diam[1], diam[2], ...(center ? [center] : [])] : [];\n const collinear =\n line.length === 2 && line.split('').every((ch) => diamLetters.includes(ch));\n const freshEndpoints = diam && !appearsBefore(ctx.problem, m[0], d);\n if (freshEndpoints && collinear && h && h !== d && h !== e && !line.includes(h)) {\n const perpName = `pc${h}`;\n out.push({\n ruleId: 'perpChordAtFoot',\n clauseIds: [c.id],\n intents: [\n // t≠0.5 để không rơi đúng tâm (dây qua tâm = đường kính, degenerate).\n addPoint(h, { kind: 'onSegment', of: line, t: 0.3 }),\n drawLine(perpName, 'perpThrough', { through: h, to: line }),\n addPoint(d, { kind: 'rightAngleViewing', a: diam[1], b: diam[2], onLine: perpName }),\n addPoint(e, { kind: 'reflectLine', of: d, through: line }),\n connect(d, e, 'segment'),\n ],\n });\n continue;\n }\n\n // Nhánh (A): đầu mút neo đã có.\n const intents = [\n addPoint(e, { kind: 'reflectLine', of: d, through: line }),\n connect(d, e, 'segment'),\n ];\n if (h && h !== d && h !== e && !line.includes(h)) {\n intents.push(addPoint(h, { kind: 'perpFoot', from: d, onLine: line }));\n }\n out.push({ ruleId: 'perpChordAtFoot', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/diameterCircleSecant.ts\n//\n// Đường tròn đường kính KHÔNG nêu tâm (chỉ 2 đầu mút) + các đường cắt nó:\n// \"vẽ đường tròn đường kính MC. BM cắt đường tròn tại D. AD cắt đường tròn tại S\"\n// → circle kMC (diameter M,C) ; D = secondIntersection(BM, kMC, other=M) ;\n// S = secondIntersection(AD, kMC, other=D).\n//\n// KHÁC circleDiameter (\"(O) đường kính AB\" — có tên tâm O): ở đây \"đường tròn\"\n// đứng NGAY trước \"đường kính\" (không \"(X)\" chen giữa) → không tên tâm → tự đặt\n// \"k<XY>\" (cùng quy ước diameterCircleCutsSides) và sở hữu LUÔN các \"… cắt đường\n// tròn tại …\" (đường tròn KHÔNG tên, lineCircleIntersection bỏ qua vì cần \"(X)\").\n//\n// `other` (điểm chung line∩circle đã biết) = đầu mút line nằm trên đường tròn:\n// theo dõi tập điểm Đà biết trên circle (2 đầu mút đường kính + các giao đã dựng),\n// chọn đầu mút line ∈ tập đó. Không xác định được → bỏ (escalate fail-safe).\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawCircle } from './_shared';\n\n// \"đường tròn đường kính XY\" KHÔNG tên tâm (không \"(.)\" giữa \"tròn\" và \"đường kính\").\nconst DIAMETER = /(?:nửa\\s+)?đường\\s*tròn\\s+đường\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])/u;\n// \"PQ cắt đường tròn (ở|tại) (điểm (thứ hai)?)? Z\" — đường tròn KHÔNG \"(X)\".\nconst CUTS = /([A-Z]{2})(?![A-Z])\\s+cắt\\s+đường\\s*tròn\\s+(?:ở|tại)\\s+(?:điểm\\s+(?:thứ\\s+hai\\s+)?)?([A-Z])(?![A-Z])/gu;\n\nexport const diameterCircleSecantRule: LanguageRule = {\n id: 'diameterCircleSecant',\n priority: 46,\n languages: ['vi'],\n patterns: [/đường\\s*tròn\\s+đường\\s*kính\\s+[A-Z]{2}/u],\n match(ctx) {\n const dm = DIAMETER.exec(ctx.problem);\n if (!dm) return [];\n const [d0, d1] = [dm[1], dm[2]];\n const dia = d0 + d1;\n const circle = `k${dia}`;\n const onCircle = new Set<string>([d0, d1]); // điểm đã biết trên đường tròn\n const out: RuleMatch[] = [];\n\n // 1) Dựng đường tròn đường kính (clause chứa \"đường kính XY\").\n for (const c of ctx.clauses) {\n if (!DIAMETER.test(c.text)) continue;\n out.push({\n ruleId: 'diameterCircleSecant',\n clauseIds: [c.id],\n intents: [drawCircle(circle, 'diameter', { endpoints: [d0, d1] })],\n });\n break;\n }\n\n // 2) Các đường cắt đường tròn (theo thứ tự xuất hiện) — other = đầu mút ∈ onCircle.\n for (const c of ctx.clauses) {\n CUTS.lastIndex = 0;\n for (const m of c.text.matchAll(CUTS)) {\n const line = m[1];\n const z = m[2];\n if (line.includes(z) || onCircle.has(z)) continue;\n const other = onCircle.has(line[0]) ? line[0] : onCircle.has(line[1]) ? line[1] : undefined;\n if (!other) continue; // không xác định điểm chung → escalate\n onCircle.add(z);\n const intent: IntentT = addPoint(z, { kind: 'secondIntersection', line, circle, other });\n out.push({ ruleId: 'diameterCircleSecant', clauseIds: [c.id], intents: [intent] });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentsAtMeet.ts\n//\n// Hai tiếp tuyến TẠI 2 điểm trên đường tròn cắt nhau:\n// \"(Các)? tiếp tuyến (của (O))? tại B và C (của (O))? cắt nhau tại J\"\n// \"Tiếp tuyến tại B, C của (O) cắt nhau tại T\"\n// → tB = tangentAt(B, circle) ; tC = tangentAt(C, circle) ; J = tB ∩ tC.\n//\n// Rất phổ biến (cực/đối cực): J/T = giao 2 tiếp tuyến tại B,C. B,C thường là đỉnh\n// tam giác / điểm trên (O) đã có. Circle = \"(X)\" duy nhất (diameter → X_c).\n//\n// KHÁC tangentAtCutsLines (\"tiếp tuyến tại X cắt <đường> tại …\"): ở đây 2 tiếp\n// tuyến cắt NHAU. \\b không khớp ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /[Tt]iếp\\s*tuyến[^.]{0,40}?tại\\s+[A-Z][^.]{0,30}?(?:và|,)\\s*[A-Z][^.]{0,30}?cắt\\s+nhau/u;\nconst CIRCLE_REF = /đường\\s*tròn\\s*(?:tâm\\s+)?\\(?\\s*([A-ZωΩ])(?:\\s*[;,]\\s*[Rr])?\\s*\\)?|\\(\\s*([A-ZωΩ])\\s*\\)/u;\n\n// \"tiếp tuyến (của (O))? tại B (và|,) C (của (O))? cắt nhau (tại|ở) J\"\nconst RE = new RegExp(\n '[Tt]iếp\\\\s*tuyến\\\\s+(?:của\\\\s+[^.]{0,14}?\\\\s+)?tại\\\\s+(?:điểm\\\\s+)?([A-Z])\\\\s*(?:và|,)\\\\s*([A-Z])(?!\\\\p{L})' +\n '(?:\\\\s+của\\\\s+[^.]{0,14}?)?\\\\s+cắt\\\\s+nhau\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])',\n 'gu',\n);\n\nfunction circleName(problem: string): string | undefined {\n const m = CIRCLE_REF.exec(problem);\n if (!m) return undefined;\n const center = m[1] ?? m[2];\n return /đường\\s*kính/u.test(problem) ? `${center}_c` : center;\n}\n\nexport const tangentsAtMeetRule: LanguageRule = {\n id: 'tangentsAtMeet',\n priority: 55, // trên intersection(45) — 2 tiếp tuyến + giao trong CÙNG match nên tự đủ thứ tự\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = circleName(ctx.problem);\n if (!circle) return [];\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const [b, cc, j] = [m[1], m[2], m[3]];\n if (new Set([b, cc, j]).size !== 3) continue;\n const tB = `t${b}`;\n const tC = `t${cc}`;\n out.push({\n ruleId: 'tangentsAtMeet',\n clauseIds: [c.id],\n intents: [\n drawLine(tB, 'tangentAt', { through: b, circle }),\n drawLine(tC, 'tangentAt', { through: cc, circle }),\n addPoint(j, { kind: 'intersection', of: [tB, tC] }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/angleBisectorCutsSideCircle.ts\n//\n// Phân giác trong góc A cắt cạnh đối tại chân D, rồi cắt đường tròn ngoại tiếp\n// tại E (điểm cung):\n// \"Đường phân giác của góc BAC cắt BC tại D và cắt (O) tại E khác A\"\n// \"Tia phân giác trong AD ... cắt (O) tại E khác A\" (chân D đã có → chỉ E)\n// → D = angleBisectorFoot(A, BC) ; E = secondIntersection(line AD, (O), other=A).\n//\n// Phân giác từ A đi qua A, D nên E nằm trên tia AD kéo dài → secondIntersection\n// theo line \"AD\". angleBisectorAngle (priority 62) vẽ TIA phân giác (visible);\n// rule này thêm chân D + giao đường tròn E.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\nconst PREFILTER = /phân\\s*giác[^.]{0,40}?cắt/u;\n\n// \"phân giác (trong)? (của)? góc (BAC|A) cắt (cạnh)? BC (tại|ở) D\" — chân D trên\n// cạnh đối. vertex = chữ GIỮA (góc BAC→A) hoặc 1 chữ (góc A). side = cặp đỉnh.\nconst FOOT = new RegExp(\n 'phân\\\\s*giác\\\\s+(?:trong\\\\s+)?(?:của\\\\s+)?góc\\\\s+([A-Z])([A-Z])?([A-Z])?(?![A-Z])' +\n '[^.]{0,20}?cắt\\\\s+(?:cạnh\\\\s+)?([A-Z])([A-Z])(?![A-Z])\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])',\n 'u',\n);\n// \"... (và)? cắt (đường tròn|(O)) (tại|ở) E (khác A)?\" — phần giao đường tròn.\nconst CIRCLE_CUT = /cắt\\s+(?:lại\\s+)?(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])\\s*\\)\\s+(?:tại|ở)\\s+(?:điểm\\s+)?([A-Z])(?![A-Z])(?:\\s+khác\\s+([A-Z])(?![A-Z]))?/u;\n\n// DẠNG NÉN distributive: \"(đường|tia)? phân giác trong (của)? (góc)? BAC cắt\n// BC, (O) lần lượt tại D, E\" → D=bisectorFoot(A,BC), E=secondIntersection(AD,O,\n// other=A). Bài 71. vertex = chữ GIỮA của \"BAC\".\n// groups: 1,2,3 = B,A,C | 4 = side BC | 5 = circle O | 6 = D | 7 = E.\nconst FOOT_CIRCLE_DISTRIB = new RegExp(\n '(?:đường\\\\s*|tia\\\\s+)?phân\\\\s*giác\\\\s+(?:trong\\\\s+)?(?:của\\\\s+)?(?:góc\\\\s+)?([A-Z])([A-Z])([A-Z])(?![A-Z])' +\n '\\\\s+cắt\\\\s+(?:cạnh\\\\s+)?([A-Z]{2})\\\\s*,\\\\s*\\\\(\\\\s*([A-Z])\\\\s*\\\\)\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?' +\n '(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'u',\n);\n\nexport const angleBisectorCutsSideCircleRule: LanguageRule = {\n id: 'angleBisectorCutsSideCircle',\n priority: 48, // sau triangle/circle/cevian; trước intersection(45)\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // Dạng nén distributive \"phân giác ... BAC cắt BC,(O) lần lượt tại D,E\".\n const dm = FOOT_CIRCLE_DISTRIB.exec(c.text);\n if (dm) {\n const vertex = dm[2];\n const side = dm[4];\n const [circle, foot, e] = [dm[5], dm[6], dm[7]];\n if (!side.includes(foot) && !side.includes(vertex) && e !== foot && e !== vertex) {\n out.push({\n ruleId: 'angleBisectorCutsSideCircle',\n clauseIds: [c.id],\n intents: [\n addPoint(foot, { kind: 'angleBisectorFoot', from: vertex, onLine: side }),\n addPoint(e, { kind: 'secondIntersection', line: vertex + foot, circle, other: vertex }),\n ],\n });\n continue;\n }\n }\n\n const fm = FOOT.exec(c.text);\n if (!fm) continue;\n // vertex: \"góc BAC\" → chữ giữa (g2); \"góc A\" → g1 (g2,g3 rỗng).\n const vertex = fm[2] && fm[3] ? fm[2] : fm[1];\n const side = fm[4] + fm[5];\n const foot = fm[6];\n if (side.includes(foot) || side.includes(vertex)) continue;\n const intents = [addPoint(foot, { kind: 'angleBisectorFoot', from: vertex, onLine: side })];\n\n // Giao đường tròn ngoại tiếp E (nếu nêu \"cắt (O) tại E\"). Line = vertex+foot\n // (tia phân giác qua A,D); other = vertex (A nằm trên (O) + trên tia).\n const cm = CIRCLE_CUT.exec(c.text);\n if (cm) {\n const circle = cm[1];\n const e = cm[2];\n const other = cm[3] ?? vertex;\n if (e !== foot && e !== vertex) {\n intents.push(\n addPoint(e, { kind: 'secondIntersection', line: vertex + foot, circle, other }),\n );\n }\n }\n out.push({ ruleId: 'angleBisectorCutsSideCircle', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circleCutsArcSecond.ts\n//\n// Đường tròn (đường kính XY) CẮT CUNG của một đường tròn khác tại giao THỨ HAI:\n// \"đường tròn đường kính MP cắt cung nhỏ BC tại điểm N khác M\"\n// → N = circleSecondIntersection(c1=kMP, c2=<đường tròn chứa cung BC>, exclude=M)\n//\n// c1 = đường tròn đường kính XY (diameterCircleSecant đặt tên \"kXY\").\n// c2 = đường tròn NGOẠI TIẾP/chính trong đề chứa cung PQ — resolve qua\n// \"nội tiếp/ngoại tiếp (đường tròn)? (tâm)? (O)\". exclude = \"khác M\" (điểm\n// chung 2 đường tròn — thường là đầu mút đường kính nằm trên cung).\n//\n// Nếu không xác định được c2 / exclude → BỎ QUA (escalate fail-safe).\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\nconst PREFILTER = /đường\\s*tròn\\s+đường\\s*kính\\s+[A-Z]{2}[^.]{0,40}?cắt\\s+(?:cung|(?:nửa\\s+)?đường\\s*tròn)/u;\n\n// \"đường tròn đường kính XY cắt cung (nhỏ|lớn)? PQ ... (tại|ở) (điểm)? N (khác M)?\"\nconst CUTS_ARC = new RegExp(\n 'đường\\\\s*tròn\\\\s+đường\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])' +\n '[^.]{0,20}?cắt\\\\s+cung\\\\s+(?:nhỏ\\\\s+|lớn\\\\s+)?([A-Z])([A-Z])(?![A-Z])' +\n '[^.]{0,24}?(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+([A-Z])(?![A-Z]))?',\n 'u',\n);\n// \"đường tròn đường kính XY cắt (nửa)? đường tròn (O') (tại|ở) N (khác M)?\"\nconst CUTS_CIRCLE = new RegExp(\n 'đường\\\\s*tròn\\\\s+đường\\\\s*kính\\\\s+([A-Z])([A-Z])(?![A-Z])' +\n \"[^.]{0,20}?cắt\\\\s+(?:nửa\\\\s+)?đường\\\\s*tròn\\\\s*\\\\(\\\\s*([A-Z])(?:['′]?)\\\\s*\\\\)\" +\n '[^.]{0,24}?(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+([A-Z])(?![A-Z]))?',\n 'u',\n);\n\n// Đường tròn ngoại tiếp/chính chứa cung: \"nội tiếp/ngoại tiếp (đường tròn)?\n// (tâm)? (O)/tâm O\". Trả tâm thô (resolveCircleNames map nếu cần).\nconst CIRCUM = /(?:nội\\s*tiếp|ngoại\\s*tiếp)\\s+(?:đường\\s*tròn\\s+)?(?:tâm\\s+)?\\(?\\s*([A-Z])(?:['′]?)\\s*\\)?/u;\n\nexport const circleCutsArcSecondRule: LanguageRule = {\n id: 'circleCutsArcSecond',\n priority: 45, // sau mọi rule dựng đường tròn + điểm chung\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n // Dạng cắt CUNG: c2 = đường tròn ngoại tiếp/chính (chứa cung).\n const ma = CUTS_ARC.exec(c.text);\n if (ma) {\n const c1 = `k${ma[1]}${ma[2]}`;\n const name = ma[5];\n const exclude = ma[6] ?? ma[1]; // \"khác M\" hoặc đầu mút đường kính thứ nhất\n const cm = CIRCUM.exec(ctx.problem);\n if (cm && name !== exclude) {\n out.push({\n ruleId: 'circleCutsArcSecond',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'circleSecondIntersection', c1, c2: cm[1], exclude })],\n });\n continue;\n }\n }\n // Dạng cắt (nửa)? đường tròn (O') — c2 nêu tường minh.\n const mc = CUTS_CIRCLE.exec(c.text);\n if (mc) {\n const c1 = `k${mc[1]}${mc[2]}`;\n const c2 = mc[3];\n const name = mc[4];\n const exclude = mc[5] ?? mc[1];\n if (name !== exclude) {\n out.push({\n ruleId: 'circleCutsArcSecond',\n clauseIds: [c.id],\n intents: [addPoint(name, { kind: 'circleSecondIntersection', c1, c2, exclude })],\n });\n }\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/angleBisectorCutsCircleLine.ts\n//\n// Phân giác của một GÓC (3 đỉnh) cắt ĐƯỜNG TRÒN tại E và (tuỳ chọn) cắt 1 đường\n// thẳng tại F — KHÔNG có chân trên cạnh đối (khác angleBisectorCutsSideCircle):\n// \"Phân giác trong của góc DAB cắt đường tròn tại E và cắt CH tại F\"\n// → E = secondIntersection(line=bisDAB, circle, other=A)\n// F = intersection(bisDAB, CH)\n//\n// bisDAB = tia phân giác (angleBisectorAngle priority 62 dựng TRƯỚC, cùng quy\n// ước tên \"bis\"+p1+vertex+p2). vertex (đỉnh góc) = chữ GIỮA; vertex nằm trên\n// đường tròn (đề kiểu nội tiếp/đường kính) nên other=vertex hợp lệ.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint } from './_shared';\n\nconst PREFILTER = /[Pp]hân\\s*giác[^.]{0,40}?cắt\\s+(?:đường\\s*tròn|\\()/u;\n\n// \"phân giác (trong)? (của)? góc XYZ cắt (đường tròn|(O)) (tại|ở) E (khác V)?\n// (và (cắt)? (đường thẳng|cạnh|đoạn)? L (tại|ở) F)?\"\nconst RE = new RegExp(\n '[Pp]hân\\\\s*giác\\\\s+(?:trong\\\\s+)?(?:của\\\\s+)?góc\\\\s+([A-Z])([A-Z])([A-Z])(?![A-Z])' +\n \"\\\\s+cắt\\\\s+(?:đường\\\\s*tròn\\\\s*)?(?:\\\\(\\\\s*([A-Z])(?:['′]?)\\\\s*\\\\))?\" +\n '[^.]{0,16}?(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+[A-Z](?![A-Z]))?' +\n '(?:\\\\s*,?\\\\s*và\\\\s+(?:cắt\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?([A-Z]{2})(?![A-Z])\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z]))?',\n 'u',\n);\n\n// Đường tròn toàn đề khi clause nêu \"đường tròn\" trần (không \"(X)\"): lấy \"(X)\" /\n// \"tâm X\" duy nhất → emit raw (resolveCircleNames map \"_c\" nếu cần).\nconst ANY_CIRCLE = /(?:đường\\s*tròn\\s*\\(\\s*([A-Z])(?:['′]?)\\s*\\)|tâm\\s+([A-Z])(?![A-Za-z]))/u;\n\nexport const angleBisectorCutsCircleLineRule: LanguageRule = {\n id: 'angleBisectorCutsCircleLine',\n // 49: TRÊN lineCircleIntersection (47) — F phải dựng trước khi \"DF cắt (O) tại\n // N\" tham chiếu đoạn DF; DƯỚI inputs (angleBisectorAngle 62, onSegment 62,\n // perpFoot 65 dựng tia/C/H trước).\n priority: 49,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = RE.exec(c.text);\n if (!m) continue;\n const [p1, vertex, p2] = [m[1], m[2], m[3]];\n const circleInline = m[4];\n const e = m[5];\n const lineF = m[6];\n const f = m[7];\n const bis = `bis${p1}${vertex}${p2}`;\n\n let circle: string | undefined = circleInline;\n if (!circle) {\n const cm = ANY_CIRCLE.exec(ctx.problem);\n circle = cm?.[1] ?? cm?.[2];\n }\n if (!circle) continue;\n if (e === vertex) continue;\n\n const intents: IntentT[] = [\n addPoint(e, { kind: 'secondIntersection', line: bis, circle, other: vertex }),\n ];\n // F = giao tia phân giác với 1 đường thẳng (nếu nêu \"và cắt L tại F\").\n if (lineF && f && f !== e && !lineF.includes(f)) {\n intents.push(addPoint(f, { kind: 'intersection', of: [bis, lineF] }));\n }\n out.push({ ruleId: 'angleBisectorCutsCircleLine', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/tangentLineNamedAtPoint.ts\n//\n// Tiếp tuyến ĐẶT TÊN bằng chữ thường (d, d1, a…) tại 1 điểm TRÊN đường tròn:\n// \"từ một điểm A trên (O) kẻ tiếp tuyến d với (O)\"\n// → draw-line d {kind:tangentAt, through:A, circle:O}\n//\n// A là tiếp điểm (đã onCircle qua onCirclePoint). Đường d sau đó được dùng làm\n// đoạn chứa điểm (\"Trên đường thẳng d lấy điểm M\" — onSegmentPoint nhận tên\n// đường chữ thường). circle emit raw (resolveCircleNames map \"_c\" nếu cần).\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawLine } from './_shared';\n\nconst PREFILTER = /(?:trên|thuộc)\\s+\\(\\s*[A-Z][^)]*\\)[^.]{0,24}?kẻ\\s+tiếp\\s*tuyến\\s+[a-z]/u;\n\n// \"(từ|qua)? (một)? điểm A (trên|thuộc) (O) ... kẻ tiếp tuyến d (với (O))?\"\nconst RE = new RegExp(\n '(?:từ\\\\s+|qua\\\\s+)?(?:một\\\\s+)?điểm\\\\s+([A-Z])(?![A-Z])\\\\s+(?:trên|thuộc)\\\\s+' +\n \"\\\\(\\\\s*([A-Z])(?:['′]?)\\\\s*\\\\)\" +\n '[^.]{0,24}?kẻ\\\\s+tiếp\\\\s*tuyến\\\\s+([a-z][0-9]?)(?!\\\\p{L})',\n 'gu',\n);\n\nexport const tangentLineNamedAtPointRule: LanguageRule = {\n id: 'tangentLineNamedAtPoint',\n priority: 63, // cao như tangentAt — đường d phải dựng trước điểm-trên-d\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const through = m[1];\n const circle = m[2];\n const line = m[3];\n out.push({\n ruleId: 'tangentLineNamedAtPoint',\n clauseIds: [c.id],\n intents: [drawLine(line, 'tangentAt', { through, circle })],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/givenDiameterCircle.ts\n//\n// Đường tròn đường kính CHO TRƯỚC, KHÔNG tên tâm, KHÔNG đa giác:\n// \"Cho nửa đường tròn đường kính AB = 2R. Từ A và B kẻ hai tiếp tuyến…\"\n// → A, B là điểm CHO (free); đường tròn \"kAB\" do diameterCircleSecant dựng.\n//\n// diameterCircleSecant chỉ vẽ đường tròn \"kXY\" (giả định X,Y có sẵn từ ngữ cảnh\n// — vd Simson: M,C phái sinh). Khi đường tròn đường kính là GIVEN gốc (không tam\n// giác/tứ giác/đa giác), 2 đầu mút CHƯA được rule nào dựng → cần free.\n//\n// GUARD (tránh dựng free đè điểm phái sinh):\n// - KHÔNG có tâm đặt tên (\"(O)\"/\"tâm O\") — circleDiameter lo dạng đó (đã free\n// A,B + center).\n// - KHÔNG có đa giác (tam giác/tứ giác/hình …) — nếu có, A,B có thể là đỉnh\n// hình (do triangle/quad dựng) → không free.\n// Priority CAO (67) để A,B dựng TRƯỚC điểm phái sinh tham chiếu (intersection 45…).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, connect } from './_shared';\n\nconst UNNAMED_DIAMETER = /(?:nửa\\s+)?đường\\s*tròn\\s+đường\\s*kính\\s+([A-Z])([A-Z])(?![A-Z])/u;\nconst HAS_NAMED_CENTER = /đường\\s*tròn\\s*(?:\\(\\s*[A-Z]|tâm\\s+[A-Z])/u;\nconst HAS_POLYGON = /tam\\s*giác|tứ\\s*giác|hình\\s+(?:vuông|chữ|bình|thoi|thang)/u;\n// Đề dùng O như điểm (\"đoạn OD\", \"tia OA\") dù đường tròn KHÔNG nêu tâm (vao10:94)\n// → tâm ngầm của đường tròn đường kính = O, emit midpoint cho ref O sống.\n// HAS_NAMED_CENTER đã loại \"(O)\"/\"tâm O\" nên O ở đây chắc chắn là tâm ngầm.\nconst USES_O = /(?<![A-Za-z])O[A-Z]?(?![a-z])/u;\n\nexport const givenDiameterCircleRule: LanguageRule = {\n id: 'givenDiameterCircle',\n priority: 67,\n languages: ['vi'],\n patterns: [UNNAMED_DIAMETER],\n match(ctx) {\n if (HAS_NAMED_CENTER.test(ctx.problem)) return [];\n if (HAS_POLYGON.test(ctx.problem)) return [];\n for (const c of ctx.clauses) {\n const m = UNNAMED_DIAMETER.exec(c.text);\n if (!m) continue;\n const [a, b] = [m[1], m[2]];\n if (a === b) continue;\n const intents = [\n addPoint(a, { kind: 'free' }),\n addPoint(b, { kind: 'free' }),\n connect(a, b, 'segment'),\n ];\n if (a !== 'O' && b !== 'O' && USES_O.test(ctx.problem)) {\n intents.push(addPoint('O', { kind: 'midpoint', of: `${a}${b}` }));\n }\n return [\n {\n ruleId: 'givenDiameterCircle',\n clauseIds: [c.id],\n intents,\n },\n ];\n }\n return [];\n },\n};\n","// src/stamps/geometry-2d/ai/rules/multiDiameterCircles.ts\n//\n// NHIỀU nửa đường tròn đường kính + tâm đặt tên, phân phối (arbelos):\n// \"Vẽ … các nửa đường tròn có đường kính theo thứ tự là AB, AC, CB và có tâm\n// theo thứ tự là O, I, K\"\n// → 3 cặp (AB,O),(AC,I),(CB,K). Mỗi cặp: center=midpoint(2 đầu mút),\n// circle \"<center>_c\" diameter [đầu mút]. 2 đầu mút của đường kính ĐẦU\n// (AB) = free (điểm cho); đầu mút khác (C) = onSegment(AB) (điểm trong).\n//\n// Bù circleDiameter (1 đường tròn / clause) + diameterCircleSecant (không tâm).\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, connect, drawCircle } from './_shared';\n\n// \"đường kính (theo thứ tự)? (là)? <blob đôi HOA> … tâm (theo thứ tự)? (là)? <blob HOA>\"\nconst RE =\n /đường\\s*kính\\s+(?:theo\\s+thứ\\s+tự\\s+)?(?:là\\s+)?((?:[A-Z]{2}\\s*,\\s*)+[A-Z]{2})(?![A-Z])[^.]{0,30}?tâm\\s+(?:theo\\s+thứ\\s+tự\\s+)?(?:là\\s+)?((?:[A-Z](?:['′])?\\s*,\\s*)+[A-Z](?:['′])?)(?![A-Z])/u;\n\nconst PREFILTER = /đường\\s*kính[^.]{0,40}?tâm/u;\n\nexport const multiDiameterCirclesRule: LanguageRule = {\n id: 'multiDiameterCircles',\n priority: 67, // như circleDiameter — dựng đầu mút + tâm trước điểm phái sinh\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n for (const c of ctx.clauses) {\n const m = RE.exec(c.text);\n if (!m) continue;\n const diams = m[1].split(',').map((s) => s.trim());\n const centers = m[2].split(',').map((s) => s.trim().replace('′', \"'\"));\n if (diams.length !== centers.length || diams.length < 2) continue;\n // mỗi đường kính = cặp 2 đỉnh HOA.\n const pairs = diams.map((d) => [d[0], d[1]] as const);\n if (pairs.some((p) => p[0] === p[1])) continue;\n\n // Đầu mút đường kính ĐẦU = extremes (free). Đầu mút khác = điểm trong đoạn đầu.\n const [exA, exB] = pairs[0];\n const intents: IntentT[] = [addPoint(exA, { kind: 'free' }), addPoint(exB, { kind: 'free' })];\n const seen = new Set([exA, exB]);\n for (const [p0, p1] of pairs) {\n for (const e of [p0, p1]) {\n if (seen.has(e)) continue;\n seen.add(e);\n intents.push(addPoint(e, { kind: 'onSegment', of: `${exA}${exB}` }));\n }\n }\n intents.push(connect(exA, exB, 'segment')); // đoạn đường kính lớn\n // mỗi cặp: tâm = trung điểm, đường tròn \"<center>_c\" đường kính.\n for (let i = 0; i < pairs.length; i++) {\n const [x, y] = pairs[i];\n const center = centers[i];\n if (center === x || center === y) continue;\n intents.push(addPoint(center, { kind: 'midpoint', of: `${x}${y}` }));\n intents.push(drawCircle(`${center}_c`, 'diameter', { endpoints: [x, y] }));\n }\n return [{ ruleId: 'multiDiameterCircles', clauseIds: [c.id], intents }];\n }\n return [];\n },\n};\n","// src/stamps/geometry-2d/ai/rules/cutCirclesDistrib.ts\n//\n// Phân phối giao của 2 ĐOẠN với 2 ĐƯỜNG TRÒN khác nhau (arbelos):\n// \"Gọi M, N theo thứ tự là giao điểm của EA, EB với các nửa đường tròn (I), (K)\"\n// → M = secondIntersection(EA, (I), other=<đầu mút EA ∈ đường kính của (I)>)\n// N = secondIntersection(EB, (K), other=<tương tự>)\n//\n// \"other\" (điểm chung đã biết) = đầu mút đoạn nằm trên đường tròn đó = đầu mút\n// trùng 1 trong 2 đầu đường kính của đường tròn (lấy từ map \"đường kính … tâm …\").\n// Không xác định được → fallback đầu mút thứ hai (vẫn nằm trên đường line∩circle).\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint } from './_shared';\n\n// \"M, N (theo thứ tự|lần lượt)? (là)? giao điểm (của)? EA, EB (với|cắt) (các)?\n// (nửa)? đường tròn (I), (K)\"\nconst RE = new RegExp(\n '([A-Z])\\\\s*,\\\\s*([A-Z])(?![A-Z])\\\\s+(?:theo\\\\s+thứ\\\\s+tự\\\\s+|lần\\\\s*lượt\\\\s+)?(?:là\\\\s+)?' +\n 'giao\\\\s*điểm\\\\s+(?:của\\\\s+)?([A-Z]{2})\\\\s*,\\\\s*([A-Z]{2})(?![A-Z])\\\\s+(?:với|cắt)\\\\s+' +\n \"(?:các\\\\s+)?(?:(?:nửa\\\\s+)?đường\\\\s*tròn\\\\s*)?\\\\(\\\\s*([A-Z](?:['′])?)\\\\s*\\\\)\\\\s*,?\\\\s*(?:và\\\\s+)?\\\\(\\\\s*([A-Z](?:['′])?)\\\\s*\\\\)\",\n 'u',\n);\n\n// map tâm → 2 đầu mút đường kính, từ \"đường kính … <blob> … tâm … <blob>\".\nconst DIA_CENTERS = /đường\\s*kính\\s+(?:theo\\s+thứ\\s+tự\\s+)?(?:là\\s+)?((?:[A-Z]{2}\\s*,\\s*)+[A-Z]{2})(?![A-Z])[^.]{0,30}?tâm\\s+(?:theo\\s+thứ\\s+tự\\s+)?(?:là\\s+)?((?:[A-Z](?:['′])?\\s*,\\s*)+[A-Z](?:['′])?)(?![A-Z])/u;\n\nfunction diameterMap(problem: string): Map<string, [string, string]> {\n const m = DIA_CENTERS.exec(problem);\n const map = new Map<string, [string, string]>();\n if (!m) return map;\n const diams = m[1].split(',').map((s) => s.trim());\n const centers = m[2].split(',').map((s) => s.trim().replace('′', \"'\"));\n if (diams.length !== centers.length) return map;\n for (let i = 0; i < diams.length; i++) {\n if (diams[i].length === 2) map.set(centers[i], [diams[i][0], diams[i][1]]);\n }\n return map;\n}\n\nconst PREFILTER = /giao\\s*điểm\\s+(?:của\\s+)?[A-Z]{2}\\s*,\\s*[A-Z]{2}[^.]{0,30}?(?:với|cắt)\\s+(?:các\\s+)?(?:(?:nửa\\s+)?đường\\s*tròn\\s*)?\\(/u;\n\nexport const cutCirclesDistribRule: LanguageRule = {\n id: 'cutCirclesDistrib',\n priority: 45,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const map = diameterMap(ctx.problem);\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = RE.exec(c.text);\n if (!m) continue;\n const [n1, n2, l1, l2, c1, c2] = [m[1], m[2], m[3], m[4], m[5], m[6]];\n const pickOther = (line: string, center: string): string => {\n const ends = map.get(center);\n if (ends) {\n if (line.includes(ends[0])) return ends[0];\n if (line.includes(ends[1])) return ends[1];\n }\n return line[1];\n };\n const intents: IntentT[] = [];\n if (!l1.includes(n1)) intents.push(addPoint(n1, { kind: 'secondIntersection', line: l1, circle: c1, other: pickOther(l1, c1) }));\n if (!l2.includes(n2)) intents.push(addPoint(n2, { kind: 'secondIntersection', line: l2, circle: c2, other: pickOther(l2, c2) }));\n if (intents.length > 0) out.push({ ruleId: 'cutCirclesDistrib', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/givenNamedCircle.ts\n//\n// Đường tròn ĐẶT TÊN cho trước, TRƠ tên (không bán kính số/chữ, không đường kính,\n// không nội/ngoại tiếp tam giác) NHƯNG CÓ điểm khai báo trên nó:\n// \"Cho đường tròn (O) và hai điểm B, C cố định trên đường tròn. Lấy A trên (O)…\"\n// → circle O (centerRadius bán kính canonical, O tự do). onCircle A,B,C trỏ O.\n//\n// circleRadius CỐ Ý bỏ \"(O)\" trơ (không số/chữ/\"đi qua\"); circleTriangle chỉ lo\n// circle gắn tam giác (nội/ngoại tiếp). Khi (O) là GIVEN gốc + có điểm trên nó\n// (onCirclePoint trỏ \"O\"/\"O_c\"), cần dựng circle \"O\" để ref hợp lệ. Đề olympiad\n// dạng \"Cho (O), A,B,C ∈ (O)\" cực phổ biến.\n//\n// resolveCircleNames sẽ đổi circle \"O\"→\"O_c\" + thêm tâm O free (center===name) và\n// map onCircle ref \"O\"→\"O_c\" — nhất quán.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawCircle, CIRCLE_KW } from './_shared';\nimport { SYMBOLIC_RADIUS } from './circleRadius';\n\n// \"(X)\" trơ: 1 ký tự HOA trong ngoặc, KHÔNG \";\"/\",\" (radius) bên trong.\nconst BARE_PAREN = /\\(\\s*([A-Z])\\s*\\)/gu;\n// Có điểm trên đường tròn (onCircle-style) → circle không \"trơ\".\nconst HAS_POINTS_ON = /(?:trên|thuộc)\\s+(?:nửa\\s+)?(?:đường\\s*tròn|cung|\\(\\s*[A-Z]\\s*\\))/u;\n\nexport const givenNamedCircleRule: LanguageRule = {\n id: 'givenNamedCircle',\n priority: 74, // dưới circleRadius(75)/circleTriangle, trên điểm onCircle(64)\n languages: ['vi'],\n patterns: [/\\(\\s*[A-Z]\\s*\\)/u],\n match(ctx) {\n if (!HAS_POINTS_ON.test(ctx.problem)) return [];\n const out: RuleMatch[] = [];\n const seen = new Set<string>();\n BARE_PAREN.lastIndex = 0;\n for (const m of ctx.problem.matchAll(BARE_PAREN)) {\n const center = m[1];\n if (seen.has(center)) continue;\n const c = center; // single [A-Z]\n // Bỏ qua nếu tâm này CÓ qualifier khác (rule khác lo): bán kính số/chữ\n // \"(O; …)\", đường kính, nội/ngoại tiếp.\n if (new RegExp(`\\\\(\\\\s*${c}\\\\s*[;,]`, 'u').test(ctx.problem)) continue; // (O; R)/(O; 3)\n if (new RegExp(`\\\\(\\\\s*${c}\\\\s*\\\\)[^.]{0,30}?đường\\\\s*kính|đường\\\\s*kính[^.]{0,30}?\\\\(\\\\s*${c}\\\\s*\\\\)`, 'u').test(ctx.problem)) continue;\n if (new RegExp(`(?:nội|ngoại)\\\\s*tiếp[^.]{0,30}?\\\\(\\\\s*${c}\\\\s*\\\\)|\\\\(\\\\s*${c}\\\\s*\\\\)[^.]{0,30}?(?:nội|ngoại)\\\\s*tiếp`, 'u').test(ctx.problem)) continue;\n // \"(O)\" phải là đường tròn (đứng sau \"đường tròn\"/\"(nửa) đường tròn\") HOẶC\n // đề mở bằng \"Cho (đường tròn)? (O)\". Yêu cầu CIRCLE_KW gần để không nuốt\n // \"(O)\" chú thích điểm.\n if (!new RegExp(`${CIRCLE_KW}\\\\s*\\\\(\\\\s*${c}\\\\s*\\\\)`, 'u').test(ctx.problem)) continue;\n seen.add(center);\n // claim clause chứa \"(center)\".\n const owner = ctx.clauses.find((cl) => new RegExp(`\\\\(\\\\s*${c}\\\\s*\\\\)`, 'u').test(cl.text));\n out.push({\n ruleId: 'givenNamedCircle',\n clauseIds: owner ? [owner.id] : [],\n intents: [drawCircle(center, 'centerRadius', { center, radius: SYMBOLIC_RADIUS })],\n });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/twoPerpLinesMeet.ts\n//\n// Giao của HAI đường vuông-góc-qua-điểm.\n//\n// Dạng 1 (gốc, 2 mệnh đề tách rời):\n// \"Đường thẳng qua M vuông góc với BM cắt đường thẳng qua N vuông góc với CN tại S\"\n// → prpM = perpThrough(M, BM); prpN = perpThrough(N, CN); S = prpM ∩ prpN.\n//\n// Dạng 2 (phân phối — gộp 2 đường vào 1 cụm):\n// \"Đường thẳng qua E,F lần lượt vuông góc với OC,OB cắt nhau tại X\"\n// → zip E↔OC, F↔OB → prpE = perpThrough(E, OC); prpF = perpThrough(F, OB);\n// X = prpE ∩ prpF.\n// (parallelPerp chỉ catch ĐƯỜNG ĐẦU \"qua E ⊥ OC\" → prpE, KHÔNG dựng prpF/X →\n// coverage báo named-missing X. Rule này emit đủ cả 3; prpE byte-identical với\n// parallelPerp nên dedup theo JSON.)\n//\n// Tên đường theo quy ước parallelPerp (\"prp\"+điểm-qua) → dedup nếu rule khác đã\n// dựng cùng đường. KHÁC perpThroughCutsLines (1 đường ⊥ cắt 2 đường có sẵn): ở\n// đây 2 đường ⊥ riêng biệt giao NHAU.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + (?!\\p{L}).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawLine } from './_shared';\n\n// PREFILTER nhận CẢ hai dạng: (a) \"…cắt đường thẳng qua…\" (gốc), (b) \"…cắt\n// nhau…\" (phân phối). Đều mở đầu \"Đường thẳng qua <P> … vuông góc/⊥\".\nconst PREFILTER =\n /[Đđ]ường\\s*thẳng\\s+qua\\s+[A-Z][^.]{0,30}?(?:vuông\\s*góc|⊥)[^.]{0,40}?cắt\\s+(?:[Đđ]ường\\s*thẳng\\s+qua|nhau)/u;\n\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*thẳng\\\\s+qua\\\\s+([A-Z])(?!\\\\p{L})\\\\s+(?:vuông\\\\s*góc|⊥)\\\\s+(?:với\\\\s+)?([A-Z])([A-Z])(?![A-Z])' +\n '[^.]{0,20}?cắt\\\\s+[Đđ]ường\\\\s*thẳng\\\\s+qua\\\\s+([A-Z])(?!\\\\p{L})\\\\s+(?:vuông\\\\s*góc|⊥)\\\\s+(?:với\\\\s+)?([A-Z])([A-Z])(?![A-Z])' +\n '\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// Dạng phân phối: \"qua <P1>,<P2> (lần lượt|theo thứ tự)? ⊥ <L1>,<L2> cắt nhau tại <S>\".\n// P1,P2 = HOA đơn; L1,L2 = cặp đỉnh (2 HOA); S = HOA đơn. Zip P1↔L1, P2↔L2.\nconst RE_DISTRIB = new RegExp(\n '[Đđ]ường\\\\s*thẳng\\\\s+qua\\\\s+([A-Z])(?!\\\\p{L})\\\\s*,\\\\s*([A-Z])(?!\\\\p{L})\\\\s+' +\n '(?:lần\\\\s*lượt\\\\s+|theo\\\\s*thứ\\\\s*tự\\\\s+)?(?:vuông\\\\s*góc|⊥)\\\\s+(?:với\\\\s+)?' +\n '([A-Z])([A-Z])(?![A-Z])\\\\s*,\\\\s*([A-Z])([A-Z])(?![A-Z])' +\n '[^.]{0,20}?cắt\\\\s+nhau\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Z])',\n 'gu',\n);\n\nexport const twoPerpLinesMeetRule: LanguageRule = {\n id: 'twoPerpLinesMeet',\n priority: 49, // sau parallelPerp (dựng đường), trước/đủ để S tham chiếu 2 đường\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n const emit = (c: { id: number }, p1: string, l1: string, p2: string, l2: string, s: string) => {\n if (p1 === p2 || s === p1 || s === p2) return;\n const n1 = `prp${p1}`;\n const n2 = `prp${p2}`;\n out.push({\n ruleId: 'twoPerpLinesMeet',\n clauseIds: [c.id],\n intents: [\n drawLine(n1, 'perpThrough', { through: p1, to: l1 }),\n drawLine(n2, 'perpThrough', { through: p2, to: l2 }),\n addPoint(s, { kind: 'intersection', of: [n1, n2] }),\n ],\n });\n };\n for (const c of ctx.clauses) {\n // Dạng gốc (2 mệnh đề tách rời).\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n emit(c, m[1], m[2] + m[3], m[4], m[5] + m[6], m[7]);\n }\n // Dạng phân phối: zip <P1>↔<L1>, <P2>↔<L2>.\n RE_DISTRIB.lastIndex = 0;\n for (const m of c.text.matchAll(RE_DISTRIB)) {\n emit(c, m[1], m[3] + m[4], m[2], m[5] + m[6], m[7]);\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/circumcircleCutsLine.ts\n//\n// Đường tròn ngoại tiếp 1 tam giác cắt 1 ĐƯỜNG THẲNG (cặp đỉnh) tại điểm thứ 2:\n// \"Đường tròn ngoại tiếp tam giác HBC cắt BI tại K khác B\"\n// → wHBC = through3(H,B,C); K = circle∩line, loại điểm chung (B nằm trên cả\n// wHBC lẫn line BI). other = đỉnh chung của tam giác và line (\"khác B\" hoặc\n// suy: đầu mút line nằm trong bộ 3 đỉnh).\n//\n// KHÁC lineCircleIntersection (đường tròn ĐẶT TÊN \"(O)\"): ở đây đường tròn là\n// CIRCUMCIRCLE vô danh của 1 tam giác → tự synth tên `w<verts>` (giống\n// circumcirclePairMeet) + dựng through3.\n//\n// \\b không khớp ký tự Việt → (?!\\p{L}) + cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { drawCircle, addPoint } from './_shared';\n\nconst PREFILTER = /[Đđ]ường\\s*tròn\\s+ngoại\\s*tiếp\\s+(?:tam\\s*giác\\s+)?[A-Z]{3}[^.]{0,20}?cắt\\s+[A-Z]{2}/u;\n\n// group1 = 3 đỉnh tam giác, 2 = line (cặp đỉnh), 3 = giao K, 4 = \"khác W\" (optional).\nconst RE = new RegExp(\n '[Đđ]ường\\\\s*tròn\\\\s+ngoại\\\\s*tiếp\\\\s+(?:tam\\\\s*giác\\\\s+)?([A-Z]{3})(?![A-Z])\\\\s+cắt\\\\s+(?:lại\\\\s+)?' +\n '(?:đường\\\\s*thẳng\\\\s+|đoạn\\\\s+|tia\\\\s+|cạnh\\\\s+)?([A-Z]{2})(?![A-Z])\\\\s+(?:tại|ở)\\\\s+' +\n '(?:điểm\\\\s+(?:thứ\\\\s+hai\\\\s+)?)?([A-Z])(?![A-Z])(?:\\\\s+khác\\\\s+([A-Z])(?![A-Z]))?',\n 'gu',\n);\n\nexport const circumcircleCutsLineRule: LanguageRule = {\n id: 'circumcircleCutsLine',\n priority: 58, // sau circleTriangle/cevian; trước intersection(45)\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const tri = m[1].split('');\n const line = m[2];\n const k = m[3];\n // Điểm chung (loại): \"khác W\" tường minh, else đầu mút line nằm trong tam giác.\n const shared = m[4] ?? line.split('').find((v) => tri.includes(v));\n if (!shared || tri.includes(k) || line.includes(k)) continue;\n const w = `w${m[1]}`;\n out.push({\n ruleId: 'circumcircleCutsLine',\n clauseIds: [c.id],\n intents: [\n drawCircle(w, 'through3', { points: tri }),\n addPoint(k, { kind: 'secondIntersection', line, circle: w, other: shared }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/lineConcurrency.ts\n//\n// Điểm ĐỒNG QUY của một bộ đường trong tam giác. Đường cao / phân giác trong /\n// trung trực / trung tuyến của tam giác đồng quy tại 1 điểm; engine chỉ cần\n// \"lấy 2 đường giao nhau\" — mà các center kind (orthocenter/incenter/\n// circumcenter/centroid) Đà render đúng như vậy (dựng 2 đường ẩn → intersection)\n// và chỉ cần tam giác + tên điểm (KHÔNG cần đặt tên đoạn).\n//\n// \"Ba đường cao của tam giác ABC đồng quy tại H\" → H = orthocenter ΔABC\n// \"Ba đường phân giác … cắt nhau tại I\" → I = incenter\n// \"Ba đường trung trực … cắt nhau tại O\" → O = circumcenter\n// \"Ba đường trung tuyến … đồng quy tại G\" → G = centroid\n//\n// GUARD (giữ path cũ byte-identical): với cao/phân giác/trung tuyến, nếu clause\n// đã đặt tên ≥2 đoạn (vd \"AD, BE, CF\") thì rule `intersection`/`perpFoot`/`cevian`\n// cũ đã dựng điểm giao của 2 đoạn THẬT → rule này KHÔNG emit (nhường). Trung trực\n// miễn guard (đường trung trực không đặt tên cặp-đỉnh nên `intersection` generic\n// không bắt → luôn emit circumcenter).\n//\n// Regex tiếng Việt: cờ 'u' + lookaround (?!\\p{L}) thay \\b (ASCII \\b không khớp\n// quanh ký tự Việt). Keyword có thể HOA đầu câu ([Đđ]ường, [Bb]a, [Cc]ác).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\ntype CenterKind = 'orthocenter' | 'incenter' | 'circumcenter' | 'centroid';\n\n// TYPE đường → center kind. `kw` khớp cụm danh từ loại đường (lookaround Việt).\n// `guarded`: bật guard named-skip (cao/phân giác/trung tuyến). Trung trực = false.\ninterface LineType {\n kind: CenterKind;\n kw: RegExp;\n guarded: boolean;\n}\n\nconst LINE_TYPES: readonly LineType[] = [\n // \"đường cao\" (luôn có \"đường\"). \"cao\" trần quá generic nên bắt buộc \"đường\".\n { kind: 'orthocenter', kw: /(?<!\\p{L})[Đđ]ường\\s+cao(?!\\p{L})/u, guarded: true },\n // \"(đường|tia)? phân giác (trong)?\" — KHÔNG nhận \"phân giác ngoài\" (excenter, defer).\n { kind: 'incenter', kw: /(?<!\\p{L})phân\\s*giác(?!\\s+ngoài)(?!\\p{L})/u, guarded: true },\n // \"(đường)? trung trực\".\n { kind: 'circumcenter', kw: /(?<!\\p{L})trung\\s*trực(?!\\p{L})/u, guarded: false },\n // \"(đường)? trung tuyến\".\n { kind: 'centroid', kw: /(?<!\\p{L})trung\\s*tuyến(?!\\p{L})/u, guarded: true },\n];\n\n// Động từ đồng quy + tên điểm: \"cắt nhau / đồng quy / gặp nhau / cùng đi qua\"\n// (tại|qua)? (điểm)? <X HOA>.\nconst CONCURRENCY =\n /(?:cắt\\s+nhau|đồng\\s*quy|gặp\\s+nhau|cùng\\s+đi\\s+qua)\\s+(?:tại\\s+|qua\\s+)?(?:điểm\\s+)?([A-Z])(?!\\p{L})/u;\n\n// Cặp đỉnh đặt tên (vd \"AD\"), neo để không nuốt bộ-3 \"ABC\". Prime tuỳ chọn.\nconst VERTEX_PAIR = /(?<!\\p{L})[A-Z][A-Z](?:['′])?(?!\\p{L})/gu;\n\n// Tam giác toàn cục.\nconst TRI_G = /tam\\s*giác\\s+(?:(?:nhọn|cân|đều|vuông|tù)\\s+)*([A-Z])([A-Z])([A-Z])(?![A-Z])/gu;\n\n// Prefilter: bất kỳ loại đường nào trên toàn đề (đủ để chạy match; logic đầy đủ\n// trong match). Non-global để .test() không lệch lastIndex.\nconst PREFILTER: readonly RegExp[] = LINE_TYPES.map((t) => t.kw);\n\nfunction trianglesIn(text: string): string[][] {\n const out: string[][] = [];\n TRI_G.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = TRI_G.exec(text)) !== null) out.push([m[1], m[2], m[3]]);\n return out;\n}\n\n/** Tam giác duy nhất toàn đề (dedup theo bộ đỉnh), else undefined (nhập nhằng). */\nfunction uniqueTriangle(problem: string): string[] | undefined {\n const all = trianglesIn(problem);\n const distinct = new Map(all.map((t) => [t.join(''), t]));\n return distinct.size === 1 ? [...distinct.values()][0] : undefined;\n}\n\n/** Đếm cặp đỉnh đặt tên trong 1 đoạn (vd \"AD, BE, CF\" → 3). */\nfunction countPairs(slice: string): number {\n VERTEX_PAIR.lastIndex = 0;\n let n = 0;\n while (VERTEX_PAIR.exec(slice) !== null) n += 1;\n return n;\n}\n\n/**\n * Suy 3 đỉnh từ các cạnh nêu sau \"trung trực\" (vd \"của AB, BC, CA\" → A,B,C).\n * Union các đỉnh; đúng 3 đỉnh phân biệt → trả (sort ổn định). Khác → undefined.\n */\nfunction triangleFromSides(slice: string): string[] | undefined {\n VERTEX_PAIR.lastIndex = 0;\n const verts = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = VERTEX_PAIR.exec(slice)) !== null) {\n verts.add(m[0][0]);\n verts.add(m[0][1]);\n }\n return verts.size === 3 ? [...verts].sort() : undefined;\n}\n\n/**\n * Bộ đường tam giác đồng quy → add-point center kind. Tam giác: in-clause →\n * unique-toàn-đề. Trung trực thêm suy-đỉnh-từ-cạnh khi không có tam giác.\n */\nexport const lineConcurrencyRule: LanguageRule = {\n id: 'lineConcurrency',\n priority: 69,\n languages: ['vi'],\n patterns: PREFILTER,\n match(ctx) {\n const fallbackTri = uniqueTriangle(ctx.problem);\n const out: RuleMatch[] = [];\n\n for (const c of ctx.clauses) {\n const conc = CONCURRENCY.exec(c.text);\n if (!conc) continue; // clause không có verb đồng quy → bỏ\n const pointName = conc[1];\n const verbIndex = conc.index;\n\n for (const lt of LINE_TYPES) {\n const km = lt.kw.exec(c.text);\n if (!km) continue;\n const kwEnd = km.index + km[0].length;\n if (kwEnd > verbIndex) continue; // keyword phải đứng TRƯỚC verb\n\n const between = c.text.slice(kwEnd, verbIndex);\n\n // Guard named-skip: cao/phân giác/trung tuyến đã đặt tên ≥2 đoạn → nhường\n // rule cũ (intersection/perpFoot/cevian). Trung trực miễn (guarded=false).\n if (lt.guarded && countPairs(between) >= 2) continue;\n\n // Tam giác: in-clause trước; trung trực có thể suy từ cạnh; fallback đề.\n const inClause = trianglesIn(c.text);\n const tri =\n (inClause.length > 0 ? inClause[0] : undefined) ??\n (!lt.guarded ? triangleFromSides(between) : undefined) ??\n fallbackTri;\n if (!tri) continue; // không suy được tam giác → escalate\n\n out.push({\n ruleId: 'lineConcurrency',\n clauseIds: [c.id],\n intents: [addPoint(pointName, { kind: lt.kind, of: tri })],\n });\n break; // 1 clause = 1 loại đường đồng quy\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/twoCirclesMeet.ts\n//\n// HAI đường tròn TỰ DO cắt nhau tại 2 điểm:\n// \"Cho hai đường tròn (O) và (O′) cắt nhau tại hai điểm A, B\"\n// \"Cho hai đường tròn (O;R) và (O′;R′) cắt nhau tại A và B\"\n//\n// → 2 circleCR (tâm O, O′ — free center, bán kính canonical) + A,B = giao điểm\n// (circleIntersection which 0/1). Builder tự inject free coord cho 2 tâm;\n// `repairCircleIntersections` (chạy trong intentToDsl) dời tâm free để 2 đường\n// tròn THỰC SỰ cắt nhau 2 điểm (|r1-r2| < d < r1+r2). Hạ tầng circleIntersection\n// (intent + add-point builder + editor tool + render) đã có sẵn — rule này chỉ\n// nối dây.\n//\n// KHÁC diameterCirclePairwise/circumcirclePairMeet (đường tròn DẪN XUẤT từ\n// đường kính / ngoại tiếp): ở đây 2 đường tròn là FREE, chỉ ràng buộc \"cắt nhau\".\n//\n// Guard: 2 tâm phải KHÁC tên (OCR hay rơi prime \"(O′)\"→\"(O)\" làm 2 tên trùng →\n// hỏng dữ liệu, escalate). A≠B, A/B ∉ {tâm}.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u' + lookaround.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint, drawCircle } from './_shared';\nimport { SYMBOLIC_RADIUS } from './circleRadius';\n\nconst PREFILTER = /hai\\s+đường\\s*tròn[^.]{0,70}?cắt\\s+nhau/u;\n\n// \"(X)\" / \"(X;R)\" với X = 1 ký tự HOA + prime optional.\n// Bán kính ký hiệu \"R\"/\"R′\" HOẶC số có đơn vị \"5cm\" (httcd:84 \"(O; 5cm)\").\nconst CIRCLE = \"\\\\(\\\\s*([A-Z]['′]?)(?:\\\\s*[;,]\\\\s*(?:[Rr]['′]?|\\\\d+(?:[.,]\\\\d+)?\\\\s*[a-z]*))?\\\\s*\\\\)\";\nconst TWO_MEET = new RegExp(\n 'hai\\\\s+đường\\\\s*tròn\\\\s*' +\n CIRCLE +\n '\\\\s*(?:[;,]\\\\s*)?và\\\\s*' +\n CIRCLE +\n '[^.]{0,50}?cắt\\\\s+nhau\\\\s+(?:ở|tại)\\\\s+(?:hai\\\\s+điểm\\\\s+)?([A-Z])(?![A-Za-z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Za-z])',\n 'u',\n);\n\n/** Chuẩn hoá prime Unicode ′ → ASCII ' để khớp LabelZ. */\nconst norm = (s: string) => s.replace(/′/g, \"'\");\n\nexport const twoCirclesMeetRule: LanguageRule = {\n id: 'two-circles-meet',\n // TRÊN chord (71) / externalPoint (68): A,B (giao 2 đường tròn) là gốc nhiều\n // phái sinh downstream → dựng sớm. DƯỚI circleRadius (75) cho nhất quán.\n priority: 74,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const m = TWO_MEET.exec(ctx.problem);\n if (!m) return [];\n const c1 = norm(m[1]);\n const c2 = norm(m[2]);\n const a = m[3];\n const b = m[4];\n if (c1 === c2) return []; // 2 tâm trùng tên (OCR mất prime) → escalate\n if (a === b || a === c1 || a === c2 || b === c1 || b === c2) return [];\n\n // Clause chứa khai báo 2 đường tròn (để coverage claim).\n const declId = ctx.clauses.find((c) => /hai\\s+đường\\s*tròn/u.test(c.text))?.id;\n const out: RuleMatch[] = [];\n out.push({\n ruleId: 'two-circles-meet',\n clauseIds: declId === undefined ? [] : [declId],\n intents: [\n drawCircle(c1, 'centerRadius', { center: c1, radius: SYMBOLIC_RADIUS }),\n drawCircle(c2, 'centerRadius', { center: c2, radius: SYMBOLIC_RADIUS }),\n addPoint(a, { kind: 'circleIntersection', c1, c2, which: 0 }),\n addPoint(b, { kind: 'circleIntersection', c1, c2, which: 1 }),\n ],\n });\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/radius.ts\n//\n// Bán kính của đường tròn — đầu mút nằm TRÊN đường tròn:\n// \"Vẽ hai bán kính OA, OB\" → A,B onCircle(O) + đoạn OA, OB\n// \"Kẻ bán kính OM\" → M onCircle(O) + đoạn OM\n//\n// Token \"OX\": chữ ĐẦU = tâm (O), chữ SAU = đầu mút trên đường tròn. Nhiều bán\n// kính phải CÙNG tâm (cùng đường tròn). Đường tròn O phải đã được dựng bởi rule\n// khác (circleRadius \"(O;R)\" / chord …) — onCircle tham chiếu nó. theta phân biệt\n// để các đầu mút không trùng.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, connect } from './_shared';\n\nconst PREFILTER = /bán\\s*kính\\s+[A-Z]{2}/u;\n// \"Vẽ/Kẻ/Dựng (hai|ba|2|3|các)? bán kính OA(, OB)(, OC)?\" — danh sách cặp HOA.\nconst DRAW_RADII = new RegExp(\n '(?:[Vv]ẽ|[Kk]ẻ|[Dd]ựng)\\\\s+(?:hai\\\\s+|ba\\\\s+|2\\\\s+|3\\\\s+|các\\\\s+)?bán\\\\s*kính\\\\s+' +\n '([A-Z]{2}(?:\\\\s*(?:,|và)\\\\s*[A-Z]{2})*)(?![A-Z])',\n 'u',\n);\n\nconst THETA0 = 0.9;\nconst THETA_STEP = 1.1;\n\nexport const radiusRule: LanguageRule = {\n id: 'radius',\n priority: 60,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = DRAW_RADII.exec(c.text);\n if (!m) continue;\n const pairs = m[1].split(/,|và/).map((s) => s.trim()).filter(Boolean);\n if (pairs.length === 0) continue;\n const center = pairs[0][0];\n // Mọi bán kính phải cùng tâm + đầu mút khác tâm + khác nhau.\n const ends = pairs.map((p) => p[1]);\n if (!pairs.every((p) => p[0] === center)) continue;\n if (ends.some((e) => e === center) || new Set(ends).size !== ends.length) continue;\n const intents: IntentT[] = [];\n ends.forEach((e, i) => {\n intents.push(addPoint(e, { kind: 'onCircle', circle: center, theta: THETA0 + i * THETA_STEP }));\n intents.push(connect(center, e, 'segment'));\n });\n out.push({ ruleId: 'radius', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/perpNamedLine.ts\n//\n// Đường thẳng ĐẶT TÊN (token tia <HOA><thường>: Ax, Od, By) vuông góc với một\n// đường, qua gốc = chữ đầu token, có thể có chân:\n// \"Từ A kẻ Ax ⊥ MN tại K\" → line Ax = perpThrough(A, MN) + K=perpFoot(A,MN)\n// \"Vẽ đường thẳng Od ⊥ OA tại O\" → line Od = perpThrough(O, OA) (O ∈ OA: không foot)\n//\n// Tạo đường ĐÚNG TÊN trong đề để clause sau (\"Tia BI cắt Ax tại C\") tham chiếu\n// được (vao10:11 — clause sau đã parse nhưng Ax chưa dựng → cascade fail).\n//\n// KHÁC parallelPerp (đặt tên synth \"prpA\", không foot) + perpFoot (\"Kẻ AH ⊥ BC\"\n// cặp HOA): ở đây token là <HOA><thường> (tên tia) nên không nhầm.\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\s+(?:đường\\s*thẳng\\s+)?[A-Z][a-z]\\s*(?:⊥|vuông\\s*góc)/u;\n\n// \"(Từ/Qua <X>)? (kẻ|vẽ|dựng) (đường thẳng)? <Token><thường> (⊥|vuông góc với)\n// <LINE> (tại <K>)?\". group1=token(2 ký tự Ax), group2=LINE(1-2 HOA), group3=K.\nconst RE = new RegExp(\n // `⊥\\\\s*` (KHÔNG `\\\\s+`): OCR hay dính \"Ax⊥MN\" (vao10:11). Dạng chữ giữ `\\\\s+`.\n '(?:[Kk]ẻ|[Vv]ẽ|[Dd]ựng)\\\\s+(?:đường\\\\s*thẳng\\\\s+)?([A-Z][a-z])(?![A-Za-z])\\\\s*' +\n '(?:⊥\\\\s*|vuông\\\\s*góc(?:\\\\s+với)?\\\\s+)(?:với\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn\\\\s+)?' +\n '([A-Z]{1,2})(?![A-Z])(?:\\\\s+(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])(?![A-Za-z]))?',\n 'gu',\n);\n\nexport const perpNamedLineRule: LanguageRule = {\n id: 'perp-named-line',\n priority: 60,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = RE.exec(c.text)) !== null) {\n const token = m[1]; // \"Ax\"\n const anchor = token[0]; // gốc = chữ đầu HOA\n const line = m[2];\n const foot = m[3];\n if (line.includes(anchor) && !foot) continue; // gốc ∈ line + không chân → degenerate\n const intents: IntentT[] = [\n drawLine(token, 'perpThrough', { through: anchor, to: line }),\n ];\n // Chân chỉ khi K ≠ gốc và K ∉ đầu mút LINE (else trùng điểm đã có).\n if (foot && foot !== anchor && !line.includes(foot)) {\n intents.push(addPoint(foot, { kind: 'perpFoot', from: anchor, onLine: line }));\n }\n out.push({ ruleId: 'perp-named-line', clauseIds: [c.id], intents });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/parallelSidePoints.ts\n//\n// Điểm trên cạnh xác định bởi RÀNG BUỘC SONG SONG (distributive 2 điểm):\n// \"Q, R lần lượt thuộc AC và AB sao cho PQ ∥ AB, PR ∥ AC\" (hinh9:59, son123:44)\n// → Q = (đường qua P song song AB) ∩ AC\n// R = (đường qua P song song AC) ∩ AB\n//\n// Mỗi điểm N (thuộc Lᵢ) có đoạn <anchor>N ∥ Pᵢ → N = giao của đường-song-song-qua-\n// anchor-với-Pᵢ và Lᵢ. anchor = chữ ĐẦU của đoạn (P trong \"PQ\"). Cả 2 đoạn phải\n// CÙNG anchor (P). Self-contained khi anchor + các cạnh đã dựng (tam giác).\n//\n// GOTCHA \\b: ký tự Việt → cờ 'u'.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { addPoint, drawLine } from './_shared';\n\nconst PREFILTER = /thuộc\\s+[A-Z]{2}\\s+và\\s+[A-Z]{2}\\s+sao\\s+cho[^.]*?(?:∥|\\/\\/|song\\s*song)/u;\n\n// \"N1, N2 (lần lượt)? thuộc L1 và L2 sao cho A N1 ∥ P1, A N2 ∥ P2\".\n// ∥ | // | \"song song\". groups: 1=n1 2=n2 3=L1 4=L2 | seg1 5=a1 6=n1b 7=par1 |\n// seg2 8=a2 9=n2b 10=par2.\nconst PAR = '(?:∥|\\\\/\\\\/|song\\\\s*song(?:\\\\s+với)?)';\nconst RE = new RegExp(\n '([A-Z])\\\\s*,\\\\s*([A-Z])(?![A-Z])\\\\s+(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?thuộc\\\\s+' +\n '([A-Z]{2})\\\\s+và\\\\s+([A-Z]{2})(?![A-Z])\\\\s+sao\\\\s+cho\\\\s+' +\n '([A-Z])([A-Z])(?![A-Z])\\\\s*' + PAR + '\\\\s*([A-Z]{2})(?![A-Z])\\\\s*(?:,|và)\\\\s*' +\n '([A-Z])([A-Z])(?![A-Z])\\\\s*' + PAR + '\\\\s*([A-Z]{2})(?![A-Z])',\n 'u',\n);\n\nexport const parallelSidePointsRule: LanguageRule = {\n id: 'parallel-side-points',\n priority: 55,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n const m = RE.exec(c.text);\n if (!m) continue;\n const [n1, n2, l1, l2, a1, n1b, par1, a2, n2b, par2] = m.slice(1);\n // đoạn phải khớp tên điểm + 2 đoạn cùng anchor.\n if (n1b !== n1 || n2b !== n2 || a1 !== a2) continue;\n const anchor = a1;\n const line1 = `par_${anchor}${par1}`;\n const line2 = `par_${anchor}${par2}`;\n const intents: IntentT[] = [\n drawLine(line1, 'parallelThrough', { through: anchor, to: par1 }),\n addPoint(n1, { kind: 'intersection', of: [line1, l1] }),\n drawLine(line2, 'parallelThrough', { through: anchor, to: par2 }),\n addPoint(n2, { kind: 'intersection', of: [line2, l2] }),\n ];\n out.push({ ruleId: 'parallel-side-points', clauseIds: [c.id], intents });\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/parallelThroughCutsCircle.ts\n//\n// Đường thẳng QUA 1 điểm P, SONG SONG với 1 đường tham chiếu, rồi CẮT đường tròn\n// (O) (và optionally 1 đường thẳng khác) tại điểm đặt tên — kể cả dạng PHÂN PHỐI\n// 2 điểm.\n//\n// A) Phân phối (Bài 65/69): \"Các đường thẳng qua hai điểm C và B song song với\n// đường thẳng AO cắt đường tròn (O) lần lượt tại E và F\"\n// → C: drawLine(parC, parallelThrough C→AO) + E = secondIntersection(parC,O,other=C)\n// B: drawLine(parB, parallelThrough B→AO) + F = secondIntersection(parB,O,other=B)\n// (\"qua C và B … cắt (O) lần lượt tại E và F\" zip C↔E, B↔F.)\n//\n// B) Đường đặt tên chữ thường, cắt 2 thứ ở 2 clause (Bài 111): \"Qua B kẻ đường\n// thẳng d song song với CD. Đường thẳng d cắt đường thẳng AC tại E, cắt đường\n// tròn (O) tại F (F khác B).\"\n// → drawLine(parB, parallelThrough B→CD)\n// E = intersection(parB, AC); F = secondIntersection(parB,O,other=B)\n// Đường \"d\" khai báo ở 1 clause, tham chiếu \"Đường thẳng d\" ở clause sau →\n// map d → parB (CÙNG quy ước parallelPerp 'par'+P nên draw-line dedup nếu\n// parallelPerp cũng khớp khai báo).\n//\n// `other` (giao đã biết của đường song song với (O)) = chính điểm qua P (P nằm\n// trên (O) trong các đề này). Emit kèm — transpile validate.\n//\n// GOTCHA \\b: dùng (?!\\p{L}) + cờ 'u' quanh ký tự Việt.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport type { IntentT } from '../intent';\nimport { drawLine, addPoint } from './_shared';\n\n// --- A) Phân phối 1 clause: \"qua C và B … song song … AO … cắt (O) … lần lượt\n// tại E và F\". groups: 1=P1 2=P2 3+4=ref 5=circle 6=pt1 7=pt2.\nconst DISTRIB = new RegExp(\n String.raw`(?:[CcNn]ác\\s+)?đường\\s*thẳng\\s+qua\\s+(?:hai\\s+điểm\\s+)?([A-Z])(?!\\p{L})\\s+và\\s+([A-Z])(?!\\p{L})` +\n String.raw`\\s+song\\s*song\\s+(?:với\\s+)?(?:đường\\s*thẳng\\s+)?([A-Z])([A-Z])(?!\\p{L})` +\n String.raw`[^.]{0,30}?cắt\\s+(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])\\s*\\)` +\n String.raw`[^.]{0,30}?lần\\s*lượt\\s+(?:ở|tại)\\s+([A-Z])\\s+và\\s+([A-Z])(?!\\p{L})`,\n 'gu',\n);\n\n// --- B-decl) Khai báo đường đặt tên chữ thường: \"Qua P kẻ đường thẳng <lc> song\n// song với <ref>\". groups: 1=P 2=tên-đường(chữ thường) 3+4=ref.\nconst DECL_NAMED = new RegExp(\n String.raw`(?:[Qq]ua|[Tt]ừ)\\s+(?:điểm\\s+)?([A-Z])(?!\\p{L})` +\n String.raw`\\s+(?:kẻ|vẽ|dựng)\\s+đường\\s*thẳng\\s+([a-z])(?!\\p{L})` +\n String.raw`\\s+song\\s*song\\s+(?:với\\s+)?(?:đường\\s*thẳng\\s+)?([A-Z])([A-Z])(?!\\p{L})`,\n 'u',\n);\n\n// --- B-cut) Tham chiếu đường đặt tên ở clause sau: \"Đường thẳng <lc> cắt (đường\n// thẳng)? <X> tại E, cắt (đường tròn)? (O) tại F\". groups: 1=tên-đường\n// 2+3=line2 4=E 5=circle 6=F.\nconst NAMED_CUT_BOTH = new RegExp(\n String.raw`[Đđ]ường\\s*thẳng\\s+([a-z])(?!\\p{L})` +\n String.raw`\\s+cắt\\s+(?:đường\\s*thẳng\\s+|cạnh\\s+|đoạn\\s+)?([A-Z])([A-Z])(?!\\p{L})\\s+(?:ở|tại)\\s+(?:điểm\\s+)?([A-Z])(?!\\p{L})` +\n String.raw`[^.]{0,8}?cắt\\s+(?:đường\\s*tròn\\s*)?\\(\\s*([A-Z])\\s*\\)\\s+(?:ở|tại)\\s+(?:điểm\\s+(?:thứ\\s+hai\\s+)?)?(?:là\\s+)?([A-Z])(?!\\p{L})`,\n 'u',\n);\n\n// Prefilter toàn đề (NON-global cho .test). HAI nhánh:\n// A) dạng phân phối/1-câu: \"qua … song song … cắt\" trong cùng 1 câu ([^.]).\n// B) dạng đường đặt tên cross-clause: khai báo \"Qua P kẻ đường thẳng <lc> song\n// song …\" KẾT THÚC bằng '.' rồi câu sau \"Đường thẳng <lc> … cắt …(\" — '.'\n// chen giữa nên nhánh A ([^.]) không bắt được. Nhánh B chỉ cần đồng-hiện\n// \"kẻ đường thẳng <lc> song song\" (match() tự validate phần \"cắt (O)\").\nconst PREFILTER =\n /(?:[Qq]ua|đường\\s*thẳng\\s+qua)\\s+[^.]{0,60}?song\\s*song[^.]{0,80}?cắt|(?:[Qq]ua|[Tt]ừ)\\s+(?:điểm\\s+)?[A-Z][^.]{0,20}?(?:kẻ|vẽ|dựng)\\s+đường\\s*thẳng\\s+[a-z]\\s+song\\s*song/u;\n\nfunction lineNameOf(through: string): string {\n return 'par' + through;\n}\n\n// Tìm đường tròn duy nhất nêu tên trong đề (\"(O)\"/\"đường tròn (O)\") → 1 ký tự HOA.\nfunction resolveCircle(problem: string): string | undefined {\n const m = /đường\\s*tròn\\s*\\(\\s*([A-Z])\\s*\\)|\\(\\s*([A-Z])\\s*\\)/u.exec(problem);\n if (!m) return undefined;\n return m[1] ?? m[2];\n}\n\nfunction secondIntersection(name: string, line: string, circle: string, other: string): IntentT {\n return addPoint(name, { kind: 'secondIntersection', line, circle, other });\n}\n\nexport const parallelThroughCutsCircleRule: LanguageRule = {\n id: 'parallelThroughCutsCircle',\n priority: 46,\n languages: ['vi'],\n patterns: [PREFILTER],\n match(ctx) {\n const circle = resolveCircle(ctx.problem);\n if (!circle) return []; // không có đường tròn duy nhất → escalate\n const out: RuleMatch[] = [];\n\n // Map tên-đường chữ thường (vd \"d\") → {through, lineName} từ clause khai báo.\n // Dùng cho dạng B (tham chiếu cross-clause).\n const namedLines = new Map<string, { through: string; lineName: string }>();\n\n for (const c of ctx.clauses) {\n // --- A) Phân phối trong 1 clause ----------------------------------------\n DISTRIB.lastIndex = 0;\n let matchedDistrib = false;\n for (const m of c.text.matchAll(DISTRIB)) {\n const [p1, p2] = [m[1], m[2]];\n const to = m[3] + m[4];\n const cir = m[5];\n const [e, f] = [m[6], m[7]];\n if (p1 === p2 || e === f) continue;\n // song song với đường CHỨA chính điểm qua → degenerate, bỏ.\n if (to.includes(p1) || to.includes(p2)) continue;\n const intents: IntentT[] = [];\n for (const [p, pt] of [\n [p1, e],\n [p2, f],\n ] as const) {\n const lineName = lineNameOf(p);\n intents.push(\n drawLine(lineName, 'parallelThrough', { through: p, to }),\n secondIntersection(pt, lineName, cir, p),\n );\n }\n out.push({ ruleId: 'parallelThroughCutsCircle', clauseIds: [c.id], intents });\n matchedDistrib = true;\n }\n if (matchedDistrib) continue;\n\n // --- B-decl) Học mapping tên-đường chữ thường --------------------------\n const decl = DECL_NAMED.exec(c.text);\n if (decl) {\n const through = decl[1];\n const named = decl[2];\n const to = decl[3] + decl[4];\n if (!to.includes(through)) {\n namedLines.set(named, { through, lineName: lineNameOf(through) });\n // Emit luôn draw-line (dedup nếu parallelPerp cũng khớp khai báo này).\n out.push({\n ruleId: 'parallelThroughCutsCircle',\n clauseIds: [c.id],\n intents: [drawLine(lineNameOf(through), 'parallelThrough', { through, to })],\n });\n }\n continue;\n }\n\n // --- B-cut) Tham chiếu \"Đường thẳng <d> cắt <X> tại E, cắt (O) tại F\" ---\n const cut = NAMED_CUT_BOTH.exec(c.text);\n if (cut) {\n const named = cut[1];\n const decl2 = namedLines.get(named);\n if (!decl2) continue; // chưa thấy khai báo đường này → bỏ (an toàn)\n const { through, lineName } = decl2;\n const line2 = cut[2] + cut[3];\n const e = cut[4];\n const cir = cut[5];\n const f = cut[6];\n if (e === f || line2.includes(e) || lineName === e) continue;\n out.push({\n ruleId: 'parallelThroughCutsCircle',\n clauseIds: [c.id],\n intents: [\n addPoint(e, { kind: 'intersection', of: [lineName, line2] }),\n secondIntersection(f, lineName, cir, through),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/lineThroughCutsTwoLines.ts\n//\n// Đường thẳng BẤT KÌ / TÙY Ý qua 1 điểm P, cắt HAI đường L1, L2 tại E, F:\n// \"Một đường thẳng bất kì qua H cắt AC, AB lần lượt tại E, F\" (hinh9 #76)\n// → E = điểm TỰ DO trên L1 (=AC)\n// F = giao( đường(H,E) , L2=AB )\n//\n// KHÔNG có primitive \"đường thẳng bất kì\" (hướng tuỳ ý). Ta mô hình hoá TRUNG\n// THỰC bằng cách: chọn 1 điểm free E trên L1, rồi lấy giao của đường (P,E) với\n// L2 ⇒ ba điểm P, E, F THẲNG HÀNG ⇒ đúng là một đường thẳng đi qua P. E phải\n// được emit TRƯỚC F vì ref 'HE' (= P+E nối chuỗi) của F cần E đã tồn tại.\n//\n// Khác perpThroughCutsLines / parallelPerp: hai rule kia sở hữu hướng ⊥ / ∥\n// (\"vuông góc\"/\"song song\"). Rule này CHỈ neo vào lời \"bất kì/tùy ý\" → KHÔNG\n// đụng. Prefilter cũng neo \"đường thẳng bất kì|tùy ý qua <P>\" để loại bài ⊥/∥.\n//\n// GOTCHA \\b: dùng cờ 'u' + (?!\\p{L}) quanh ký tự Việt, KHÔNG dùng \\b ASCII.\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// \"(Một)? đường thẳng (bất kì|bất kỳ|tùy ý) qua P cắt L1 , L2 (lần lượt)? tại E , F\"\n// group1 = P (1 HOA); group2 = L1 (cặp HOA); group3 = L2 (cặp HOA);\n// group4 = E (1 HOA); group5 = F (1 HOA).\nconst RE = new RegExp(\n '(?:[Mm]ột\\\\s+)?đường\\\\s*thẳng\\\\s+(?:bất\\\\s*k[iìyỳ]|tùy\\\\s*ý)\\\\s+(?:nào\\\\s+)?(?:đi\\\\s+)?qua\\\\s+(?:điểm\\\\s+)?([A-Z])(?!\\\\p{L})' +\n '[^.]{0,20}?cắt\\\\s+(?:các\\\\s+)?(?:đường\\\\s*thẳng\\\\s+|cạnh\\\\s+|đoạn(?:\\\\s+thẳng)?\\\\s+)?' +\n '([A-Z]\\\\s*[A-Z])(?![A-Z])\\\\s*(?:,|và)\\\\s*([A-Z]\\\\s*[A-Z])(?![A-Z])' +\n '[^.]{0,20}?(?:lần\\\\s*lượt\\\\s+|theo\\\\s+thứ\\\\s+tự\\\\s+)?(?:tại|ở)\\\\s+(?:điểm\\\\s+)?([A-Z])\\\\s*(?:,|và)\\\\s*([A-Z])(?![A-Z])',\n 'gu',\n);\n\n// Prefilter: chỉ kích hoạt khi có \"đường thẳng bất kì/tùy ý qua <HOA>\" — né hẳn\n// các bài hướng ⊥/∥ (perpThroughCutsLines / parallelPerp sở hữu).\nconst PREFILTER = [/đường\\s*thẳng\\s+(?:bất\\s*k[iìyỳ]|tùy\\s*ý)\\s+(?:nào\\s+)?(?:đi\\s+)?qua\\s+[A-Z]/u];\n\nexport const lineThroughCutsTwoLinesRule: LanguageRule = {\n id: 'lineThroughCutsTwoLines',\n priority: 44,\n languages: ['vi'],\n patterns: PREFILTER,\n match(ctx) {\n const out: RuleMatch[] = [];\n for (const c of ctx.clauses) {\n RE.lastIndex = 0;\n for (const m of c.text.matchAll(RE)) {\n const through = m[1];\n const line1 = m[2].replace(/\\s+/g, '');\n const line2 = m[3].replace(/\\s+/g, '');\n const e = m[4];\n const f = m[5];\n // Validate: P 1 HOA, L1/L2 cặp HOA, E/F 1 HOA, tất cả phân biệt.\n if (!/^[A-Z]{2}$/u.test(line1) || !/^[A-Z]{2}$/u.test(line2)) continue;\n if (line1 === line2) continue;\n if (e === f) continue;\n // E/F không được là chính P; E phải nằm trên L1 (không trùng đầu mút L1).\n const names = new Set([through, e, f]);\n if (names.size !== 3) continue;\n if (line1.includes(e)) continue; // E trùng đầu mút L1 → không phải điểm mới\n const ref = through + e; // 'H' + 'E' → 'HE' (resolveSegmentRef tách lại)\n out.push({\n ruleId: 'lineThroughCutsTwoLines',\n clauseIds: [c.id],\n intents: [\n // E TRƯỚC F: ref 'HE' của F cần E đã có.\n addPoint(e, { kind: 'onSegment', of: line1 }),\n addPoint(f, { kind: 'intersection', of: [ref, line2] }),\n ],\n });\n }\n }\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/rightAngleViewing.ts\n//\n// \"Góc vuông nhìn đoạn\": điểm V trên đường L sao cho ∠aVb = 90° (hoặc Va ⊥ Vb)\n// → addPoint(V, { kind:'rightAngleViewing', a, b, onLine: L })\n// Builder dựng midpoint(ab) ẩn + đường tròn đường kính ab ẩn (Thales) + giao\n// L ∩ circle — xem intent-builders/add-point/rightAngleViewing.ts.\n//\n// Port từ completeRightAngle.ts (Stage 1.5c của pipeline cũ — chết dead-code khi\n// xoá path DSL free-form 2026-06-09) thành rule chính quy để Track A tự dựng.\n// Khác bản cũ: (1) token đường sau \"trên/thuộc\" phải đứng RỜI ((?![\\p{L}\\d]))\n// — bản cũ nuốt \"đường tròn\" thành \"tr\"; (2) [A-Z] không kèm cờ i (tên điểm\n// phải HOA thật); (3) chặn vertex dính vào cụm in hoa khác ((?<!\\p{L})).\n//\n// Priority 63: TRÊN onSegmentPoint (62) để intent rightAngleViewing của V đứng\n// trước intent onSegment cùng tên (builder add-point idempotent first-wins),\n// DƯỚI onCirclePoint (64).\nimport type { LanguageRule, RuleMatch } from './_types';\nimport { addPoint } from './_shared';\n\n// ∠AMB = 90° / góc AMB = 90 độ / góc AMB bằng 90° / góc AMB vuông — vertex GIỮA.\nconst ANGLE_EQ_RE =\n /(?:[Gg]óc|∠)\\s*([A-Z])\\s*([A-Z])\\s*([A-Z])\\s*(?:=|bằng|là)?\\s*90\\s*(?:°|độ|o(?![A-Za-z]))/u;\nconst ANGLE_VUONG_RE = /(?:[Gg]óc|∠)\\s*([A-Z])\\s*([A-Z])\\s*([A-Z])\\s*vuông/u;\n// MA ⊥ MB / MA vuông góc (với) MB — vertex = chữ CHUNG của 2 cặp.\nconst PERP_RE = /([A-Z])([A-Z])\\s*(?:⊥|vuông\\s*góc(?:\\s*với)?)\\s*([A-Z])([A-Z])(?![A-Z])/u;\n\ninterface RightAngleSpec {\n vertex: string;\n a: string;\n b: string;\n onLine: string;\n}\n\n/**\n * Đường mà `vertex` nằm trên: \"V (là (một) điểm)? (nằm trên|trên|thuộc)\n * (đường thẳng|đường cao|cạnh|tia|đoạn)? <TOKEN>\" — TOKEN 1-2 chữ cái đứng rời\n * (cặp đỉnh \"CK\" hoặc đường đặt tên thường \"d\"). KHÔNG nhận \"đường tròn\" (điểm\n * trên đường tròn là chuyện của onCirclePoint).\n */\nfunction findOnLine(problem: string, vertex: string): string | null {\n const re = new RegExp(\n `(?<!\\\\p{L})${vertex}\\\\s*(?:là\\\\s+(?:một\\\\s+)?điểm\\\\s+)?(?:nằm\\\\s+trên|trên|thuộc)\\\\s+` +\n `(?:đường\\\\s*thẳng\\\\s+|đường\\\\s*cao\\\\s+|cạnh\\\\s+|tia\\\\s+|đoạn(?:\\\\s*thẳng)?\\\\s+)?` +\n `([A-Za-z][A-Za-z]?)(?![\\\\p{L}\\\\d])`,\n 'u',\n );\n const m = re.exec(problem);\n return m ? m[1] : null;\n}\n\nfunction detectSpec(problem: string): RightAngleSpec | null {\n // 1. ∠/góc = 90 / vuông: vertex là chữ giữa.\n for (const re of [ANGLE_EQ_RE, ANGLE_VUONG_RE]) {\n const m = re.exec(problem);\n if (m) {\n const [, a, vertex, b] = m;\n if (a === b || a === vertex || b === vertex) continue;\n const onLine = findOnLine(problem, vertex);\n if (onLine) return { vertex, a, b, onLine };\n }\n }\n // 2. Perp 2 cặp chung đỉnh: chữ chung là vertex.\n const p = PERP_RE.exec(problem);\n if (p) {\n const [, x1, x2, y1, y2] = p;\n let vertex: string | null = null;\n let a: string | null = null;\n let b: string | null = null;\n if (x1 === y1) { vertex = x1; a = x2; b = y2; }\n else if (x1 === y2) { vertex = x1; a = x2; b = y1; }\n else if (x2 === y1) { vertex = x2; a = x1; b = y2; }\n else if (x2 === y2) { vertex = x2; a = x1; b = y1; }\n if (vertex && a && b && a !== b) {\n const onLine = findOnLine(problem, vertex);\n if (onLine) return { vertex, a, b, onLine };\n }\n }\n return null;\n}\n\nexport const rightAngleViewingRule: LanguageRule = {\n id: 'rightAngleViewing',\n priority: 63,\n languages: ['vi'],\n patterns: [\n /(?:[Gg]óc|∠)[^.;\\n]{0,18}90/u,\n /(?:[Gg]óc|∠)\\s*[A-Z]{3}\\s*vuông/u,\n /[A-Z]{2}\\s*(?:⊥|vuông\\s*góc)\\s*[A-Z]{2}/u,\n ],\n match(ctx) {\n const spec = detectSpec(ctx.problem);\n if (!spec) return [];\n\n // Claim các clause chứa điều kiện góc-vuông hoặc mệnh đề trên-đường của vertex\n // (clause không-geo đã bị lọc khỏi ctx.clauses → claim [] vẫn hợp lệ).\n const clauseIds = ctx.clauses\n .filter(\n (c) =>\n ANGLE_EQ_RE.test(c.text) ||\n ANGLE_VUONG_RE.test(c.text) ||\n PERP_RE.test(c.text) ||\n findOnLine(c.text, spec.vertex) !== null,\n )\n .map((c) => c.id);\n\n const out: RuleMatch[] = [\n {\n ruleId: 'rightAngleViewing',\n clauseIds,\n intents: [\n addPoint(spec.vertex, {\n kind: 'rightAngleViewing',\n a: spec.a,\n b: spec.b,\n onLine: spec.onLine,\n }),\n ],\n },\n ];\n return out;\n },\n};\n","// src/stamps/geometry-2d/ai/rules/registry.ts\n//\n// Đăng ký rule + engine chạy theo priority. Thêm construct mới = import module\n// + thêm vào ALL_RULES (không sửa engine).\nimport type { LanguageRule, RuleContext, RuleMatch } from './_types';\nimport { triangleRule } from './triangle';\nimport { quadRule } from './quad';\nimport { connectRule } from './connect';\nimport { midpointRule } from './midpoint';\nimport { perpBisectorRule } from './perpBisector';\nimport { cevianRule } from './cevian';\nimport { angleBisectorAngleRule } from './angleBisectorAngle';\nimport { centersRule } from './centers';\nimport { perpFootRule } from './perpFoot';\nimport { circleRadiusRule } from './circleRadius';\nimport { circleTriangleRule } from './circleTriangle';\nimport { tangentFromExtRule } from './tangentFromExt';\nimport { externalPointRule } from './externalPoint';\nimport { arcMidpointRule } from './arcMidpoint';\nimport { excenterRule } from './excenter';\nimport { parallelPerpRule } from './parallelPerp';\nimport { reflectionRule } from './reflection';\nimport { pointAtDistanceRule } from './pointAtDistance';\nimport { eulerLineRule } from './eulerLine';\nimport { radicalAxisRule } from './radicalAxis';\nimport { simsonRule } from './simson';\nimport { ninePointRule } from './ninePoint';\nimport { diameterCirclePairwiseRule } from './diameterCirclePairwise';\nimport { angleBisectorFootRule } from './angleBisectorFoot';\nimport { intersectionRule } from './intersection';\nimport { chordRule } from './chord';\nimport { incircleTangencyRule } from './incircleTangency';\nimport { altitudeDiameterCirclesRule } from './altitudeDiameterCircles';\nimport { diameterCircleCutsSidesRule } from './diameterCircleCutsSides';\nimport { circleDiameterRule } from './circleDiameter';\nimport { onCirclePointRule } from './onCirclePoint';\nimport { tangentAtRule } from './tangentAt';\nimport { onSegmentPointRule } from './onSegmentPoint';\nimport { lineCircleIntersectionRule } from './lineCircleIntersection';\nimport { incenterNamedTriangleRule } from './incenterNamedTriangle';\nimport { perpThroughCutsLinesRule } from './perpThroughCutsLines';\nimport { tangentRayRule } from './tangentRay';\nimport { pointOnTangentRayRule } from './pointOnTangentRay';\nimport { pointOnTangentAtRule } from './pointOnTangentAt';\nimport { intersectRayRule } from './intersectRay';\nimport { tangentFromPointAtRule } from './tangentFromPointAt';\nimport { perpLineTakePointRule } from './perpLineTakePoint';\nimport { pairSecondIntersectionRule } from './pairSecondIntersection';\nimport { circleCenterRadiusSegmentRule } from './circleCenterRadiusSegment';\nimport { perpDiametersRule } from './perpDiameters';\nimport { perpLineCutsTangentRule } from './perpLineCutsTangent';\nimport { perpChordThroughPointRule } from './perpChordThroughPoint';\nimport { polygonInscribedCircleRule } from './polygonInscribedCircle';\nimport { perpAtPointCutsLineRule } from './perpAtPointCutsLine';\nimport { tangentAtCutsLinesRule } from './tangentAtCutsLines';\nimport { diameterEndpointRule } from './diameterEndpoint';\nimport { circleThroughTwoCutsSidesRule } from './circleThroughTwoCutsSides';\nimport { circumcircleNamedDistribRule } from './circumcircleNamedDistrib';\nimport { circumcirclePairMeetRule } from './circumcirclePairMeet';\nimport { tangentCircleAtPointRule } from './tangentCircleAtPoint';\nimport { externalBisectorCutsLinesRule } from './externalBisectorCutsLines';\nimport { tangentTwoSidesCircleRule } from './tangentTwoSidesCircle';\nimport { interiorPointRule } from './interiorPoint';\nimport { parallelCutsTangentAtRule } from './parallelCutsTangentAt';\nimport { inExCircleTangentBCRule } from './inExCircleTangentBC';\nimport { tangentPointsFromExtRule } from './tangentPointsFromExt';\nimport { circleExternalPointRule } from './circleExternalPoint';\nimport { tangentNamedFromExtRule } from './tangentNamedFromExt';\nimport { secantRule } from './secant';\nimport { oppositeRayPointRule } from './oppositeRayPoint';\nimport { perpChordAtFootRule } from './perpChordAtFoot';\nimport { diameterCircleSecantRule } from './diameterCircleSecant';\nimport { tangentsAtMeetRule } from './tangentsAtMeet';\nimport { angleBisectorCutsSideCircleRule } from './angleBisectorCutsSideCircle';\nimport { circleCutsArcSecondRule } from './circleCutsArcSecond';\nimport { angleBisectorCutsCircleLineRule } from './angleBisectorCutsCircleLine';\nimport { tangentLineNamedAtPointRule } from './tangentLineNamedAtPoint';\nimport { givenDiameterCircleRule } from './givenDiameterCircle';\nimport { multiDiameterCirclesRule } from './multiDiameterCircles';\nimport { cutCirclesDistribRule } from './cutCirclesDistrib';\nimport { givenNamedCircleRule } from './givenNamedCircle';\nimport { twoPerpLinesMeetRule } from './twoPerpLinesMeet';\nimport { circumcircleCutsLineRule } from './circumcircleCutsLine';\nimport { lineConcurrencyRule } from './lineConcurrency';\nimport { twoCirclesMeetRule } from './twoCirclesMeet';\nimport { radiusRule } from './radius';\nimport { perpNamedLineRule } from './perpNamedLine';\nimport { parallelSidePointsRule } from './parallelSidePoints';\nimport { parallelThroughCutsCircleRule } from './parallelThroughCutsCircle';\nimport { lineThroughCutsTwoLinesRule } from './lineThroughCutsTwoLines';\nimport { rightAngleViewingRule } from './rightAngleViewing';\n\nconst RULES: readonly LanguageRule[] = [\n circumcircleCutsLineRule,\n lineConcurrencyRule,\n parallelThroughCutsCircleRule,\n lineThroughCutsTwoLinesRule,\n rightAngleViewingRule,\n triangleRule,\n quadRule,\n connectRule,\n midpointRule,\n perpBisectorRule,\n cevianRule,\n angleBisectorAngleRule,\n centersRule,\n perpFootRule,\n circleRadiusRule,\n circleTriangleRule,\n tangentFromExtRule,\n externalPointRule,\n arcMidpointRule,\n excenterRule,\n parallelPerpRule,\n reflectionRule,\n pointAtDistanceRule,\n eulerLineRule,\n radicalAxisRule,\n simsonRule,\n ninePointRule,\n diameterCirclePairwiseRule,\n angleBisectorFootRule,\n intersectionRule,\n chordRule,\n incircleTangencyRule,\n altitudeDiameterCirclesRule,\n diameterCircleCutsSidesRule,\n circleDiameterRule,\n onCirclePointRule,\n tangentAtRule,\n onSegmentPointRule,\n lineCircleIntersectionRule,\n incenterNamedTriangleRule,\n perpThroughCutsLinesRule,\n tangentRayRule,\n pointOnTangentRayRule,\n pointOnTangentAtRule,\n intersectRayRule,\n tangentFromPointAtRule,\n perpLineTakePointRule,\n pairSecondIntersectionRule,\n circleCenterRadiusSegmentRule,\n perpDiametersRule,\n perpLineCutsTangentRule,\n perpChordThroughPointRule,\n polygonInscribedCircleRule,\n perpAtPointCutsLineRule,\n tangentAtCutsLinesRule,\n diameterEndpointRule,\n circleThroughTwoCutsSidesRule,\n circumcircleNamedDistribRule,\n circumcirclePairMeetRule,\n tangentCircleAtPointRule,\n externalBisectorCutsLinesRule,\n tangentTwoSidesCircleRule,\n interiorPointRule,\n parallelCutsTangentAtRule,\n inExCircleTangentBCRule,\n tangentPointsFromExtRule,\n circleExternalPointRule,\n tangentNamedFromExtRule,\n secantRule,\n oppositeRayPointRule,\n perpChordAtFootRule,\n diameterCircleSecantRule,\n tangentsAtMeetRule,\n angleBisectorCutsSideCircleRule,\n circleCutsArcSecondRule,\n angleBisectorCutsCircleLineRule,\n tangentLineNamedAtPointRule,\n givenDiameterCircleRule,\n multiDiameterCirclesRule,\n cutCirclesDistribRule,\n givenNamedCircleRule,\n twoPerpLinesMeetRule,\n twoCirclesMeetRule,\n radiusRule,\n perpNamedLineRule,\n parallelSidePointsRule,\n];\n\n/** Sắp xếp priority giảm dần (cao chạy trước) — tính 1 lần ở module load. */\nexport const ALL_RULES: readonly LanguageRule[] = [...RULES].sort(\n (a, b) => b.priority - a.priority,\n);\n\nexport function runRules(ctx: RuleContext): RuleMatch[] {\n const matches: RuleMatch[] = [];\n for (const rule of ALL_RULES) {\n if (!rule.patterns.some((p) => p.test(ctx.problem))) continue;\n matches.push(...rule.match(ctx));\n }\n return matches;\n}\n","// src/stamps/geometry-2d/ai/deterministic/normalizeText.ts\n//\n// Chuẩn hoá văn bản đề TRƯỚC khi segment + chạy rule. Quy các biến thể ký hiệu\n// về dạng canonical mà rule engine đã hiểu — tránh phải nhân đôi regex ở mọi rule.\n//\n// \"ΔABC\" / \"∆ABC\" → \"tam giác ABC\" (Δ U+0394 Greek, ∆ U+2206 increment)\n// \"vòng tròn\" → \"đường tròn\" (đồng nghĩa)\n//\n// Idempotent + thuần (không side-effect). KHÔNG đổi độ dài cách-từ ngoài các thay\n// thế trên để giữ ổn định coverage/clause-split.\n\nconst TRIANGLE_SYMBOL = /[Δ∆]\\s*(?=[A-Z])/gu;\nconst CIRCLE_SYNONYM = /vòng\\s+tròn/giu;\n// \"◊ABCD\" (U+25CA lozenge) / \"▱\" / \"□\" → \"tứ giác ABCD\" (đề toán 8 hay dùng).\nconst QUAD_SYMBOL = /[◊▱□]\\s*(?=[A-Z])/gu;\n// Ký hiệu căn \"√\" (nhiễu OCR chèn giữa câu, vd \"hình chiếu của H lên √ √ √ AB,AC\")\n// → khoảng trắng. KHÔNG mang nghĩa hình học khi dựng hình (chỉ trong biểu thức độ\n// dài). Thay bằng ' ' (không '') để không dính chữ (\"lên√AB\"→\"lên AB\"); rule dùng\n// \\s+ nên khoảng trắng dư vô hại; không tạo/huỷ ranh giới câu.\nconst SQRT_NOISE = /√/gu;\n// Prime cong ’ (U+2019) / ′ (U+2032) / ´ (U+00B4) SAU chữ-cái-số → ASCII ' —\n// canonical hoá nhãn phái sinh (O'/A'/d') để mọi rule dùng `['′]` (hoặc ') khớp\n// đồng nhất. Chỉ thay khi đứng sau [A-Za-z0-9] (ngữ cảnh prime), không nuốt dấu\n// nháy mở đầu cụm.\nconst PRIME_VARIANT = /([A-Za-z0-9])[’′´]/gu;\n\n// OCR glue (mất space): tách ở ranh giới TIN CẬY để không phá chữ thường.\n// (a) từ-vựng-hình-học THƯỜNG dính nhãn HOA: \"cắtBC\"→\"cắt BC\", \"tâmF\"→\"tâm F\".\n// Từ phải lowercase (không khớp \"Cho\"/\"Trên\" HOA đầu câu) + theo NGAY bởi HOA.\n// (b) nhãn HOA dính TỪ-KHOÁ lowercase: \"Asao\"→\"A sao\", \"Qlần\"→\"Q lần\", \"Bvà\"→\"B và\".\n// Danh sách từ-khoá cụ thể nên KHÔNG tách \"Cho\"(C+ho)/\"Đường\"(Đ+ường).\n// \"và\" đã AN TOÀN re-add sau khi perpThroughCutsLines dựng chân \"tại E\" (trước\n// đó tách \"Evà\"→\"E và\" làm lộ E thiếu → regress vao10:119, nay đã vá).\nconst GLUE_WORD_LABEL = /(cắt|tâm|điểm|cạnh|tia|dây|cung|qua|của|và|tại|trên|đến)([A-Z])/gu;\nconst GLUE_LABEL_WORD = /([A-Z])(sao|nằm|lần|thuộc|cắt|của|đến|trên|tại|và)/gu;\n\nexport function normalizeProblemText(problem: string): string {\n return problem\n .replace(TRIANGLE_SYMBOL, 'tam giác ')\n .replace(QUAD_SYMBOL, 'tứ giác ')\n .replace(CIRCLE_SYNONYM, 'đường tròn')\n .replace(SQRT_NOISE, ' ')\n .replace(PRIME_VARIANT, \"$1'\")\n .replace(GLUE_WORD_LABEL, '$1 $2')\n .replace(GLUE_LABEL_WORD, '$1 $2');\n}\n","// src/stamps/geometry-2d/ai/deterministic/runDeterministicIntents.ts\n//\n// Track A orchestrator: rule engine → IntentT[] + coverage gate.\n// Chỉ lo NLU; gate transpile/verify do router (buildFigureIntent) áp dụng sau.\nimport type { IntentT } from '../intent';\nimport { segmentClauses, computeCoverage, type Clause, type CoverageReport } from './coverage';\nimport { runRules } from '../rules/registry';\nimport { normalizeProblemText } from './normalizeText';\nimport { countGeometryKeywords } from './vocabulary';\n\nexport type DetIntentResult =\n | { ok: true; intents: IntentT[]; coverage: CoverageReport }\n | {\n ok: false;\n reason: 'incomplete-coverage' | 'no-match';\n coverage: CoverageReport;\n };\n\ninterface Collected {\n /** Intent từ MỌI clause có rule claim, deduped theo JSON. */\n intents: IntentT[];\n coverage: CoverageReport;\n matchCount: number;\n}\n\n// Segment → rules → coverage → dedup. Dùng chung cho gate đầy đủ\n// (runDeterministicIntents) lẫn partial (tryPartialDeterministic).\n// Dedupe intent y hệt nhau: nhiều rule cùng tham chiếu 1 hình (vd \"tam giác ABC\"\n// xuất hiện ở nhiều clause → triangle rule emit lặp; centers/cevian cũng cần nó).\nfunction collectDeterministic(rawProblem: string): Collected {\n const problem = normalizeProblemText(rawProblem);\n const clauses = segmentClauses(problem);\n const drawableClauses = clauses.filter((c) => c.hasGeometry);\n let drawableProblem = problem;\n for (const c of clauses) {\n if (c.hasGeometry) continue;\n // segmentClauses tách \"(O; 3)\" thành \"(O\" + \"3)\"; phần \"3)\" không tự có\n // keyword hình học nhưng vẫn cần giữ để các rule quét toàn đề parse đủ paren.\n if (/^\\s*(?:\\d+(?:[,.]\\d+)?|[Rr])\\s*\\)/u.test(c.text)) continue;\n // CHỈ blank proof/locus clause CÓ geometry keyword (câu dài, gần như duy\n // nhất — \"Chứng minh tứ giác BCDE nội tiếp\"). KHÔNG blank fragment ngắn\n // không keyword (\"AB\", \"AD\", \"AC = AE\" tách từ \"Chứng minh AD.AC=AE.AB\"):\n // \".replace(c.text,' ')\" replace occurrence ĐẦU TIÊN — \"AB\" sẽ nuốt \"tam\n // giác ABC\" → \"tam giác C\", mất construction. Fragment không keyword vô hại\n // (không rule nào construct từ chúng) nên để nguyên.\n if (countGeometryKeywords(c.text) === 0) continue;\n drawableProblem = drawableProblem.replace(c.text, ' ');\n }\n const matches = runRules({ problem: drawableProblem, clauses: drawableClauses });\n const coverage = computeCoverage(clauses, matches);\n\n const seen = new Set<string>();\n const intents = matches\n .flatMap((m) => m.intents)\n .filter((i) => {\n const key = JSON.stringify(i);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n return { intents, coverage, matchCount: matches.length };\n}\n\nexport function runDeterministicIntents(problem: string): DetIntentResult {\n const { intents, coverage, matchCount } = collectDeterministic(problem);\n\n if (matchCount === 0) return { ok: false, reason: 'no-match', coverage };\n if (!coverage.complete) return { ok: false, reason: 'incomplete-coverage', coverage };\n return { ok: true, intents, coverage };\n}\n\nexport interface PartialDeterministicResult {\n /** Intent deterministic từ các clause đã được rule claim (deduped). */\n detIntents: IntentT[];\n /** Clause geo CHƯA được phủ — phần LLM cần bù (hybrid Phase 2). */\n uncovered: Clause[];\n coverage: CoverageReport;\n /**\n * true khi deterministic phủ MỘT PHẦN: có rule match + ≥1 intent NHƯNG coverage\n * CHƯA đầy đủ. Đây là điều kiện kích hoạt hybrid (Phase 2 gọi LLM bù `uncovered`\n * rồi mergeIntents). false khi: complete (Track A lo đủ) hoặc no-match/0 intent\n * (full LLM Track B).\n */\n hasPartial: boolean;\n}\n\n/**\n * Deterministic-only (KHÔNG LLM): thu intent phần đã phủ + clause còn thiếu, kể\n * cả khi coverage incomplete. Nền cho hybrid partial-coverage — Phase 2 sẽ gọi\n * LLM bù `uncovered` rồi `mergeIntents(detIntents, llmIntents)`.\n */\nexport function tryPartialDeterministic(problem: string): PartialDeterministicResult {\n const { intents, coverage, matchCount } = collectDeterministic(problem);\n return {\n detIntents: intents,\n uncovered: coverage.uncovered,\n coverage,\n hasPartial: matchCount > 0 && !coverage.complete && intents.length > 0,\n };\n}\n","// src/stamps/geometry-2d/ai/deterministic/guards.ts\n//\n// Hai guard fail-safe cho deterministic-first: nếu DSL dựng được KHÔNG trung thành\n// với đề, router escalate AI thay vì render hình sai/thiếu. Bổ sung cho coverage\n// clause-level (vốn coarse, dễ bỏ lọt khi 1 clause chứa nhiều construct).\nimport type { DslInputT } from '../../dsl/schema';\nimport type { IntentT } from '../intent';\nimport { segmentClauses } from './coverage';\n\n// ── Guard 1: named-entity present ────────────────────────────────────────────\n// Mọi đỉnh/điểm được ĐẶT TÊN hay KHAI BÁO trong đề phải tồn tại trong DSL.\n// KHÔNG dùng \\b (ASCII) quanh ký tự Việt.\n\n// Tên điểm dẫn nhập 1 ký tự HOA: \"Gọi M\", \"lấy điểm D\", \"cắt … tại D\", \"N là …\",\n// \"H, K lần lượt\", \"và P là\".\n// Issue #46 nhóm A: prime (' U+0027 / ′ U+2032) là PHẦN của tên (\"D′\" ≠ \"D\").\n// Group prime đứng ngay sau chữ cái — collect bằng letter + normalize(prime) để\n// expected-name khớp DSL (rule pointAtDistance giữ prime → DSL có \"D'\").\nconst NAMED_INTRO = /(?:Gọi|gọi|Lấy|lấy|Dựng|dựng|Đặt|đặt|tại|điểm|và)\\s+(?:điểm\\s+)?([A-Z])(['′]?)(?![A-Za-z])/gu;\n// LƯU Ý: KHÔNG dùng `là\\b` — `\\b` của JS theo ASCII, mà 'à' (U+00E0) là\n// non-word-char ASCII → `\\b` sau 'là' KHÔNG khớp khi theo sau là space/dấu câu\n// → pattern chết, bỏ sót mọi \"X là <construct>\" (bug silent-incomplete). Dùng\n// lookahead non-letter Unicode (?!\\p{L}) để neo cuối \"là\".\nconst NAMED_LA = /([A-Z])(['′]?)(?![A-Za-z])\\s+là(?!\\p{L})/gu;\nconst NAMED_LANLUOT = /([A-Z])(['′]?)(?![A-Za-z])\\s*,\\s*([A-Z])(['′]?)(?![A-Za-z])\\s+lần lượt/gu;\n\n// Ghép chữ cái + prime đã normalize (′→') thành tên đầy đủ. Đồng bộ với\n// rules/pointAtDistance.ts normalizePointName — giữ naming layer nhất quán.\nfunction joinPrime(letter: string | undefined, prime: string | undefined): string | undefined {\n if (!letter) return undefined;\n return prime ? `${letter}'` : letter;\n}\n\n// Đỉnh của hình khai báo: \"tam giác ABC\", \"tứ giác ABCD\", \"hình vuông/… ABCD\".\n// Bắt cụm 3-4 ký tự HOA LIỀN ngay sau tên hình (mỗi đỉnh phải có trong DSL).\nconst SHAPE_TRI = /tam giác\\s+([A-Z]{3})(?![A-Z])/gu;\nconst SHAPE_QUAD = /(?:tứ giác|hình\\s+(?:vuông|chữ nhật|bình hành|thoi|thang))\\s+([A-Z]{4})(?![A-Z])/gu;\n\nexport interface NamedEntityReport {\n ok: boolean;\n missing: string[];\n}\n\nfunction collectExpectedNames(problem: string): Set<string> {\n const names = new Set<string>();\n // Mỗi entry [letterGroup, primeGroup]: tên = letter + normalize(prime).\n const add = (re: RegExp, groups: [number, number][]) => {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(problem)) !== null) {\n for (const [lg, pg] of groups) {\n const name = joinPrime(m[lg], m[pg]);\n if (name) names.add(name);\n }\n }\n };\n add(NAMED_INTRO, [[1, 2]]);\n add(NAMED_LA, [[1, 2]]);\n add(NAMED_LANLUOT, [[1, 2], [3, 4]]);\n // Đỉnh hình: tách cụm 3/4 ký tự thành từng đỉnh.\n for (const re of [SHAPE_TRI, SHAPE_QUAD]) {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(problem)) !== null) {\n for (const ch of m[1]) names.add(ch);\n }\n }\n return names;\n}\n\nexport function allNamedEntitiesPresent(problem: string, dsl: DslInputT): NamedEntityReport {\n const present = new Set<string>();\n for (const p of dsl.points) present.add(p.name);\n for (const s of dsl.shapes) present.add(s.name);\n\n const missing: string[] = [];\n const constructionProblem = segmentClauses(problem)\n .filter((c) => c.hasGeometry)\n .map((c) => c.text)\n .join('. ');\n for (const name of collectExpectedNames(constructionProblem)) {\n if (!present.has(name)) missing.push(name);\n }\n return { ok: missing.length === 0, missing };\n}\n\n// ── Guard 2: intent → DSL fidelity ───────────────────────────────────────────\n// Mỗi add-point intent dựng điểm phái sinh (không phải 'free') PHẢI hiện diện\n// trong DSL đúng dạng. Builder idempotent DROP add-point khi tên trùng đỉnh sẵn\n// có (vd \"đường cao AB\" → foot B trùng vertex B) → điểm để 'free' → guard bắt.\n\nexport interface FidelityReport {\n ok: boolean;\n dropped: string[];\n}\n\nexport function verifyIntentFidelity(intents: readonly IntentT[], dsl: DslInputT): FidelityReport {\n const byName = new Map<string, { kind: string }>();\n for (const p of dsl.points) byName.set(p.name, p as unknown as { kind: string });\n\n const dropped: string[] = [];\n for (const intent of intents) {\n if (intent.op !== 'add-point') continue;\n const kind = (intent as { constraint?: { kind?: string } }).constraint?.kind;\n // free point không phải construct phái sinh → skip fidelity.\n // externalToCircle CỐ TÌNH dựng FREE point ngoài circle (như fixture canonical\n // tangent-from-external-named.ts): builder đặt A kind 'free' tại coord ngoài\n // circle, KHÔNG phải điểm phái sinh đặc thù bị drop. Nếu builder fail-safe skip\n // (circle thiếu / tâm không free) → A missing → guard allNamedEntitiesPresent\n // bắt (named-missing). Vì vậy bỏ externalToCircle khỏi fidelity check.\n if (!kind || kind === 'free' || kind === 'externalToCircle') continue;\n const name = (intent as { name: string }).name;\n const pt = byName.get(name);\n // Thiếu hẳn, hoặc bị builder hạ về 'free' (đã bị drop bởi vertex trùng tên).\n if (!pt || pt.kind === 'free') dropped.push(name);\n }\n return { ok: dropped.length === 0, dropped };\n}\n","// src/stamps/geometry-2d/ai/normalizeIntent.ts\n//\n// Post-LLM variant normalizer cho Intent pipeline.\n//\n// Mục đích: fix 2 nhóm bias quan sát được trong eval gemma3:12b:\n// 1. LLM emit isoceles variant SAI position (vd \"cân tại A\" → 'isoceles-AB'\n// thay vì 'isoceles-BC') vì naming rule canonical không trực giác.\n// 2. LLM follow prompt \"rectangle: wide | tall\" → emit 'wide' trong khi\n// eval + đa số sản phẩm muốn 'standard' (rendering identical với 'wide').\n//\n// Pure function, không mutate input.\n\nimport type { IntentT, DrawShapeIntentT, DrawLineIntentT } from './intent';\n\nconst CAN_TAI_RE = /c[aâ]n\\s+t[aạ]i\\s+([A-Z])/i;\nconst ISOCELES_AT_RE = /isoceles\\s+(?:at|with\\s+apex)\\s+([A-Z])/i;\nconst TALL_RECT_RE = /(cao|hẹp|thin|tall|portrait)/i;\n\n/**\n * Apply variant normalization. Returns new array; input unmodified.\n *\n * Rules áp dụng (chỉ override khi MATCH chắc; otherwise pass-through):\n * - triangle + \"cân tại X\" → variant theo position của X trong labels\n * - rectangle: default 'standard' (giữ 'tall' khi đề có \"cao\"/\"hẹp\")\n * - square|rhombus|parallelogram: ép 'standard' (chỉ 1 variant hợp lệ)\n */\nexport function normalizeIntents(\n intents: readonly IntentT[],\n problem: string,\n): IntentT[] {\n // Đếm tam giác: chỉ normalize \"cân tại X\" khi đề có ĐÚNG 1 tam giác — đa tam\n // giác thì không thể bind \"cân tại X\" toàn-problem cho đúng tam giác, mà rule\n // deterministic (window) / LLM đã set variant per-intent → tin theo đó.\n const triangleCount = intents.filter(\n (i) => i.op === 'draw-shape' && i.shape === 'triangle',\n ).length;\n return intents.map((intent) => {\n if (intent.op === 'draw-shape') return normalizeShape(intent, problem, triangleCount);\n if (intent.op === 'draw-line') return normalizeLine(intent);\n return intent;\n });\n}\n\n// Builder enforce strict field per kind. LLM nhầm field giữa các kind cùng\n// schema (through/from/to/circle/which đều optional). Fix: swap field khi\n// pattern rõ ràng (no ambiguity).\n//\n// Rules:\n// - tangentAt cần `through` (điểm trên đường tròn). Nếu LLM dùng `from` → swap.\n// - tangentFromExt cần `from` (điểm ngoài). Nếu LLM dùng `through` → swap.\n// - perpThrough / parallelThrough cần `through` (điểm) + `to` (line).\n// Nếu LLM dùng `from` thay `through` → swap.\nfunction normalizeLine(intent: DrawLineIntentT): DrawLineIntentT {\n if (intent.kind === 'tangentAt' && intent.from && !intent.through) {\n const { from, ...rest } = intent;\n return { ...rest, through: from };\n }\n if (intent.kind === 'tangentFromExt' && intent.through && !intent.from) {\n const { through, ...rest } = intent;\n return { ...rest, from: through };\n }\n if (\n (intent.kind === 'perpThrough' || intent.kind === 'parallelThrough') &&\n intent.from &&\n !intent.through\n ) {\n const { from, ...rest } = intent;\n return { ...rest, through: from };\n }\n return intent;\n}\n\nfunction normalizeShape(\n intent: DrawShapeIntentT,\n problem: string,\n triangleCount: number,\n): IntentT {\n switch (intent.shape) {\n case 'triangle':\n return normalizeTriangle(intent, problem, triangleCount);\n case 'rectangle':\n return normalizeRectangle(intent, problem);\n case 'square':\n case 'rhombus':\n case 'parallelogram':\n return forceStandard(intent);\n default:\n return intent;\n }\n}\n\nfunction normalizeRectangle(\n intent: DrawShapeIntentT,\n problem: string,\n): DrawShapeIntentT {\n if (intent.variant === 'tall' && TALL_RECT_RE.test(problem)) return intent;\n if (intent.variant === 'standard') return intent;\n return { ...intent, variant: 'standard' };\n}\n\nfunction forceStandard(intent: DrawShapeIntentT): DrawShapeIntentT {\n if (intent.variant === 'standard') return intent;\n return { ...intent, variant: 'standard' };\n}\n\nfunction normalizeTriangle(\n intent: DrawShapeIntentT,\n problem: string,\n triangleCount: number,\n): DrawShapeIntentT {\n // Đa tam giác: không clobber — variant đã được set đúng per-intent ở nguồn.\n if (triangleCount !== 1) return intent;\n const m = problem.match(CAN_TAI_RE) ?? problem.match(ISOCELES_AT_RE);\n if (!m) return intent;\n const apex = m[1].toUpperCase();\n const i = intent.labels.indexOf(apex);\n if (i < 0) return intent;\n // Variant POSITIONAL theo INDEX apex (builder: isoceles-BC ⇒ apex=vertex[0]).\n // KHÔNG dùng chữ-cái-nhãn để đúng cho nhãn ≠ ABC.\n const variantByPos: Record<number, DrawShapeIntentT['variant']> = {\n 0: 'isoceles-BC',\n 1: 'isoceles-CA',\n 2: 'isoceles-AB',\n };\n const target = variantByPos[i];\n if (!target || intent.variant === target) return intent;\n return { ...intent, variant: target };\n}\n","// src/stamps/geometry-2d/ai/resolveCircleNames.ts\n//\n// Preprocessor giải quyết naming collision giữa circle name và point ref.\n// DSL schema enforce global-unique name (point + shape share namespace), nên\n// circle X + point X không cùng tồn tại được. Notation Việt \"(O)\" thường ám\n// chỉ TÂM (point) của đường tròn, nhưng Claude/LLM hay đặt circle name là \"O\"\n// → connect M→O segment fail KIND_MISMATCH.\n//\n// Pure function — không gọi AI, idempotent:\n// 1. Detect circle names được reference như point trong intent khác\n// 2. Inject add-point center (circumcenter/incenter dựa trên spec) BEFORE circle\n// 3. Rename circle \"X\" → \"X_c\"\n// 4. Rewrite các CIRCLE-context ref tới circle name → \"X_c\"\n\nimport type { IntentT } from './intent';\n\nexport function resolveCircleNameCollisions(intents: readonly IntentT[]): IntentT[] {\n const circleNames = new Set<string>();\n for (const i of intents) {\n if (i.op === 'draw-circle') circleNames.add(i.name);\n }\n if (circleNames.size === 0) return [...intents];\n\n const pointRefs = collectPointRefs(intents);\n\n const existingPoints = new Set<string>();\n for (const i of intents) {\n if (i.op === 'draw-shape') {\n for (const l of i.labels) existingPoints.add(l);\n } else if (i.op === 'add-point') {\n existingPoints.add(i.name);\n }\n }\n\n // Circumcircle/incircle đặt tên kiểu NHÃN-TÂM (vd \"(O)\", \"(I)\", \"O1\", \"O′\"):\n // notation Việt \"(O)\" = đường tròn CÓ TÂM O, nên tâm LUÔN là điểm thật. Tách\n // vô điều kiện (dù O không bị tham chiếu như point ở đâu) → circle.ts đổi tên\n // circle → \"O_c\" làm `isCenter` thành false → tắt helper tâm cố định màu cam;\n // center point inject (circumcenter/incenter) vẽ chấm scene chọn được, đổi\n // tên/màu như mọi điểm. Tên synth không-phải-nhãn-tâm (vd \"w\") KHÔNG tách.\n const centerLabel = /^[A-Z]['′]?\\d*$/u;\n const forceSplit = new Set<string>();\n for (const i of intents) {\n if (\n i.op === 'draw-circle' &&\n (i.spec === 'through3' || i.spec === 'inscribedIn') &&\n centerLabel.test(i.name)\n ) {\n forceSplit.add(i.name);\n }\n }\n\n const collisions = new Set<string>();\n for (const name of circleNames) {\n if (pointRefs.has(name) || existingPoints.has(name) || forceSplit.has(name)) {\n collisions.add(name);\n }\n }\n\n const rename = new Map<string, string>();\n for (const name of collisions) {\n rename.set(name, `${name}_c`);\n }\n\n // circle-by-center: vài rule (circleDiameter) Đà đặt tên circle \"O_c\" + center\n // point \"O\", trong khi rule khác (lineCircleIntersection/onCircle) emit ref THÔ\n // \"O\" cho circle. Map base \"O\" → \"O_c\" để rewrite các ref đó. Chỉ khi KHÔNG có\n // circle thật tên \"O\" (nếu có thì ref \"O\" hợp lệ, không đụng).\n for (const name of circleNames) {\n if (!name.endsWith('_c')) continue;\n const base = name.slice(0, -2);\n if (circleNames.has(base)) continue; // circle \"O\" thật tồn tại → ref hợp lệ\n if (rename.has(base)) continue; // đã rename do collision\n rename.set(base, name);\n }\n\n if (rename.size === 0) return [...intents];\n\n const result: IntentT[] = [];\n for (const i of intents) {\n if (i.op === 'draw-circle' && collisions.has(i.name)) {\n if (!existingPoints.has(i.name)) {\n const centerIntent = makeCenterIntent(i);\n if (centerIntent) {\n result.push(centerIntent);\n existingPoints.add(i.name);\n }\n }\n result.push({ ...i, name: rename.get(i.name)! });\n } else {\n result.push(rewriteCircleRefs(i, rename));\n }\n }\n\n return result;\n}\n\nfunction makeCenterIntent(circle: Extract<IntentT, { op: 'draw-circle' }>): IntentT | null {\n if (circle.spec === 'through3' && circle.points) {\n return {\n op: 'add-point',\n name: circle.name,\n constraint: { kind: 'circumcenter', of: circle.points },\n };\n }\n if (circle.spec === 'inscribedIn' && circle.triangle) {\n return {\n op: 'add-point',\n name: circle.name,\n constraint: { kind: 'incenter', of: circle.triangle },\n };\n }\n // centerThrough/centerRadius: AI nhiều khi đặt `center === name` (vd `(O)` =\n // circle \"O\" có center \"O\") — cần inject `add-point name=center kind=free`\n // để point tồn tại sau khi circle được rename. Trường hợp center khác name\n // thì caller phải đảm bảo point center đã tồn tại (preprocessor không derive).\n if (\n (circle.spec === 'centerThrough' || circle.spec === 'centerRadius') &&\n circle.center === circle.name\n ) {\n return {\n op: 'add-point',\n name: circle.name,\n constraint: { kind: 'free' },\n };\n }\n return null;\n}\n\nfunction collectPointRefs(intents: readonly IntentT[]): Set<string> {\n const refs = new Set<string>();\n // 2-letter line/edge ref (vd \"BC\", \"AO\") → tách thành single-letter chars.\n // Cần thiết để detect collision khi line ref CHỨA tên circle (vd `line:\"AO\"`\n // + circle name \"O\" → O dùng như point ở \"AO\", phải inject center O).\n const addEdgeRef = (ref: string) => {\n if (/^[A-Za-z]{2}$/.test(ref)) {\n refs.add(ref[0]);\n refs.add(ref[1]);\n }\n };\n for (const i of intents) {\n if (i.op === 'connect') {\n refs.add(i.from);\n refs.add(i.to);\n } else if (i.op === 'add-point') {\n const c = i.constraint;\n if (c.kind === 'centroid' || c.kind === 'circumcenter' || c.kind === 'incenter' || c.kind === 'orthocenter') {\n for (const v of c.of) refs.add(v);\n } else if (c.kind === 'perpFoot' || c.kind === 'angleBisectorFoot') {\n refs.add(c.from);\n addEdgeRef(c.onLine);\n } else if (c.kind === 'tangentPoint') {\n refs.add(c.from);\n } else if (c.kind === 'secondIntersection') {\n refs.add(c.other);\n addEdgeRef(c.line);\n } else if (c.kind === 'tangencyPoint') {\n addEdgeRef(c.onLine);\n } else if (c.kind === 'midpoint' || c.kind === 'onSegment') {\n addEdgeRef(c.of);\n } else if (c.kind === 'intersection') {\n for (const r of c.of) addEdgeRef(r);\n } else if (c.kind === 'reflectPoint') {\n // through = tâm/điểm đối xứng. \"đối xứng A qua O\" với O là circle name →\n // O dùng như POINT (tâm) → collision, phải inject center + rename circle.\n refs.add(c.through);\n } else if (c.kind === 'reflectLine') {\n addEdgeRef(c.through);\n }\n } else if (i.op === 'draw-circle') {\n if (i.center) refs.add(i.center);\n if (i.through) refs.add(i.through);\n if (i.points) for (const p of i.points) refs.add(p);\n if (i.triangle) for (const p of i.triangle) refs.add(p);\n } else if (i.op === 'draw-line') {\n if (i.through) refs.add(i.through);\n if (i.from) refs.add(i.from);\n if (i.to) addEdgeRef(i.to);\n // i.circle là circle ref — skip.\n } else if (i.op === 'mark-shape') {\n for (const l of i.labels) refs.add(l);\n }\n }\n return refs;\n}\n\nfunction rewriteCircleRefs(intent: IntentT, rename: Map<string, string>): IntentT {\n if (intent.op === 'add-point') {\n const c = intent.constraint;\n if (\n c.kind === 'tangencyPoint' ||\n c.kind === 'tangentPoint' ||\n c.kind === 'secondIntersection' ||\n c.kind === 'externalToCircle' ||\n c.kind === 'onCircle' ||\n c.kind === 'arcMidpoint'\n ) {\n const newCircle = rename.get(c.circle);\n if (newCircle) {\n return { ...intent, constraint: { ...c, circle: newCircle } };\n }\n } else if (c.kind === 'circleIntersection' || c.kind === 'circleSecondIntersection') {\n const newC1 = rename.get(c.c1) ?? c.c1;\n const newC2 = rename.get(c.c2) ?? c.c2;\n if (newC1 !== c.c1 || newC2 !== c.c2) {\n return { ...intent, constraint: { ...c, c1: newC1, c2: newC2 } };\n }\n } else if (c.kind === 'intersection') {\n // `of` có thể chứa tên CIRCLE (line∩circle \"BD\",\"O\"). Rewrite entry trùng\n // circle bị đổi tên; entry line (segment) không có trong rename → giữ.\n const newOf = c.of.map((r) => rename.get(r) ?? r) as [string, string];\n if (newOf[0] !== c.of[0] || newOf[1] !== c.of[1]) {\n return { ...intent, constraint: { ...c, of: newOf } };\n }\n }\n } else if (intent.op === 'draw-line') {\n if (intent.circle && rename.has(intent.circle)) {\n return { ...intent, circle: rename.get(intent.circle)! };\n }\n if (intent.kind === 'radicalAxis') {\n const n1 = intent.circle1 ? rename.get(intent.circle1) : undefined;\n const n2 = intent.circle2 ? rename.get(intent.circle2) : undefined;\n if (n1 || n2) {\n return { ...intent, circle1: n1 ?? intent.circle1, circle2: n2 ?? intent.circle2 };\n }\n }\n }\n return intent;\n}\n","import type { DslPointT, DslShapeT } from '../dsl/schema';\n\n// Reposition auto-injected circle centers so two circles referenced by a\n// `circleIntersection` point actually cross at TWO points.\n//\n// Bối cảnh: builder inject free coord cho circle center theo bảng spread cách\n// nhau ~6 unit. Hai circle centerRadius cùng r=3 → distance = 6 = r1+r2 →\n// tiếp xúc ngoài (1 điểm) → JSXGraph intersection branch 0/1 trùng nhau hoặc\n// NaN → cascade hỏng (bug eval cau-08). Disjoint (d > r1+r2) còn tệ hơn.\n//\n// Điều kiện 2 giao điểm: |r1-r2| < d < r1+r2.\n// Khi d nằm ngoài \"vùng an toàn\" (sát biên tiếp xúc / disjoint), dời 1 center\n// FREE dọc theo hướng hiện tại về khoảng cách mục tiêu = trung điểm của khoảng\n// hợp lệ = (|r1-r2| + r1+r2)/2 = max(r1, r2). Giữ nguyên hướng để bố cục tương\n// đối không đảo lộn.\n\ntype FreePoint = Extract<DslPointT, { kind: 'free' }>;\n\n/** Resolve toạ độ tĩnh cho center (free hoặc midpoint của free/midpoint). */\nfunction resolveCoord(points: DslPointT[], name: string): [number, number] | null {\n const p = points.find((x) => x.name === name);\n if (!p) return null;\n if (p.kind === 'free') return [p.x, p.y];\n if (p.kind === 'midpoint') {\n const a = resolveCoord(points, p.p1);\n const b = resolveCoord(points, p.p2);\n if (!a || !b) return null;\n return [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];\n }\n return null;\n}\n\nexport function repairCircleIntersections(points: DslPointT[], shapes: DslShapeT[]): void {\n const shapeByName = new Map(shapes.map((s) => [s.name, s]));\n\n for (const pt of points) {\n if (pt.kind !== 'circleIntersection') continue;\n const c1 = shapeByName.get(pt.c1);\n const c2 = shapeByName.get(pt.c2);\n if (!c1 || !c2 || c1.kind !== 'circleCR' || c2.kind !== 'circleCR') continue;\n\n const r1 = c1.radius;\n const r2 = c2.radius;\n const lower = Math.abs(r1 - r2);\n const upper = r1 + r2;\n\n const coord1 = resolveCoord(points, c1.center);\n const coord2 = resolveCoord(points, c2.center);\n if (!coord1 || !coord2) continue;\n\n const d = Math.hypot(coord1[0] - coord2[0], coord1[1] - coord2[1]);\n const safeLow = lower * 1.05 + 1e-6;\n const safeHigh = upper * 0.95;\n if (d > safeLow && d < safeHigh) continue; // đã cắt 2 điểm gọn gàng\n\n // Cần 1 center FREE để dời. Ưu tiên center của c2 (thường inject sau), fallback c1.\n const p1 = points.find((p) => p.name === c1.center);\n const p2 = points.find((p) => p.name === c2.center);\n let mover: FreePoint | undefined;\n let anchor: [number, number] | undefined;\n if (p2?.kind === 'free') { mover = p2; anchor = coord1; }\n else if (p1?.kind === 'free') { mover = p1; anchor = coord2; }\n if (!mover || !anchor) continue; // không có center free để dời an toàn\n\n const targetD = (lower + upper) / 2; // = max(r1, r2)\n let dx = mover.x - anchor[0];\n let dy = mover.y - anchor[1];\n const len = Math.hypot(dx, dy);\n if (len < 1e-9) { dx = 1; dy = 0; }\n const norm = Math.hypot(dx, dy) || 1;\n mover.x = anchor[0] + (targetD * dx) / norm;\n mover.y = anchor[1] + (targetD * dy) / norm;\n }\n}\n","// src/stamps/geometry-2d/dsl/transpile/errors.ts\nimport type { State } from '../../../../core/scene/types';\n\nexport type TranspileErrorCode =\n | 'SCHEMA'\n | 'DUPLICATE_NAME'\n | 'UNKNOWN_REF'\n | 'KIND_MISMATCH'\n | 'CYCLE';\n\nexport interface TranspileError {\n code: TranspileErrorCode;\n message: string;\n path?: string[];\n hint?: string;\n}\n\nexport type TranspileResult =\n | { ok: true; state: State }\n | { ok: false; errors: TranspileError[] };\n\nexport function mkError(\n code: TranspileErrorCode,\n message: string,\n opts?: { path?: string[]; hint?: string },\n): TranspileError {\n return { code, message, path: opts?.path, hint: opts?.hint };\n}\n","// src/stamps/geometry-2d/dsl/transpile/refs.ts\nimport type { DslInputT, DslPointT, DslShapeT } from '../schema';\nimport { KIND_REGISTRY, LINE_LIKE_SHAPE_KINDS, CIRCLE_KINDS } from '../registry';\nimport type { RefRole, RefSpec } from '../kinds/_types';\nimport type { Symbol } from './symbols';\nimport { mkError, type TranspileError } from './errors';\n\nfunction isPointLike(sym: Symbol | undefined): boolean {\n return !!sym && sym.role === 'point';\n}\n\nfunction isLineLike(sym: Symbol | undefined): boolean {\n if (!sym || sym.role !== 'shape') return false;\n return LINE_LIKE_SHAPE_KINDS.has((sym.entity as DslShapeT).kind);\n}\n\nfunction isCircleLike(sym: Symbol | undefined): boolean {\n if (!sym || sym.role !== 'shape') return false;\n return CIRCLE_KINDS.has((sym.entity as DslShapeT).kind);\n}\n\nfunction isSegmentExact(sym: Symbol | undefined): boolean {\n return !!sym && sym.role === 'shape' && (sym.entity as DslShapeT).kind === 'segment';\n}\n\nconst ROLE_PREDICATE: Record<RefRole, (s: Symbol | undefined) => boolean> = {\n point: isPointLike,\n 'line-like': isLineLike,\n circle: isCircleLike,\n segment: isSegmentExact,\n 'line-or-circle': (s) => isLineLike(s) || isCircleLike(s),\n shape: (s) => !!s && s.role === 'shape',\n 'any-existing': (s) => !!s,\n};\nconst ROLE_EXPECTED: Record<RefRole, string> = {\n point: 'point',\n 'line-like': 'line-like',\n circle: 'circle',\n segment: 'segment',\n 'line-or-circle': 'line-like hoặc circle',\n shape: 'shape',\n 'any-existing': 'tồn tại',\n};\n\nexport interface RefsResult {\n errors: TranspileError[];\n}\n\nexport function validateRefs(dsl: DslInputT, symbols: Map<string, Symbol>): RefsResult {\n const errors: TranspileError[] = [];\n\n const check = (\n owner: string,\n field: string,\n refName: string,\n predicate: (s: Symbol | undefined) => boolean,\n expected: string,\n ) => {\n const sym = symbols.get(refName);\n if (!sym) {\n errors.push(mkError('UNKNOWN_REF',\n `${owner}.${field} tham chiếu \"${refName}\" không tồn tại`,\n { path: [owner, field] }));\n return;\n }\n if (!predicate(sym)) {\n errors.push(mkError('KIND_MISMATCH',\n `${owner}.${field}=\"${refName}\" sai kiểu (cần ${expected}, gặp ${sym.role === 'point' ? 'point' : (sym.entity as DslShapeT).kind})`,\n { path: [owner, field] }));\n }\n };\n\n // Registry-driven DUY NHẤT (switch legacy đã xoá 2026-06-12): mọi kind khai\n // refSpecs trong module của nó — mảng tĩnh, hàm theo entity cho discriminated\n // union (arcMidpoint/pointAtDistance), dotted path cho ref nested. Kind không\n // khai refSpecs → không validate (parity switch cũ: circleDiameter/\n // mixtilinearPoint/onPerpBisector vốn không có case).\n const runSpecs = (owner: string, entity: DslPointT | DslShapeT): void => {\n const mod = KIND_REGISTRY.get(entity.kind);\n const raw = mod?.refSpecs;\n if (!raw) return;\n const specs: readonly RefSpec[] =\n typeof raw === 'function' ? raw(entity as never) : raw;\n for (const spec of specs) {\n // field hỗ trợ dotted path ('distance.circle') cho ref nested trong\n // object con (vd pointAtDistance.distance.*).\n const val = spec.field\n .split('.')\n .reduce<unknown>((o, k) => (o as Record<string, unknown> | undefined)?.[k], entity);\n const names: string[] = spec.many\n ? ((val as string[]) ?? [])\n : val == null\n ? []\n : [val as string];\n names.forEach((refName, i) => {\n const field = spec.many ? `${spec.field}[${i}]` : spec.field;\n check(owner, field, refName, ROLE_PREDICATE[spec.role], ROLE_EXPECTED[spec.role]);\n });\n }\n };\n for (const p of dsl.points) runSpecs(p.name, p);\n for (const s of dsl.shapes) runSpecs(s.name, s);\n\n return { errors };\n}\n\n// Helper export cho cycles.ts: collect refs cho mỗi entity (name) trả về list ref names.\nexport function collectRefs(entity: DslPointT | DslShapeT): string[] {\n const mod = KIND_REGISTRY.get(entity.kind);\n if (!mod) throw new Error(`collectRefs: no registry entry for kind \"${entity.kind}\"`);\n return mod.collectRefs(entity as never);\n}\n","// src/stamps/geometry-2d/ai/layout/disjointOffset.ts\n//\n// Layout pass (issue #46 nhóm D, D1, Mức 1): tách các component RỜI NHAU (không\n// chia điểm/ref) theo trục ngang để không render chồng tại canonical origin.\n//\n// Pure, mutate in place (giống repairCircleIntersections). Chỉ dịch free point\n// (kind:'free' — điểm DUY NHẤT có x/y); điểm phái sinh KHÔNG có coord → transpile\n// tính lại từ ref đã dịch → tự đúng. Bất biến: ≤1 component → no-op (đề 1-figure\n// byte-identical).\n\nimport type { DslPointT, DslShapeT } from '../../dsl/schema';\nimport { collectRefs } from '../../dsl/transpile/refs';\n\nconst GAP = 2; // board-unit giữa 2 component liền kề\n\ntype FreePoint = Extract<DslPointT, { kind: 'free' }>;\ninterface Bbox { minX: number; maxX: number; minY: number; maxY: number; }\n\nexport function layoutDisjointComponents(points: DslPointT[], shapes: DslShapeT[]): void {\n // --- union-find trên mọi entity name (point + shape) ---\n const parent = new Map<string, string>();\n const find = (x: string): string => {\n const r = parent.get(x);\n if (r === undefined) { parent.set(x, x); return x; }\n if (r === x) return x;\n const root = find(r);\n parent.set(x, root);\n return root;\n };\n const union = (a: string, b: string) => {\n const ra = find(a), rb = find(b);\n if (ra !== rb) parent.set(ra, rb);\n };\n\n const entities: (DslPointT | DslShapeT)[] = [...points, ...shapes];\n for (const e of entities) {\n find(e.name); // đảm bảo node tồn tại\n for (const ref of collectRefs(e)) union(e.name, ref);\n }\n\n // --- free point + thứ tự xuất hiện trong mảng points ---\n const freeByName = new Map<string, { p: FreePoint; index: number }>();\n points.forEach((p, i) => {\n if (p.kind === 'free') freeByName.set(p.name, { p, index: i });\n });\n if (freeByName.size === 0) return;\n\n // --- gom free point theo component root + min free-index ---\n const compFree = new Map<string, { p: FreePoint; index: number }[]>();\n const compMinIndex = new Map<string, number>();\n for (const [name, rec] of freeByName) {\n const root = find(name);\n if (!compFree.has(root)) { compFree.set(root, []); compMinIndex.set(root, rec.index); }\n compFree.get(root)!.push(rec);\n compMinIndex.set(root, Math.min(compMinIndex.get(root)!, rec.index));\n }\n\n // --- bất biến: ≤1 component có free point → no-op ---\n if (compFree.size <= 1) return;\n\n // --- thứ tự component theo min free-index (= thứ tự đọc đề) ---\n const roots = [...compFree.keys()].sort(\n (a, b) => compMinIndex.get(a)! - compMinIndex.get(b)!,\n );\n\n // --- bbox per-component: free-point coords + mở rộng bán kính khi tâm là free ---\n const bboxOf = (root: string): Bbox => {\n let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;\n const ext = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n };\n for (const { p } of compFree.get(root)!) ext(p.x, p.y);\n for (const s of shapes) {\n if (find(s.name) !== root) continue;\n if (s.kind === 'circleCR') {\n const c = freeByName.get(s.center);\n if (c) { ext(c.p.x - s.radius, c.p.y - s.radius); ext(c.p.x + s.radius, c.p.y + s.radius); }\n } else if (s.kind === 'circleCP') {\n const c = freeByName.get(s.center);\n const sp = freeByName.get(s.surfacePoint);\n if (c && sp) {\n const r = Math.hypot(c.p.x - sp.p.x, c.p.y - sp.p.y);\n ext(c.p.x - r, c.p.y - r); ext(c.p.x + r, c.p.y + r);\n }\n }\n }\n return { minX, maxX, minY, maxY };\n };\n\n // --- pack ngang trái→phải (anchor giữ gốc, dx=0) ---\n let cursorX = bboxOf(roots[0]).maxX + GAP;\n for (let i = 1; i < roots.length; i++) {\n const root = roots[i];\n const bb = bboxOf(root);\n const dx = cursorX - bb.minX;\n for (const { p } of compFree.get(root)!) p.x += dx;\n cursorX = bb.maxX + dx + GAP;\n }\n}\n","// src/stamps/geometry-2d/ai/intent-builders/_types.ts\n//\n// Shared types cho intent-builders: BuildState (mutable build context),\n// newState() factory, IntentBuilderError, và IntentBuilder signature.\n// Tách ra từ intentToDsl.ts (Phase 2a, #45) — không đổi logic.\n\nimport type { DslPointT, DslShapeT } from '../../dsl/schema';\nimport type { IntentT } from '../intent';\n\nexport interface BuildState {\n points: DslPointT[];\n shapes: DslShapeT[];\n /** Map label → ensures uniqueness. */\n pointNames: Set<string>;\n shapeNames: Set<string>;\n /** Map \"AB\"/\"BA\" → segment shape name, dùng cho lookup of='BC'. */\n segmentByEnds: Map<string, string>;\n}\n\nexport function newState(): BuildState {\n return {\n points: [],\n shapes: [],\n pointNames: new Set(),\n shapeNames: new Set(),\n segmentByEnds: new Map(),\n };\n}\n\nexport class IntentBuilderError extends Error {\n constructor(\n message: string,\n public readonly intent: IntentT,\n public readonly cause?: string,\n ) {\n super(message);\n this.name = 'IntentBuilderError';\n }\n}\n\n/** Builder mutate BuildState theo 1 intent op (idempotent, giữ thứ tự gọi). */\nexport type IntentBuilder<T extends IntentT = IntentT> = (s: BuildState, intent: T) => void;\n","// src/stamps/geometry-2d/ai/intent-builders/shared.ts\n//\n// Shared helpers + canonical coord tables + SHAPE_VARIANTS cho intent-builders.\n// Move verbatim từ intentToDsl.ts (Phase 2a, #45) — không đổi logic.\n\nimport type { DslPointT, DslShapeT } from '../../dsl/schema';\nimport type { BuildState } from './_types';\n\n// ---------------------------------------------------------------------------\n// Canonical coord tables\n// ---------------------------------------------------------------------------\n\nexport type Pt = readonly [number, number];\n\nexport const SQRT3 = 1.7320508075688772;\n\nexport function triangleCanonical(variant: string): readonly [Pt, Pt, Pt] {\n switch (variant) {\n case 'equilateral':\n return [[0, 0], [4, 0], [2, 2 * SQRT3]];\n case 'isoceles-AB':\n // AB là đáy, C đỉnh cân\n return [[0, 0], [4, 0], [2, 3]];\n case 'isoceles-BC':\n // BC là đáy, A đỉnh cân\n return [[0, 3], [-2, 0], [2, 0]];\n case 'isoceles-CA':\n // CA là đáy, B đỉnh cân\n return [[0, 0], [2, 3], [4, 0]];\n case 'right-at-A':\n return [[0, 0], [4, 0], [0, 3]];\n case 'right-at-B':\n return [[0, 0], [4, 0], [4, 3]];\n case 'right-at-C':\n // C ở (4,3); AC ⊥ BC\n // chọn A=(0,0), C=(4,3), B=(7.36,1.92) sao cho CA·CB=0\n // Đơn giản hơn: A=(0,0), B=(7,0), C=(0,4) → vuông tại A. Wait — đó là right-at-A.\n // Cần vuông tại C: chọn 3 đỉnh sao cho (CA)·(CB)=0.\n // A=(0,0), B=(7,0), C=(3,4). Check: CA=(−3,−4), CB=(4,−4), dot=−12+16=4 ≠0. Sửa.\n // A=(0,0), C=(3,3), B=(6,0): CA=(−3,−3), CB=(3,−3), dot=−9+9=0 ✓\n return [[0, 0], [6, 0], [3, 3]];\n case 'any':\n default:\n // Tam giác scalene cố định, tránh vuông tại gốc\n return [[0, 0], [5, 0], [2, 3]];\n }\n}\n\nexport function squareCanonical(): readonly [Pt, Pt, Pt, Pt] {\n // Cạnh 4, gốc tại đỉnh đầu (counter-clockwise)\n return [[0, 0], [4, 0], [4, 4], [0, 4]];\n}\n\nexport function rectangleCanonical(variant: string): readonly [Pt, Pt, Pt, Pt] {\n if (variant === 'tall') return [[0, 0], [2.5, 0], [2.5, 4], [0, 4]];\n // wide / standard (default)\n return [[0, 0], [4, 0], [4, 2.5], [0, 2.5]];\n}\n\nexport function rhombusCanonical(): readonly [Pt, Pt, Pt, Pt] {\n // Đường chéo nằm trên trục, 4 đỉnh trên trục: (±2, 0) và (0, ±1.5)\n return [[-2, 0], [0, -1.5], [2, 0], [0, 1.5]];\n}\n\nexport function trapezoidCanonical(variant: string): readonly [Pt, Pt, Pt, Pt] {\n switch (variant) {\n case 'right':\n // Vuông tại A và D\n return [[0, 0], [5, 0], [3, 3], [0, 3]];\n case 'isoceles':\n // Cân — AB đáy lớn, CD đáy nhỏ\n return [[0, 0], [5, 0], [4, 3], [1, 3]];\n case 'general':\n default:\n return [[0, 0], [5, 0], [3.5, 3], [1, 3]];\n }\n}\n\nexport function parallelogramCanonical(): readonly [Pt, Pt, Pt, Pt] {\n return [[0, 0], [4, 0], [5, 3], [1, 3]];\n}\n\nexport function quadrilateralCanonical(): readonly [Pt, Pt, Pt, Pt] {\n return [[0, 0], [5, 0], [4.5, 3.5], [0.5, 3]];\n}\n\n// ---------------------------------------------------------------------------\n// Build helpers\n// ---------------------------------------------------------------------------\n\nexport function addPoint(s: BuildState, p: DslPointT) {\n if (s.pointNames.has(p.name)) {\n // Upgrade: 1 điểm 'free' (placeholder, vd endpoint đường kính do circleDiameter\n // emit) phải nhường cho constraint tường minh đến sau (onSegment/midpoint/…).\n // Thay tại CHỖ để giữ thứ tự array (intent khác có thể đã tham chiếu tên này).\n if (p.kind !== 'free') {\n const idx = s.points.findIndex((q) => q.name === p.name);\n if (idx >= 0 && s.points[idx].kind === 'free') s.points[idx] = p;\n }\n return; // idempotent (constraint đã có → free đến sau bị bỏ)\n }\n s.points.push(p);\n s.pointNames.add(p.name);\n}\n\n// Default coord cho free point khi LLM không truyền `at`. Spread theo thứ tự\n// thêm để tránh nhiều free point collide tại (3, 3) → segment degenerate,\n// circle radius=0, intersection NaN cascade (bug eval cau-14: A=B=D=(3,3)).\n// Pattern: 8 vị trí phân bố xung quanh gốc, vòng lại khi >8.\nexport const FREE_DEFAULT_SPREAD: readonly [number, number][] = [\n [3, 3],\n [-3, 3],\n [3, -3],\n [-3, -3],\n [4, 0],\n [-4, 0],\n [0, 4],\n [0, -4],\n];\n\nexport function defaultFreeCoord(s: BuildState): [number, number] {\n // Đếm số free point đã add (cả từ polygon vertices + add-point free).\n // Position trong array trùng index modulo SPREAD.\n let count = 0;\n for (const p of s.points) if (p.kind === 'free') count++;\n return [...FREE_DEFAULT_SPREAD[count % FREE_DEFAULT_SPREAD.length]];\n}\n\nexport function addShape(s: BuildState, sh: DslShapeT) {\n if (s.shapeNames.has(sh.name)) return;\n s.shapes.push(sh);\n s.shapeNames.add(sh.name);\n}\n\nexport function uniqueShapeName(s: BuildState, base: string): string {\n if (!s.shapeNames.has(base)) return base;\n let i = 2;\n while (s.shapeNames.has(`${base}${i}`)) i++;\n return `${base}${i}`;\n}\n\nexport function uniquePointName(s: BuildState, base: string): string {\n if (!s.pointNames.has(base)) return base;\n let i = 2;\n while (s.pointNames.has(`${base}${i}`)) i++;\n return `${base}${i}`;\n}\n\nexport function ensureSegment(s: BuildState, a: string, b: string): string {\n const k1 = `${a}-${b}`;\n const k2 = `${b}-${a}`;\n const existing = s.segmentByEnds.get(k1) ?? s.segmentByEnds.get(k2);\n if (existing) return existing;\n const name = uniqueShapeName(s, `${a}${b}`);\n addShape(s, { name, kind: 'segment', p1: a, p2: b });\n s.segmentByEnds.set(k1, name);\n return name;\n}\n\n// Resolve line ref cho draw-line (perpThrough/parallelThrough) với fallback:\n// LLM nhiều khi nhầm \"Đường vuông góc với AB tại B\" → to:\"A\" (1 chữ — POINT)\n// thay vì to:\"AB\" (2 chữ — LINE). Khi `ref` là 1 chữ POINT và `anchor` cũng\n// 1 chữ POINT khác, auto build segment qua 2 điểm (alphabetize canonical).\nexport function resolveLineRefWithFallback(s: BuildState, ref: string, anchor: string): string {\n // Single-letter point swap fallback — chỉ áp dụng khi cả 2 đều là POINT\n // đã định nghĩa và khác nhau.\n if (\n /^[A-Za-z]$/.test(ref) && /^[A-Za-z]$/.test(anchor) && ref !== anchor &&\n s.pointNames.has(ref) && s.pointNames.has(anchor)\n ) {\n const [a, b] = ref < anchor ? [ref, anchor] : [anchor, ref];\n return ensureSegment(s, a, b);\n }\n // Path bình thường: 2-char shorthand hoặc tên shape đã có.\n return resolveSegmentRef(s, ref);\n}\n\nexport function resolveSegmentRef(s: BuildState, ref: string): string {\n // ref có thể là tên segment ('AB') hoặc shape name đã có.\n // Tên shape đã có (gồm circle \"AB\" nếu lỡ đặt) → giữ nguyên.\n if (s.shapeNames.has(ref)) return ref;\n // 2 ký tự HOA \"AN\" = cặp đỉnh → ensureSegment OPTIMISTIC, kể cả khi điểm CHƯA\n // add (điểm phái sinh dựng sau do priority thấp hơn — vd onArc N < perpFoot).\n // intentsToDsl KHÔNG topo-sort theo dep nên ref tới điểm-dựng-sau hay thất bại;\n // segment trỏ p1/p2 = tên điểm, transpile resolve theo thứ tự + validate → token\n // KHÔNG phải điểm sẽ fail-safe escalate (không render sai).\n if (/^[A-Z][A-Z]$/u.test(ref)) {\n return ensureSegment(s, ref[0], ref[1]);\n }\n // Tách \"AB\" → A,B (mixed-case / đã tồn tại).\n if (ref.length === 2 && s.pointNames.has(ref[0]) && s.pointNames.has(ref[1])) {\n return ensureSegment(s, ref[0], ref[1]);\n }\n // Pattern \"A-B\" / \"AB\"\n const dashMatch = ref.match(/^([A-Za-z][A-Za-z0-9'_]*)[-_]?([A-Za-z][A-Za-z0-9'_]*)$/);\n if (dashMatch && s.pointNames.has(dashMatch[1]) && s.pointNames.has(dashMatch[2])) {\n return ensureSegment(s, dashMatch[1], dashMatch[2]);\n }\n // Cặp điểm CÓ CHỈ SỐ không dấu phân tách (\"B1C1\" = B1,C1; \"A1P\" = A1,P): tách\n // thành 2 điểm Đà BIẾT bằng longest-prefix match. Đề projective hay đặt tên\n // A1,B1…; \"B1C1\" → \"B1\"+\"C1\" (ưu tiên prefix dài, không \"B\"+\"1C1\").\n const sub = splitKnownPair(s, ref);\n if (sub) return ensureSegment(s, sub[0], sub[1]);\n // Trả về ref gốc (transpile sẽ báo lỗi nếu invalid)\n return ref;\n}\n\n/** Tách \"B1C1\"/\"A1P\" → [p1,p2] khi CẢ HAI là điểm đã biết; longest-prefix. */\nexport function splitKnownPair(s: BuildState, ref: string): [string, string] | null {\n for (let i = ref.length - 1; i >= 1; i--) {\n const a = ref.slice(0, i);\n const b = ref.slice(i);\n if (s.pointNames.has(a) && s.pointNames.has(b)) return [a, b];\n }\n return null;\n}\n\nexport function parseEnds(ref: string): [string, string] | null {\n if (ref.length === 2) return [ref[0], ref[1]];\n const m = ref.match(/^([A-Za-z][A-Za-z0-9'_]*)[-_]?([A-Za-z][A-Za-z0-9'_]*)$/);\n if (m) return [m[1], m[2]];\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// draw-shape variants\n// ---------------------------------------------------------------------------\n\n// Map shape → allowed variants (runtime check, schema cho phép enum chung)\nexport const SHAPE_VARIANTS: Record<string, readonly string[]> = {\n triangle: ['any', 'equilateral', 'isoceles-AB', 'isoceles-BC', 'isoceles-CA', 'right-at-A', 'right-at-B', 'right-at-C'],\n square: ['standard'],\n rectangle: ['standard', 'wide', 'tall'],\n rhombus: ['standard'],\n trapezoid: ['right', 'isoceles', 'general'],\n parallelogram: ['standard'],\n quadrilateral: ['any'],\n};\n","// src/stamps/geometry-2d/ai/intent-builders/draw-shape.ts\n//\n// op: draw-shape — move verbatim từ intentToDsl.ts handleDrawShape (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport {\n addPoint, addShape, uniqueShapeName,\n SHAPE_VARIANTS, triangleCanonical, squareCanonical, rectangleCanonical,\n rhombusCanonical, trapezoidCanonical, parallelogramCanonical, quadrilateralCanonical,\n type Pt,\n} from './shared';\nimport type { DrawShapeIntentT } from '../intent';\n\nexport const buildDrawShape: IntentBuilder<DrawShapeIntentT> = (s, intent) => {\n const labels = intent.labels;\n const explicit = intent.explicitCoords ?? {};\n\n // Validate variant ∈ allowed\n const allowed = SHAPE_VARIANTS[intent.shape];\n if (!allowed || !allowed.includes(intent.variant)) {\n // Fallback to default variant cho shape thay vì throw\n intent = { ...intent, variant: (allowed?.[0] ?? 'any') as typeof intent.variant };\n }\n\n let coords: readonly Pt[];\n switch (intent.shape) {\n case 'triangle': coords = triangleCanonical(intent.variant); break;\n case 'square': coords = squareCanonical(); break;\n case 'rectangle': coords = rectangleCanonical(intent.variant); break;\n case 'rhombus': coords = rhombusCanonical(); break;\n case 'trapezoid': coords = trapezoidCanonical(intent.variant); break;\n case 'parallelogram': coords = parallelogramCanonical(); break;\n case 'quadrilateral': coords = quadrilateralCanonical(); break;\n default:\n throw new IntentBuilderError(`Shape không hỗ trợ: ${intent.shape}`, intent);\n }\n\n if (coords.length !== labels.length) {\n throw new IntentBuilderError(\n `Shape ${intent.shape} cần ${coords.length} labels, nhận ${labels.length}`,\n intent,\n );\n }\n\n labels.forEach((label, i) => {\n const ec = explicit[label];\n const [x, y] = ec ?? coords[i];\n addPoint(s, { name: label, kind: 'free', x, y });\n });\n\n const polyName = uniqueShapeName(s, labels.join(''));\n addShape(s, { name: polyName, kind: 'polygon', vertices: [...labels] });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/midpoint.ts\n//\n// add-point constraint.kind=midpoint — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { IntentBuilderError } from '../_types';\nimport { addPoint, ensureSegment, parseEnds } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildMidpoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'midpoint') return;\n const name = intent.name;\n const ends = parseEnds(c.of);\n if (!ends) throw new IntentBuilderError(`midpoint.of không parse được: ${c.of}`, intent);\n // Ensure segment for the midpoint reference (optional but nice for rendering)\n ensureSegment(s, ends[0], ends[1]);\n addPoint(s, { name, kind: 'midpoint', p1: ends[0], p2: ends[1] });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/onPerpBisector.ts\n//\n// add-point constraint.kind=onPerpBisector — điểm tự do trên trung trực (p1,p2).\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildOnPerpBisector = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'onPerpBisector') return;\n addPoint(s, { name: intent.name, kind: 'onPerpBisector', p1: c.p1, p2: c.p2 });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/perpFoot.ts\n//\n// add-point constraint.kind=perpFoot — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildPerpFoot = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'perpFoot') return;\n const name = intent.name;\n const lineName = resolveSegmentRef(s, c.onLine);\n addPoint(s, { name, kind: 'perpFoot', from: c.from, onLine: lineName });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/centers.ts\n//\n// add-point centers: centroid/circumcenter/incenter/orthocenter/excenter\n// — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildCentroid = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'centroid') return;\n addPoint(s, { name: intent.name, kind: 'centroid', vertices: c.of });\n};\n\nexport const buildCircumcenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'circumcenter') return;\n addPoint(s, { name: intent.name, kind: 'circumcenter', vertices: c.of });\n};\n\nexport const buildIncenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'incenter') return;\n addPoint(s, { name: intent.name, kind: 'incenter', vertices: c.of });\n};\n\nexport const buildOrthocenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'orthocenter') return;\n addPoint(s, { name: intent.name, kind: 'orthocenter', vertices: c.of });\n};\n\nexport const buildExcenter = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'excenter') return;\n addPoint(s, { name: intent.name, kind: 'excenter', vertices: c.of, opposite: c.opposite });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/intersections.ts\n//\n// add-point intersections: intersection/secondIntersection/circleIntersection\n// — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'intersection') return;\n const r1 = resolveSegmentRef(s, c.of[0]);\n const r2 = resolveSegmentRef(s, c.of[1]);\n addPoint(s, {\n name: intent.name,\n kind: 'intersection',\n ref1: r1,\n ref2: r2,\n ...(c.branch !== undefined ? { branch: c.branch } : {}),\n });\n};\n\nexport const buildSecondIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'secondIntersection') return;\n const lineRef = resolveSegmentRef(s, c.line);\n addPoint(s, {\n name: intent.name, kind: 'secondIntersection',\n line: lineRef, circle: c.circle, other: c.other,\n });\n};\n\nexport const buildCircleIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'circleIntersection') return;\n addPoint(s, {\n name: intent.name, kind: 'circleIntersection',\n c1: c.c1, c2: c.c2, which: c.which,\n });\n};\n\nexport const buildCircleSecondIntersection = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'circleSecondIntersection') return;\n addPoint(s, {\n name: intent.name, kind: 'circleSecondIntersection',\n c1: c.c1, c2: c.c2, exclude: c.exclude,\n });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/tangency.ts\n//\n// add-point tangency: tangencyPoint/tangentPoint — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildTangencyPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'tangencyPoint') return;\n const lineRef = resolveSegmentRef(s, c.onLine);\n addPoint(s, {\n name: intent.name, kind: 'tangencyPoint',\n circle: c.circle, onLine: lineRef,\n });\n};\n\nexport const buildTangentPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'tangentPoint') return;\n addPoint(s, {\n name: intent.name, kind: 'tangentPointExt',\n from: c.from, circle: c.circle, which: c.which,\n });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/onSegment-free.ts\n//\n// add-point onSegment/free — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, defaultFreeCoord, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\nimport { LINE_LIKE_SHAPE_KINDS } from '../../../dsl/registry';\n\nexport const buildOnSegment = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'onSegment') return;\n const ref = resolveSegmentRef(s, c.of);\n // Nếu ref trỏ tới một shape line-like KHÔNG phải 'segment' (vd 'tangent',\n // 'perpendicular', 'parallel', 'ray', 'lineThrough') → glider phải dùng DSL\n // kind 'onLine' (lineId), không phải 'onSegment' (segmentId) — onSegment chỉ\n // chấp nhận đoạn thẳng (KIND_MISMATCH ngược lại). Dùng để đặt điểm trên tiếp\n // tuyến đặt tên (Bài 7: \"lấy trên tiếp tuyến Ax một điểm P\").\n const shape = s.shapes.find((sh) => sh.name === ref);\n if (shape && shape.kind !== 'segment' && LINE_LIKE_SHAPE_KINDS.has(shape.kind)) {\n addPoint(s, { name: intent.name, kind: 'onLine', lineId: ref, t: c.t ?? 0.5 });\n return;\n }\n addPoint(s, { name: intent.name, kind: 'onSegment', segmentId: ref, t: c.t ?? 0.5 });\n};\n\nexport const buildFree = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'free') return;\n const [x, y] = c.at ?? defaultFreeCoord(s);\n addPoint(s, { name: intent.name, kind: 'free', x, y });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/angleBisectorFoot.ts\n//\n// add-point constraint.kind=angleBisectorFoot — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n// Multi-emit: angleBisector shape + ensureSegment + intersection point.\n\nimport type { BuildState } from '../_types';\nimport { IntentBuilderError } from '../_types';\nimport { addPoint, addShape, ensureSegment, parseEnds, resolveSegmentRef, uniqueShapeName } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildAngleBisectorFoot = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'angleBisectorFoot') return;\n const name = intent.name;\n const ends = parseEnds(c.onLine);\n if (!ends) throw new IntentBuilderError(`angleBisectorFoot.onLine không parse: ${c.onLine}`, intent);\n const bisName = uniqueShapeName(s, `ab_${c.from}${c.onLine}`);\n addShape(s, { name: bisName, kind: 'angleBisector', p1: ends[0], vertex: c.from, p2: ends[1] });\n ensureSegment(s, ends[0], ends[1]);\n addPoint(s, { name, kind: 'intersection', ref1: bisName, ref2: resolveSegmentRef(s, c.onLine) });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/externalAngleBisectorFoot.ts\n//\n// add-point constraint.kind=externalAngleBisectorFoot — phân giác NGOÀI (Issue #46 nhóm A).\n// Mirror buildAngleBisectorFoot, nhưng phân giác ngoài = đường VUÔNG GÓC với phân\n// giác trong tại đỉnh `from`. Multi-emit:\n// 1. angleBisector shape (phân giác TRONG — helper, làm cơ sở dựng);\n// 2. perpendicular shape qua `from`, ⊥ phân giác trong = phân giác NGOÀI;\n// 3. ensureSegment(onLine) — cạnh đối (kéo dài) để giao;\n// 4. intersection point = phân giác ngoài ∩ đường thẳng cạnh đối.\n\nimport type { BuildState } from '../_types';\nimport { IntentBuilderError } from '../_types';\nimport { addPoint, addShape, ensureSegment, parseEnds, resolveSegmentRef, uniqueShapeName } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildExternalAngleBisectorFoot = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'externalAngleBisectorFoot') return;\n const name = intent.name;\n const ends = parseEnds(c.onLine);\n if (!ends) throw new IntentBuilderError(`externalAngleBisectorFoot.onLine không parse: ${c.onLine}`, intent);\n // Phân giác trong (helper, cơ sở dựng phân giác ngoài).\n const bisName = uniqueShapeName(s, `ab_${c.from}${c.onLine}`);\n addShape(s, { name: bisName, kind: 'angleBisector', p1: ends[0], vertex: c.from, p2: ends[1] });\n // Phân giác ngoài = đường vuông góc với phân giác trong tại đỉnh `from`.\n const extName = uniqueShapeName(s, `abx_${c.from}${c.onLine}`);\n addShape(s, { name: extName, kind: 'perpendicular', throughPoint: c.from, toLine: bisName });\n ensureSegment(s, ends[0], ends[1]);\n addPoint(s, { name, kind: 'intersection', ref1: extName, ref2: resolveSegmentRef(s, c.onLine) });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/rightAngleViewing.ts\n//\n// add-point constraint.kind=rightAngleViewing — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n// Multi-emit: hidden midpoint + hidden circleCP (Thales diameter) + intersection line∩circle.\n\nimport type { BuildState } from '../_types';\nimport { addPoint, addShape, resolveSegmentRef, uniquePointName, uniqueShapeName } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildRightAngleViewing = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'rightAngleViewing') return;\n const name = intent.name;\n // ∠ a-name-b = 90° ⇔ name trên đường tròn đường kính ab (Thales).\n // Dựng: midpoint(ab) ẩn → circleCP đường kính ab ẩn → giao line∩circle.\n const midName = uniquePointName(s, `mid_${c.a}${c.b}`);\n addPoint(s, { name: midName, kind: 'midpoint', p1: c.a, p2: c.b, visible: false });\n const circName = uniqueShapeName(s, `dia_${c.a}${c.b}`);\n addShape(s, { name: circName, kind: 'circleCP', center: midName, surfacePoint: c.a, visible: false });\n const lineRef = resolveSegmentRef(s, c.onLine);\n addPoint(s, { name, kind: 'intersection', ref1: lineRef, ref2: circName, branch: c.which ?? 0 });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/arcMidpoint.ts\n//\n// add-point constraint.kind=arcMidpoint (Cụm A) — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildArcMidpoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'arcMidpoint') return;\n addPoint(s, {\n name: intent.name, kind: 'arcMidpoint', circle: c.circle, a: c.a, b: c.b,\n // notContaining/containing optional: cung không mơ hồ (nửa đường tròn) → bỏ cả hai.\n ...(c.containing\n ? { containing: c.containing }\n : c.notContaining\n ? { notContaining: c.notContaining }\n : {}),\n });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/reflect.ts\n//\n// add-point reflectPoint/reflectLine (Cụm A) — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n\nimport type { BuildState } from '../_types';\nimport { addPoint, resolveSegmentRef } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildReflectPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'reflectPoint') return;\n addPoint(s, { name: intent.name, kind: 'reflectPoint', of: c.of, through: c.through });\n};\n\nexport const buildReflectLine = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'reflectLine') return;\n const lineRef = resolveSegmentRef(s, c.through);\n addPoint(s, { name: intent.name, kind: 'reflectLine', of: c.of, through: lineRef });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/pointAtDistance.ts\n//\n// add-point constraint.kind=pointAtDistance (Cụm B) — move verbatim từ handleAddPoint switch (Phase 2b, #45).\n// Multi-emit: ensureSegment + pointAtDistance point.\n\nimport type { BuildState } from '../_types';\nimport { addPoint, ensureSegment } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildPointAtDistance = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'pointAtDistance') return;\n ensureSegment(s, c.from, c.through);\n addPoint(s, { name: intent.name, kind: 'pointAtDistance', from: c.from, through: c.through, distance: c.distance });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/externalToCircle.ts\n//\n// add-point externalToCircle — điểm A nằm NGOÀI đường tròn `circle` (free\n// external point). Builder đọc circle shape từ build state, tính tâm+bán kính,\n// rồi đặt A = free tại [cx + d, cy] với d = max(r*2, r+2) (đảm bảo distance > r\n// → A NGOÀI). Unblock tangentFromExt render END-TO-END (đề \"Lấy A ngoài (O), kẻ\n// 2 tiếp tuyến\").\n//\n// Fail-safe (skip → A KHÔNG add → tangent UNKNOWN_REF / named-missing →\n// escalate, KHÔNG render sai):\n// - circle shape không tồn tại trong build state.\n// - tâm/bán kính không xác định được (tâm không phải free, surfacePoint thiếu).\n//\n// Field name theo dsl/schema.ts: circleCR = { center, radius }; circleCP =\n// { center, surfacePoint } (KHÔNG phải `through`).\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildExternalToCircle = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'externalToCircle') return;\n const circle = s.shapes.find((sh) => sh.name === c.circle);\n if (!circle) return; // fail-safe: A không add → escalate\n\n let cx: number | undefined;\n let cy: number | undefined;\n let r: number | undefined;\n\n if (circle.kind === 'circleCR') {\n const center = s.points.find((p) => p.name === circle.center);\n if (center && center.kind === 'free') {\n cx = center.x;\n cy = center.y;\n r = circle.radius;\n }\n } else if (circle.kind === 'circleCP') {\n const center = s.points.find((p) => p.name === circle.center);\n const surf = s.points.find((p) => p.name === circle.surfacePoint);\n if (center && center.kind === 'free' && surf && surf.kind === 'free') {\n cx = center.x;\n cy = center.y;\n r = Math.hypot(surf.x - cx, surf.y - cy);\n }\n }\n\n if (cx === undefined || cy === undefined || r === undefined || !(r > 0)) return; // fail-safe\n const d = Math.max(r * 2, r + 2);\n addPoint(s, { name: intent.name, kind: 'free', x: cx + d, y: cy });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/onCircle.ts\n//\n// add-point constraint.kind=onCircle — điểm trên đường tròn `circle` tại góc\n// `theta` (glider). Map intent.circle → DSL circleId, theta default 0. Dùng cho\n// đường thẳng Simson (issue #47): P trên đường tròn ngoại tiếp tam giác.\n\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildOnCircle = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'onCircle') return;\n addPoint(s, { name: intent.name, kind: 'onCircle', circleId: c.circle, theta: c.theta ?? 0 });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/mixtilinear.ts\nimport type { BuildState } from '../_types';\nimport { addPoint } from '../shared';\nimport type { AddPointIntentT } from '../../intent';\n\nexport const buildMixtilinearPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const c = intent.constraint;\n if (c.kind !== 'mixtilinearPoint') return;\n addPoint(s, { name: intent.name, kind: 'mixtilinearPoint', vertices: c.of, which: c.which });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/add-point/index.ts\n//\n// Dispatcher cho op add-point: map constraint.kind → builder (Phase 2b, #45).\n// ADD_POINT_BUILDERS được export cho Phase 6 matrix script.\n\nimport type { BuildState } from '../_types';\nimport type { AddPointIntentT } from '../../intent';\nimport { buildMidpoint } from './midpoint';\nimport { buildOnPerpBisector } from './onPerpBisector';\nimport { buildPerpFoot } from './perpFoot';\nimport { buildCentroid, buildCircumcenter, buildIncenter, buildOrthocenter, buildExcenter } from './centers';\nimport { buildIntersection, buildSecondIntersection, buildCircleIntersection, buildCircleSecondIntersection } from './intersections';\nimport { buildTangencyPoint, buildTangentPoint } from './tangency';\nimport { buildOnSegment, buildFree } from './onSegment-free';\nimport { buildAngleBisectorFoot } from './angleBisectorFoot';\nimport { buildExternalAngleBisectorFoot } from './externalAngleBisectorFoot';\nimport { buildRightAngleViewing } from './rightAngleViewing';\nimport { buildArcMidpoint } from './arcMidpoint';\nimport { buildReflectPoint, buildReflectLine } from './reflect';\nimport { buildPointAtDistance } from './pointAtDistance';\nimport { buildExternalToCircle } from './externalToCircle';\nimport { buildOnCircle } from './onCircle';\nimport { buildMixtilinearPoint } from './mixtilinear';\n\nexport const ADD_POINT_BUILDERS: Record<string, (s: BuildState, intent: AddPointIntentT) => void> = {\n midpoint: buildMidpoint, onPerpBisector: buildOnPerpBisector, perpFoot: buildPerpFoot,\n centroid: buildCentroid, circumcenter: buildCircumcenter, incenter: buildIncenter,\n orthocenter: buildOrthocenter, excenter: buildExcenter,\n intersection: buildIntersection, secondIntersection: buildSecondIntersection, circleIntersection: buildCircleIntersection,\n circleSecondIntersection: buildCircleSecondIntersection,\n tangencyPoint: buildTangencyPoint, tangentPoint: buildTangentPoint,\n onSegment: buildOnSegment, free: buildFree,\n angleBisectorFoot: buildAngleBisectorFoot, externalAngleBisectorFoot: buildExternalAngleBisectorFoot,\n rightAngleViewing: buildRightAngleViewing,\n arcMidpoint: buildArcMidpoint, reflectPoint: buildReflectPoint, reflectLine: buildReflectLine,\n pointAtDistance: buildPointAtDistance,\n externalToCircle: buildExternalToCircle,\n onCircle: buildOnCircle,\n mixtilinearPoint: buildMixtilinearPoint,\n};\n\nexport const buildAddPoint = (s: BuildState, intent: AddPointIntentT): void => {\n const fn = ADD_POINT_BUILDERS[intent.constraint.kind];\n if (fn) fn(s, intent);\n};\n","// src/stamps/geometry-2d/ai/intent-builders/connect.ts\n//\n// op: connect — move verbatim từ intentToDsl.ts handleConnect (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { ensureSegment, addShape, uniqueShapeName } from './shared';\nimport type { ConnectIntentT } from '../intent';\n\nexport const buildConnect: IntentBuilder<ConnectIntentT> = (s, intent) => {\n const { from, to, style } = intent;\n switch (style) {\n case 'segment':\n ensureSegment(s, from, to);\n break;\n case 'line':\n addShape(s, { name: uniqueShapeName(s, `l_${from}${to}`), kind: 'line', p1: from, p2: to });\n break;\n case 'ray':\n addShape(s, { name: uniqueShapeName(s, `r_${from}${to}`), kind: 'ray', origin: from, through: to });\n break;\n case 'perpBisector':\n addShape(s, { name: uniqueShapeName(s, `pb_${from}${to}`), kind: 'perpBisector', p1: from, p2: to });\n break;\n case 'angleBisector':\n // angleBisector cần 3 điểm (p1, vertex, p2). connect chỉ có 2 điểm → bỏ qua,\n // caller nên dùng intent.add-point với incenter/internalBisector.\n throw new IntentBuilderError(\n 'connect.style=angleBisector cần 3 điểm; dùng add-point/incenter thay',\n intent,\n );\n }\n};\n","// src/stamps/geometry-2d/ai/intent-builders/draw-circle.ts\n//\n// op: draw-circle — move verbatim từ intentToDsl.ts handleDrawCircle (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { addPoint, addShape, defaultFreeCoord } from './shared';\nimport type { DrawCircleIntentT } from '../intent';\n\nexport const buildDrawCircle: IntentBuilder<DrawCircleIntentT> = (s, intent) => {\n if (intent.spec === 'centerThrough') {\n if (!intent.center || !intent.through) {\n throw new IntentBuilderError('centerThrough cần center + through', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'circleCP',\n center: intent.center,\n surfacePoint: intent.through,\n });\n } else if (intent.spec === 'through3') {\n if (!intent.points) {\n throw new IntentBuilderError('through3 cần points', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'circle3',\n p1: intent.points[0],\n p2: intent.points[1],\n p3: intent.points[2],\n });\n } else if (intent.spec === 'centerRadius') {\n if (!intent.center || intent.radius === undefined) {\n throw new IntentBuilderError('centerRadius cần center + radius', intent);\n }\n if (!s.points.find((p) => p.name === intent.center)) {\n const [x, y] = defaultFreeCoord(s);\n addPoint(s, { name: intent.center!, kind: 'free', x, y });\n }\n addShape(s, { name: intent.name, kind: 'circleCR', center: intent.center, radius: intent.radius });\n } else if (intent.spec === 'diameter') {\n if (!intent.endpoints) {\n throw new IntentBuilderError('diameter cần endpoints', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'circleDiameter',\n p1: intent.endpoints[0],\n p2: intent.endpoints[1],\n });\n } else if (intent.spec === 'inscribedIn') {\n if (!intent.triangle) throw new IntentBuilderError('inscribedIn cần triangle', intent);\n for (const v of intent.triangle) {\n if (!s.points.find((p) => p.name === v)) {\n throw new IntentBuilderError(`inscribedIn: vertex ${v} chưa định nghĩa`, intent);\n }\n }\n addShape(s, { name: intent.name, kind: 'incircle', vertices: intent.triangle });\n }\n};\n","// src/stamps/geometry-2d/ai/intent-builders/draw-line.ts\n//\n// op: draw-line — move verbatim từ intentToDsl.ts handleDrawLine (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { addShape, resolveLineRefWithFallback } from './shared';\nimport type { DrawLineIntentT } from '../intent';\n\nexport const buildDrawLine: IntentBuilder<DrawLineIntentT> = (s, intent) => {\n switch (intent.kind) {\n case 'perpThrough': {\n if (!intent.through || !intent.to) throw new IntentBuilderError('perpThrough cần through + to', intent);\n const toLine = resolveLineRefWithFallback(s, intent.to, intent.through);\n addShape(s, { name: intent.name, kind: 'perpendicular', throughPoint: intent.through, toLine });\n break;\n }\n case 'parallelThrough': {\n if (!intent.through || !intent.to) throw new IntentBuilderError('parallelThrough cần through + to', intent);\n const toLine = resolveLineRefWithFallback(s, intent.to, intent.through);\n addShape(s, { name: intent.name, kind: 'parallel', throughPoint: intent.through, toLine });\n break;\n }\n case 'tangentAt': {\n if (!intent.through || !intent.circle) throw new IntentBuilderError('tangentAt cần through + circle', intent);\n addShape(s, { name: intent.name, kind: 'tangent', throughPoint: intent.through, toCircle: intent.circle, branch: 'on' });\n break;\n }\n case 'tangentFromExt': {\n if (!intent.from || !intent.circle) throw new IntentBuilderError('tangentFromExt cần from + circle', intent);\n if (intent.which === 'both') {\n addShape(s, { name: `${intent.name}_0`, kind: 'tangent', throughPoint: intent.from, toCircle: intent.circle, branch: 0 });\n addShape(s, { name: `${intent.name}_1`, kind: 'tangent', throughPoint: intent.from, toCircle: intent.circle, branch: 1 });\n } else {\n const branch = intent.which === 'second' ? 1 : 0;\n addShape(s, { name: intent.name, kind: 'tangent', throughPoint: intent.from, toCircle: intent.circle, branch });\n }\n break;\n }\n case 'angleBisector': {\n // Phân giác TRONG của góc ∠(p1·vertex·p2), VISIBLE, KHÔNG sinh chân\n // (khác cevian \"phân giác AD\" → foot). vertex = đỉnh góc. Issue #46 nhóm A.\n if (!intent.p1 || !intent.vertex || !intent.p2) {\n throw new IntentBuilderError('angleBisector cần p1 + vertex + p2', intent);\n }\n addShape(s, {\n name: intent.name,\n kind: 'angleBisector',\n p1: intent.p1,\n vertex: intent.vertex,\n p2: intent.p2,\n });\n break;\n }\n case 'lineThrough': {\n // Đường qua ≥2 điểm đồng tuyến (vd Euler line qua G/H/O — issue #47).\n if (!intent.points || intent.points.length < 2) {\n throw new IntentBuilderError('lineThrough cần ≥2 điểm', intent);\n }\n addShape(s, { name: intent.name, kind: 'lineThrough', points: intent.points });\n break;\n }\n case 'radicalAxis': {\n // Trục đẳng phương 2 đường tròn (issue #47, construct 2).\n if (!intent.circle1 || !intent.circle2) {\n throw new IntentBuilderError('radicalAxis cần circle1 + circle2', intent);\n }\n addShape(s, { name: intent.name, kind: 'radicalAxis', circle1: intent.circle1, circle2: intent.circle2 });\n break;\n }\n case 'perpBisector': {\n // Trung trực đoạn p1p2 (line construction). Dùng cho tâm đường tròn tiếp\n // xúc đường tại 1 điểm + qua 1 điểm (tâm = perpBisector ∩ perp-tại-tiếp-điểm).\n if (!intent.p1 || !intent.p2) throw new IntentBuilderError('perpBisector cần p1 + p2', intent);\n addShape(s, { name: intent.name, kind: 'perpBisector', p1: intent.p1, p2: intent.p2 });\n break;\n }\n }\n};\n","// src/stamps/geometry-2d/ai/intent-builders/mark-shape.ts\n//\n// op: mark-shape — move verbatim từ intentToDsl.ts handleMarkShape (Phase 2b, #45).\n\nimport type { IntentBuilder } from './_types';\nimport { IntentBuilderError } from './_types';\nimport { addShape, uniqueShapeName } from './shared';\nimport type { MarkShapeIntentT } from '../intent';\n\nexport const buildMarkShape: IntentBuilder<MarkShapeIntentT> = (s, intent) => {\n for (const label of intent.labels) {\n if (!s.points.find((p) => p.name === label)) {\n throw new IntentBuilderError(`mark-shape: label ${label} chưa định nghĩa`, intent);\n }\n }\n const polyName = uniqueShapeName(s, intent.labels.join(''));\n addShape(s, { name: polyName, kind: 'polygon', vertices: [...intent.labels] });\n};\n","// src/stamps/geometry-2d/ai/intent-builders/registry.ts\n//\n// OP_BUILDERS: map intent.op → builder (Phase 2b, #45).\n// Thêm 1 op = 1 builder module + 1 dòng ở đây, không sửa switch trung tâm.\n\nimport type { BuildState } from './_types';\nimport type { IntentT } from '../intent';\nimport { buildDrawShape } from './draw-shape';\nimport { buildAddPoint } from './add-point';\nimport { buildConnect } from './connect';\nimport { buildDrawCircle } from './draw-circle';\nimport { buildDrawLine } from './draw-line';\nimport { buildMarkShape } from './mark-shape';\n\nexport const OP_BUILDERS: Record<IntentT['op'], (s: BuildState, intent: any) => void> = {\n 'draw-shape': buildDrawShape,\n 'add-point': buildAddPoint,\n 'connect': buildConnect,\n 'draw-circle': buildDrawCircle,\n 'draw-line': buildDrawLine,\n 'mark-shape': buildMarkShape,\n};\n","// src/stamps/geometry-2d/ai/intentToDsl.ts\n//\n// Stage 2: deterministic Intent[] → DslInputT builder.\n//\n// Pure function. Không gọi AI. Mỗi Intent op map sang 1 hoặc nhiều DSL entries\n// với canonical coords cố định per variant. Builder rejects intent không hợp lệ\n// (vd connect to point chưa tồn tại) thay vì silent skip.\n//\n// Phase 2b (#45): orchestrator mỏng — dispatch qua OP_BUILDERS registry.\n// Thứ tự loop intents giữ nguyên (ordering dependency: draw-shape trước add-point\n// tham chiếu điểm của nó). repairCircleIntersections chạy post-dispatch.\n\nimport type { DslInputT } from '../dsl/schema';\nimport type { IntentT } from './intent';\nimport { repairCircleIntersections } from './repairCircleIntersections';\nimport { layoutDisjointComponents } from './layout/disjointOffset';\nimport { newState } from './intent-builders/_types';\nimport { OP_BUILDERS } from './intent-builders/registry';\n\nexport { IntentBuilderError } from './intent-builders/_types';\n\nexport function intentsToDsl(intents: readonly IntentT[]): DslInputT {\n const s = newState();\n for (const intent of intents) {\n const build = OP_BUILDERS[intent.op];\n if (build) build(s, intent);\n }\n // Geometric repair: đảm bảo circle dùng cho circleIntersection thực sự cắt\n // nhau 2 điểm (dời center auto-inject nếu tiếp xúc/rời nhau).\n repairCircleIntersections(s.points, s.shapes);\n // Layout: tách các component RỜI NHAU theo trục ngang (không chồng origin).\n layoutDisjointComponents(s.points, s.shapes);\n return { version: 1, points: s.points, shapes: s.shapes };\n}\n","// src/stamps/geometry-2d/ai/intentTopo.ts\n//\n// Stable topological reorder cho IntentT[] theo quan hệ produce/consume TÊN:\n// - produce: draw-shape→labels; add-point/draw-circle/draw-line→name.\n// - consume: mọi string value trong intent (deep) resolve được về tên đã\n// produce — trực tiếp (\"M\", \"O_c\", \"d\") hoặc tách cặp đỉnh longest-prefix\n// (\"BC\"→B+C, \"B1C1\"→B1+C1, như splitKnownPair của intent-builders).\n//\n// Stable Kahn (giống dsl/transpile/topology.ts): thứ tự ĐÃ hợp lệ giữ NGUYÊN\n// 100% (mỗi pass quét theo thứ tự gốc); chỉ intent đứng trước producer của nó\n// mới bị trì hoãn. Cycle/ref không ai produce → không chặn, append thứ tự gốc\n// (transpile fail-safe escalate như cũ).\n//\n// Dùng làm RETRY trong buildAndTranspile (tryDeterministicFigure) — KHÔNG chạy\n// mặc định, vì builder có hành vi phụ thuộc thứ tự hợp lệ cần bảo toàn\n// (defaultFreeCoord spread, uniqueShapeName) → case đang pass byte-identical.\nimport type { IntentT } from './intent';\n\n/** Field mang tên do CHÍNH intent đó sinh ra — bỏ qua khi gom consume. */\nconst PRODUCE_FIELDS: Record<IntentT['op'], readonly string[]> = {\n 'draw-shape': ['labels', 'explicitCoords'],\n 'add-point': ['name'],\n 'draw-circle': ['name'],\n 'draw-line': ['name'],\n connect: [],\n 'mark-shape': [],\n};\n\nfunction producesOf(intent: IntentT): string[] {\n switch (intent.op) {\n case 'draw-shape':\n return [...intent.labels];\n case 'add-point':\n case 'draw-circle':\n case 'draw-line':\n return [intent.name];\n case 'connect':\n case 'mark-shape':\n return [];\n }\n}\n\nfunction walkStrings(val: unknown, skipKeys: ReadonlySet<string>, out: string[]): void {\n if (typeof val === 'string') {\n out.push(val);\n return;\n }\n if (Array.isArray(val)) {\n for (const v of val) walkStrings(v, skipKeys, out);\n return;\n }\n if (val && typeof val === 'object') {\n for (const [k, v] of Object.entries(val)) {\n if (skipKeys.has(k)) continue;\n walkStrings(v, skipKeys, out);\n }\n }\n}\n\n/** Token → các tên đã-produce mà nó tham chiếu ([] nếu không resolve được). */\nfunction resolveToken(token: string, produced: ReadonlySet<string>): string[] {\n if (produced.has(token)) return [token];\n // Cặp đỉnh ghép (\"BC\", \"B1C1\", \"AH'\") — longest-prefix như splitKnownPair.\n for (let i = token.length - 1; i >= 1; i--) {\n const a = token.slice(0, i);\n const b = token.slice(i);\n if (produced.has(a) && produced.has(b)) return [a, b];\n }\n return [];\n}\n\nexport function orderIntentsByDependency(intents: readonly IntentT[]): IntentT[] {\n const producesArr = intents.map(producesOf);\n // name → index intent ĐẦU TIÊN produce nó (addPoint idempotent first-wins).\n const producerIdx = new Map<string, number>();\n producesArr.forEach((names, i) => {\n for (const n of names) if (!producerIdx.has(n)) producerIdx.set(n, i);\n });\n const produced = new Set(producerIdx.keys());\n\n const depsArr = intents.map((intent, i) => {\n const skip = new Set<string>(['op', ...PRODUCE_FIELDS[intent.op]]);\n const tokens: string[] = [];\n walkStrings(intent, skip, tokens);\n const own = new Set(producesArr[i]);\n const deps = new Set<number>();\n for (const t of tokens) {\n for (const name of resolveToken(t, produced)) {\n if (own.has(name)) continue;\n const pi = producerIdx.get(name);\n if (pi !== undefined && pi !== i) deps.add(pi);\n }\n }\n return deps;\n });\n\n const emitted = new Set<number>();\n const order: number[] = [];\n let progressed = true;\n while (progressed && order.length < intents.length) {\n progressed = false;\n for (let i = 0; i < intents.length; i++) {\n if (emitted.has(i)) continue;\n let ready = true;\n for (const d of depsArr[i]) {\n if (!emitted.has(d)) {\n ready = false;\n break;\n }\n }\n if (ready) {\n emitted.add(i);\n order.push(i);\n progressed = true;\n }\n }\n }\n // Cycle leftovers: append theo thứ tự gốc (fail-safe, đủ phần tử).\n for (let i = 0; i < intents.length; i++) {\n if (!emitted.has(i)) order.push(i);\n }\n return order.map((i) => intents[i]);\n}\n","// src/stamps/geometry-2d/dsl/schema.ts\nimport { z } from 'zod';\nimport { NameZ } from './names';\nimport { KIND_REGISTRY, POINT_KINDS } from './registry';\n\n// Re-export NameZ for backward compat with consumers.\nexport { NameZ } from './names';\n\nfunction asTuple(arr: z.ZodObject<any>[]): [z.ZodObject<any>, z.ZodObject<any>, ...z.ZodObject<any>[]] {\n if (arr.length < 2) throw new Error('schema: need at least 2 variants for discriminatedUnion');\n return arr as never;\n}\n\nconst pointSchemas = Array.from(KIND_REGISTRY.values())\n .filter((m) => POINT_KINDS.has(m.kind))\n .map((m) => m.schema);\n\nconst shapeSchemas = Array.from(KIND_REGISTRY.values())\n .filter((m) => !POINT_KINDS.has(m.kind))\n .map((m) => m.schema);\n\n// Runtime schemas assembled from the registry (Phase 6).\nexport const DslPoint = z.discriminatedUnion('kind', asTuple(pointSchemas));\nexport const DslShape = z.discriminatedUnion('kind', asTuple(shapeSchemas));\n\nexport const DslInput = z.object({\n version: z.literal(1),\n points: z.array(DslPoint),\n shapes: z.array(DslShape).default([]),\n});\n\n// -----------------------------------------------------------------------------\n// Static types\n//\n// We cannot derive these via `z.infer<typeof DslPoint>` because the kind\n// modules use `Extract<DslPointT, { kind: '...' }>` to type their `emit` /\n// `collectRefs` callbacks. That creates a type-graph cycle\n// (schema.ts -> registry.ts -> kinds/* -> schema.ts) which TypeScript collapses\n// to `any` (and `Extract<any, ...>` to `never`) because the registry stores\n// schemas as the erased `z.ZodObject<any>`.\n//\n// Keeping the discriminated union types listed explicitly here breaks the cycle\n// while still letting `DslPoint`/`DslShape` (runtime) be registry-assembled.\n// Adding a new kind = 1 new module file + 1 entry in registry.ts + 1 variant\n// listed below (a single object literal — much smaller than duplicating the\n// full Zod schema).\n// -----------------------------------------------------------------------------\n\ntype Name = z.infer<typeof NameZ>;\n\n// scale/offset OPTIONAL (Issue #46 nhóm C): d = scale·base + offset. Absent →\n// d = base như cũ (additive, serialize/golden không đổi).\nexport type DslDistanceSpec =\n | { kind: 'circleRadius'; circle: Name; scale?: number; offset?: number }\n | { kind: 'segmentLength'; p1: Name; p2: Name; scale?: number; offset?: number }\n | { kind: 'literal'; value: number; scale?: number; offset?: number };\n\nexport type DslPointT =\n | { name: Name; kind: 'free'; x: number; y: number }\n | { name: Name; kind: 'midpoint'; p1: Name; p2: Name; visible?: boolean }\n | { name: Name; kind: 'onPerpBisector'; p1: Name; p2: Name; t?: number }\n | { name: Name; kind: 'onSegment'; segmentId: Name; t: number }\n | { name: Name; kind: 'onLine'; lineId: Name; t: number }\n | { name: Name; kind: 'onCircle'; circleId: Name; theta: number }\n | { name: Name; kind: 'perpFoot'; from: Name; onLine: Name }\n | { name: Name; kind: 'circumcenter'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'incenter'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'centroid'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'orthocenter'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'intersection'; ref1: Name; ref2: Name; branch?: 0 | 1 }\n // NEW Tier 4+5\n | { name: Name; kind: 'secondIntersection'; line: Name; circle: Name; other: Name }\n | { name: Name; kind: 'circleIntersection'; c1: Name; c2: Name; which: 0 | 1 }\n | { name: Name; kind: 'circleSecondIntersection'; c1: Name; c2: Name; exclude: Name }\n | { name: Name; kind: 'tangencyPoint'; circle: Name; onLine: Name }\n | { name: Name; kind: 'tangentPointExt'; from: Name; circle: Name; which: 0 | 1 }\n // Cụm A\n | { name: Name; kind: 'arcMidpoint'; circle: Name; a: Name; b: Name; notContaining?: Name; containing?: Name }\n | { name: Name; kind: 'excenter'; vertices: [Name, Name, Name]; opposite: Name }\n | { name: Name; kind: 'mixtilinearPoint'; vertices: [Name, Name, Name]; which: 'center' | 'touch' }\n | { name: Name; kind: 'reflectPoint'; of: Name; through: Name }\n | { name: Name; kind: 'reflectLine'; of: Name; through: Name }\n // Cụm B points\n | { name: Name; kind: 'pointAtDistance'; from: Name; through: Name; distance: DslDistanceSpec };\n\nexport type DslShapeT =\n | { name: Name; kind: 'segment'; p1: Name; p2: Name }\n | { name: Name; kind: 'line'; p1: Name; p2: Name }\n | { name: Name; kind: 'ray'; origin: Name; through: Name }\n | { name: Name; kind: 'polygon'; vertices: Name[] }\n | { name: Name; kind: 'perpendicular'; throughPoint: Name; toLine: Name }\n | { name: Name; kind: 'parallel'; throughPoint: Name; toLine: Name }\n | { name: Name; kind: 'perpBisector'; p1: Name; p2: Name }\n | { name: Name; kind: 'angleBisector'; p1: Name; vertex: Name; p2: Name }\n | { name: Name; kind: 'lineThrough'; points: Name[] }\n | { name: Name; kind: 'radicalAxis'; circle1: Name; circle2: Name }\n | { name: Name; kind: 'tangent'; throughPoint: Name; toCircle: Name; branch?: 0 | 1 | 'on' }\n | { name: Name; kind: 'circleCP'; center: Name; surfacePoint: Name; visible?: boolean }\n | { name: Name; kind: 'circle3'; p1: Name; p2: Name; p3: Name }\n | { name: Name; kind: 'circleDiameter'; p1: Name; p2: Name; visible?: boolean }\n // NEW Tier 4+5\n | { name: Name; kind: 'circleCR'; center: Name; radius: number }\n | { name: Name; kind: 'incircle'; vertices: [Name, Name, Name] }\n | { name: Name; kind: 'excircle'; vertices: [Name, Name, Name]; opposite: Name };\n\nexport type DslInputT = {\n version: 1;\n points: DslPointT[];\n shapes: DslShapeT[];\n};\n","// src/stamps/geometry-2d/dsl/transpile/symbols.ts\nimport type { DslInputT, DslPointT, DslShapeT } from '../schema';\nimport { mkError, type TranspileError } from './errors';\n\nexport type Role = 'point' | 'shape';\n\nexport interface Symbol {\n name: string;\n role: Role;\n entity: DslPointT | DslShapeT;\n index: number; // vị trí trong list nguyên thuỷ (cho deterministic id assign sau)\n}\n\nexport interface SymbolResult {\n symbols: Map<string, Symbol>;\n errors: TranspileError[];\n}\n\nexport function buildSymbols(dsl: DslInputT): SymbolResult {\n const symbols = new Map<string, Symbol>();\n const errors: TranspileError[] = [];\n let counter = 0;\n\n for (const p of dsl.points) {\n if (symbols.has(p.name)) {\n errors.push(mkError('DUPLICATE_NAME', `Tên trùng: \"${p.name}\"`, { path: [p.name] }));\n continue;\n }\n symbols.set(p.name, { name: p.name, role: 'point', entity: p, index: counter++ });\n }\n\n for (const s of dsl.shapes) {\n if (symbols.has(s.name)) {\n errors.push(mkError('DUPLICATE_NAME', `Tên trùng: \"${s.name}\"`, { path: [s.name] }));\n continue;\n }\n symbols.set(s.name, { name: s.name, role: 'shape', entity: s, index: counter++ });\n }\n\n return { symbols, errors };\n}\n","// src/stamps/geometry-2d/dsl/transpile/cycles.ts\nimport type { Symbol } from './symbols';\nimport { collectRefs } from './refs';\nimport { mkError, type TranspileError } from './errors';\n\ntype Color = 'white' | 'gray' | 'black';\n\nexport interface CyclesResult {\n errors: TranspileError[];\n}\n\nexport function detectCycles(symbols: Map<string, Symbol>): CyclesResult {\n const color = new Map<string, Color>();\n const parent = new Map<string, string | null>();\n const errors: TranspileError[] = [];\n const reportedCycles = new Set<string>();\n\n for (const name of symbols.keys()) color.set(name, 'white');\n\n function reportCycle(start: string, hit: string) {\n // reconstruct chain hit ← ... ← start\n const chain: string[] = [start];\n let cur: string | null | undefined = parent.get(start);\n while (cur && cur !== hit && chain.length < symbols.size + 2) {\n chain.push(cur);\n cur = parent.get(cur);\n }\n chain.push(hit);\n // normalize cho dedupe (rotate min-first)\n const minIdx = chain.indexOf(chain.reduce((a, b) => (a < b ? a : b)));\n const rotated = [...chain.slice(minIdx), ...chain.slice(0, minIdx)];\n const key = rotated.join('→');\n if (reportedCycles.has(key)) return;\n reportedCycles.add(key);\n errors.push(mkError('CYCLE',\n `Phụ thuộc vòng: ${chain.reverse().join(' → ')}`,\n { path: [...chain], hint: 'Kiểm tra lại quan hệ midpoint/perpFoot/intersection.' }));\n }\n\n function dfs(name: string) {\n color.set(name, 'gray');\n const sym = symbols.get(name);\n if (sym) {\n for (const ref of collectRefs(sym.entity)) {\n if (!symbols.has(ref)) continue; // unknown — refs.ts handle\n const c = color.get(ref);\n if (c === 'gray') {\n reportCycle(name, ref);\n continue;\n }\n if (c === 'white') {\n parent.set(ref, name);\n dfs(ref);\n }\n }\n }\n color.set(name, 'black');\n }\n\n for (const name of symbols.keys()) {\n if (color.get(name) === 'white') {\n parent.set(name, null);\n dfs(name);\n }\n }\n\n return { errors };\n}\n","// src/stamps/geometry-2d/dsl/transpile/topology.ts\n//\n// Stable topological sort: preserve DSL insertion order khi không có constraint,\n// chỉ trì hoãn entity tới khi mọi reference đã emit. Fix bug render perpFoot\n// đứng trước segment dùng làm onLine.\n//\n// Khác DFS post-order (kéo deps lên trước): Kahn-style iterative đảm bảo\n// roundtrip stability — entity không có constraint phụ thuộc lẫn nhau giữ\n// đúng thứ tự DSL gốc.\n\nimport type { Symbol } from './symbols';\nimport { collectRefs } from './refs';\n\n/**\n * Trả về danh sách tên entity theo thứ tự topological STABLE:\n * - Mọi name X xuất hiện SAU mọi name X tham chiếu.\n * - Khi 2 entity không phụ thuộc lẫn nhau, giữ relative order từ symbols\n * (= DSL insertion order: points trước shapes, mỗi nhóm theo DSL order).\n *\n * Giả định cycles đã được loại bởi detectCycles trước đó. Nếu vẫn có cycle,\n * entity unresolved sẽ append cuối để output đủ count.\n */\nexport function topoSort(symbols: Map<string, Symbol>): string[] {\n const all = [...symbols.keys()];\n const emitted = new Set<string>();\n const order: string[] = [];\n\n // Pre-compute deps filtered xuống chỉ tên có trong symbols.\n const depsOf = new Map<string, string[]>();\n for (const name of all) {\n const sym = symbols.get(name);\n if (!sym) {\n depsOf.set(name, []);\n continue;\n }\n const refs = collectRefs(sym.entity).filter((r) => symbols.has(r));\n depsOf.set(name, refs);\n }\n\n // Lặp: mỗi vòng emit tất cả entity có deps đã emit, theo DSL order.\n // Worst case O(n^2) but n nhỏ (~20 entity/figure).\n let progressed = true;\n while (progressed) {\n progressed = false;\n for (const name of all) {\n if (emitted.has(name)) continue;\n const deps = depsOf.get(name)!;\n if (deps.every((d) => emitted.has(d))) {\n emitted.add(name);\n order.push(name);\n progressed = true;\n }\n }\n }\n\n // Cycle leftovers (defensive — detectCycles đáng lẽ catch): append đúng count.\n for (const name of all) {\n if (!emitted.has(name)) order.push(name);\n }\n\n return order;\n}\n","// src/stamps/geometry-2d/dsl/transpile/ids.ts\nimport type { Symbol } from './symbols';\nimport { KIND_REGISTRY } from '../registry';\n\nexport function assignIds(symbols: Map<string, Symbol>): Map<string, string> {\n const counters = new Map<string, number>();\n const ids = new Map<string, string>();\n for (const [name, sym] of symbols.entries()) {\n const mod = KIND_REGISTRY.get(sym.entity.kind);\n if (!mod) throw new Error(`assignIds: no registry entry for kind \"${sym.entity.kind}\"`);\n const prefix = mod.prefix;\n counters.set(prefix, (counters.get(prefix) ?? 0) + 1);\n ids.set(name, `${prefix}${counters.get(prefix)}`);\n }\n return ids;\n}\n","// src/stamps/geometry-2d/dsl/transpile.ts\nimport type { SceneObject, State } from '../../../core/scene/types';\nimport { createEmptyState } from '../../../core/scene/types';\nimport { DslInput, type DslInputT, type DslPointT, type DslShapeT } from './schema';\nimport { buildSymbols } from './transpile/symbols';\nimport { validateRefs } from './transpile/refs';\nimport { detectCycles } from './transpile/cycles';\nimport { topoSort } from './transpile/topology';\nimport { assignIds } from './transpile/ids';\nimport { mkError, type TranspileError, type TranspileResult } from './transpile/errors';\nimport { KIND_REGISTRY } from './registry';\nimport type { EmitContext, EmittedEntity, KindRole } from './kinds/_types';\n\ntype EntityKindHint = 'point' | 'line' | 'segment' | 'ray' | 'lineConstruction' | 'circle';\n\nfunction hintOf(entity: DslPointT | DslShapeT): EntityKindHint {\n const mod = KIND_REGISTRY.get(entity.kind);\n if (!mod) throw new Error(`hintOf: no registry entry for kind \"${entity.kind}\"`);\n // 'polygon' role maps to 'point' for legacy MVP behavior (polygon never used as ref target).\n return mod.role === 'polygon' ? 'point' : (mod.role as EntityKindHint);\n}\n\nfunction buildEmitContext(\n ids: Map<string, string>,\n kindHints: Map<string, EntityKindHint>,\n): EmitContext {\n const auxCounters = new Map<string, number>();\n return {\n resolveId(name) {\n const id = ids.get(name);\n if (!id) throw new Error(`emit: id not assigned for \"${name}\"`);\n return id;\n },\n hintOf(name) {\n const hint = kindHints.get(name);\n if (!hint) throw new Error(`emit: hint not assigned for \"${name}\"`);\n // EntityKindHint and KindRole share these literals; safe to widen.\n return hint as KindRole;\n },\n mintAuxId(parentName, suffix) {\n const key = `${parentName}.${suffix}`;\n auxCounters.set(key, (auxCounters.get(key) ?? 0) + 1);\n const seq = auxCounters.get(key)!;\n return `aux_${parentName}_${suffix}${seq}`;\n },\n };\n}\n\nexport function transpile(dslRaw: unknown): TranspileResult {\n // Stage 1: schema parse\n const parsed = DslInput.safeParse(dslRaw);\n if (!parsed.success) {\n const errors: TranspileError[] = parsed.error.issues.map((iss) =>\n mkError('SCHEMA', iss.message, { path: iss.path.map(String) }),\n );\n return { ok: false, errors };\n }\n // Cast: parsed.data is statically `{[x: string]: any}[]` because the registry\n // stores schemas as the erased `z.ZodObject<any>`. Runtime parse already\n // validated the variant shape, so widening to DslInputT is safe.\n const dsl = parsed.data as DslInputT;\n\n // Stage 2-4: collect errors\n const { symbols, errors: dupErrors } = buildSymbols(dsl);\n const { errors: refErrors } = validateRefs(dsl, symbols);\n const { errors: cycleErrors } = detectCycles(symbols);\n\n const allErrors = [...dupErrors, ...refErrors, ...cycleErrors];\n if (allErrors.length > 0) return { ok: false, errors: allErrors };\n\n // Stage 5: id assignment\n const ids = assignIds(symbols);\n\n // Build kindHints (DSL name → EntityKindHint) cho intersection inference.\n const kindHints = new Map<string, EntityKindHint>();\n for (const [name, sym] of symbols.entries()) {\n kindHints.set(name, hintOf(sym.entity));\n }\n\n // Stage 6: emit via registry\n const objects: Record<string, SceneObject> = {};\n const order: string[] = [];\n const ctx = buildEmitContext(ids, kindHints);\n\n const emitEntity = (entity: DslPointT | DslShapeT) => {\n const mod = KIND_REGISTRY.get(entity.kind);\n if (!mod) throw new Error(`emit: no registry entry for kind \"${entity.kind}\"`);\n const emitted: EmittedEntity[] = mod.emit(entity as never, ctx);\n for (const ent of emitted) {\n objects[ent.object.id] = ent.object;\n order.push(ent.object.id);\n }\n };\n\n // Emit theo thứ tự topological — đảm bảo entity dependent emit SAU mọi\n // reference của nó (vd perpFoot point sau segment dùng làm onLine).\n const sortedNames = topoSort(symbols);\n for (const name of sortedNames) {\n const sym = symbols.get(name);\n if (sym) emitEntity(sym.entity);\n }\n\n const empty = createEmptyState('2d');\n const state: State = {\n objects,\n order,\n counter: order.length,\n meta: empty.meta,\n };\n return { ok: true, state };\n}\n","// src/stamps/geometry-2d/ai/verify.ts\n//\n// Stage 4 verifier. Sau khi Intent[] → DSL → render, kiểm tra 3 trục:\n// - đủ (missing): intent expected nhưng DSL không có\n// - đúng (wrong): variant/labels mismatch\n// - không thừa (extra): DSL có entity không tương ứng intent nào\n//\n// Hai chế độ dùng:\n// 1. eval mode: so sánh actualIntents vs expectedIntents (golden)\n// 2. runtime mode: tự verify pipeline (intent→DSL, không có golden)\n\nimport type { DslInputT } from '../dsl/schema';\nimport type { IntentT, DrawShapeIntentT, AddPointIntentT } from './intent';\n\nexport interface VerifyIssue {\n readonly axis: 'missing' | 'wrong' | 'extra';\n readonly detail: string;\n}\n\nexport interface VerifyReport {\n readonly ok: boolean;\n readonly missing: readonly VerifyIssue[];\n readonly wrong: readonly VerifyIssue[];\n readonly extra: readonly VerifyIssue[];\n readonly geometric?: readonly VerifyIssue[];\n}\n\n// ---------------------------------------------------------------------------\n// Eval-mode: compare actual intents vs golden expected\n// ---------------------------------------------------------------------------\n\nexport function compareIntents(\n expected: readonly IntentT[],\n actual: readonly IntentT[],\n): VerifyReport {\n const expectedKey = expected.map(intentKey);\n const actualKey = actual.map(intentKey);\n\n const missing: VerifyIssue[] = [];\n const extra: VerifyIssue[] = [];\n const wrong: VerifyIssue[] = [];\n\n // Track which expected/actual entries matched.\n const matchedActual = new Set<number>();\n for (let i = 0; i < expectedKey.length; i++) {\n const ek = expectedKey[i];\n // Exact match first\n const exactIdx = actualKey.findIndex((ak, idx) => !matchedActual.has(idx) && ak === ek);\n if (exactIdx >= 0) {\n matchedActual.add(exactIdx);\n continue;\n }\n // Partial match: same op + same shape/name → \"wrong\"\n const partialIdx = actualKey.findIndex((ak, idx) =>\n !matchedActual.has(idx) && samePrefix(ak, ek, 2),\n );\n if (partialIdx >= 0) {\n matchedActual.add(partialIdx);\n wrong.push({\n axis: 'wrong',\n detail: `expected ${ek}, got ${actualKey[partialIdx]}`,\n });\n continue;\n }\n // No match → missing\n missing.push({ axis: 'missing', detail: ek });\n }\n // Unmatched actual entries → extra\n for (let i = 0; i < actualKey.length; i++) {\n if (!matchedActual.has(i)) {\n extra.push({ axis: 'extra', detail: actualKey[i] });\n }\n }\n\n return {\n ok: missing.length === 0 && wrong.length === 0 && extra.length === 0,\n missing,\n wrong,\n extra,\n };\n}\n\n// \"draw-shape/triangle/equilateral/A,B,C\" — canonical short string for compare.\nfunction intentKey(intent: IntentT): string {\n switch (intent.op) {\n case 'draw-shape':\n return [\n 'draw-shape',\n intent.shape,\n (intent as DrawShapeIntentT).variant,\n intent.labels.join(','),\n ].join('/');\n case 'add-point':\n return ['add-point', intent.name, intent.constraint.kind, constraintKey(intent.constraint)].join('/');\n case 'connect':\n return ['connect', intent.style, intent.from, intent.to].join('/');\n case 'draw-circle': {\n if (intent.spec === 'centerThrough') return `draw-circle/${intent.name}/centerThrough/${intent.center}/${intent.through}`;\n if (intent.spec === 'through3') return `draw-circle/${intent.name}/through3/${intent.points?.join(',') ?? ''}`;\n if (intent.spec === 'centerRadius') return `draw-circle/${intent.name}/centerRadius/${intent.center}/${intent.radius}`;\n if (intent.spec === 'inscribedIn') return `draw-circle/${intent.name}/inscribedIn/${intent.triangle?.join(',') ?? ''}`;\n return `draw-circle/${intent.name}/${(intent as any).spec}`;\n }\n case 'draw-line': {\n const base = [\n 'draw-line', intent.name, intent.kind,\n intent.through ?? '', intent.to ?? '', intent.from ?? '', intent.circle ?? '', intent.which ?? '',\n ].join('/');\n if (intent.kind === 'lineThrough') return `${base}/${(intent.points ?? []).join('+')}`;\n if (intent.kind === 'radicalAxis') return `${base}/${intent.circle1 ?? ''}+${intent.circle2 ?? ''}`;\n return base;\n }\n case 'mark-shape':\n return ['mark-shape', intent.shape, intent.labels.join(',')].join('/');\n }\n}\n\nfunction constraintKey(c: AddPointIntentT['constraint']): string {\n switch (c.kind) {\n case 'midpoint': return c.of;\n case 'onPerpBisector': return `onPerpBisector:${c.p1}:${c.p2}`;\n case 'perpFoot': return `${c.from}->${c.onLine}`;\n case 'centroid':\n case 'circumcenter':\n case 'incenter':\n case 'orthocenter':\n return c.of.join(',');\n case 'intersection': return c.of.join('×');\n case 'onSegment': return `${c.of}@${c.t ?? 'mid'}`;\n case 'free': return c.at ? c.at.join(',') : '*';\n case 'secondIntersection': return `secondIntersection:${c.line}:${c.circle}:${c.other}`;\n case 'circleIntersection': return `circleIntersection:${c.c1}:${c.c2}:${c.which}`;\n case 'circleSecondIntersection': return `circleSecondIntersection:${c.c1}:${c.c2}:${c.exclude}`;\n case 'tangencyPoint': return `tangencyPoint:${c.circle}:${c.onLine}`;\n case 'tangentPoint': return `tangentPoint:${c.from}:${c.circle}:${c.which}`;\n case 'angleBisectorFoot': return `angleBisectorFoot:${c.from}:${c.onLine}`;\n case 'externalAngleBisectorFoot': return `externalAngleBisectorFoot:${c.from}:${c.onLine}`;\n case 'arcMidpoint': return `arcMidpoint:${c.circle}:${c.a}:${c.b}:${c.notContaining}`;\n case 'reflectPoint': return `reflectPoint:${c.of}:${c.through}`;\n case 'reflectLine': return `reflectLine:${c.of}:${c.through}`;\n case 'excenter': return `excenter:${c.of.join(',')}:${c.opposite}`;\n case 'mixtilinearPoint': return `mixtilinearPoint:${c.of.join(',')}:${c.which}`;\n case 'rightAngleViewing': return `rightAngleViewing:${c.a}:${c.b}:${c.onLine}:${c.which ?? 0}`;\n case 'pointAtDistance': {\n const d = c.distance;\n const dKey = d.kind === 'circleRadius' ? `r:${d.circle}`\n : d.kind === 'segmentLength' ? `seg:${d.p1}:${d.p2}`\n : `lit:${d.value}`;\n return `pointAtDistance:${c.from}:${c.through}:${dKey}`;\n }\n case 'externalToCircle': return `externalToCircle:${c.circle}`;\n case 'onCircle': return `onCircle:${c.circle}:${c.theta ?? ''}`;\n }\n}\n\nfunction samePrefix(a: string, b: string, depth: number): boolean {\n const aP = a.split('/').slice(0, depth).join('/');\n const bP = b.split('/').slice(0, depth).join('/');\n return aP === bP;\n}\n\n// ---------------------------------------------------------------------------\n// Intent metric: recall / precision / F1 (for eval)\n// ---------------------------------------------------------------------------\n\nexport interface IntentMetrics {\n recall: number;\n precision: number;\n f1: number;\n matched: number;\n expected: number;\n actual: number;\n}\n\nexport function computeIntentMetrics(\n expected: readonly IntentT[],\n actual: readonly IntentT[],\n): IntentMetrics {\n const expectedKeys = expected.map(intentKey);\n const actualKeys = actual.map(intentKey);\n const matched = new Set<number>();\n let hit = 0;\n for (const ek of expectedKeys) {\n const idx = actualKeys.findIndex((ak, i) => !matched.has(i) && ak === ek);\n if (idx >= 0) { matched.add(idx); hit++; }\n }\n const recall = expectedKeys.length === 0 ? 1 : hit / expectedKeys.length;\n const precision = actualKeys.length === 0 ? 1 : hit / actualKeys.length;\n const f1 = (recall + precision) === 0 ? 0 : (2 * recall * precision) / (recall + precision);\n return {\n recall, precision, f1,\n matched: hit,\n expected: expectedKeys.length,\n actual: actualKeys.length,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Geometric verification on DSL with resolved coords (scope: on-circle only;\n// tangent-touch / concyclic / collinear deferred until JSXGraph runtime hook).\n// ---------------------------------------------------------------------------\n\nconst GEOM_TOL = 1e-3;\n\nfunction resolveCoord(dsl: DslInputT, name: string): [number, number] | null {\n const p = dsl.points.find((x) => x.name === name);\n if (!p) return null;\n if (p.kind === 'free') return [p.x, p.y];\n if (p.kind === 'midpoint') {\n const a = resolveCoord(dsl, p.p1);\n const b = resolveCoord(dsl, p.p2);\n if (!a || !b) return null;\n return [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];\n }\n // Other kinds: computed by JSXGraph at runtime — skip static check.\n return null;\n}\n\nexport function verifyGeometric(dsl: DslInputT): VerifyReport {\n const geometric: VerifyIssue[] = [];\n\n for (const shape of dsl.shapes) {\n if (shape.kind !== 'circleCR') continue;\n // on-circle check: any point with onCircle constraint referencing this circle\n for (const p of dsl.points) {\n if (p.kind !== 'onCircle') continue;\n if (p.circleId !== shape.name) continue;\n const c = resolveCoord(dsl, shape.center);\n const pp = resolveCoord(dsl, p.name);\n if (!c || !pp) continue;\n const d = Math.hypot(pp[0] - c[0], pp[1] - c[1]);\n if (Math.abs(d - shape.radius) > GEOM_TOL) {\n geometric.push({\n axis: 'wrong',\n detail: `on-circle: |${p.name}-${shape.name}|=${d.toFixed(3)} ≠ R=${shape.radius}`,\n });\n }\n }\n }\n\n return {\n ok: geometric.length === 0,\n missing: [],\n wrong: [],\n extra: [],\n geometric,\n } as VerifyReport;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime-mode: verify DSL geometry constraints\n// ---------------------------------------------------------------------------\n\nexport function verifyGeometry(intents: readonly IntentT[], dsl: DslInputT): VerifyReport {\n const issues: VerifyIssue[] = [];\n\n // Check right-triangle variant has actual right angle at named vertex.\n for (const intent of intents) {\n if (intent.op !== 'draw-shape' || intent.shape !== 'triangle') continue;\n const variant = intent.variant;\n if (!variant.startsWith('right-at-')) continue;\n const apex = variant.slice('right-at-'.length); // 'A' | 'B' | 'C'\n const [A, B, C] = intent.labels;\n const ptByName = new Map(\n dsl.points.filter((p) => p.kind === 'free').map((p) => [p.name, [p.x, p.y] as [number, number]]),\n );\n const pA = ptByName.get(A);\n const pB = ptByName.get(B);\n const pC = ptByName.get(C);\n if (!pA || !pB || !pC) continue;\n const apexP = apex === 'A' ? pA : apex === 'B' ? pB : pC;\n const other1 = apex === 'A' ? pB : apex === 'B' ? pA : pA;\n const other2 = apex === 'A' ? pC : apex === 'B' ? pC : pB;\n const v1 = [other1[0] - apexP[0], other1[1] - apexP[1]];\n const v2 = [other2[0] - apexP[0], other2[1] - apexP[1]];\n const dot = v1[0] * v2[0] + v1[1] * v2[1];\n if (Math.abs(dot) > 1e-6) {\n issues.push({\n axis: 'wrong',\n detail: `triangle ${A}${B}${C} variant=right-at-${apex} không vuông (dot=${dot.toFixed(3)})`,\n });\n }\n }\n\n return {\n ok: issues.length === 0,\n missing: [],\n wrong: issues,\n extra: [],\n };\n}\n","// src/stamps/geometry-2d/ai/deterministic/tryDeterministicFigure.ts\n//\n// Track A đầy đủ: rule NLU → coverage gate → normalize → resolve circle collisions\n// → build DSL → transpile → verifyGeometry → named-entity guard. Trả figure SẴN\n// RENDER nếu qua HẾT 4 lớp gate; ngược lại { ok:false } để router escalate AI.\n//\n// Tách khỏi buildFigureIntent để test độc lập toàn bộ logic quyết định.\nimport type { IntentT } from '../intent';\nimport type { DslInputT } from '../../dsl/schema';\nimport type { TranspileResult } from '../../dsl/transpile/errors';\nimport type { VerifyReport } from '../verify';\nimport type { CoverageReport } from './coverage';\nimport { runDeterministicIntents } from './runDeterministicIntents';\nimport { allNamedEntitiesPresent, verifyIntentFidelity } from './guards';\nimport { normalizeIntents } from '../normalizeIntent';\nimport { normalizeProblemText } from './normalizeText';\nimport { resolveCircleNameCollisions } from '../resolveCircleNames';\nimport { intentsToDsl } from '../intentToDsl';\nimport { orderIntentsByDependency } from '../intentTopo';\nimport { transpile } from '../../dsl';\nimport { verifyGeometry } from '../verify';\n\nexport type DeterministicReason =\n | 'no-match'\n | 'incomplete-coverage'\n | 'build-throw'\n | 'transpile-throw'\n | 'transpile-fail'\n | 'verify-fail'\n | 'named-missing'\n | 'intent-dropped';\n\nexport interface DeterministicFigure {\n intents: IntentT[];\n dsl: DslInputT;\n transpile: Extract<TranspileResult, { ok: true }>;\n verify: VerifyReport;\n coverage: CoverageReport;\n}\n\nexport type TryDeterministicResult =\n | { ok: true; figure: DeterministicFigure }\n | { ok: false; reason: DeterministicReason; detail?: string; coverage?: CoverageReport };\n\n// ── Build + transpile với ORDER-RETRY ────────────────────────────────────────\n// Attempt 1 theo đúng thứ tự intent (giữ defaultFreeCoord spread/uniqueShapeName\n// của mọi case đang pass → byte-identical). CHỈ khi fail vì-thứ-tự (build-throw\n// hoặc transpile UNKNOWN_REF) mới retry với thứ tự topo (intentTopo). Retry vẫn\n// fail → giữ lỗi attempt 1 cho chẩn đoán ổn định.\n// Gỡ coupling \"rule priority quyết định thứ tự build\" — rule mới không còn phải\n// canh priority thấp hơn mọi rule tạo điểm như intersection (priority 45).\n\nexport type BuildAndTranspileResult =\n | { ok: true; intents: readonly IntentT[]; dsl: DslInputT; tResult: Extract<TranspileResult, { ok: true }> }\n | { ok: false; reason: 'build-throw' | 'transpile-throw' | 'transpile-fail'; detail: string; orderSensitive: boolean };\n\nfunction attemptBuild(intents: readonly IntentT[]): BuildAndTranspileResult {\n let dsl: DslInputT;\n try {\n dsl = intentsToDsl(intents);\n } catch (e) {\n return { ok: false, reason: 'build-throw', detail: errMsg(e), orderSensitive: true };\n }\n let tResult: TranspileResult;\n try {\n tResult = transpile(dsl);\n } catch (e) {\n return { ok: false, reason: 'transpile-throw', detail: errMsg(e), orderSensitive: false };\n }\n if (!tResult.ok) {\n return {\n ok: false,\n reason: 'transpile-fail',\n detail: tResult.errors.map((x) => `${x.code}:${x.message}`).join('; '),\n // UNKNOWN_REF có thể do consumer đứng trước producer (segment optimistic\n // trỏ tên điểm dựng-sau) — đáng thử lại với thứ tự topo.\n orderSensitive: tResult.errors.some((x) => x.code === 'UNKNOWN_REF'),\n };\n }\n return { ok: true, intents, dsl, tResult };\n}\n\nexport function buildAndTranspile(intents: readonly IntentT[]): BuildAndTranspileResult {\n const first = attemptBuild(intents);\n if (first.ok || !first.orderSensitive) return first;\n const reordered = orderIntentsByDependency(intents);\n const sameOrder = reordered.every((it, i) => it === intents[i]);\n if (sameOrder) return first;\n const second = attemptBuild(reordered);\n return second.ok ? second : first;\n}\n\nexport function tryDeterministicFigure(rawProblem: string): TryDeterministicResult {\n // Chuẩn hoá ký hiệu (Δ→tam giác, vòng tròn→đường tròn) MỘT lần để mọi stage\n // (rule, normalizeIntents, named-entity guard) thấy text nhất quán.\n const problem = normalizeProblemText(rawProblem);\n const det = runDeterministicIntents(problem);\n if (!det.ok) return { ok: false, reason: det.reason, coverage: det.coverage };\n\n // Cùng các stage chuẩn hoá như Track B (LLM) để 2 path hội tụ.\n const built = buildAndTranspile(\n resolveCircleNameCollisions(normalizeIntents(det.intents, problem)),\n );\n if (!built.ok) {\n return { ok: false, reason: built.reason, detail: built.detail, coverage: det.coverage };\n }\n const { intents, dsl, tResult } = built;\n\n const vReport = verifyGeometry(intents, dsl);\n if (!vReport.ok) {\n return { ok: false, reason: 'verify-fail', coverage: det.coverage };\n }\n\n // Guard 1: tên xuất hiện/khai báo trong đề phải có trong DSL (chống drop construct).\n const named = allNamedEntitiesPresent(problem, dsl);\n if (!named.ok) {\n return { ok: false, reason: 'named-missing', detail: named.missing.join(','), coverage: det.coverage };\n }\n\n // Guard 2: add-point phái sinh phải dựng trung thành (không bị builder drop vì\n // trùng tên đỉnh sẵn có → điểm thực tế là 'free' thay vì construct).\n const fidelity = verifyIntentFidelity(intents, dsl);\n if (!fidelity.ok) {\n return { ok: false, reason: 'intent-dropped', detail: fidelity.dropped.join(','), coverage: det.coverage };\n }\n\n return {\n ok: true,\n figure: { intents: [...intents], dsl, transpile: tResult, verify: vReport, coverage: det.coverage },\n };\n}\n\nfunction errMsg(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n","// src/stamps/geometry-2d/ai/deterministic/describeMiss.ts\n//\n// Dịch lý do deterministic miss (mã kỹ thuật) → câu tiếng Việt dễ hiểu cho\n// chế độ deterministicOnly (\"dùng tạm rule base, tắt LLM\"). Phân 2 nhóm để người\n// tối ưu rule base phân biệt ngay:\n// - \"chưa phủ\" (no-match / incomplete-coverage / named-missing) → CẦN THÊM RULE.\n// - \"rule khớp nhưng dựng lỗi\" (build/transpile/verify/intent-dropped) → có thể LỖI RULE.\n// Hàm thuần, không I/O — message này được gán vào IntentFailureResult.message và\n// nổi lên AiFigureUiResult để consumer (hoctotbachkhoa) hiển thị / ghi log.\nimport type { DeterministicReason } from './tryDeterministicFigure';\nimport type { CoverageReport } from './coverage';\n\nexport interface DeterministicMiss {\n reason: DeterministicReason;\n /** Chi tiết kỹ thuật theo reason (tên thiếu, mã lỗi transpile, …). */\n detail?: string;\n /** Báo cáo coverage — dùng `uncovered[].text` để nêu cụm đề chưa phủ. */\n coverage?: CoverageReport;\n}\n\n/** \", \" sau detail nếu có (else chuỗi rỗng) — tránh \"(undefined)\". */\nfunction detailSuffix(detail?: string): string {\n const d = detail?.trim();\n return d ? `: ${d}` : '';\n}\n\n/** \"D,E\" → \"D, E\" (thêm khoảng trắng sau phẩy cho dễ đọc). */\nfunction formatNames(detail?: string): string {\n const names = (detail ?? '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n return names.length > 0 ? names.join(', ') : 'một số đối tượng';\n}\n\nexport function describeDeterministicMiss(miss: DeterministicMiss): string {\n const { reason, detail, coverage } = miss;\n switch (reason) {\n // === Nhóm \"chưa phủ\" → cần bổ sung rule ===\n case 'no-match':\n return 'Rule base chưa nhận ra cấu trúc hình học nào trong đề (cần bổ sung rule cho dạng này).';\n case 'incomplete-coverage': {\n const parts = (coverage?.uncovered ?? []).map((c) => `«${c.text}»`);\n if (parts.length === 0) {\n return 'Rule base mới phủ được một phần đề (cần bổ sung rule cho phần còn lại).';\n }\n return `Rule base mới phủ được một phần đề. Chưa dựng được: ${parts.join('; ')} (cần bổ sung rule).`;\n }\n case 'named-missing':\n return `Đề nhắc tới ${formatNames(detail)} nhưng rule base chưa dựng được (cần bổ sung rule).`;\n\n // === Nhóm \"rule khớp nhưng dựng lỗi\" → có thể lỗi rule ===\n case 'build-throw':\n return `Rule đã khớp nhưng dựng hình thất bại — có thể lỗi rule${detailSuffix(detail)}.`;\n case 'transpile-throw':\n case 'transpile-fail':\n return `Rule đã khớp nhưng biên dịch hình lỗi — có thể lỗi rule${detailSuffix(detail)}.`;\n case 'verify-fail':\n return 'Rule dựng được hình nhưng sai kiểm tra hình học — có thể lỗi rule.';\n case 'intent-dropped':\n return `Rule khớp nhưng một số điểm phái sinh bị bỏ (${formatNames(detail)}) — có thể lỗi rule.`;\n\n default: {\n // Exhaustive guard: thêm reason mới mà quên xử lý → type error tại compile.\n const _never: never = reason;\n return `Rule base chưa dựng được (${String(_never)}).`;\n }\n }\n}\n","// src/stamps/geometry-2d/ai/deterministic/partialFigure.ts\n//\n// Partial deterministic render (Hướng A — cắt tỉa theo phụ thuộc + verify lại):\n// khi tryDeterministicFigure MISS (không phủ đủ đề), thử cứu vãn phần CHẮC CHẮN\n// ĐÚNG thay vì vứt toàn bộ. Render phần dựng được (≥1 hình thật) + trả to-do list\n// để user tự dựng nốt. KHÔNG gọi LLM.\n//\n// Khác tryDeterministicFigure: hàm này CỐ TÌNH chấp nhận coverage incomplete, rồi\n// 1. cắt mọi phần tử DSL phụ thuộc entity chưa dựng được (ref treo, lan truyền),\n// 2. cắt phần tử khiến transpile lỗi (theo owner trong error path),\n// 3. cắt tam giác sai khi verify-fail,\n// và CHỈ render khi phần còn lại transpile + verify SẠCH (giữ cam kết \"đúng\").\n//\n// Hàm thuần, không I/O. Spec: docs/superpowers/specs/2026-06-10-partial-deterministic-render-design.md\nimport type { DslInputT, DslPointT, DslShapeT } from '../../dsl/schema';\nimport type { TranspileResult, TranspileError } from '../../dsl/transpile/errors';\nimport type { VerifyReport } from '../verify';\nimport type { Clause } from './coverage';\nimport type { DeterministicFigure } from './tryDeterministicFigure';\nimport { tryPartialDeterministic } from './runDeterministicIntents';\nimport { allNamedEntitiesPresent } from './guards';\nimport { normalizeIntents } from '../normalizeIntent';\nimport { normalizeProblemText } from './normalizeText';\nimport { resolveCircleNameCollisions } from '../resolveCircleNames';\nimport { intentsToDsl } from '../intentToDsl';\nimport { collectRefs } from '../../dsl/transpile/refs';\nimport { transpile } from '../../dsl';\nimport { verifyGeometry } from '../verify';\n\n/** Bound vòng cắt-rồi-thử lại transpile/verify (mỗi vòng bỏ ≥1 phần tử). */\nconst MAX_SALVAGE_ITERS = 6;\n\nexport interface PartialTodo {\n /** Clause geo chưa có rule nào khớp (nguyên văn) — \"chưa hỗ trợ cấu trúc\". */\n uncovered: Clause[];\n /**\n * Tên đối tượng đề CÓ nêu (vd \"P là điểm Fermat\", đỉnh D) nhưng KHÔNG dựng được\n * — nguồn từ named-entity guard. Đây là kịch bản \"ABC vẽ được, D thì không\":\n * clause được rule claim (coverage complete) nhưng entity không ra → không phải\n * ref treo, chỉ guard này thấy. Đã loại trùng với `pruned`.\n */\n missingNamed: string[];\n /** Tên entity bị cắt vì phụ thuộc phần chưa dựng được (transitive). */\n pruned: string[];\n}\n\nexport interface PartialFigureResult {\n /** Hình phần đã cắt — đã qua transpile + verify, sẵn render. */\n figure: DeterministicFigure;\n todo: PartialTodo;\n}\n\n/**\n * Thử dựng phần CHẮC CHẮN ĐÚNG của đề khi không phủ đủ. Trả `null` nếu không cứu\n * được phần hình thật nào (→ caller báo miss toàn bộ như cũ).\n */\nexport function tryPartialFigure(rawProblem: string): PartialFigureResult | null {\n const problem = normalizeProblemText(rawProblem);\n const part = tryPartialDeterministic(problem);\n // Không rule nào khớp → không có gì để cứu.\n if (part.detIntents.length === 0) return null;\n\n // Mirror đúng các stage chuẩn hoá của tryDeterministicFigure để 2 path hội tụ.\n const intents = resolveCircleNameCollisions(normalizeIntents(part.detIntents, problem));\n\n let dsl: DslInputT;\n try {\n dsl = intentsToDsl(intents);\n } catch {\n return null;\n }\n\n const pruned = new Set<string>();\n\n // (1) Cắt lan truyền các phần tử có ref treo (entity của clause chưa phủ).\n pruneDangling(dsl, pruned);\n\n // (2)+(3) Transpile + verify; cắt phần tử gây lỗi rồi thử lại tới khi sạch.\n let tOk: Extract<TranspileResult, { ok: true }> | null = null;\n let vOk: VerifyReport | null = null;\n for (let iter = 0; iter < MAX_SALVAGE_ITERS; iter++) {\n let t: TranspileResult;\n try {\n t = transpile(dsl);\n } catch {\n return null;\n }\n if (!t.ok) {\n const owners = uniqueOwners(t.errors);\n if (owners.length === 0) return null; // không pin được lỗi → thà miss\n dropNames(dsl, owners, pruned);\n pruneDangling(dsl, pruned);\n continue;\n }\n const v = verifyGeometry(intents, dsl);\n if (!v.ok) {\n const bad = namesFromVerify(v);\n if (bad.length === 0) return null;\n dropNames(dsl, bad, pruned);\n pruneDangling(dsl, pruned);\n continue;\n }\n tOk = t;\n vOk = v;\n break;\n }\n if (!tOk || !vOk) return null;\n\n // Ngưỡng: chỉ render khi còn ≥1 HÌNH THẬT (đoạn/đường/đa giác/đường tròn).\n // Vài điểm rời rạc → vô nghĩa, để caller báo miss toàn bộ.\n if (dsl.shapes.length === 0) return null;\n\n // Named-entity thiếu (đề nêu D/P… nhưng không dựng được) — loại trùng `pruned`.\n const prunedList = [...pruned].sort();\n const prunedSet = new Set(prunedList);\n const missingNamed = allNamedEntitiesPresent(problem, dsl).missing.filter(\n (n) => !prunedSet.has(n),\n );\n\n return {\n figure: { intents, dsl, transpile: tOk, verify: vOk, coverage: part.coverage },\n todo: { uncovered: part.uncovered, missingNamed, pruned: prunedList },\n };\n}\n\n/**\n * Lặp tới fixpoint: bỏ mọi point/shape mà `collectRefs` trỏ tới tên KHÔNG còn\n * trong DSL (ref treo). Phần tử vừa bỏ làm dependent của nó treo ở vòng sau.\n */\nfunction pruneDangling(dsl: DslInputT, pruned: Set<string>): void {\n let changed = true;\n while (changed) {\n changed = false;\n const present = new Set<string>([\n ...dsl.points.map((p) => p.name),\n ...dsl.shapes.map((s) => s.name),\n ]);\n const dangling = (e: DslPointT | DslShapeT): boolean => {\n let refs: string[];\n try {\n refs = collectRefs(e);\n } catch {\n return false; // kind lạ (không có registry) → giữ, không tự ý cắt\n }\n return refs.some((r) => !present.has(r));\n };\n const beforeP = dsl.points.length;\n const beforeS = dsl.shapes.length;\n dsl.points = dsl.points.filter((p) => {\n if (dangling(p)) {\n pruned.add(p.name);\n return false;\n }\n return true;\n });\n dsl.shapes = dsl.shapes.filter((s) => {\n if (dangling(s)) {\n pruned.add(s.name);\n return false;\n }\n return true;\n });\n if (dsl.points.length !== beforeP || dsl.shapes.length !== beforeS) changed = true;\n }\n}\n\n/** Bỏ các phần tử theo tên (owner lỗi / tam giác sai). Dependent dọn ở pruneDangling sau. */\nfunction dropNames(dsl: DslInputT, names: readonly string[], pruned: Set<string>): void {\n const drop = new Set(names);\n const kill = (n: string): boolean => {\n if (drop.has(n)) {\n pruned.add(n);\n return true;\n }\n return false;\n };\n dsl.points = dsl.points.filter((p) => !kill(p.name));\n dsl.shapes = dsl.shapes.filter((s) => !kill(s.name));\n}\n\n/** Tên entity gây lỗi transpile (path[0] = owner). Dedup. */\nfunction uniqueOwners(errors: readonly TranspileError[]): string[] {\n const out = new Set<string>();\n for (const e of errors) {\n const owner = e.path?.[0];\n if (owner) out.add(owner);\n }\n return [...out];\n}\n\n/** Trích tên hình (tam giác ABC) từ verify issue để cắt. */\nfunction namesFromVerify(v: VerifyReport): string[] {\n const out = new Set<string>();\n for (const issue of v.wrong) {\n const m = /triangle\\s+([A-Za-z0-9_]+)/.exec(issue.detail ?? '');\n if (m) out.add(m[1]);\n }\n return [...out];\n}\n\n/**\n * Dịch to-do partial → câu tiếng Việt cho panel AI. Phân 2 nhóm:\n * - uncovered → \"chưa hỗ trợ cấu trúc này\"\n * - pruned → \"phụ thuộc phần chưa vẽ được\"\n */\nexport function describePartialTodo(todo: PartialTodo): string {\n const items: string[] = [];\n for (const c of todo.uncovered) items.push(`• «${c.text.trim()}» (chưa hỗ trợ cấu trúc này)`);\n for (const name of todo.missingNamed) items.push(`• ${name} (chưa dựng được — tự xác định)`);\n for (const name of todo.pruned) items.push(`• ${name} — phụ thuộc phần chưa vẽ được`);\n if (items.length === 0) {\n return '✅ Rule base đã dựng được phần chắc chắn đúng. Bạn kiểm tra lại phần còn lại.';\n }\n return ['✅ Rule base đã dựng được phần chắc chắn đúng.', '✏️ Bạn tự dựng nốt:', ...items].join(\n '\\n',\n );\n}\n","// src/stamps/geometry-2d/ai/buildFigureIntent.ts\n//\n// Deterministic-only figure builder (rule-base, KHÔNG LLM).\n// Track A: tryDeterministicFigure() — rule engine + 4 gate\n// (coverage / transpile / verify / named-entity).\n// Success → trả figure (intents + dsl + transpile + verify).\n// Miss → trả failure `deterministic_miss` kèm lý do (describeDeterministicMiss)\n// để người tối ưu rule base thấy phần đề chưa phủ. KHÔNG fallback LLM.\n//\n// Trả về IntentGenerateResult tương thích shape cũ để consumer dùng được.\n\nimport type { TranspileResult } from '../dsl';\nimport { intentsToDsl } from './intentToDsl';\nimport type { IntentT } from './intent';\nimport { type VerifyReport } from './verify';\nimport { tryDeterministicFigure } from './deterministic/tryDeterministicFigure';\nimport { describeDeterministicMiss } from './deterministic/describeMiss';\nimport { tryPartialFigure, describePartialTodo } from './deterministic/partialFigure';\n\nconst ZERO_USAGE: IntentTokenUsage = {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n};\n\nexport interface GenerateIntentOptions {\n signal?: AbortSignal;\n}\n\nexport interface IntentTokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n}\n\nexport interface IntentSuccessResult {\n ok: true;\n intents: readonly IntentT[];\n dsl: ReturnType<typeof intentsToDsl>;\n transpile: Extract<TranspileResult, { ok: true }>;\n verify: VerifyReport;\n usage: IntentTokenUsage;\n provider: string;\n /**\n * Có mặt khi đây là PARTIAL render: rule base chỉ dựng được một phần đề (phần\n * chắc chắn đúng), `message` là to-do list cho user tự dựng nốt. Vắng = full.\n */\n partial?: { message: string };\n}\n\nexport interface IntentFailureResult {\n ok: false;\n reason:\n | 'builder_error'\n | 'transpile_error'\n | 'verify_error'\n | 'deterministic_miss';\n message: string;\n intents?: readonly IntentT[];\n dsl?: ReturnType<typeof intentsToDsl>;\n usage?: IntentTokenUsage;\n provider?: string;\n}\n\nexport type IntentGenerateResult = IntentSuccessResult | IntentFailureResult;\n\nexport async function generateFigureIntent(\n problem: string,\n _opts: GenerateIntentOptions = {},\n): Promise<IntentGenerateResult> {\n // === Track A: deterministic ===\n // Rule engine + 4 lớp gate (coverage/transpile/verify/named-entity). Đề dễ→trung\n // bình dựng tại đây, KHÔNG tốn token. Miss → trả deterministic_miss (KHÔNG LLM).\n const det = tryDeterministicFigure(problem);\n if (det.ok) {\n return {\n ok: true,\n intents: det.figure.intents,\n dsl: det.figure.dsl,\n transpile: det.figure.transpile,\n verify: det.figure.verify,\n usage: ZERO_USAGE,\n provider: 'deterministic',\n };\n }\n\n // === Partial render ===\n // Full miss nhưng có thể rule base vẫn dựng được PHẦN chắc chắn đúng (vd tam\n // giác ABC ok, chỉ điểm cuối D dùng construct chưa hỗ trợ). Cắt phần phụ thuộc\n // entity chưa dựng được, verify lại tập con; nếu còn ≥1 hình thật → render phần\n // đó + trả to-do list cho user tự dựng nốt. KHÔNG LLM.\n const partial = tryPartialFigure(problem);\n if (partial) {\n return {\n ok: true,\n intents: partial.figure.intents,\n dsl: partial.figure.dsl,\n transpile: partial.figure.transpile,\n verify: partial.figure.verify,\n usage: ZERO_USAGE,\n provider: 'deterministic-partial',\n partial: { message: describePartialTodo(partial.todo) },\n };\n }\n\n // Miss → trả failure kèm lý do (det.reason) để người tối ưu rule base thấy gap.\n // (no-match / incomplete-coverage / transpile-fail / named-missing / verify-fail / …)\n return {\n ok: false,\n reason: 'deterministic_miss',\n message: describeDeterministicMiss(det),\n usage: ZERO_USAGE,\n provider: 'deterministic',\n };\n}\n","// Façade HTTP transport cho rule-engine intent pipeline (generateFigureIntent).\n// Map IntentGenerateResult → AiFigureUiResult ({ ok, state }) — shape mà\n// <Whiteboard generateGeometryFigure> + playground route dùng trực tiếp.\n//\n// 2026-06-09: repurpose từ path buildFigure (free-form DSL, đã xoá) sang intent\n// pipeline DETERMINISTIC-ONLY. generateFigureIntent chạy rule engine\n// (tryDeterministicFigure → 21 rule + 4 gate); miss → deterministic_miss (KHÔNG\n// LLM). Façade chỉ cần map kết quả. Contract AiFigureUiResult GIỮ NGUYÊN →\n// consumer (playground, hoctotbachkhoa) không phải đổi route.\n\nimport type { AiFigureUiResult } from '../../shared/types';\nimport {\n generateFigureIntent,\n type GenerateIntentOptions,\n type IntentGenerateResult,\n} from './buildFigureIntent';\n\nexport interface HandleGenerateFigureInput {\n /** Đề bài tiếng Việt từ teacher. */\n problem: string;\n}\n\nexport interface HandleGenerateFigureOptions extends GenerateIntentOptions {\n /**\n * Telemetry hook: gọi cho MỖI attempt với IntentGenerateResult nội bộ trước\n * khi map sang AiFigureUiResult — consumer dùng để log usage/cost/error.\n * Không throw từ logger (swallow để không vỡ response).\n *\n * @param result IntentGenerateResult của attempt\n * @param attempt 1-indexed (1 = lần đầu, 2 = retry, ...)\n */\n onResult?: (result: IntentGenerateResult, attempt: number) => void;\n /**\n * Số attempt tối đa khi build error (transpile/builder). Default 2 (1 retry).\n * Rule base deterministic → retry hiếm khi đổi kết quả, giữ để tương thích\n * contract cũ. Clamp [1,5].\n */\n maxAttempts?: number;\n}\n\nconst DEFAULT_MAX_ATTEMPTS = 2;\n\n/**\n * Gọi rule-engine intent pipeline và trả về `AiFigureUiResult` mà\n * `<Whiteboard generateGeometryFigure>` chấp nhận trực tiếp.\n *\n * Deterministic rule base chạy trong `generateFigureIntent` — đề dễ→trung bình\n * dựng KHÔNG tốn token. Miss → `deterministic_miss` (KHÔNG LLM fallback).\n *\n * Auto-retry: chỉ retry khi `transpile_error`/`builder_error`. KHÔNG retry\n * `deterministic_miss` (rule base ổn định, retry vô nghĩa).\n *\n * Server-side caller giữ `IntentGenerateResult` đầy đủ qua `onResult` cho\n * telemetry/logging.\n */\nexport async function handleGenerateFigure(\n input: HandleGenerateFigureInput,\n opts: HandleGenerateFigureOptions = {},\n): Promise<AiFigureUiResult> {\n if (!input.problem.trim()) {\n return { ok: false, message: 'Đề bài rỗng' };\n }\n\n const { onResult, maxAttempts: rawMax, ...genOpts } = opts;\n const maxAttempts = clampAttempts(rawMax ?? DEFAULT_MAX_ATTEMPTS);\n\n let last: IntentGenerateResult | null = null;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const r = await generateFigureIntent(input.problem, genOpts);\n last = r;\n if (onResult) {\n try { onResult(r, attempt); } catch { /* swallow telemetry errors */ }\n }\n if (r.ok) return toSuccessUi(r);\n if ((r.reason === 'transpile_error' || r.reason === 'builder_error') && attempt < maxAttempts) {\n continue;\n }\n break;\n }\n return mapErrorToUi(last!);\n}\n\nfunction clampAttempts(n: number): number {\n if (!Number.isFinite(n)) return DEFAULT_MAX_ATTEMPTS;\n return Math.max(1, Math.min(5, Math.floor(n)));\n}\n\n/** Map intent success → UI, kèm `partial` to-do nếu là partial render. */\nfunction toSuccessUi(r: Extract<IntentGenerateResult, { ok: true }>): AiFigureUiResult {\n return r.partial\n ? { ok: true, state: r.transpile.state, partial: r.partial }\n : { ok: true, state: r.transpile.state };\n}\n\nfunction mapErrorToUi(result: IntentGenerateResult): AiFigureUiResult {\n if (result.ok) return toSuccessUi(result);\n\n switch (result.reason) {\n case 'builder_error':\n case 'transpile_error':\n case 'verify_error':\n return {\n ok: false,\n message:\n 'Không dựng được hình (đã thử lại). Vui lòng tách thành 1 yêu cầu/lần hoặc diễn đạt khác.',\n };\n case 'deterministic_miss':\n default:\n // Rule base chưa phủ đề này: `message` đã là câu tiếng Việt dễ hiểu từ\n // describeDeterministicMiss (nêu rõ cần bổ sung rule / có thể lỗi rule +\n // phần đề chưa phủ) → trả thẳng cho UI/log, không bọc jargon.\n return { ok: false, message: result.message };\n }\n}\n","// src/stamps/geometry-2d/ai/envelope.ts\n//\n// Envelope schema cho figure build I/O:\n// { decision: 'build', figure: <DslInput> }\n// { decision: 'refuse', reason: '...' }\n//\n// 1 schema, parse + validate ở 1 chỗ. Giữ cho advanced consumer muốn dùng\n// envelope build-side (FigureEnvelopeZ + envelopeBuildDsl) trực tiếp.\n\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { DslInput, type DslInputT } from '../dsl';\n\nexport const FigureEnvelopeZ = z\n .object({\n decision: z.enum(['build', 'refuse']),\n // figure: DslInput khi build; bỏ qua khi refuse.\n figure: DslInput.optional(),\n // reason: lý do từ chối (Việt) khi refuse; bỏ qua khi build.\n reason: z.string().optional(),\n })\n .refine(\n (e) => (e.decision === 'build' ? e.figure != null : e.reason != null && e.reason.length > 0),\n {\n message:\n 'decision=build cần `figure`; decision=refuse cần `reason` không rỗng',\n },\n );\n\nexport type FigureEnvelopeT = z.infer<typeof FigureEnvelopeZ>;\n\n// JSON Schema bản phẳng cho consumer cần schema constraint.\n// Note: refine() chỉ run ở Zod runtime; JSON Schema không representable.\n// Validate qua FigureEnvelopeZ để bắt vi phạm refine.\nexport function envelopeJsonSchema(): Record<string, unknown> {\n return zodToJsonSchema(FigureEnvelopeZ, {\n target: 'jsonSchema7',\n $refStrategy: 'none',\n }) as Record<string, unknown>;\n}\n\n/** Helper: ép envelope build hợp lệ về DslInputT (sau khi đã validate). */\nexport function envelopeBuildDsl(env: FigureEnvelopeT): DslInputT {\n if (env.decision !== 'build' || env.figure == null) {\n throw new Error('envelopeBuildDsl: envelope không phải decision=build hoặc thiếu figure');\n }\n // Zod infer cho DslInput rộng `{[x: string]: any}[]` (discriminatedUnion từ\n // registry với schemas erased `ZodObject<any>`); runtime parse đã validate,\n // safe widen sang DslInputT (xem comment trong schema.ts).\n return env.figure as unknown as DslInputT;\n}\n","// src/stamps/geometry-2d/ai/intent.ts\n//\n// Intent schema — replacement for free-form DSL output.\n//\n// AI emit Intent[] thay vì DSL trực tiếp. Mỗi Intent là 1 \"lệnh vẽ\" cấp\n// semantic (\"vẽ tam giác đều ABC\", \"thêm trung điểm M của BC\"). Builder\n// (intentToDsl.ts) deterministic dịch Intent → DSL với canonical coords.\n//\n// Lợi ích:\n// - AI chỉ làm NLU (đọc-tách-lệnh), không tự đặt coord → 0% hallucinate coord\n// - Variant enum loại bỏ \"tam giác vuông tại A nhưng coord vuông tại B\"\n// - Schema explicit slot cho augmentations → guard \"không thừa\"\n\nimport { z } from 'zod';\n\n// Tên label/point — alphanumeric, 1-8 chars, không trùng kind enum.\nexport const LabelZ = z.string().min(1).max(8).regex(/^[A-Za-z][A-Za-z0-9'_]*$/);\n\n// ---------------------------------------------------------------------------\n// Shape variants per shape type\n// ---------------------------------------------------------------------------\n\n// triangle variants\nexport const TriangleVariantZ = z.enum([\n 'any', // tam giác bất kỳ (scalene cố định)\n 'equilateral', // tam giác đều\n 'isoceles-AB', // cân tại C (AB đáy)\n 'isoceles-BC', // cân tại A (BC đáy)\n 'isoceles-CA', // cân tại B (CA đáy)\n 'right-at-A', // vuông tại A\n 'right-at-B', // vuông tại B\n 'right-at-C', // vuông tại C\n]);\n\nexport const QuadVariantZ = z.enum([\n 'any', // tứ giác bất kỳ\n]);\n\nexport const SquareVariantZ = z.enum([\n 'standard', // canonical\n]);\n\nexport const RectangleVariantZ = z.enum([\n 'wide', // mặc định 4×2.5\n 'tall', // 2.5×4\n]);\n\nexport const RhombusVariantZ = z.enum([\n 'standard', // canonical (diagonals 4,2)\n]);\n\nexport const TrapezoidVariantZ = z.enum([\n 'right', // vuông\n 'isoceles', // cân\n 'general', // thường\n]);\n\nexport const ParallelogramVariantZ = z.enum([\n 'standard', // mặc định\n]);\n\n// ---------------------------------------------------------------------------\n// Intent ops\n// ---------------------------------------------------------------------------\n//\n// Note: zod's discriminatedUnion không cho phép duplicate discriminator value\n// (vd nhiều 'draw-shape' schemas khác nhau). Solution: flatten — mỗi op là 1\n// schema duy nhất với `shape` là enum, runtime check variant ∈ allowed-for-shape\n// trong builder. Đánh đổi: kém type-safety hơn variant-per-shape DSU, nhưng\n// schema flatter → JSON Schema rõ ràng hơn, không nested anyOf.\n\nconst ShapeNameZ = z.enum([\n 'triangle',\n 'square',\n 'rectangle',\n 'rhombus',\n 'trapezoid',\n 'parallelogram',\n 'quadrilateral',\n]);\n\n// Tất cả variant gộp 1 enum — runtime check ở builder.\nconst ShapeVariantZ = z.enum([\n // triangle\n 'any', 'equilateral',\n 'isoceles-AB', 'isoceles-BC', 'isoceles-CA',\n 'right-at-A', 'right-at-B', 'right-at-C',\n // square / rhombus / parallelogram\n 'standard',\n // rectangle\n 'wide', 'tall',\n // trapezoid\n 'right', 'isoceles', 'general',\n]);\n\n// op: draw-shape\nexport const DrawShapeIntentZ = z.object({\n op: z.literal('draw-shape'),\n shape: ShapeNameZ,\n labels: z.array(LabelZ).min(3).max(8),\n variant: ShapeVariantZ.default('any'),\n explicitCoords: z.record(LabelZ, z.tuple([z.number(), z.number()])).optional(),\n});\n\n// op: add-point\nexport const AddPointIntentZ = z.object({\n op: z.literal('add-point'),\n name: LabelZ,\n constraint: z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('midpoint'), of: z.string() }),\n z.object({ kind: z.literal('onPerpBisector'), p1: LabelZ, p2: LabelZ }),\n z.object({ kind: z.literal('perpFoot'), from: LabelZ, onLine: z.string() }),\n z.object({ kind: z.literal('centroid'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({ kind: z.literal('circumcenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({ kind: z.literal('incenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({ kind: z.literal('orthocenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]) }),\n z.object({\n kind: z.literal('intersection'),\n of: z.tuple([z.string(), z.string()]),\n branch: z.union([z.literal(0), z.literal(1)]).optional(),\n }),\n z.object({ kind: z.literal('onSegment'), of: z.string(), t: z.number().min(0).max(1).optional() }),\n z.object({ kind: z.literal('free'), at: z.tuple([z.number(), z.number()]).optional() }),\n // Điểm A nằm NGOÀI đường tròn `circle` (free external point) — builder đọc\n // tâm+bán kính của circle từ build state rồi đặt A free tại coord ngoài\n // circle. Unblock tangentFromExt render (đề \"Lấy A ngoài (O), kẻ 2 tiếp tuyến\").\n z.object({ kind: z.literal('externalToCircle'), circle: LabelZ }),\n // Điểm trên đường tròn `circle` tại góc `theta` (mặc định 0) — glider.\n // Dùng cho đường thẳng Simson (issue #47): P trên đường tròn ngoại tiếp.\n z.object({ kind: z.literal('onCircle'), circle: LabelZ, theta: z.number().optional() }),\n // NEW Tier 4+5\n z.object({ kind: z.literal('secondIntersection'), line: z.string(), circle: LabelZ, other: LabelZ }),\n z.object({ kind: z.literal('circleIntersection'), c1: LabelZ, c2: LabelZ, which: z.union([z.literal(0), z.literal(1)]) }),\n // Giao điểm THỨ HAI của 2 đường tròn, loại điểm chung `exclude` (đề \"đường\n // tròn đường kính AB, AC đôi một cắt nhau lần thứ hai\" — điểm chung A).\n z.object({ kind: z.literal('circleSecondIntersection'), c1: LabelZ, c2: LabelZ, exclude: LabelZ }),\n z.object({ kind: z.literal('tangencyPoint'), circle: LabelZ, onLine: z.string() }),\n z.object({ kind: z.literal('tangentPoint'), from: LabelZ, circle: LabelZ, which: z.union([z.literal(0), z.literal(1)]) }),\n z.object({ kind: z.literal('angleBisectorFoot'), from: LabelZ, onLine: z.string() }),\n // Phân giác NGOÀI: chân phân giác ngoài đỉnh `from` trên đường thẳng `onLine`\n // (phân giác ngoài ⊥ phân giác trong tại `from`). Issue #46 nhóm A.\n z.object({ kind: z.literal('externalAngleBisectorFoot'), from: LabelZ, onLine: z.string() }),\n // Cụm A\n z.object({ kind: z.literal('arcMidpoint'), circle: LabelZ, a: LabelZ, b: LabelZ, notContaining: LabelZ.optional(), containing: LabelZ.optional() }),\n z.object({ kind: z.literal('reflectPoint'), of: LabelZ, through: LabelZ }),\n z.object({ kind: z.literal('reflectLine'), of: LabelZ, through: z.string() }),\n z.object({ kind: z.literal('excenter'), of: z.tuple([LabelZ, LabelZ, LabelZ]), opposite: LabelZ }),\n z.object({ kind: z.literal('mixtilinearPoint'), of: z.tuple([LabelZ, LabelZ, LabelZ]), which: z.union([z.literal('center'), z.literal('touch')]) }),\n // Góc vuông nhìn đoạn: M trên onLine sao cho ∠ a-name-b = 90°\n z.object({ kind: z.literal('rightAngleViewing'), a: LabelZ, b: LabelZ, onLine: z.string(), which: z.union([z.literal(0), z.literal(1)]).optional() }),\n z.object({\n kind: z.literal('pointAtDistance'),\n from: LabelZ,\n through: LabelZ,\n // scale/offset OPTIONAL (Issue #46 nhóm C): d = scale·base + offset.\n // scale > 0; absent → giữ d = base như cũ (additive).\n distance: z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('circleRadius'), circle: LabelZ, scale: z.number().positive().optional(), offset: z.number().optional() }),\n z.object({ kind: z.literal('segmentLength'), p1: LabelZ, p2: LabelZ, scale: z.number().positive().optional(), offset: z.number().optional() }),\n z.object({ kind: z.literal('literal'), value: z.number().positive(), scale: z.number().positive().optional(), offset: z.number().optional() }),\n ]),\n }),\n ]),\n});\n\n// op: connect\nexport const ConnectIntentZ = z.object({\n op: z.literal('connect'),\n from: LabelZ,\n to: LabelZ,\n style: z.enum([\n 'segment',\n 'line',\n 'ray',\n 'perpBisector',\n 'angleBisector',\n ]).default('segment'),\n});\n\n// op: draw-circle — single schema, spec là enum, points conditional\nexport const DrawCircleIntentZ = z.object({\n op: z.literal('draw-circle'),\n name: LabelZ,\n spec: z.enum(['centerThrough', 'through3', 'centerRadius', 'inscribedIn', 'diameter']),\n center: LabelZ.optional(),\n through: LabelZ.optional(),\n points: z.tuple([LabelZ, LabelZ, LabelZ]).optional(),\n // NEW Tier 4+5\n radius: z.number().positive().optional(),\n triangle: z.tuple([LabelZ, LabelZ, LabelZ]).optional(),\n // spec 'diameter' — đường tròn đường kính nối 2 đầu mút.\n endpoints: z.tuple([LabelZ, LabelZ]).optional(),\n});\n\n// op: draw-line\nexport const DrawLineIntentZ = z.object({\n op: z.literal('draw-line'),\n name: LabelZ,\n kind: z.enum(['perpThrough', 'parallelThrough', 'tangentAt', 'tangentFromExt', 'angleBisector', 'lineThrough', 'radicalAxis', 'perpBisector']),\n through: LabelZ.optional(),\n to: LabelZ.optional(),\n from: LabelZ.optional(),\n circle: LabelZ.optional(),\n which: z.enum(['first', 'second', 'both']).optional(),\n // lineThrough (đường qua ≥2 điểm đồng tuyến — vd Euler line G/H/O, issue #47).\n points: z.array(LabelZ).optional(),\n // radicalAxis (trục đẳng phương 2 đường tròn — issue #47, construct 2).\n circle1: LabelZ.optional(),\n circle2: LabelZ.optional(),\n // angleBisector (phân giác TRONG của góc ∠p1·vertex·p2, VISIBLE, không foot —\n // Issue #46 nhóm A). vertex = đỉnh góc.\n p1: LabelZ.optional(),\n vertex: LabelZ.optional(),\n p2: LabelZ.optional(),\n});\n\n// op: mark-shape (sub-shape từ điểm đã có, không tạo coord mới)\nexport const MarkShapeIntentZ = z.object({\n op: z.literal('mark-shape'),\n shape: z.enum(['triangle', 'quadrilateral']),\n labels: z.array(LabelZ).min(3).max(4),\n});\n\n// Master discriminated union — 6 variants theo op\nexport const IntentZ = z.discriminatedUnion('op', [\n DrawShapeIntentZ,\n AddPointIntentZ,\n ConnectIntentZ,\n DrawCircleIntentZ,\n DrawLineIntentZ, // NEW\n MarkShapeIntentZ, // NEW\n]);\n\n// Re-export variant enums cho consumer (vd UI dropdown)\nexport {\n TriangleVariantZ as TriangleVariants,\n SquareVariantZ as SquareVariants,\n RectangleVariantZ as RectangleVariants,\n RhombusVariantZ as RhombusVariants,\n TrapezoidVariantZ as TrapezoidVariants,\n ParallelogramVariantZ as ParallelogramVariants,\n QuadVariantZ as QuadVariants,\n};\n\nexport type IntentT = z.infer<typeof IntentZ>;\nexport type DrawShapeIntentT = z.infer<typeof DrawShapeIntentZ>;\nexport type AddPointIntentT = z.infer<typeof AddPointIntentZ>;\nexport type ConnectIntentT = z.infer<typeof ConnectIntentZ>;\nexport type DrawCircleIntentT = z.infer<typeof DrawCircleIntentZ>;\nexport type DrawLineIntentT = z.infer<typeof DrawLineIntentZ>;\nexport type MarkShapeIntentT = z.infer<typeof MarkShapeIntentZ>;\n\n// ---------------------------------------------------------------------------\n// Envelope — wraps intents[] + decision\n// ---------------------------------------------------------------------------\n\nexport const IntentEnvelopeZ = z\n .object({\n decision: z.enum(['build', 'refuse']),\n intents: z.array(IntentZ).optional(),\n reason: z.string().optional(),\n })\n .refine(\n (e) =>\n e.decision === 'build'\n ? Array.isArray(e.intents) && e.intents.length > 0\n : e.reason != null && e.reason.length > 0,\n {\n message:\n 'decision=build cần intents non-empty; decision=refuse cần reason',\n },\n );\n\nexport type IntentEnvelopeT = z.infer<typeof IntentEnvelopeZ>;\n","// src/stamps/geometry-2d/ai/intentEnvelope.ts\n//\n// JSON Schema helper cho Intent envelope (giữ cho advanced consumer cần\n// schema constraint). Refine() check ở Zod runtime; JSON Schema không representable.\n\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { IntentEnvelopeZ, type IntentEnvelopeT } from './intent';\nimport type { IntentT } from './intent';\n\nexport function intentEnvelopeJsonSchema(): Record<string, unknown> {\n return zodToJsonSchema(IntentEnvelopeZ, {\n target: 'jsonSchema7',\n $refStrategy: 'none',\n }) as Record<string, unknown>;\n}\n\nexport function envelopeIntentList(env: IntentEnvelopeT): readonly IntentT[] {\n if (env.decision !== 'build' || env.intents == null) {\n throw new Error(\n 'envelopeIntentList: envelope không phải decision=build hoặc thiếu intents',\n );\n }\n return env.intents;\n}\n","// src/stamps/geometry-2d/ai/intentPrompt.ts\n//\n// System prompt cho Intent extraction (Stage 1). AI chỉ làm NLU — đọc đề\n// (VN hoặc EN), tách thành Intent[]. KHÔNG sinh DSL, KHÔNG đặt tọa độ.\n//\n// Khác prompt cũ (prompt.ts):\n// - Output là `intents: Intent[]` thay vì `figure: DSL`\n// - Bilingual: ví dụ cả VN + EN\n// - Anti-pattern explicit: AI không tự thêm intent ngoài đề\n//\n// IntentEnvelopeZ.refine() guards build/refuse semantics.\n\nimport type { IntentT, IntentEnvelopeT } from './intent';\n\ninterface IntentFixture {\n problem: string;\n intents: IntentT[];\n}\n\n// Tier 0+1 sample fixtures (in-prompt examples).\n// Note: chỉ shape examples — augmentation examples thêm khi mở Tier 1.\nconst FIXTURES: IntentFixture[] = [\n {\n problem: 'Tam giác ABC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n ],\n },\n {\n problem: 'Tam giác đều ABC cạnh 4.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'equilateral' },\n ],\n },\n {\n problem: 'Tam giác ABC vuông tại A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'right-at-A' },\n ],\n },\n {\n problem: 'Hình vuông MNPQ.',\n intents: [\n { op: 'draw-shape', shape: 'square', labels: ['M', 'N', 'P', 'Q'], variant: 'standard' },\n ],\n },\n {\n problem: 'Hình chữ nhật ABCD.',\n intents: [\n { op: 'draw-shape', shape: 'rectangle', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n ],\n },\n // \"cân tại X\" → X là đỉnh cân, cạnh đối diện là đáy\n {\n problem: 'Tam giác ABC cân tại A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'isoceles-BC' },\n ],\n },\n {\n problem: 'Tam giác MNP cân tại N.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['M', 'N', 'P'], variant: 'isoceles-CA' },\n ],\n },\n {\n problem: 'Hình thoi ABCD.',\n intents: [\n { op: 'draw-shape', shape: 'rhombus', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n ],\n },\n {\n problem: 'Hình bình hành ABCD.',\n intents: [\n { op: 'draw-shape', shape: 'parallelogram', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n ],\n },\n {\n problem: 'Hình thang ABCD cân, AB là đáy lớn.',\n intents: [\n { op: 'draw-shape', shape: 'trapezoid', labels: ['A', 'B', 'C', 'D'], variant: 'isoceles' },\n ],\n },\n // Tier 1 examples\n {\n problem: 'Tam giác ABC, M là trung điểm BC, vẽ đoạn AM.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'M', constraint: { kind: 'midpoint', of: 'BC' } },\n { op: 'connect', from: 'A', to: 'M', style: 'segment' },\n ],\n },\n {\n problem: 'Tam giác ABC, H là chân đường cao từ A xuống BC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'H', constraint: { kind: 'perpFoot', from: 'A', onLine: 'BC' } },\n { op: 'connect', from: 'A', to: 'H', style: 'segment' },\n ],\n },\n {\n problem: 'Triangle ABC with M the midpoint of BC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'M', constraint: { kind: 'midpoint', of: 'BC' } },\n ],\n },\n {\n problem: 'Triangle ABC, G is the centroid.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'G', constraint: { kind: 'centroid', of: ['A', 'B', 'C'] } },\n ],\n },\n // Compound: triangle + circumcircle (cần CẢ HAI intent)\n {\n problem: 'Đường tròn đi qua 3 điểm A, B, C.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n ],\n },\n {\n problem: 'Tam giác ABC nội tiếp đường tròn O.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n ],\n },\n // Compound: parallelogram with diagonals + intersection\n {\n problem: 'Hình bình hành ABCD, hai đường chéo AC và BD cắt nhau tại O.',\n intents: [\n { op: 'draw-shape', shape: 'parallelogram', labels: ['A', 'B', 'C', 'D'], variant: 'standard' },\n { op: 'connect', from: 'A', to: 'C', style: 'segment' },\n { op: 'connect', from: 'B', to: 'D', style: 'segment' },\n { op: 'add-point', name: 'O', constraint: { kind: 'intersection', of: ['AC', 'BD'] } },\n ],\n },\n // Build examples — đề có MỆNH LỆNH proof/tính NHƯNG mô tả hình → vẫn build\n {\n problem: 'Cho tam giác ABC vuông tại A. Chứng minh rằng AB² + AC² = BC².',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'right-at-A' },\n ],\n },\n {\n problem: 'Cho tứ giác ABCD nội tiếp (O). Chứng minh rằng AC.BD = AB.CD + AD.BC.',\n intents: [\n { op: 'draw-shape', shape: 'quadrilateral', labels: ['A', 'B', 'C', 'D'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n { op: 'connect', from: 'A', to: 'C', style: 'segment' },\n { op: 'connect', from: 'B', to: 'D', style: 'segment' },\n ],\n },\n // draw-line: perpThrough — đường vuông góc với LINE, đi qua POINT\n {\n problem: 'Tam giác ABC. Vẽ đường thẳng d vuông góc với AB tại B.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-line', name: 'd', kind: 'perpThrough', through: 'B', to: 'AB' },\n ],\n },\n // draw-line: tangentAt — tiếp tuyến TẠI POINT trên CIRCLE\n {\n problem: 'Tam giác ABC nội tiếp đường tròn (O). Vẽ tiếp tuyến tại A của (O).',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n { op: 'draw-line', name: 'tA', kind: 'tangentAt', through: 'A', circle: 'O' },\n ],\n },\n // draw-line: tangentFromExt — tiếp tuyến TỪ POINT ngoài CIRCLE (chọn nhánh)\n {\n problem: 'Cho đường tròn (O) và điểm P ngoài đường tròn. Vẽ hai tiếp tuyến PT₁ và PT₂ từ P tới (O).',\n intents: [\n { op: 'draw-circle', name: 'O', spec: 'centerRadius', center: 'O', radius: 3 },\n { op: 'add-point', name: 'P', constraint: { kind: 'free' } },\n { op: 'draw-line', name: 'PT1', kind: 'tangentFromExt', from: 'P', circle: 'O', which: 'first' },\n { op: 'draw-line', name: 'PT2', kind: 'tangentFromExt', from: 'P', circle: 'O', which: 'second' },\n ],\n },\n // Refuse examples — đề THUẦN tính / KHÔNG mô tả hình hình học\n {\n problem: 'Tính sin(30°) + cos(60°).',\n intents: [],\n },\n {\n problem: 'Vẽ con mèo.',\n intents: [],\n },\n {\n problem: 'Giải phương trình x² - 5x + 6 = 0.',\n intents: [],\n },\n {\n problem: 'Tam giác ABC nội tiếp (O). M là trung điểm cung BC không chứa A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'draw-circle', name: 'O', spec: 'through3', points: ['A', 'B', 'C'] },\n { op: 'add-point', name: 'M', constraint: { kind: 'arcMidpoint', circle: 'O', a: 'B', b: 'C', notContaining: 'A' } },\n ],\n },\n {\n problem: 'Tam giác ABC trực tâm H. D là điểm đối xứng của H qua BC.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'H', constraint: { kind: 'orthocenter', of: ['A', 'B', 'C'] } },\n { op: 'add-point', name: 'D', constraint: { kind: 'reflectLine', of: 'H', through: 'BC' } },\n ],\n },\n {\n problem: 'Tam giác ABC, J là tâm bàng tiếp góc A.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'J', constraint: { kind: 'excenter', of: ['A', 'B', 'C'], opposite: 'A' } },\n ],\n },\n {\n problem: 'Cho tam giác nhọn ABC, đường cao CK, H là trực tâm. Gọi M là một điểm trên CK sao cho góc AMB = 90°.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'C'], variant: 'any' },\n { op: 'add-point', name: 'K', constraint: { kind: 'perpFoot', from: 'C', onLine: 'AB' } },\n { op: 'add-point', name: 'H', constraint: { kind: 'orthocenter', of: ['A', 'B', 'C'] } },\n { op: 'connect', from: 'C', to: 'K', style: 'segment' },\n { op: 'add-point', name: 'M', constraint: { kind: 'rightAngleViewing', a: 'A', b: 'B', onLine: 'CK' } },\n ],\n },\n {\n problem: 'Cho đoạn AB và đường thẳng d. Điểm M trên d sao cho góc AMB = 90°.',\n intents: [\n { op: 'draw-shape', shape: 'triangle', labels: ['A', 'B', 'D'], variant: 'any' },\n { op: 'add-point', name: 'M', constraint: { kind: 'rightAngleViewing', a: 'A', b: 'B', onLine: 'd' } },\n ],\n },\n];\n\nexport function buildIntentSystemPrompt(): string {\n const examples = FIXTURES.map((f, i) => {\n const envelope: IntentEnvelopeT =\n f.intents.length > 0\n ? { decision: 'build', intents: f.intents }\n : { decision: 'refuse', reason: 'Đề không phải hình học — không vẽ được hình.' };\n return `### Ví dụ ${i + 1}\n**Đề:** ${f.problem}\n**Output:**\n${JSON.stringify(envelope, null, 2)}`;\n }).join('\\n\\n');\n\n return `Bạn là trợ lý tách lệnh vẽ hình học 2D cho học sinh THCS / lớp 10.\nChấp nhận đề bài tiếng Việt HOẶC tiếng Anh.\n\n## Nhiệm vụ\nĐọc đề → tách thành danh sách \"intents\" (lệnh vẽ cấp cao). KHÔNG sinh tọa độ,\nKHÔNG sinh DSL chi tiết — chỉ tách lệnh.\n\n## Output format (CHỈ JSON, KHÔNG markdown, KHÔNG text khác)\n{ \"decision\": \"build\", \"intents\": [ ... ] }\nhoặc\n{ \"decision\": \"refuse\", \"reason\": \"lý do tiếng Việt\" }\n\n## Quy tắc tuyệt đối\n\n1. **MỘT intent = MỘT đối tượng nêu trong đề.** Đề nói gì, emit intent đó.\n KHÔNG tự thêm trung tuyến/đường cao/tâm nếu đề không nói.\n\n2. **Shape variant phải khớp đề:**\n - \"đều\" → variant: \"equilateral\"\n - \"vuông tại X\" → variant: \"right-at-X\" (X là label đầu tiên trong labels[] khớp đề)\n - \"cân tại X\" — X là ĐỈNH CÂN, base là cạnh đối diện:\n * \"tam giác ABC cân tại A\" → variant: \"isoceles-BC\" (BC là đáy, A là apex)\n * \"tam giác MNP cân tại N\" → variant: \"isoceles-CA\" (CA là đáy theo canonical position)\n * Rule: variant đặt tên theo position trong labels[], KHÔNG phải tên literal.\n apex ở position 0 → \"isoceles-BC\"; position 1 → \"isoceles-CA\"; position 2 → \"isoceles-AB\".\n - không có từ khoá đặc biệt → variant: \"any\"\n\n3. **Labels phải đúng đề:** \"tam giác MNP\" → labels: [\"M\",\"N\",\"P\"], không tự đổi sang ABC.\n\n4. **Augmentations (Tier 1) dùng add-point + connect:**\n - \"M trung điểm BC\" → add-point name=M, constraint=midpoint of=BC\n - \"H chân đường cao từ A xuống BC\" → add-point name=H, constraint=perpFoot from=A onLine=BC\n - \"vẽ đoạn AM\" → connect from=A to=M\n - Trọng tâm/tâm ngoại/nội/trực tâm → add-point constraint=centroid/circumcenter/incenter/orthocenter\n\n5. **KHÔNG bịa.** Nếu đề mơ hồ hoặc không thuộc hình học 2D phổ thông → decision=refuse.\n\n6. **Đặt tên draw-circle**: nếu đề có ký hiệu rõ ràng \"(X)\" (vd \"(O)\", \"(I)\", \"(I1)\") → dùng đúng ký hiệu đó làm name. KHÔNG thêm hậu tố như \"Ic\", \"In\", \"Oc\". Nếu đề không có ký hiệu thì name tự do (preprocessor xử lý mọi collision).\n\n7. **Mệnh lệnh \"Chứng minh\" / \"Tính\" / \"Tìm\" / \"Hỏi\" KHÔNG ảnh hưởng quyết định build/refuse.** Quyết định CHỈ dựa vào việc đề có MÔ TẢ hình vẽ được hay không. Nếu đề bắt đầu / kết thúc bằng \"Chứng minh rằng …\" hoặc \"Tính …\" nhưng phần MÔ TẢ (giả thiết) có hình (tam giác, tứ giác, đường tròn, giao điểm …) → vẫn decision=build, vẽ phần giả thiết. KẾT QUẢ proof / phép tính KHÔNG cần biểu diễn. Chỉ refuse khi đề THUẦN tính / đại số không kèm mô tả hình (vd \"Tính sin(30°)+cos(60°)\", \"Giải x²-5x+6=0\").\n\n## Variant enum (chỉ dùng giá trị này)\n- triangle: any | equilateral | isoceles-AB | isoceles-BC | isoceles-CA | right-at-A | right-at-B | right-at-C\n- square: standard\n- rectangle: standard (default) | wide | tall\n- rhombus: standard\n- trapezoid: right | isoceles | general\n- parallelogram: standard\n- quadrilateral: any\n\n## Constraint kinds (cho add-point)\nmidpoint, perpFoot, centroid, circumcenter, incenter, orthocenter, intersection, onSegment, free, secondIntersection, circleIntersection, tangencyPoint, tangentPoint, angleBisectorFoot, externalAngleBisectorFoot, arcMidpoint, reflectPoint, reflectLine, excenter, rightAngleViewing, pointAtDistance\n\n## Style enum (cho connect)\nsegment, line, ray, perpBisector\n\n## draw-line — phân biệt field theo kind (RẤT QUAN TRỌNG, dễ sai)\n\ndraw-line dùng cho 4 loại đường thẳng đặc biệt. Mỗi kind có schema field khác\nnhau — đặt đúng field, KHÔNG bỏ field bắt buộc, KHÔNG nhầm POINT với LINE:\n\n- **perpThrough** — đường vuông góc với một đường thẳng, đi qua một điểm.\n Fields: \\`through\\` (POINT), \\`to\\` (LINE — ≥2 chữ, vd \"AB\", \"BC\").\n - Ví dụ: \"Đường vuông góc với AB tại B\" → \\`{kind:\"perpThrough\", through:\"B\", to:\"AB\"}\\`.\n - **SAI**: \\`{through:\"B\", to:\"A\"}\\` (A là 1 chữ → POINT, không phải LINE).\n - Nếu đề chỉ nói \"vuông góc với AB\" thì \\`to:\"AB\"\\` (2 chữ); KHÔNG đặt \\`to:\"A\"\\` hay \\`to:\"B\"\\`.\n\n- **parallelThrough** — đường song song với LINE, đi qua POINT. Field giống\n perpThrough: \\`through\\` (POINT), \\`to\\` (LINE 2+ chữ).\n - Ví dụ: \"qua M kẻ đường song song với BC\" → \\`{kind:\"parallelThrough\", through:\"M\", to:\"BC\"}\\`.\n\n- **tangentAt** — tiếp tuyến TẠI điểm trên đường tròn.\n Fields: \\`through\\` (POINT, phải nằm TRÊN circle), \\`circle\\` (CIRCLE name).\n - Ví dụ: \"Tiếp tuyến tại A của (O)\" → \\`{kind:\"tangentAt\", through:\"A\", circle:\"O\"}\\`.\n - KHÔNG dùng \\`from\\` ở đây — chỉ tangentFromExt mới dùng \\`from\\`.\n\n- **tangentFromExt** — tiếp tuyến TỪ điểm NGOÀI đường tròn (có 2 nhánh).\n Fields: \\`from\\` (POINT, ngoài circle), \\`circle\\` (CIRCLE), \\`which\\` ('first'|'second'|'both').\n - Ví dụ: \"Vẽ tiếp tuyến PA và PB từ P\" → 2 intent với \\`which:\"first\"\\` và \\`which:\"second\"\\`.\n\n## Cụm A — constraint hình học nâng cao (đặt ĐÚNG field)\n\n- **arcMidpoint** — trung điểm CUNG. Fields: \\`circle\\` (tên đường tròn), \\`a\\`, \\`b\\` (2 đầu cung), \\`notContaining\\` (đỉnh KHÔNG nằm trên cung đó).\n - Ví dụ: \"M là trung điểm cung BC không chứa A của (O)\" → \\`{kind:\"arcMidpoint\", circle:\"O\", a:\"B\", b:\"C\", notContaining:\"A\"}\\`.\n - LƯU Ý: phải có draw-circle tạo \\`circle\\` trước (vd đường tròn ngoại tiếp → spec:\"through3\", points:[A,B,C]).\n\n- **reflectPoint** — đối xứng qua một ĐIỂM. Fields: \\`of\\` (điểm gốc), \\`through\\` (tâm đối xứng, 1 chữ = POINT).\n - Ví dụ: \"Q đối xứng P qua trung điểm M\" → \\`{kind:\"reflectPoint\", of:\"P\", through:\"M\"}\\`.\n\n- **reflectLine** — đối xứng qua một ĐƯỜNG. Fields: \\`of\\` (điểm gốc), \\`through\\` (đường, 2 chữ = LINE vd \"BC\").\n - Ví dụ: \"D đối xứng H qua BC\" → \\`{kind:\"reflectLine\", of:\"H\", through:\"BC\"}\\`.\n\n- **excenter** — tâm BÀNG tiếp tam giác. Fields: \\`of\\` ([A,B,C]), \\`opposite\\` (đỉnh đối diện).\n - Ví dụ: \"J là tâm bàng tiếp góc A của tam giác ABC\" → \\`{kind:\"excenter\", of:[\"A\",\"B\",\"C\"], opposite:\"A\"}\\`.\n - KHÁC incenter (tâm NỘI tiếp): bàng tiếp nằm NGOÀI tam giác.\n\n- **rightAngleViewing** — điểm GÓC VUÔNG nhìn đoạn. Fields: \\`a\\`, \\`b\\` (2 mút đoạn), \\`onLine\\` (đường điểm nằm trên), \\`which\\` (0|1, optional — chọn giao điểm).\n - Dùng khi: \"M trên <đường> sao cho góc AMB = 90°\" / \"∠AMB = 90°\" / \"góc AMB vuông\" / \"MA ⊥ MB\" / \"M nhìn AB dưới góc vuông\".\n - Chữ GIỮA của góc = tên điểm (name); 2 chữ ngoài = \\`a\\`, \\`b\\`.\n - Ví dụ: \"M trên CK sao cho góc AMB = 90°\" → \\`{op:\"add-point\", name:\"M\", constraint:{kind:\"rightAngleViewing\", a:\"A\", b:\"B\", onLine:\"CK\"}}\\`.\n - KHÔNG tự tạo đường tròn phụ — chỉ phát ra constraint này, hệ thống tự dựng đường tròn đường kính AB (Thales).\n- **pointAtDistance** — điểm trên TIA kéo dài, cách mốc một khoảng cho trước. Fields: \\`from\\` (điểm gốc của tia), \\`through\\` (điểm mốc — điểm mới nằm BÊN NGOÀI \\`through\\` trên tia from→through), \\`distance\\` — một trong:\n - \\`{kind:\"circleRadius\", circle:\"O\"}\\` = bán kính R của đường tròn (O)\n - \\`{kind:\"segmentLength\", p1:\"O\", p2:\"A\"}\\` = độ dài đoạn OA\n - \\`{kind:\"literal\", value:2}\\` = số đo cho sẵn\n - Ví dụ: \"Kéo dài AB về phía B, lấy C sao cho BC = R của (O)\" → \\`{op:\"add-point\", name:\"C\", constraint:{kind:\"pointAtDistance\", from:\"A\", through:\"B\", distance:{kind:\"circleRadius\", circle:\"O\"}}}\\`.\n - Ví dụ: \"Trên tia đối của tia BA lấy D sao cho BD = AB\" (hướng từ B ra xa A) → \\`{op:\"add-point\", name:\"D\", constraint:{kind:\"pointAtDistance\", from:\"A\", through:\"B\", distance:{kind:\"segmentLength\", p1:\"A\", p2:\"B\"}}}\\`.\n - KHÁC reflectPoint (cho 2·through−from, không cần distance) và onSegment (nằm GIỮA hai điểm, t∈[0,1]).\n\n## Quy ước LINE name\n- 2 ký tự viết liền = SEGMENT/LINE qua 2 điểm: \"AB\", \"BC\", \"MN\" → \\`to: \"AB\"\\`.\n- 1 ký tự = POINT, KHÔNG dùng cho field \\`to\\` của perpThrough/parallelThrough.\n- Nếu đề chỉ nêu 2 điểm và bạn cần đường thẳng qua chúng, gọi nó là \"AB\"\n (alphabet order canonical), KHÔNG cần emit connect intent riêng — builder\n tự suy ra đoạn.\n\n---\n\n# ${FIXTURES.length} ví dụ\n\n${examples}\n`;\n}\n","// src/stamps/geometry-2d/ai/handleGenerateFigureIntent.ts\n//\n// Façade cho HTTP transport — wrap generateFigureIntent với error mapping\n// tới AiFigureIntentUiResult (pattern giống handleGenerateFigure cũ).\n\nimport { generateFigureIntent, type GenerateIntentOptions } from './buildFigureIntent';\nimport type { IntentT } from './intent';\nimport type { DslInputT } from '../dsl/schema';\n\nexport interface HandleGenerateFigureIntentOptions extends GenerateIntentOptions {}\n\nexport interface HandleGenerateFigureIntentInput {\n problem: string;\n}\n\nexport type AiFigureIntentUiResult =\n | {\n kind: 'success';\n dsl: DslInputT;\n intents: readonly IntentT[];\n svg?: string;\n usage: { inputTokens: number; outputTokens: number };\n /** Có mặt khi partial render: `message` là to-do list cho user tự dựng nốt. */\n partial?: { message: string };\n }\n | {\n kind: 'refused';\n message: string;\n }\n | {\n kind: 'error';\n code: string;\n message: string;\n };\n\nexport async function handleGenerateFigureIntent(\n problem: string,\n opts: HandleGenerateFigureIntentOptions = {},\n): Promise<AiFigureIntentUiResult> {\n try {\n const r = await generateFigureIntent(problem, opts);\n if (r.ok) {\n return {\n kind: 'success',\n dsl: r.dsl,\n intents: r.intents,\n usage: {\n inputTokens: r.usage.inputTokens,\n outputTokens: r.usage.outputTokens,\n },\n ...(r.partial ? { partial: r.partial } : {}),\n };\n }\n return { kind: 'error', code: r.reason, message: r.message };\n } catch (e) {\n return {\n kind: 'error',\n code: 'unexpected',\n message: e instanceof Error ? e.message : String(e),\n };\n }\n}\n","// src/stamps/geometry-2d/ai/mergeIntents.ts\n//\n// Hybrid partial-coverage (Phase 1): gộp intent deterministic + intent LLM bù\n// phần clause chưa phủ. Hai quy tắc:\n// 1. Dedup exact (cùng JSON).\n// 2. Deterministic SỞ HỮU tên (đỉnh draw-shape / name add-point/draw-circle/\n// draw-line) → LLM KHÔNG được định nghĩa lại tên đó (drop bản LLM, det thắng).\n// intent tham chiếu (connect…) KHÔNG sở hữu tên → luôn giữ.\n//\n// Det luôn đứng trước, LLM (đã lọc) nối sau — giữ thứ tự dựng.\nimport type { IntentT } from './intent';\n\n/** Tên mà 1 intent ĐỊNH NGHĨA (tạo mới). connect/ref → [] (chỉ tham chiếu). */\nfunction intentOwnedNames(intent: IntentT): string[] {\n const i = intent as unknown as { op: string; labels?: unknown; name?: unknown };\n if (i.op === 'draw-shape') {\n return Array.isArray(i.labels) ? (i.labels as string[]) : [];\n }\n // add-point / draw-circle / draw-line đều có `name` định danh entity mới.\n if (typeof i.name === 'string') return [i.name];\n return [];\n}\n\n/**\n * Gộp intent deterministic (det) + intent LLM bù (llm). Det giữ nguyên; mỗi\n * intent LLM bị loại nếu: trùng JSON với intent đã có, HOẶC định nghĩa lại tên\n * mà det đã sở hữu (det thắng — phần deterministic đã đúng, đừng để LLM ghi đè).\n */\nexport function mergeIntents(det: readonly IntentT[], llm: readonly IntentT[]): IntentT[] {\n const detOwned = new Set<string>();\n for (const i of det) for (const n of intentOwnedNames(i)) detOwned.add(n);\n\n const seen = new Set<string>(det.map((i) => JSON.stringify(i)));\n const out: IntentT[] = [...det];\n\n for (const i of llm) {\n const key = JSON.stringify(i);\n if (seen.has(key)) continue; // trùng exact\n const owned = intentOwnedNames(i);\n if (owned.some((n) => detOwned.has(n))) continue; // redefine tên det → drop\n seen.add(key);\n out.push(i);\n }\n return out;\n}\n"]}
|