ref: 86a1bffad7063d1f51dfe44c2126bbdf8b7fe5c8
dir: /scratch.js/
import {toNumber, toString, Dispatcher} from "./compile.js" import {MakeBlock, setInput} from "./model.js" import {Stop, library as library0, NumberSlot, PositiveSlot} from "./core.js" let operatorOptions = [] function Operator(label, fn) { let make = MakeBlock({run: value => fn(toNumber(value)), name: value => [{options: operatorOptions}, "of", value], category: "operators", shape: "reporter", slots: [NumberSlot], output: "number"}) operatorOptions.push({label, morph, type: make.type}) return make function morph(block) { let block1 = make() setInput(block1, 0, block.inputs[0]) return block1 } } function toRadians(n) { return Math.PI / 180 * n } function fromRadians(n) { return 180 / Math.PI * n } export let Round = MakeBlock({run: value => Math.round(toNumber(value)), name: value => ["round", value], category: "operators", shape: "reporter", slots: [NumberSlot], output: "number"}) export let Abs = Operator("abs", Math.abs) export let Ceiling = Operator("ceiling", Math.ceil) export let Floor = Operator("floor", Math.floor) export let Sqrt = Operator("sqrt", Math.sqrt) export let Sin = Operator("sin", n => Math.sin(toRadians(n))) export let Cos = Operator("cos", n => Math.cos(toRadians(n))) export let Tan = Operator("tan", n => Math.tan(toRadians(n))) export let ArcSin = Operator("asin", n => fromRadians(Math.asin(n))) export let ArcCos = Operator("acos", n => fromRadians(Math.acos(n))) export let ArcTan = Operator("atan", n => fromRadians(Math.atan(n))) export let Ln = Operator("ln", Math.log) export let Log = Operator("log", Math.log10) export let Exp = Operator("e ^", Math.exp) export let Exp10 = Operator("10 ^", n => 10 ** n) export let PickRandom = MakeBlock({run: random, name: (a, b) => ["pick random", a, "to", b], category: "operators", shape: "reporter", slots: [NumberSlot, NumberSlot], defaults: [1, 10]}) export let Wait = MakeBlock({async: true, run: value => new Promise(resolve => setTimeout(resolve, toNumber(value) * 1000)), name: seconds => ["wait", seconds, "seconds"], category: "control", slots: [PositiveSlot], defaults: [1]}) export let DaysSince2000 = MakeBlock({run: () => Date.now() / 86400 / 1000 - 10957, name: () => ["days since 2000"], category: "sensing", shape: "reporter"}) function random(a, b) { let an = toNumber(a) let bn = toNumber(b) if (isFractional(toString(a)) || isFractional(toString(b))) { return Math.random() * (bn - an) + an } if (an > bn) [an, bn] = [bn, an] return Math.floor(Math.random() * (bn - an + 1) + an) } function isFractional(v) { return v.includes(".") || v.includes("e-") } export function Scratch(options = {}) { let dispatcher = options.dispatcher ?? new Dispatcher(options.tick) let date = new Date() let time0 = performance.now() let time1 = time0 options.onBeforeTick(() => { time1 = performance.now() date = new Date() }) let dateOptions = [] function DatePart(label, fn) { let make = MakeBlock({run: () => fn(), name: () => ["current", {options: dateOptions}], category: "sensing", shape: "reporter", output: "number"}) dateOptions.push({label, morph: () => make(), type: make.type}) return make } let Timer = MakeBlock({run: () => (time1 - time0) / 1000, name: () => ["timer"], category: "sensing", shape: "reporter", output: "number"}) let ResetTimer = MakeBlock({run: () => time1 = time0 = performance.now(), name: () => ["reset timer"], category: "sensing"}) let Username = MakeBlock({run: () => options.username ?? "zamfofex", name: () => ["username"], category: "sensing", shape: "reporter", output: "text"}) let Year = DatePart("year", () => date.getFullYear()) let Month = DatePart("month", () => date.getMonth() + 1) let Day = DatePart("date", () => date.getDate()) let DayOfWeek = DatePart("day of week", () => date.getDay() + 1) let Hour = DatePart("hour", () => date.getHours()) let Minute = DatePart("minute", () => date.getMinutes()) let Second = DatePart("second", () => date.getSeconds()) let other = options.other ?? (id => dispatcher.all().filter(id1 => id1 !== id)) let StopAll = MakeBlock({run: () => dispatcher.stop(), name: (...args) => getName(StopAll.type, ...args), category: "control", cap: true}) let StopOther = MakeBlock({run: ({id}) => dispatcher.stop(other(id)), name: (...args) => getName(StopOther.type, ...args), category: "control"}) let getName = NameFunction({StopAll, StopOther}) let blocks = {Wait, Round, PickRandom, Timer, ResetTimer, Username, DaysSince2000, Abs, Year} let library = [...library0, ...Object.values(blocks)] return { ...blocks, Abs, Ceiling, Floor, Sqrt, Sin, Cos, Tan, ArcSin, ArcCos, ArcTan, Ln, Log, Exp, Exp10, Year, Month, Day, DayOfWeek, Hour, Minute, Second, StopAll, StopOther, library, dispatcher, getName, } } let NameFunction = ({StopOther, StopAll}) => { let name = ["stop", { options: [ {label: "this script", morph: () => Stop(), type: Stop.type}, {label: "other scripts in sprite", morph: () => StopOther(), type: StopOther.type}, {label: "all", morph: () => StopAll(), type: StopAll.type}, ] }] function getName(type) { if (type !== Stop.type && type !== StopAll.type && type !== StopOther.type) return return name } return getName }