- {visualizing && (
-
+
+ {/* Left side: Grid */}
+
+
+ {!visualizing && !userPlaying && (
+
+ Click on the board to place or remove units. Use the buttons below to switch between unit types.
+
)}
- {!visualizing && (
-
+ {!visualizing && userPlaying && (
+
+ Place a player (P) and blocks (B) on the board to create your escape route. Click to toggle between empty, player, and block.
+
)}
-
+
+ {visualizing && (
+
+ )}
+ {!visualizing && (
+
+
+
+ {(userPlaying ? userSolution : map).map((row, y) =>
+ row.map((cell, x) => (
+
{
+ const newMap = userPlaying
+ ? [...userSolution]
+ : [...map];
+ if (userPlaying) {
+ // Count existing players and blocks
+ const playerCount = newMap.flat().filter(c => c === "P").length;
+ const blockCount = newMap.flat().filter(c => c === "B").length;
+
+ // Toggle logic for play mode
+ if (cell === " ") {
+ if (playerCount === 0) {
+ newMap[y][x] = "P";
+ } else if (blockCount < 2) {
+ newMap[y][x] = "B";
+ }
+ } else if (cell === "P") {
+ newMap[y][x] = " ";
+ } else if (cell === "B") {
+ newMap[y][x] = " ";
+ }
+ userPlaying
+ ? setUserSolution(newMap)
+ : handleChangeMap(newMap);
+ } else {
+ // Toggle between empty, zombie, and rock for edit mode
+ if (cell === " ") newMap[y][x] = "Z";
+ else if (cell === "Z") newMap[y][x] = "R";
+ else newMap[y][x] = " ";
+ }
+ userPlaying
+ ? setUserSolution(newMap)
+ : handleChangeMap(newMap);
+ }}
+ />
+ ))
+ )}
+
+
+ )}
+
+
-
-
- {isAdmin && (
+
+ {/* Right side: Action Panel */}
+
+
+ {userPlaying || solution !== null ? (
<>
-
Model (~$0.002)
-
- {!userPlaying && solution === null && (
+
+ {userPlaying && (
)}
>
+ ) : (
+ <>
+
+
+
+ >
)}
- {(solution !== null || userPlaying) && (
-
- )}
- {solution === null && !simulating && !userPlaying && (
-
+
+ {error !== null &&
{error}
}
+ {visualizingUserSolution &&
}
+ {reasoning !== null && (
+
)}
- {userPlaying && (
-
+
+ {isAdmin && !userPlaying && solution === null && (
+ <>
+
+
+
Model (~$0.002)
+
+
+
+ >
)}
- {error !== null && {error}
}
- {visualizingUserSolution && }
- {reasoning !== null && (
-
- )}
-
+
);
diff --git a/convex/maps.ts b/convex/maps.ts
index eb8a42d..003dc04 100644
--- a/convex/maps.ts
+++ b/convex/maps.ts
@@ -11,7 +11,7 @@ import {
query,
} from "./_generated/server";
import { Prompt } from "./prompts";
-import { adminMutationBuilder } from "./users";
+import { adminMutationBuilder, authenticatedMutation } from "./users";
const LEVELS = [
{
@@ -150,23 +150,16 @@ export const addMap = mutation({
},
});
-export const publishMap = adminMutationBuilder({
+export const submitMap = authenticatedMutation({
args: {
map: v.array(v.array(v.string())),
},
handler: async (ctx, args) => {
- const maps = await ctx.db
- .query("maps")
- .filter((q) => q.neq("level", undefined))
- .collect();
-
- const lastLevel = maps.sort((a, b) => b.level! - a.level!)[0].level!;
-
await ctx.db.insert("maps", {
grid: args.map,
- level: lastLevel + 1,
- submittedBy: ctx.admin.id,
- isReviewed: true,
+ level: undefined,
+ submittedBy: ctx.userId,
+ isReviewed: false,
});
},
});
diff --git a/convex/users.ts b/convex/users.ts
index a14c505..30dbeb7 100644
--- a/convex/users.ts
+++ b/convex/users.ts
@@ -5,6 +5,7 @@ import {
customQuery,
} from "convex-helpers/server/customFunctions";
import { mutation, query } from "./_generated/server";
+import { ConvexError } from "convex/values";
export const viewer = query({
args: {},
@@ -99,3 +100,19 @@ export const adminMutationBuilder = customMutation(
};
}),
);
+
+
+export const authenticatedMutation = customMutation(
+ mutation,
+ customCtx(async (ctx) => {
+ const userId = await getAuthUserId(ctx);
+
+ if (userId === null) {
+ throw new ConvexError("You must be signed in to perform this action");
+ }
+
+ return {
+ userId,
+ };
+ }),
+);