diff --git a/src/Plant/Microwave/Microwave.css b/src/Plant/Microwave/Microwave.css new file mode 100644 index 0000000..907b531 --- /dev/null +++ b/src/Plant/Microwave/Microwave.css @@ -0,0 +1,14 @@ +rect.microwaveButtonHelper { + fill-opacity: 0; +} + +rect.microwaveButtonHelper:hover { + fill: rgba(46, 211, 197); + fill-opacity: 0.5; +} + +rect.microwaveButtonHelper:active { + /* fill: rgba(47, 0, 255); */ + fill: red; + fill-opacity: 0.5; +} diff --git a/src/Plant/Microwave/Microwave.tsx b/src/Plant/Microwave/Microwave.tsx new file mode 100644 index 0000000..458eb37 --- /dev/null +++ b/src/Plant/Microwave/Microwave.tsx @@ -0,0 +1,183 @@ +import { preload } from "react-dom"; +import imgSmallClosedOff from "./small_closed_off.png"; +import imgSmallClosedOn from "./small_closed_on.png"; +import imgSmallOpenedOff from "./small_opened_off.png"; +import imgSmallOpenedOn from "./small_opened_off.png"; + +import fontDigital from "../DigitalWatch/digital-font.ttf"; + +import sndBell from "./bell.wav"; +import sndRunning from "./running.wav"; +import { Plant } from "../Plant"; +import { RaisedEvent } from "@/statecharts/runtime_types"; +import { useEffect, useState } from "react"; + +import "./Microwave.css"; + +export type MagnetronState = "on" | "off"; +export type DoorState = "open" | "closed"; + +export function toggleDoor(d: DoorState) { + if (d === "open") { + return "closed"; + } + else return "open"; +} + +export function toggleMagnetron(m: MagnetronState) { + if (m === "on") { + return "off"; + } + return "on"; +} + +export type MicrowaveState = { + // Note: the door state is not part of the MicrowaveState because it is not controlled by the statechart, but by the plant. + timeDisplay: number, + bell: boolean, // whether the bell should ring + magnetron: MagnetronState, +} + +export type MicrowaveProps = { + state: MicrowaveState, + callbacks: { + startPressed: () => void; + stopPressed: () => void; + incTimePressed: () => void; + incTimeReleased: () => void; + doorOpened: () => void; + doorClosed: () => void; + } +} + +const imgs = { + closed: { off: imgSmallClosedOff, on: imgSmallClosedOn }, + open: { off: imgSmallOpenedOff, on: imgSmallOpenedOn }, +} + + +const BUTTON_HEIGHT = 18; +const BUTTON_WIDTH = 60; + +const BUTTON_X0 = 412; +const BUTTON_X1 = BUTTON_X0 + BUTTON_WIDTH; + +const START_X0 = BUTTON_X0; +const START_Y0 = 234; +const START_X1 = BUTTON_X1; +const START_Y1 = START_Y0 + BUTTON_HEIGHT; + +const STOP_X0 = BUTTON_X0; +const STOP_Y0 = 211; +const STOP_X1 = BUTTON_X1; +const STOP_Y1 = STOP_Y0 + BUTTON_HEIGHT; + +const INCTIME_X0 = BUTTON_X0; +const INCTIME_Y0 = 188; +const INCTIME_X1 = BUTTON_X1; +const INCTIME_Y1 = INCTIME_Y0 + BUTTON_HEIGHT; + +const DOOR_X0 = 26; +const DOOR_Y0 = 68; +const DOOR_WIDTH = 353; +const DOOR_HEIGHT = 217; + + +export function Magnetron({state: {timeDisplay, bell, magnetron}, callbacks}: MicrowaveProps) { + const [door, setDoor] = useState("closed"); + const [playBell, setPlayBell] = useState(false); + + // a bit hacky: when the bell-state changes to true, we play the bell sound for 610 ms... + useEffect(() => { + let timeout: NodeJS.Timeout; + if (bell) { + setPlayBell(true); + timeout = setTimeout(() => { + setPlayBell(false); + }, 610); + } + return () => { if (timeout) clearTimeout(timeout); }; + }, [bell]); + + preload(imgSmallClosedOff, {as: "image"}); + preload(imgSmallClosedOn, {as: "image"}); + preload(imgSmallOpenedOff, {as: "image"}); + preload(imgSmallOpenedOn, {as: "image"}); + preload(sndBell, {as: "audio"}); + preload(sndRunning, {as: "audio"}); + + const openDoor = () => { + setDoor("open"); + callbacks.doorOpened(); + } + const closeDoor = () => { + setDoor("closed"); + callbacks.doorClosed(); + } + + return <> + + + + + callbacks.startPressed()} + /> + callbacks.stopPressed()} + /> + callbacks.incTimePressed()} + onMouseUp={() => callbacks.incTimeReleased()} + /> + door === "open" ? closeDoor() : openDoor()} + /> + + {timeDisplay} + + + {magnetron === "on" && } + + {playBell && } + ; +} + +export const MicrowavePlant: Plant = { + inputEvents: [], + outputEvents: [], + initial: { + timeDisplay: 0, + magnetron: "off", + bell: false, + }, + reduce: (inputEvent: RaisedEvent, state: MicrowaveState) => { + if (inputEvent.name === "setMagnetron") { + return { ...state, magnetron: inputEvent.param, bell: false }; + } + if (inputEvent.name === "setTimeDisplay") { + return { ...state, timeDisplay: inputEvent.param, bell: false }; + } + if (inputEvent.name === "ringBell") { + return { ...state, bell: true }; + } + return state; // unknown event - ignore it + }, + render: (state, raiseEvent) => raiseEvent({name: "startPressed"}), + stopPressed: () => raiseEvent({name: "stopPressed"}), + incTimePressed: () => raiseEvent({name: "incTimePressed"}), + incTimeReleased: () => raiseEvent({name: "incTimeReleased"}), + doorOpened: () => raiseEvent({name: "door", param: "open"}), + doorClosed: () => raiseEvent({name: "door", param: "closed"}), + }}/>, +} diff --git a/src/Plant/Microwave/bell.wav b/src/Plant/Microwave/bell.wav new file mode 100644 index 0000000..3fe70fa Binary files /dev/null and b/src/Plant/Microwave/bell.wav differ diff --git a/src/Plant/Microwave/running.wav b/src/Plant/Microwave/running.wav new file mode 100644 index 0000000..ca35830 Binary files /dev/null and b/src/Plant/Microwave/running.wav differ diff --git a/src/Plant/Microwave/small_closed_off.png b/src/Plant/Microwave/small_closed_off.png new file mode 100644 index 0000000..3280c99 Binary files /dev/null and b/src/Plant/Microwave/small_closed_off.png differ diff --git a/src/Plant/Microwave/small_closed_on.png b/src/Plant/Microwave/small_closed_on.png new file mode 100644 index 0000000..793166f Binary files /dev/null and b/src/Plant/Microwave/small_closed_on.png differ diff --git a/src/Plant/Microwave/small_opened_off.png b/src/Plant/Microwave/small_opened_off.png new file mode 100644 index 0000000..7c829f0 Binary files /dev/null and b/src/Plant/Microwave/small_opened_off.png differ diff --git a/src/Plant/Microwave/small_opened_on.png b/src/Plant/Microwave/small_opened_on.png new file mode 100644 index 0000000..6f8708a Binary files /dev/null and b/src/Plant/Microwave/small_opened_on.png differ