{"version":3,"sources":["../src/types.ts","../src/rule.ts","../src/lsystem.ts","../src/turtle.ts"],"sourcesContent":["export const alphabetSymbols = ['F', 'G', 'H', 'L', 'M', 'D', 'U', '+', '-', '[', ']'] as const;\r\nexport type AlphabetSymbol = typeof alphabetSymbols[number];\r\n\r\nexport const isValidAlphabetSymbol = (chr: string) => alphabetSymbols.includes(chr as AlphabetSymbol);\r\n","import { AlphabetSymbol, isValidAlphabetSymbol } from \"./types\";\r\n\r\nexport class Rule {\r\n    \r\n    private _base: AlphabetSymbol;\r\n\r\n    private _next: AlphabetSymbol[];\r\n\r\n    constructor(rule: string) {\r\n        const matches = rule.replace(/\\s/g, '').match(/^(.)(-|=)>(.+)$/);\r\n        if (!matches) {\r\n            throw new Error('Unrecognized rule pattern');\r\n        }\r\n        const base = matches[1] as AlphabetSymbol;\r\n        const next = matches[3];\r\n        if (!isValidAlphabetSymbol(base)) {\r\n            throw new Error(`Symbol '${base}' not recognized in condition`);\r\n        }    \r\n        this._base = base;\r\n        this._next = [];\r\n        next.split('').forEach(c => {\r\n            if (!isValidAlphabetSymbol(c)) {\r\n                throw new Error(`Symbol '${c}' not recognized in predicate`);\r\n            }\r\n            this._next.push(c as AlphabetSymbol);\r\n        });\r\n    }\r\n\r\n    get base(): AlphabetSymbol {\r\n        return this._base;\r\n    }\r\n\r\n    get next(): AlphabetSymbol[] {\r\n        return this._next;\r\n    }\r\n    \r\n    get nextString(): string {\r\n        return this._next.join('');\r\n    }\r\n\r\n    public toString(): string {\r\n        return `${this.base} => ${this._next.join('')}`;\r\n    }\r\n};","import { Rule } from \"./rule\";\r\nimport { isValidAlphabetSymbol } from \"./types\";\r\n\r\nexport class LSystem {\r\n\r\n    private _axiom: string = '';\r\n    private _rules: Rule[];\r\n    private _sentence: string = '';\r\n    private _generation: number = 0;\r\n\r\n    constructor (axiom: string, rules: (string | Rule)[]) {\r\n        this.axiom = axiom;\r\n        this._rules = rules.map(rule => typeof rule === 'string' ? new Rule(rule) : rule);\r\n        this.init();\r\n    }\r\n\r\n    private init() {\r\n        this._sentence = this._axiom;\r\n        this._generation = 0;\r\n    }\r\n\r\n    /**\r\n     * \r\n     * @param { number } n \r\n     */\r\n    generate(n: number = 1): void {\r\n        let nextGen: string;\r\n\r\n        for (let i = 0; i < n; i++) {\r\n            nextGen = '';\r\n            this._sentence.split('').forEach(c => {\r\n                const rule = this._rules.find(r => r.base === c);\r\n                nextGen = nextGen.concat(rule === undefined ? c : rule.nextString);\r\n            });\r\n            this._sentence = nextGen;\r\n            this._generation++;\r\n        }\r\n    }\r\n\r\n    get sentence(): string {\r\n        return this._sentence;\r\n    }\r\n\r\n    get generation(): number {\r\n        return this._generation;\r\n    }\r\n\r\n    get rules(): Rule[] {\r\n        return [ ...this._rules ];\r\n    }\r\n\r\n    set axiom(val: string) {\r\n        val.split('').forEach((c) => {\r\n            if (!isValidAlphabetSymbol(c)) {\r\n                throw new Error(`Symbol '${c}' not recognized in axiom`);\r\n            }\r\n        });\r\n        this._axiom = val;\r\n        this.init();\r\n    }\r\n\r\n    get axiom(): string {\r\n        return this._axiom;\r\n    }\r\n}\r\n","import { AlphabetSymbol } from \"./types\";\r\n\r\nexport interface ScaleConfig {\r\n    ratio: number,\r\n    scaleStrokeSize?: boolean,\r\n    scaleStrokeWeight?: boolean,\r\n    scaleAngle?: boolean,\r\n};\r\n\r\nexport interface TurtleConfig {\r\n    context: CanvasRenderingContext2D,\r\n    strokeSize: number,\r\n    strokeWeight: number,\r\n    angle: number,\r\n    scale: ScaleConfig,\r\n};\r\n\r\nexport class Turtle {\r\n\r\n    /**\r\n     * @type { number }\r\n     */\r\n    private currentScale: number = 1\r\n\r\n    private readonly alphabetMap: Record<AlphabetSymbol, () => void> = {\r\n        F: () => {\r\n            const ctx = this.config.context;\r\n            const lineWith = this.config.scale.scaleStrokeWeight ? this.config.strokeWeight * this.currentScale : this.config.strokeWeight;\r\n            const lineSize = this.config.scale.scaleStrokeSize ? this.config.strokeSize * this.currentScale : this.config.strokeSize;\r\n            ctx.beginPath();\r\n            ctx.moveTo(0, 0);\r\n            ctx.lineCap = 'round';\r\n            ctx.lineWidth = lineWith;\r\n            ctx.lineTo(lineSize, 0);\r\n            ctx.stroke();\r\n            ctx.translate(lineSize, 0);\r\n        },\r\n        G: () => {\r\n            const ctx = this.config.context;\r\n            const lineWith = this.config.scale.scaleStrokeWeight ? this.config.strokeWeight * this.currentScale : this.config.strokeWeight;\r\n            const lineSize = this.config.scale.scaleStrokeSize ? this.config.strokeSize * this.currentScale : this.config.strokeSize;\r\n            ctx.beginPath();\r\n            ctx.moveTo(0, 0);\r\n            ctx.lineCap = 'round';\r\n            ctx.lineWidth = lineWith;\r\n            ctx.lineTo(lineSize, 0);\r\n            ctx.stroke();\r\n            ctx.translate(lineSize, 0);\r\n        },\r\n        H: () => {\r\n            const ctx = this.config.context;\r\n            const lineWith = this.config.scale.scaleStrokeWeight ? this.config.strokeWeight * this.currentScale : this.config.strokeWeight;\r\n            const lineSize = this.config.scale.scaleStrokeSize ? this.config.strokeSize * this.currentScale : this.config.strokeSize;\r\n            ctx.beginPath();\r\n            ctx.moveTo(0, 0);\r\n            ctx.lineCap = 'round';\r\n            ctx.lineWidth = lineWith;\r\n            ctx.lineTo(lineSize, 0);\r\n            ctx.stroke();\r\n            ctx.translate(lineSize, 0);\r\n        },\r\n        L: () => {\r\n            const ctx = this.config.context;\r\n            const lineWith = this.config.scale.scaleStrokeWeight ? this.config.strokeWeight * this.currentScale : this.config.strokeWeight;\r\n            const lineSize = this.config.scale.scaleStrokeSize ? this.config.strokeSize * this.currentScale : this.config.strokeSize;\r\n            ctx.beginPath();\r\n            ctx.moveTo(0, 0);\r\n            ctx.lineCap = 'round';\r\n            ctx.lineWidth = lineWith;\r\n            ctx.arc(lineSize * 0.5, lineSize * 0.5, lineSize * Math.SQRT1_2, Math.PI * 1.25, Math.PI * 1.75);\r\n            ctx.arc(lineSize * 0.5, -lineSize * 0.5, lineSize * Math.SQRT1_2, Math.PI * 0.25, Math.PI * 0.75);\r\n            ctx.stroke();\r\n        },\r\n        M: () => {\r\n            const lineSize = this.config.scale.scaleStrokeSize ? this.config.strokeSize * this.currentScale : this.config.strokeSize;\r\n            this.config.context.translate(lineSize, 0);\r\n        },\r\n        D: () => this.currentScale *= this.config.scale.ratio,\r\n        U: () => this.currentScale /= this.config.scale.ratio,\r\n        \"+\": () => {\r\n            const angle = this.config.scale.scaleAngle ? this.config.angle * this.currentScale : this.config.angle;\r\n            this.config.context.rotate(angle);\r\n        },\r\n        \"-\": () => {\r\n            const angle = this.config.scale.scaleAngle ? this.config.angle * this.currentScale : this.config.angle;\r\n            this.config.context.rotate(-angle);\r\n        },\r\n        \"[\": () => this.config.context.save(),\r\n        \"]\": () => this.config.context.restore()\r\n    };\r\n\r\n    \r\n    constructor(public config: TurtleConfig) {\r\n    }\r\n\r\n    /**\r\n     * \r\n     * @param { string } sentence \r\n     */\r\n    render(sentence: string) {\r\n        for (let i = 0; i < sentence.length; i++) {\r\n            const chr = sentence[i] as AlphabetSymbol;\r\n            const fn = this.alphabetMap[chr];\r\n            if (typeof fn === 'function') {\r\n                fn.call(this);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * \r\n     * @param { number } x \r\n     * @param { number } y \r\n     * @param { number } angle \r\n     */\r\n    init(x: number, y: number, angle: number) {\r\n        this.config.context.resetTransform();\r\n        this.config.context.translate(x, y);\r\n        this.config.context.rotate(angle);\r\n        this.currentScale = 1;\r\n    }\r\n}"],"mappings":"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","names":[]}