Skip to content

Commit

Permalink
Merge pull request #144 from MZT7/main
Browse files Browse the repository at this point in the history
Dynamic Blocks and Landmines
  • Loading branch information
delasy authored Nov 13, 2024
2 parents 8e8ac6e + 72dc114 commit 968eb44
Show file tree
Hide file tree
Showing 15 changed files with 205 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ next-env.d.ts

# ignored for the template, you probably want to remove it:
package-lock.json

.env.local
39 changes: 25 additions & 14 deletions app/play/[level]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export default function PlayLevelPage({
const [placementMode, setPlacementMode] = useState<PlacementMode>("player");
const [blockCount, setBlockCount] = useState(0);
const [landmineCount, setLandmineCount] = useState(0);
const [maxBlocks, setMaxBlocks] = useState(0);
const [maxLandmines, setMaxLandmines] = useState(0);
const flags = useQuery(api.flags.getFlags);
const [mode, setMode] = useState<"play" | "test">("play");
const [replaySpeed, setReplaySpeed] = useState(DEFAULT_REPLAY_SPEED);
Expand All @@ -47,6 +49,8 @@ export default function PlayLevelPage({
useEffect(() => {
if (map) {
setPlayerMap(map.grid.map((row) => [...row]));
setMaxBlocks(Number(map.maxBlocks) ?? 0);
setMaxLandmines(Number(map.maxLandmines) ?? 0);
}
}, [map]);

Expand Down Expand Up @@ -219,20 +223,27 @@ export default function PlayLevelPage({
>
Place Player
</Button>
<Button
onClick={() => handlePlacementModeChange("block")}
variant={placementMode === "block" ? "default" : "outline"}
className="h-10"
>
Place Block ({2 - blockCount} left)
</Button>
<Button
onClick={() => handlePlacementModeChange("landmine")}
variant={placementMode === "landmine" ? "default" : "outline"}
className="h-10"
>
Place Landmine ({1 - landmineCount} left)
</Button>
{maxBlocks > 0 && (
<Button
onClick={() => handlePlacementModeChange("block")}
variant={placementMode === "block" ? "default" : "outline"}
className="h-10"
>
Place Block ({maxBlocks - blockCount} left)
</Button>
)}

{maxLandmines > 0 && (
<Button
onClick={() => handlePlacementModeChange("landmine")}
variant={
placementMode === "landmine" ? "default" : "outline"
}
className="h-10"
>
Place Landmine ({maxLandmines - landmineCount} left)
</Button>
)}
</div>
<div className="mb-8 flex flex-col items-center">
<h2 className="mb-4 text-xl font-semibold">
Expand Down
35 changes: 32 additions & 3 deletions app/playground/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useToast } from "@/components/ui/use-toast";
import { api } from "@/convex/_generated/api";
import { Id } from "@/convex/_generated/dataModel";
Expand Down Expand Up @@ -61,6 +63,8 @@ export default function PlaygroundPage() {
const [userSolution, setUserSolution] = useState<string[][]>([]);
const [visualizingUserSolution, setVisualizingUserSolution] = useState(false);
const [openSignInModal, setOpenSignInModal] = useState(false);
const [maxBlocks, setMaxBlocks] = useState(2);
const [maxLandmines, setMaxLandmines] = useState(0);

const {
isSimulating,
Expand Down Expand Up @@ -89,7 +93,7 @@ export default function PlaygroundPage() {
setPublishing(true);

try {
const submitted = await submitMap({ map });
const submitted = await submitMap({ map, maxBlocks, maxLandmines });

if (submitted == 200) {
toast({
Expand Down Expand Up @@ -341,9 +345,9 @@ export default function PlaygroundPage() {
if (cell === " ") {
if (playerCount === 0) {
newMap[y][x] = "P";
} else if (blockCount < 2) {
} else if (blockCount < maxBlocks) {
newMap[y][x] = "B";
} else if (landmineCount === 0) {
} else if (landmineCount === maxLandmines) {
newMap[y][x] = "L";
}
} else if (cell === "P") {
Expand Down Expand Up @@ -472,6 +476,31 @@ export default function PlaygroundPage() {
</>
) : (
<>
<div className="flex gap-2">
<div>
<Label htmlFor="block">Max Block</Label>
<Input
placeholder="Max Blocks"
type="number"
id="block"
onChange={(e) => setMaxBlocks(Number(e.target.value))}
value={maxBlocks}
/>
</div>
<div>
<Label htmlFor="landmine">Max Landmine</Label>
<Input
placeholder="Max Landmines"
type="number"
id="landmine"
onChange={(e) =>
setMaxLandmines(Number(e.target.value))
}
value={maxLandmines}
/>
</div>
</div>

<div className="flex flex-col">
<Button
disabled={publishing}
Expand Down
26 changes: 26 additions & 0 deletions components/ui/label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use client"

import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)

const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
))
Label.displayName = LabelPrimitive.Root.displayName

export { Label }
90 changes: 90 additions & 0 deletions convex/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Welcome to your Convex functions directory!

Write your Convex functions here.
See https://docs.convex.dev/functions for more.

A query function that takes two arguments looks like:

```ts
// functions.js
import { query } from "./_generated/server";
import { v } from "convex/values";

export const myQueryFunction = query({
// Validators for arguments.
args: {
first: v.number(),
second: v.string(),
},

// Function implementation.
handler: async (ctx, args) => {
// Read the database as many times as you need here.
// See https://docs.convex.dev/database/reading-data.
const documents = await ctx.db.query("tablename").collect();

// Arguments passed from the client are properties of the args object.
console.log(args.first, args.second);

// Write arbitrary JavaScript here: filter, aggregate, build derived data,
// remove non-public properties, or create new objects.
return documents;
},
});
```

Using this query function in a React component looks like:

```ts
const data = useQuery(api.functions.myQueryFunction, {
first: 10,
second: "hello",
});
```

A mutation function looks like:

```ts
// functions.js
import { mutation } from "./_generated/server";
import { v } from "convex/values";

export const myMutationFunction = mutation({
// Validators for arguments.
args: {
first: v.string(),
second: v.string(),
},

// Function implementation.
handler: async (ctx, args) => {
// Insert or modify documents in the database here.
// Mutations can also read from the database like queries.
// See https://docs.convex.dev/database/writing-data.
const message = { body: args.first, author: args.second };
const id = await ctx.db.insert("messages", message);

// Optionally, return a value from your mutation.
return await ctx.db.get(id);
},
});
```

Using this mutation function in a React component looks like:

```ts
const mutation = useMutation(api.functions.myMutationFunction);
function handleButtonPress() {
// fire and forget, the most common way to use mutations
mutation({ first: "Hello!", second: "me" });
// OR
// use the result once the mutation has completed
mutation({ first: "Hello!", second: "me" }).then((result) =>
console.log(result),
);
}
```

Use the Convex CLI to push your functions to a deployment. See everything
the Convex CLI can do by running `npx convex -h` in your project root
directory. To learn more, launch the docs with `npx convex docs`.
4 changes: 0 additions & 4 deletions convex/_generated/api.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* prettier-ignore-start */

/* eslint-disable */
/**
* Generated `api` utility.
Expand Down Expand Up @@ -153,5 +151,3 @@ export declare const components: {
};
};
};

/* prettier-ignore-end */
4 changes: 0 additions & 4 deletions convex/_generated/api.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* prettier-ignore-start */

/* eslint-disable */
/**
* Generated `api` utility.
Expand All @@ -23,5 +21,3 @@ import { anyApi, componentsGeneric } from "convex/server";
export const api = anyApi;
export const internal = anyApi;
export const components = componentsGeneric();

/* prettier-ignore-end */
4 changes: 0 additions & 4 deletions convex/_generated/dataModel.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* prettier-ignore-start */

/* eslint-disable */
/**
* Generated data model types.
Expand Down Expand Up @@ -60,5 +58,3 @@ export type Id<TableName extends TableNames | SystemTableNames> =
* `mutationGeneric` to make them type-safe.
*/
export type DataModel = DataModelFromSchemaDefinition<typeof schema>;

/* prettier-ignore-end */
4 changes: 0 additions & 4 deletions convex/_generated/server.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* prettier-ignore-start */

/* eslint-disable */
/**
* Generated utilities for implementing server-side Convex query and mutation functions.
Expand Down Expand Up @@ -149,5 +147,3 @@ export type DatabaseReader = GenericDatabaseReader<DataModel>;
* for the guarantees Convex provides your functions.
*/
export type DatabaseWriter = GenericDatabaseWriter<DataModel>;

/* prettier-ignore-end */
4 changes: 0 additions & 4 deletions convex/_generated/server.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* prettier-ignore-start */

/* eslint-disable */
/**
* Generated utilities for implementing server-side Convex query and mutation functions.
Expand Down Expand Up @@ -90,5 +88,3 @@ export const internalAction = internalActionGeneric;
* @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.
*/
export const httpAction = httpActionGeneric;

/* prettier-ignore-end */
16 changes: 15 additions & 1 deletion convex/maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ export const addMap = mutation({
export const submitMap = authenticatedMutation({
args: {
map: v.array(v.array(v.string())),
maxBlocks: v.number(),
maxLandmines: v.number(),
},
handler: async (ctx, args) => {
try {
Expand All @@ -170,6 +172,8 @@ export const submitMap = authenticatedMutation({
await ctx.db.insert("maps", {
grid: args.map,
level: undefined,
maxBlocks: args.maxBlocks,
maxLandmines: args.maxLandmines,
submittedBy: ctx.userId,
isReviewed: false,
});
Expand All @@ -193,11 +197,15 @@ export const seedMaps = internalMutation({
if (existingMap) {
ctx.db.patch(existingMap._id, {
grid: map.grid,
maxBlocks: 2,
maxLandmines: 0,
});
} else {
ctx.db.insert("maps", {
level: idx + 1,
grid: map.grid,
maxBlocks: 2,
maxLandmines: 0,
isReviewed: true,
});
}
Expand Down Expand Up @@ -362,6 +370,7 @@ export const playMapAction = internalAction({
args.modelId,
map.grid,
activePrompt.prompt,
map.maxBlocks,
);

await ctx.runMutation(internal.results.updateResult, {
Expand Down Expand Up @@ -423,7 +432,12 @@ export const testAIModel = action({
outputTokens,
totalTokensUsed,
totalRunCost,
} = await runModel(args.modelId, map.grid, activePrompt.prompt);
} = await runModel(
args.modelId,
map.grid,
activePrompt.prompt,
map.maxBlocks,
);

return {
map: solution,
Expand Down
1 change: 1 addition & 0 deletions convex/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const defaultPrompt = `Your task is to play a game. We will give you a 2d array
- You can not place the player in a location already used by a zombie or rock.
- You can not place a block over the player or another block.
- You must place both blocks and the player before starting the game.
- You can place {MAX_BLOCKS} blocks on the map.
# Grid Descriptions
The 2d Grid is made up of characters, where each character has a meaning.
Expand Down
2 changes: 2 additions & 0 deletions convex/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export default defineSchema({
maps: defineTable({
level: v.optional(v.number()),
grid: v.array(v.array(v.string())),
maxBlocks: v.optional(v.number()),
maxLandmines: v.optional(v.number()),
submittedBy: v.optional(v.id("users")),
isReviewed: v.boolean(),
})
Expand Down
Loading

0 comments on commit 968eb44

Please sign in to comment.