@empirica/core
Version:
Empirica Core
748 lines (737 loc) • 26.4 kB
JavaScript
import {
Consent,
Finished,
Loading,
NoGames,
PlayerCreate,
useConsent,
useGlobal,
usePartConnected,
useParticipantContext,
usePlayerID,
useTajribaConnected
} from "./chunk-UMPSA52E.js";
import {
error,
warn
} from "./chunk-TIKLWCJI.js";
// src/player/classic/react/EmpiricaContext.tsx
import React3 from "react";
// src/player/classic/react/Lobby.tsx
import React from "react";
// src/player/classic/react/hooks.ts
import { useEffect, useRef, useState } from "react";
function usePlayer() {
return usePartModeCtxKey(
"player"
);
}
function useGame() {
return usePartModeCtxKey("game");
}
function useRound() {
return usePartModeCtxKey(
"round"
);
}
function useStage() {
return usePartModeCtxKey(
"stage"
);
}
function useStageTimer() {
const stage = useStage();
const [val, setVal] = useState({
tick: stage?.timer?.current
});
const timerSubscription = useRef(null);
useEffect(() => {
if (!stage || !stage.timer) {
return;
}
if (timerSubscription.current === null) {
timerSubscription.current = stage.timer.obs().subscribe({
next(val2) {
setVal({ tick: val2 });
}
});
}
return () => {
timerSubscription?.current?.unsubscribe.bind(timerSubscription.current);
timerSubscription.current = null;
};
}, [stage?.timer]);
return val.tick;
}
function usePlayers() {
return usePartModeCtxKey(
"players"
);
}
function usePartModeCtx() {
const ctx = useParticipantContext();
const [mode, setMode] = useState({
data: ctx?.mode?.getValue()
});
useEffect(() => {
if (!ctx || !ctx.mode) {
return;
}
const sub = ctx.mode.subscribe({
next(m) {
setMode({ data: m });
}
});
return sub.unsubscribe.bind(sub);
}, [ctx]);
return mode.data;
}
function usePartModeCtxKey(name) {
const mode = usePartModeCtx();
const iniVal = mode && mode[name];
const [val, setVal] = useState({
data: iniVal?.getValue()
});
useEffect(() => {
if (!mode) {
return;
}
const obs = mode[name];
const sub = obs.subscribe({
next(val2) {
setVal({ data: val2 });
}
});
return sub.unsubscribe.bind(sub);
}, [mode]);
return val.data;
}
// src/player/classic/react/Lobby.tsx
function Lobby() {
const player = usePlayer();
if (!player) {
return /* @__PURE__ */ React.createElement(Loading, null);
}
const treatment = player.get("treatment");
if (!treatment || !treatment.playerCount) {
warn("lobby: no treatment found on player");
return /* @__PURE__ */ React.createElement(Loading, null);
}
return /* @__PURE__ */ React.createElement("div", { className: "flex h-full items-center justify-center" }, /* @__PURE__ */ React.createElement("div", { className: "text-center" }, /* @__PURE__ */ React.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 640 512",
className: "mx-auto h-12 w-12 text-gray-400",
stroke: "none",
fill: "currentColor",
"aria-hidden": "true"
},
/* @__PURE__ */ React.createElement("path", { d: "M544 224c44.2 0 80-35.8 80-80s-35.8-80-80-80-80 35.8-80 80 35.8 80 80 80zm0-128c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM320 256c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm0-192c44.1 0 80 35.9 80 80s-35.9 80-80 80-80-35.9-80-80 35.9-80 80-80zm244 192h-40c-15.2 0-29.3 4.8-41.1 12.9 9.4 6.4 17.9 13.9 25.4 22.4 4.9-2.1 10.2-3.3 15.7-3.3h40c24.2 0 44 21.5 44 48 0 8.8 7.2 16 16 16s16-7.2 16-16c0-44.1-34.1-80-76-80zM96 224c44.2 0 80-35.8 80-80s-35.8-80-80-80-80 35.8-80 80 35.8 80 80 80zm0-128c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zm304.1 180c-33.4 0-41.7 12-80.1 12-38.4 0-46.7-12-80.1-12-36.3 0-71.6 16.2-92.3 46.9-12.4 18.4-19.6 40.5-19.6 64.3V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-44.8c0-23.8-7.2-45.9-19.6-64.3-20.7-30.7-56-46.9-92.3-46.9zM480 432c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16v-44.8c0-16.6 4.9-32.7 14.1-46.4 13.8-20.5 38.4-32.8 65.7-32.8 27.4 0 37.2 12 80.2 12s52.8-12 80.1-12c27.3 0 51.9 12.3 65.7 32.8 9.2 13.7 14.1 29.8 14.1 46.4V432zM157.1 268.9c-11.9-8.1-26-12.9-41.1-12.9H76c-41.9 0-76 35.9-76 80 0 8.8 7.2 16 16 16s16-7.2 16-16c0-26.5 19.8-48 44-48h40c5.5 0 10.8 1.2 15.7 3.3 7.5-8.5 16.1-16 25.4-22.4z" })
), /* @__PURE__ */ React.createElement("h3", { className: "mt-2 text-sm font-medium text-gray-900" }, treatment.playerCount > 1 ? "Waiting for other players" : "Game loading"), /* @__PURE__ */ React.createElement("p", { className: "mt-1 text-sm text-gray-500" }, "Please wait for the game to be ready.")));
}
// src/player/classic/react/Steps.tsx
import React2, { useEffect as useEffect2, useState as useState2 } from "react";
function Steps({
steps,
progressKey,
doneKey,
object,
children
}) {
let obj;
const game = useGame();
const player = usePlayer();
const [stps, setStps] = useState2([]);
const [stpsSet, setStpsSet] = useState2(false);
useEffect2(() => {
let s;
if (typeof steps === "function") {
s = steps({ game, player });
} else {
s = steps;
}
setStps(s);
setStpsSet(true);
}, [steps]);
useEffect2(() => {
if (obj && !obj.get(doneKey) && stpsSet && (!stps || stps.length === 0)) {
obj.set(doneKey, true);
}
}, [stps]);
if (object) {
obj = object;
} else if (player) {
obj = player;
} else {
error("no receiver and no player in Steps");
return /* @__PURE__ */ React2.createElement("div", null, "Missing attribute");
}
if (obj.get(doneKey)) {
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, children);
}
const index = obj.get(progressKey) || 0;
const next = () => {
if (index + 1 >= stps.length) {
obj.set(doneKey, true);
} else {
obj.set(progressKey, index + 1);
}
};
const previous = () => {
if (index > 0) {
obj.set(progressKey, index - 1);
}
};
const Step2 = stps[index];
if (!Step2) {
return /* @__PURE__ */ React2.createElement(React2.Fragment, null);
}
return /* @__PURE__ */ React2.createElement(Step2, { index, previous, next });
}
// src/player/classic/react/EmpiricaContext.tsx
function EmpiricaContext({
noGames: NoGamesComp = NoGames,
consent: ConsentComp = Consent,
playerCreate: PlayerCreateForm = PlayerCreate,
introSteps = [],
lobby = Lobby,
exitSteps = [],
finished = Finished,
loading: LoadingComp = Loading,
connecting: ConnectingComp = Loading,
unmanagedGame = false,
unmanagedAssignment = false,
disableConsent = false,
disableNoGames = false,
disableURLParamsCapture = false,
children
}) {
const tajribaConnected = useTajribaConnected();
const participantConnected = usePartConnected();
const globals = useGlobal();
const player = usePlayer();
const game = useGame();
const [connecting, hasPlayer, onPlayerID] = usePlayerID();
const [consented, onConsent] = useConsent();
if (!tajribaConnected || connecting) {
return /* @__PURE__ */ React3.createElement(ConnectingComp, null);
}
if (player && player.get("ended")) {
return /* @__PURE__ */ React3.createElement(Exit, { exitSteps, finished });
}
if (!globals || hasPlayer && (!participantConnected || !player || game === void 0)) {
return /* @__PURE__ */ React3.createElement(LoadingComp, null);
}
if (!disableNoGames && !globals.get("experimentOpen") && (!hasPlayer || !player?.get("gameID"))) {
return /* @__PURE__ */ React3.createElement(NoGamesComp, null);
}
if (!disableConsent && !consented) {
return /* @__PURE__ */ React3.createElement(ConsentComp, { onConsent });
}
if (!hasPlayer) {
return /* @__PURE__ */ React3.createElement(PlayerCreateForm, { onPlayerID, connecting });
}
if (!player || !unmanagedGame && !game) {
return /* @__PURE__ */ React3.createElement(LoadingComp, null);
}
if (!disableURLParamsCapture && !player.get("urlParams")) {
const urlParams = new URLSearchParams(window.location.search);
player.set("urlParams", Object.fromEntries(urlParams.entries()));
}
if (unmanagedAssignment) {
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, children);
}
if (game && game.hasEnded) {
if (!player.get("ended")) {
return /* @__PURE__ */ React3.createElement(LoadingComp, null);
}
return /* @__PURE__ */ React3.createElement(Exit, { exitSteps, finished });
}
return /* @__PURE__ */ React3.createElement(Steps, { progressKey: "intro", doneKey: "introDone", steps: introSteps }, /* @__PURE__ */ React3.createElement(
EmpiricaInnerContext,
{
exitSteps,
lobby,
finished,
loading: LoadingComp,
unmanagedGame
},
children
));
}
function EmpiricaInnerContext({
children,
lobby: Lobby2,
finished,
exitSteps,
loading: LoadingComp,
unmanagedGame = false
}) {
const player = usePlayer();
const game = useGame();
const allReady = useAllReady();
if (!game) {
if (unmanagedGame) {
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, children);
} else {
return /* @__PURE__ */ React3.createElement(LoadingComp, null);
}
}
if (!Boolean(game.get("status"))) {
return /* @__PURE__ */ React3.createElement(Lobby2, null);
}
if (game.hasEnded) {
if (!player?.get("ended")) {
return /* @__PURE__ */ React3.createElement(LoadingComp, null);
}
return /* @__PURE__ */ React3.createElement(Exit, { exitSteps, finished });
}
if (unmanagedGame || allReady) {
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, children);
}
return /* @__PURE__ */ React3.createElement(LoadingComp, null);
}
function Exit({
exitSteps,
finished: Finished2
}) {
const gameReady = useGameReady();
if (!gameReady) {
return /* @__PURE__ */ React3.createElement(Loading, null);
}
return /* @__PURE__ */ React3.createElement(Steps, { progressKey: "exitStep", doneKey: "exitStepDone", steps: exitSteps }, /* @__PURE__ */ React3.createElement(Finished2, null));
}
function useAllReady() {
const player = usePlayer();
const players = usePlayers();
const game = useGame();
const stage = useStage();
const round = useRound();
if (!player || !players || !stage || !round || !game || !player.game || !player.round || !player.stage) {
return false;
}
const playerCount = game.get("actualPlayerCount");
if (playerCount !== void 0 && players.length < playerCount) {
return false;
}
for (const p of players) {
if (!p.game || !p.round || !p.stage) {
return false;
}
}
return true;
}
function useGameReady() {
const player = usePlayer();
const players = usePlayers();
const game = useGame();
if (player && !player.get("gameID")) {
return true;
}
if (player && game && !game.get("start")) {
return true;
}
if (!player || !players || !game || !player.game) {
return false;
}
const playerCount = game.get("actualPlayerCount");
if (playerCount !== void 0 && players.length < playerCount) {
return false;
}
for (const p of players) {
if (!p.game) {
return false;
}
}
return true;
}
// src/player/classic/react/Quiz.tsx
import React4, { useState as useState3 } from "react";
function Quiz({ next }) {
const labelClassName = "block text-sm font-medium text-gray-700 mb-2";
const inputClassName = "appearance-none block px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-empirica-500 focus:border-empirica-500 sm:text-sm";
const [sum, setSum] = useState3("");
const [horse, setHorse] = useState3("");
function handleSubmit(e) {
e.preventDefault();
if (sum !== "4" || horse !== "white") {
alert("Incorrect! Read the instructions and please try again.");
} else {
next();
}
}
return /* @__PURE__ */ React4.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ React4.createElement("div", { className: "mt-6 sm:mt-24" }, /* @__PURE__ */ React4.createElement("h3", { className: "text-2xl font-semi-bold text-gray-900" }, "Quiz"), /* @__PURE__ */ React4.createElement("form", { className: "mt-4", onSubmit: handleSubmit }, /* @__PURE__ */ React4.createElement("p", { className: "mb-5" }, /* @__PURE__ */ React4.createElement("label", { className: labelClassName }, "What is 2+2?"), /* @__PURE__ */ React4.createElement(
"input",
{
className: inputClassName,
type: "text",
dir: "auto",
id: "sum",
name: "sum",
placeholder: "e.g. 3",
value: sum,
onChange: (e) => setSum(e.target.value),
autoComplete: "off",
autoFocus: true,
required: true
}
)), /* @__PURE__ */ React4.createElement("p", { className: "mb-5" }, /* @__PURE__ */ React4.createElement("label", { className: labelClassName }, "What color was Napoleon's white horse?"), /* @__PURE__ */ React4.createElement(
"input",
{
className: inputClassName,
type: "text",
dir: "auto",
id: "horse",
name: "horse",
placeholder: "brown",
value: horse,
onChange: (e) => setHorse(e.target.value),
autoComplete: "off",
required: true
}
)), /* @__PURE__ */ React4.createElement(
"button",
{
type: "submit",
className: "inline-flex items-center px-4 py-2 border text-sm font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-empirica-500"
},
"Submit"
))));
}
// src/player/classic/react/Slider.tsx
import React5, { useRef as useRef2 } from "react";
function Slider({
value,
onChange,
min = 0,
max = 100,
stepSize = 1,
disabled = false
}) {
const noVal = value === null || value === void 0;
const val = noVal ? (max - min) / 2 : value;
const cls = noVal ? "slider-thumb-zero" : "slider-thumb";
const ref = useRef2(null);
if (value !== null && ref.current) {
const nmin = min ? min : 0;
const nmax = max ? max : 100;
const newVal = Number((value - nmin) * 100 / (nmax - nmin));
ref.current.style.left = `calc(${newVal}% + (${8 - newVal * 0.15}px))`;
}
return /* @__PURE__ */ React5.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React5.createElement(
"input",
{
className: cls,
type: "range",
min,
max,
step: stepSize,
value: val,
onChange,
disabled
}
), noVal ? "" : /* @__PURE__ */ React5.createElement(
"output",
{
ref,
className: "font-mono absolute w-12 h-7 flex items-center justify-center left-1/2 bottom-7 rounded transform -translate-x-1/2 bg-gray-200"
},
value
));
}
// src/player/classic/react/chat/Chat.tsx
import React6, {
useEffect as useEffect3,
useRef as useRef3,
useState as useState4
} from "react";
function Chat({
scope,
attribute = "messages",
loading: LoadingComp = Loading
}) {
const player = usePlayer();
if (!scope || !player) {
return /* @__PURE__ */ React6.createElement(LoadingComp, null);
}
const handleNewMessage = (text) => {
scope.append(attribute, {
text,
sender: {
id: player.id,
name: player.get("name") || player.id,
avatar: player.get("avatar")
}
});
};
const msgs = scope.getAttribute(attribute)?.items || [];
return /* @__PURE__ */ React6.createElement("div", { className: "h-full w-full flex flex-col" }, /* @__PURE__ */ React6.createElement(Messages, { msgs }), /* @__PURE__ */ React6.createElement(Input, { onNewMessage: handleNewMessage }));
}
function Messages(props) {
const { msgs } = props;
const scroller = useRef3(null);
const [msgCount, setMsgCount] = useState4(0);
useEffect3(() => {
if (!scroller.current) {
return;
}
if (msgCount !== msgs.length) {
setMsgCount(msgs.length);
scroller.current.scrollTop = scroller.current.scrollHeight;
}
}, [scroller, props, msgCount]);
if (msgs.length === 0) {
return /* @__PURE__ */ React6.createElement("div", { className: "h-full w-full flex justify-center items-center" }, /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col justify-center items-center w-2/3 space-y-2" }, /* @__PURE__ */ React6.createElement("div", { className: "w-24 h-24 text-gray-200" }, /* @__PURE__ */ React6.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
className: "h-full w-full fill-current",
viewBox: "0 0 512 512"
},
/* @__PURE__ */ React6.createElement("path", { d: "M123.6 391.3c12.9-9.4 29.6-11.8 44.6-6.4c26.5 9.6 56.2 15.1 87.8 15.1c124.7 0 208-80.5 208-160s-83.3-160-208-160S48 160.5 48 240c0 32 12.4 62.8 35.7 89.2c8.6 9.7 12.8 22.5 11.8 35.5c-1.4 18.1-5.7 34.7-11.3 49.4c17-7.9 31.1-16.7 39.4-22.7zM21.2 431.9c1.8-2.7 3.5-5.4 5.1-8.1c10-16.6 19.5-38.4 21.4-62.9C17.7 326.8 0 285.1 0 240C0 125.1 114.6 32 256 32s256 93.1 256 208s-114.6 208-256 208c-37.1 0-72.3-6.4-104.1-17.9c-11.9 8.7-31.3 20.6-54.3 30.6c-15.1 6.6-32.3 12.6-50.1 16.1c-.8 .2-1.6 .3-2.4 .5c-4.4 .8-8.7 1.5-13.2 1.9c-.2 0-.5 .1-.7 .1c-5.1 .5-10.2 .8-15.3 .8c-6.5 0-12.3-3.9-14.8-9.9c-2.5-6-1.1-12.8 3.4-17.4c4.1-4.2 7.8-8.7 11.3-13.5c1.7-2.3 3.3-4.6 4.8-6.9c.1-.2 .2-.3 .3-.5z" })
)), /* @__PURE__ */ React6.createElement("h4", { className: "text-gray-700 font-semibold" }, "No chat yet"), /* @__PURE__ */ React6.createElement("p", { className: "text-gray-500 text-center" }, "Send a message to start the conversation.")));
}
return /* @__PURE__ */ React6.createElement("div", { className: "h-full overflow-auto pl-2 pr-4 pb-2", ref: scroller }, msgs.map((msg) => /* @__PURE__ */ React6.createElement(MessageComp, { key: msg.id, attribute: msg })));
}
function MessageComp({ attribute }) {
const msg = attribute.value;
const ts = attribute.createdAt;
let avatar = msg.sender.avatar;
if (!avatar) {
avatar = `https://avatars.dicebear.com/api/identicon/${msg.sender.id}.svg`;
}
let avatarImage = /* @__PURE__ */ React6.createElement(
"img",
{
className: "inline-block h-9 w-9 rounded-full",
src: avatar,
alt: msg.sender.id
}
);
if (!avatar.startsWith("http")) {
avatarImage = /* @__PURE__ */ React6.createElement("div", { className: "inline-block h-9 w-9 rounded-full" }, avatar);
}
return /* @__PURE__ */ React6.createElement("div", { className: "flex items-start my-2" }, /* @__PURE__ */ React6.createElement("div", { className: "flex-shrink-0" }, avatarImage), /* @__PURE__ */ React6.createElement("div", { className: "ml-3 text-sm" }, /* @__PURE__ */ React6.createElement("p", null, /* @__PURE__ */ React6.createElement("span", { className: "font-semibold text-gray-900 group-hover:text-gray-800" }, msg.sender.name), /* @__PURE__ */ React6.createElement("span", { className: "pl-2 text-gray-400" }, ts && relTime(ts))), /* @__PURE__ */ React6.createElement("p", { className: "text-gray-900 group-hover:text-gray-800" }, msg.text)));
}
function Input({ onNewMessage }) {
const [text, setText] = useState4("");
const resize = (e) => {
const target = e.target;
target.style.height = "inherit";
target.style.height = `${Math.min(target.scrollHeight, 200)}px`;
};
const handleSubmit = (e) => {
e.preventDefault();
const txt = text.trim();
if (txt === "") {
return;
}
if (txt.length > 1024) {
e.preventDefault();
alert("Max message length is 1024");
return;
}
onNewMessage(txt);
setText("");
};
const handleKeyDown = (e) => {
if (e.key === "Enter" && e.shiftKey === false) {
handleSubmit(e);
resize(e);
}
};
const handleKeyUp = (e) => {
resize(e);
};
return /* @__PURE__ */ React6.createElement(
"form",
{
className: "p-2 flex items-strech gap-2 border-t",
onSubmit: handleSubmit
},
/* @__PURE__ */ React6.createElement(
"textarea",
{
name: "message",
id: "message",
rows: 1,
className: "peer resize-none bg-transparent block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-200 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-empirica-500 sm:text-sm sm:leading-6",
placeholder: "Say something",
onKeyDown: handleKeyDown,
onKeyUp: handleKeyUp,
value: text,
onChange: (e) => setText(e.target.value)
}
),
/* @__PURE__ */ React6.createElement(
"button",
{
type: "button",
className: "rounded-md bg-gray-100 w-9 h-9 p-2 text-sm font-semibold text-gray-500 shadow-sm hover:bg-gray-200 hover:text-empirica-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-empirica-500",
onClick: handleSubmit
},
/* @__PURE__ */ React6.createElement(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
className: "h-full w-full fill-current",
viewBox: "0 0 512 512"
},
/* @__PURE__ */ React6.createElement("path", { d: "M498.1 5.6c10.1 7 15.4 19.1 13.5 31.2l-64 416c-1.5 9.7-7.4 18.2-16 23s-18.9 5.4-28 1.6L284 427.7l-68.5 74.1c-8.9 9.7-22.9 12.9-35.2 8.1S160 493.2 160 480V396.4c0-4 1.5-7.8 4.2-10.7L331.8 202.8c5.8-6.3 5.6-16-.4-22s-15.7-6.4-22-.7L106 360.8 17.7 316.6C7.1 311.3 .3 300.7 0 288.9s5.9-22.8 16.1-28.7l448-256c10.7-6.1 23.9-5.5 34 1.4z" })
)
)
);
}
function relTime(date) {
const difference = ((/* @__PURE__ */ new Date()).getTime() - date.getTime()) / 1e3;
if (difference < 60) {
return `now`;
} else if (difference < 3600) {
return `${Math.floor(difference / 60)}m`;
} else if (difference < 86400) {
return `${Math.floor(difference / 3600)}h`;
} else if (difference < 2620800) {
return `${Math.floor(difference / 86400)} days ago`;
} else if (difference < 31449600) {
return `${Math.floor(difference / 2620800)} months ago`;
} else {
return `${Math.floor(difference / 31449600)} years ago`;
}
}
// src/player/classic/react/examples/Sweeper.tsx
import React7, { useEffect as useEffect4 } from "react";
var buttonStyle = {
width: 40,
height: 40,
backgroundColor: "#888",
color: "black",
verticalAlign: "top",
fontSize: "32px",
borderLeft: "5px solid rgb(220,220,220)",
borderTop: "5px solid rgb(220,220,220)",
borderBottom: "5px solid #333",
borderRight: "5px solid #333",
display: "inline-block"
};
var visitStyle = {
width: 40,
height: 40,
itemsAlign: "center",
backgroundColor: "#555",
color: "white",
fontWeight: "bold",
border: "1px solid black",
verticalAlign: "top",
fontSize: "24px",
display: "inline-block"
};
function Sweeper() {
const round = useRound();
if (!round) {
return null;
}
const player = usePlayer();
if (!player) {
return null;
}
const visited = round.get("visited");
const bombs = round.get("bombs");
const lost = round.get("lost");
useEffect4(function() {
generateBombs();
}, []);
function generateBombs() {
if (bombs || !round) {
return;
}
let bombArr = new Array(10).fill(0).map(() => new Array(10).fill(0));
for (let i = 0; i < bombArr.length; i++) {
let bombPos = Math.floor(Math.random() * 10);
bombArr[i][bombPos] = "X";
}
for (let i = 0; i < bombArr.length; i++) {
for (let j = 0; j < bombArr[i].length; j++) {
if (bombArr[i][j] !== "X") {
let sum = 0;
if (i > 0 && bombArr[i - 1][j] == "X")
sum++;
if (i < bombArr.length - 1 && bombArr[i + 1][j] == "X")
sum++;
if (j < bombArr.length - 1 && bombArr[i][j + 1] == "X")
sum++;
if (j > 0 && bombArr[i][j - 1] == "X")
sum++;
if (i < bombArr.length - 1 && j > 0 && bombArr[i + 1][j - 1] == "X")
sum++;
if (i < bombArr.length - 1 && j < bombArr.length - 1 && bombArr[i + 1][j + 1] == "X")
sum++;
if (i > 0 && j > 0 && bombArr[i - 1][j - 1] == "X")
sum++;
if (i > 0 && j < bombArr.length - 1 && bombArr[i - 1][j + 1] == "X")
sum++;
bombArr[i][j] = sum;
}
}
}
round.set("bombs", bombArr);
let cover = Array(10).fill(0).map(() => Array(10).fill(0));
round.set("visited", cover);
}
const visitCell = (i, j) => {
if (lost || !bombs || !visited) {
return;
}
if (bombs[i][j] === "X") {
round.set("lost", true);
}
dfsCells(i, j);
visited[i][j] = 1;
round.set("visited", [...visited]);
};
function dfsCells(i, j) {
if (!round || !bombs || !visited) {
return;
}
if (i < 0 || i > visited.length - 1 || j < 0 || j > visited[0].length - 1 || visited[i][j] == 1 || bombs[i][j] == "X")
return;
visited[i][j] = 1;
round.set("visited", [...visited]);
const cell = bombs[i][j];
if (typeof cell === "number" && cell < 1) {
dfsCells(i + 1, j);
dfsCells(i - 1, j);
dfsCells(i, j + 1);
dfsCells(i, j - 1);
}
}
if (!bombs) {
return null;
}
return /* @__PURE__ */ React7.createElement("div", { className: "text-sm relative" }, lost ? /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement("div", { className: "absolute h-full w-full flex items-center justify-center text-6xl white font-black bg-opacity-50 bg-gray-300" }, "YOU LOST"), /* @__PURE__ */ React7.createElement("div", { className: "absolute h-full w-full flex items-center justify-center text-6xl white font-black mt-1 ml-1 text-white" }, "YOU LOST")) : "", bombs.map((arr, index) => /* @__PURE__ */ React7.createElement("div", { key: index }, arr.map((_, i) => /* @__PURE__ */ React7.createElement(
"div",
{
key: i,
onClick: () => visitCell(index, i),
style: visited[index][i] == 0 ? buttonStyle : visitStyle
},
/* @__PURE__ */ React7.createElement("div", { className: "h-full w-full flex items-center justify-center" }, visited[index][i] == 0 ? null : bombs[index][i] == 0 ? "" : bombs[index][i])
)))));
}
export {
usePlayer,
useGame,
useRound,
useStage,
useStageTimer,
usePlayers,
usePartModeCtx,
usePartModeCtxKey,
Lobby,
EmpiricaContext,
Quiz,
Slider,
Chat,
Sweeper
};
//# sourceMappingURL=chunk-J6LPACOK.js.map