diff options
author | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2024-02-08 18:36:10 -0700 |
---|---|---|
committer | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2024-02-08 18:36:10 -0700 |
commit | 5b8b3abcba8746502014266583907421b71a330b (patch) | |
tree | fc3d8a2159a17c8af1d432d93307ff01474fb053 /src | |
parent | c18b81b2f26123481558cb3fffc794c2c13f74ad (diff) | |
download | compiling-the-lambda-calculus-5b8b3abcba8746502014266583907421b71a330b.tar.gz compiling-the-lambda-calculus-5b8b3abcba8746502014266583907421b71a330b.zip |
add hungry partner function
Diffstat (limited to 'src')
-rw-r--r-- | src/components/function_box.tsx | 180 | ||||
-rw-r--r-- | src/project.meta | 2 | ||||
-rw-r--r-- | src/scenes/first_box.tsx | 23 | ||||
-rw-r--r-- | src/scenes/hungry_partner.meta | 5 | ||||
-rw-r--r-- | src/scenes/hungry_partner.tsx | 108 | ||||
-rw-r--r-- | src/scenes/index.ts | 14 |
6 files changed, 237 insertions, 95 deletions
diff --git a/src/components/function_box.tsx b/src/components/function_box.tsx index e046d63..43d3985 100644 --- a/src/components/function_box.tsx +++ b/src/components/function_box.tsx @@ -1,31 +1,10 @@ -import { - Img, - Rect, - Node, - Video, - makeScene2D, - Txt, - Line, - LineSegment, - NodeProps, -} from "@motion-canvas/2d"; -import { - Direction, - beginSlide, - createRef, - map, - slideTransition, - tween, - all, - waitFor, - range, - makeRef, -} from "@motion-canvas/core"; +import { Rect, Node, Txt, Line, NodeProps } from "@motion-canvas/2d"; +import { createRef, all, range, makeRef } from "@motion-canvas/core"; import { CodeBlock } from "@motion-canvas/2d/lib/components/CodeBlock"; import { theme } from "../theme"; -import * as ts from "typescript"; +import { transpile } from "typescript"; export interface FunctionBoxProps extends NodeProps { source?: string; @@ -33,6 +12,9 @@ export interface FunctionBoxProps extends NodeProps { padding?: number; delta?: number; + inputFontSize?: number; + outputFontSize?: number; + workingText?: string; idlingText?: string; @@ -43,18 +25,6 @@ export interface FunctionBoxProps extends NodeProps { type FunctionArgs = { node?: Node; val: any }[]; -/* -<Node ref={this.node} opacity={0}> - <CodeBlock - fontFamily={theme.font} - language="typescript" - ref={this.block} - fontSize={1} - code={this.source} - ></CodeBlock> - </Node> - */ - export class FunctionBox extends Node { private readonly source: string; private readonly workingText: string; @@ -72,11 +42,14 @@ export class FunctionBox extends Node { private readonly inputSegments: Line[] = []; private readonly inputs: Rect[] = []; private readonly outputSegment = createRef<Line>(); - private readonly output = createRef<Node>(); + private readonly output = createRef<Rect>(); private readonly child = createRef<FunctionBox>(); private readonly isChild: boolean; + private readonly inputFontSize: number; + private readonly outputFontSize: number; + private currentArgs: FunctionArgs = []; public constructor(props?: FunctionBoxProps) { @@ -91,7 +64,7 @@ export class FunctionBox extends Node { } else { this.source = props?.source ?? `(x: number): number => x + 2`; - const functionCode = ts.transpile(this.source); + const functionCode = transpile(this.source); this.function = eval(functionCode); } @@ -103,6 +76,9 @@ export class FunctionBox extends Node { this.isChild = props?.isChild ?? false; + this.outputFontSize = props?.outputFontSize ?? 30; + this.inputFontSize = props?.inputFontSize ?? 30; + this.add( <Rect opacity={this.opacity} @@ -115,6 +91,7 @@ export class FunctionBox extends Node { <Rect direction={"row"} alignItems={"center"} gap={10}> <Rect direction={"row"} + fontSize={this.inputFontSize} ref={makeRef(this.inputs, i)} justifyContent={"end"} opacity={1} @@ -141,11 +118,19 @@ export class FunctionBox extends Node { padding={60} direction={"row"} height={"100%"} - gap={40} > <Txt fontFamily={theme.font} fill={theme.text.hex} ref={this.boxMoji}> {this.idlingText} </Txt> + <Node ref={this.node} opacity={0}> + <CodeBlock + fontFamily={theme.font} + language="typescript" + ref={this.block} + fontSize={0} + code={this.source} + ></CodeBlock> + </Node> </Rect> <Rect direction={"column"} height={"100%"} alignItems={"end"}> @@ -163,6 +148,7 @@ export class FunctionBox extends Node { ref={this.output} justifyContent={"end"} opacity={1} + fontSize={this.outputFontSize} ></Rect> </Rect> </Rect> @@ -173,22 +159,25 @@ export class FunctionBox extends Node { public *resetInput(duration: number) { yield* all( ...this.inputs.map((x) => - all( - x.opacity(0, duration), - x.height(0, duration), - x.width(0, duration), - ), + all(x.opacity(0, duration), x.fontSize(0, duration)), + ), + ...this.inputSegments.map((segment) => + all(segment.points([], duration), segment.opacity(1, duration)), ), - ...this.inputSegments.map((segment) => segment.points([], duration)), ); + + this.inputs.forEach((x) => x.removeChildren()); } public *resetOutput(duration: number) { yield* all( this.output().opacity(0, duration), + this.output().fontSize(0, duration), this.outputSegment().points([], duration), + this.outputSegment().opacity(0, duration), ); - yield this.output().removeChildren(); + + this.output().removeChildren(); } public *reset(duration: number) { @@ -204,7 +193,7 @@ export class FunctionBox extends Node { input.removeChildren(); input.add( args[i].node ?? ( - <Txt fontFamily={theme.font} fontSize={30} fill={theme.text.hex}> + <Txt fontFamily={theme.font} fill={theme.text.hex}> {args[i].val.toString()} </Txt> ), @@ -222,68 +211,99 @@ export class FunctionBox extends Node { ), ...this.inputs.map((input) => all( - input.height(40, duration), - input.width(40, duration), input.opacity(1, duration), + input.fontSize(this.inputFontSize, duration), ), ), ); } public *propogateInput(duration: number) { - const opacityChangeDuration = 0.1; - yield* all( ...this.inputSegments.map((segment) => - segment.opacity(0.2, opacityChangeDuration), + all(segment.opacity(0.2, duration), segment.points([], duration)), ), ); - yield* all( - ...this.inputSegments.map((segment) => segment.points([], duration)), - ); - - yield* all( - ...this.inputSegments.map((segment) => - segment.opacity(1, opacityChangeDuration), - ), - ...this.inputs.map((input) => input.opacity(0, opacityChangeDuration)), + this.resetInput(duration), this.boxMoji().text(this.workingText, duration), ); } public *propogateOutput(duration: number) { + yield* all( + this.boxMoji().text(this.idlingText, duration), + this.child()?.opacity(0.2, duration), + this.output().opacity(0.2, duration), + this.outputSegment().opacity(0, duration), + ); + const output = this.function(...this.currentArgs.map((input) => input.val)); - if (typeof output === "function") { - this.output().add( - <FunctionBox - opacity={0} - isChild={true} - ref={this.child} - fn={output} - ></FunctionBox>, - ); - } else { - this.output().add( - <Txt fontFamily={theme.font} fontSize={30} fill={theme.text.hex}> - {output.toString()} - </Txt>, - ); - } - yield* this.boxMoji().text(this.idlingText, duration); + switch (typeof output) { + case "function": + yield this.output().add( + <FunctionBox + opacity={0} + isChild={true} + ref={this.child} + fn={output} + ></FunctionBox>, + ); + break; + case "number": + case "string": + yield this.output().add( + <Txt fontFamily={theme.font} fill={theme.text.hex}> + {output.toString()} + </Txt>, + ); + break; + default: + yield this.output().add( + <CodeBlock + fontFamily={theme.font} + language="typescript" + fontSize={15} + code={JSON.stringify(output, null, 2)} + ></CodeBlock>, + ); + } yield* all( this.outputSegment().points( [ - { x: -this.delta, y: 0 }, + { x: 0, y: 0 }, { x: this.padding, y: 0 }, ], duration, ), + this.outputSegment().opacity(1, duration), + this.output().fontSize(this.outputFontSize, duration), this.child()?.opacity(1, duration), this.output().opacity(1, duration), - this.outputSegment().opacity(1, duration), ); } + + public *showCode(duration: number) { + yield* all( + this.boxMoji().text("", duration), + this.boxMoji().opacity(0, duration), + this.block().fontSize(30, duration), + this.node().opacity(1, duration), + ); + } + + public *hideCode(duration: number) { + yield* this.boxMoji().text(this.idlingText, 0); + yield* all( + this.block().fontSize(0, duration), + this.node().opacity(0, duration), + this.boxMoji().opacity(1, duration), + ); + } + + public getChild() { + return this.child; + } } diff --git a/src/project.meta b/src/project.meta index 9093235..7c59eb3 100644 --- a/src/project.meta +++ b/src/project.meta @@ -25,7 +25,7 @@ "options": { "fileType": "image/png", "quality": 100, - "groupByScene": false + "groupByScene": true } } } diff --git a/src/scenes/first_box.tsx b/src/scenes/first_box.tsx index b3957af..31ee631 100644 --- a/src/scenes/first_box.tsx +++ b/src/scenes/first_box.tsx @@ -4,8 +4,6 @@ import { beginSlide, createRef, slideTransition, - all, - waitFor, } from "@motion-canvas/core"; import { FunctionBox } from "../components/function_box"; @@ -23,14 +21,15 @@ export default makeScene2D(function* (view) { yield* beginSlide("Black Box"); - for (const [a, b] of [ - [-1, 2], + for (const [[a, b], i] of [ + [1, 2], [3, 4], - [5, 6], - ] as [number, number][]) { - const inputId = "(" + [a, b].join(",") + ")"; + [1, 2], + [1, 2], + ].map((x, i) => [x, i]) as [[number, number], number][]) { + const inputId = "(" + [a, b, i].join(",") + ")"; - yield* all(functionBox().reset(0.25)); + yield* functionBox().reset(0.5); yield* functionBox().setInputs([{ val: a }, { val: b }], 0.5); yield* beginSlide("Add Inputs " + inputId); @@ -41,4 +40,12 @@ export default makeScene2D(function* (view) { yield* functionBox().propogateOutput(0.5); yield* beginSlide("Propogate Outputs of " + inputId); } + + yield* functionBox().reset(0.5); + + yield* functionBox().showCode(0.85); + yield* beginSlide("Show Code"); + + yield* functionBox().hideCode(0.85); + yield* beginSlide("Hide Code"); }); diff --git a/src/scenes/hungry_partner.meta b/src/scenes/hungry_partner.meta new file mode 100644 index 0000000..cec20cc --- /dev/null +++ b/src/scenes/hungry_partner.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 3141613664 +}
\ No newline at end of file diff --git a/src/scenes/hungry_partner.tsx b/src/scenes/hungry_partner.tsx new file mode 100644 index 0000000..696870e --- /dev/null +++ b/src/scenes/hungry_partner.tsx @@ -0,0 +1,108 @@ +import { Node, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; + +import { FunctionBox } from "../components/function_box"; +import { theme } from "../theme"; + +const hungryValentine = `( + savoryCravingRatio: number, sweetCravingRatio: number, + acidityCravingRatio: number, spiceCravingRatio: number, +): string => { + const foods = { + "🍕": {savory: 0.8, sweet: 0.1, acidity: 0.5, spice: 0.5}, + "🧁": {savory: 0.2, sweet: 0.9, acidity: 0.1, spice: 0.1}, + "🍋🍰": {savory: 0.1, sweet: 0.8, acidity: 0.9, spice: 0.1}, + "🌮🔥": {savory: 0.6, sweet: 0.2, acidity: 0.5, spice: 0.8}, + }; + + const weight = (foodProfile: Record<string, number>) => + foodProfile["savory"] * savoryCravingRatio + + foodProfile["sweet"] * sweetCravingRatio + + foodProfile["acidity"] * acidityCravingRatio + + foodProfile["spice"] * spiceCravingRatio; + + const bestFood = Object.keys(foods).reduce((a, b) => + weight(foods[a]) > weight(foods[b]) ? a : b + ); + + const foodNames = Array.from(Object.keys(foods)); + const shouldChooseRandom = Math.random() > 0.4; // side effect + return shouldChooseRandom + ? foodNames[Math.floor(Math.random() * foodNames.length)] + : bestFood; +};`; + +export default makeScene2D(function* (view) { + const functionBox = createRef<FunctionBox>(); + + view.add( + <FunctionBox + arity={4} + idlingText={"😴"} + workingText={"😋💭"} + source={hungryValentine} + ref={functionBox} + />, + ); + + yield* slideTransition(Direction.Right); + + yield* beginSlide("Get Best Food For Partner"); + + const order = ["savory", "sweet", "acidic", "spice"]; + + for (const [[a, b, c, d], i] of [ + [0.7, 0.1, 0.4, 0.1], + [0.7, 0.1, 0.4, 0.1], + [0.7, 0.1, 0.4, 0.1], + [0.7, 0.1, 0.4, 0.1], + ].map((x, i) => [x, i]) as [[number, number, number, number], number][]) { + const inputId = "(" + [a, b, c, d, i].join(",") + ")"; + + yield* functionBox().reset(0.5); + yield* functionBox().setInputs( + [a, b, c, d].map((ratio, i) => ({ + val: ratio, + node: ( + <Txt fontFamily={theme.font} fill={theme.text.hex}> + {order[i]}:{" "} + <Txt + fontFamily={theme.font} + fill={ + ratio > 0.6 + ? theme.red.hex + : ratio < 0.3 + ? theme.green.hex + : theme.lavender.hex + } + > + {ratio.toString()} + </Txt> + </Txt> + ), + })), + 0.5, + ); + + yield* beginSlide("Add Inputs " + inputId); + + yield* functionBox().propogateInput(0.5); + yield* beginSlide("Propogate Inputs " + inputId); + + yield* functionBox().propogateOutput(0.5); + yield* beginSlide("Propogate Outputs of " + inputId); + } + + yield* functionBox().reset(0.5); + + yield* functionBox().showCode(0.85); + yield* beginSlide("Show Code"); + + yield* functionBox().hideCode(0.85); + yield* beginSlide("Hide Code"); +}); diff --git a/src/scenes/index.ts b/src/scenes/index.ts index 56fda2b..d21da3b 100644 --- a/src/scenes/index.ts +++ b/src/scenes/index.ts @@ -4,12 +4,14 @@ import partone from "./partone?scene"; import flirtingwithfunctions from "./flirtingwithfunctions?scene"; import doctor from "./doctor?scene"; import first_box from "./first_box?scene"; +import hungry_partner from "./hungry_partner?scene"; export const scenes = [ - title, - me, - partone, - flirtingwithfunctions, - doctor, - first_box, + // title, + // me, + // partone, + // flirtingwithfunctions, + // doctor, + // first_box, + hungry_partner, ]; |