Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 36x 36x 36x 36x 36x 36x 72x 72x 66x 36x 36x | import type {
ConstructionState,
ConstructionElement,
IntersectionCandidate,
GhostLayer,
} from '../types'
import type { FactStore } from './factStore'
import type { EqualityFact } from './facts'
import { recipeToMacroDef } from './recipe/adapters'
import {
RECIPE_PROP_1,
RECIPE_PROP_2,
RECIPE_PROP_3,
RECIPE_REGISTRY,
} from './recipe/definitions/registry'
/** Structured definition for a single macro input slot. */
export interface MacroInput {
/** Semantic role — machine-readable tag for UI/chat/preview */
role: string
/** User-facing label shown in MacroToolPanel prompt ("Select ___") */
label: string
/** Maps to the source proposition's given point ID (e.g. 'pt-A') */
givenId: string
}
export interface MacroDef {
propId: number
label: string
inputs: MacroInput[]
/**
* Pairs of input indices that must refer to distinct points.
* E.g. [[0,1]] means input 0 and input 1 cannot be the same point.
* Used to reject degenerate selections (zero-length segments, etc.)
* while still allowing legitimate repeats (I.3 shares an endpoint
* between its two segment arguments).
*/
distinctInputPairs: [number, number][]
execute: (
state: ConstructionState,
inputPointIds: string[],
candidates: IntersectionCandidate[],
factStore: FactStore,
atStep: number,
extendSegments?: boolean,
outputLabels?: Record<string, string>
) => MacroResult
}
/** Derive input count from structured inputs */
export function macroInputCount(def: MacroDef): number {
return def.inputs.length
}
/** Derive legacy label array from structured inputs */
export function macroInputLabels(def: MacroDef): string[] {
return def.inputs.map((i) => i.label)
}
/** Derive legacy givenId mapping from structured inputs */
export function macroInputGivenIds(def: MacroDef): string[] {
return def.inputs.map((i) => i.givenId)
}
export interface MacroResult {
state: ConstructionState
candidates: IntersectionCandidate[]
addedElements: ConstructionElement[]
newFacts: EqualityFact[]
ghostLayers: GhostLayer[]
}
// ── Recipe-derived macro definitions ──────────────────────────────
export const MACRO_REGISTRY: Record<number, MacroDef> = {
1: recipeToMacroDef(RECIPE_PROP_1, RECIPE_REGISTRY),
2: recipeToMacroDef(RECIPE_PROP_2, RECIPE_REGISTRY),
3: recipeToMacroDef(RECIPE_PROP_3, RECIPE_REGISTRY),
}
/**
* Check whether selecting `candidatePointId` as the next input (at index
* `selectedSoFar.length`) would violate any distinctness constraint.
*/
export function wouldViolateDistinctness(
distinctInputPairs: [number, number][],
selectedSoFar: string[],
candidatePointId: string
): boolean {
const nextIndex = selectedSoFar.length
return distinctInputPairs.some(([i, j]) => {
if (nextIndex === j && i < nextIndex && selectedSoFar[i] === candidatePointId) return true
if (nextIndex === i && j < nextIndex && selectedSoFar[j] === candidatePointId) return true
return false
})
}
|