Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/api/seed/drizzle-test.sql
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ CREATE TABLE IF NOT EXISTS personalitys (
randomness REAL NOT NULL
);

INSERT INTO users (name) VALUES ("hello");
INSERT INTO users (name) VALUES ("hello");
INSERT INTO users (id, name) VALUES ('550e8400-e29b-41d4-a716-446655440000', 'Player');
INSERT INTO users (id, name) VALUES ('550e8400-e29b-41d4-a716-446655440001', 'Enemy');
36 changes: 35 additions & 1 deletion apps/api/src/db/schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
import { sqliteTable, text } from "drizzle-orm/sqlite-core";
import { sqliteTable, text, integer, check, real } from "drizzle-orm/sqlite-core";
import { sql } from "drizzle-orm";

export const users = sqliteTable("users", {
id: text().primaryKey(),
name: text().notNull(),
});

export const games = sqliteTable(
"games",
{
id: integer("id").primaryKey({ autoIncrement: true }),
player_id: text()
.notNull()
.references(() => users.id),
enemy_id: text()
.notNull()
.references(() => users.id),
first_player: text().notNull(),
winner: text("winner").default(sql`NULL`),
},
(table) => [
check(
"first_player_check",
sql`${table.first_player} IN (${table.player_id}, ${table.enemy_id})`,
),
check(
"winner_check",
sql`${table.winner} IN ('player', 'enemy', 'draw') OR ${table.winner} IS NULL`,
),
],
);

export const personalitys = sqliteTable("personalitys", {
id: integer().primaryKey(),
obedience: real().notNull(),
aggressiveness: real().notNull(),
fear: real().notNull(),
randomness: real().notNull(),
});
18 changes: 16 additions & 2 deletions apps/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import {
VoiceInputSuccessResponseSchema,
VoiceInputErrorResponseSchema,
ResolveActionInputSchema,
initGameSchema,
UserCreatedInputSchema,
} from "@repo/schema";
import { createGeminiClient } from "./lib/gemini";
import { transformVoiceInput } from "./lib/voice-input-transformer";
import { resolveAction } from "./lib/resolve-action";
import { drizzle } from "drizzle-orm/d1";
import { users } from "./db/schema";
import { createGame } from "./lib/create-game";

type Bindings = {
ASSETS: Fetcher;
Expand All @@ -32,10 +34,10 @@ const api = new Hono<{ Bindings: Bindings }>()
return c.json(UsersResponseSchema.parse(response));
})
.post("/v1/users", zValidator("json", UserCreatedInputSchema), async (c) => {
const params = c.req.valid("json");
const params = c.req.valid("json");
const db = drizzle(c.env.DB);
const uuid = self.crypto.randomUUID();
await db.insert(users).values({ id: uuid, name: params.name});
await db.insert(users).values({ id: uuid, name: params.name });
return c.json({ userId: uuid, success: true }, 201);
})
.post("/voice-input/transform", zValidator("json", VoiceInputRequestSchema), async (c) => {
Expand Down Expand Up @@ -81,6 +83,18 @@ const api = new Hono<{ Bindings: Bindings }>()
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
return c.json({ error: errorMessage }, 500);
}
})
.post("/v1/createGame", zValidator("json", initGameSchema), async (c) => {
try {
const db = drizzle(c.env.DB);
const gameData = c.req.valid("json");
const result = await createGame(gameData, db);

return c.json(result, 201);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
return c.json({ error: errorMessage }, 500);
}
});

// Main app
Expand Down
51 changes: 51 additions & 0 deletions apps/api/src/lib/create-game.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
type initGame,
type initGameResponse,
initGameResponseSchema,
} from "@repo/schema";
import { DrizzleD1Database } from "drizzle-orm/d1";
import { games, personalitys } from "../db/schema";

export async function createGame(
gameData: initGame,
db: DrizzleD1Database
): Promise<initGameResponse> {
try {
const result = await db
.insert(games)
.values({
player_id: gameData.player_id,
enemy_id: gameData.enemy_id,
first_player: gameData.first_player,
})
.returning();

// game ID のみ取得
const game_id = result[0].id;

// Generate random personalitys for response
const allPersonalitys = await db.select().from(personalitys).all();

if (allPersonalitys.length == 0) {
throw new Error("No personalitys found in database");
}

const randomPersonalitys = [];
for (let i = 0; i < 32; i++) {
randomPersonalitys[i] =
allPersonalitys[Math.floor(Math.random() * allPersonalitys.length)];
}

const response = initGameResponseSchema.parse({
game_id: game_id,
personalitys: randomPersonalitys,
});
return response;
} catch (error) {
throw new Error(
`Failed to create game: ${
error instanceof Error ? error.message : String(error)
}`
);
}
}
5 changes: 1 addition & 4 deletions apps/frontend/src/features/chess/compomemt/Board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,7 @@ const Board: React.FC<BoardProps> = ({ className }) => {
/>
)}

<group
rotation={[-Math.PI / 5, 0, turn === "black" ? 3.15 : 0]}
scale={[1.5, 1, 1]}
>
<group rotation={[-Math.PI / 5, 0, turn === "black" ? 3.15 : 0]} scale={[1.5, 1, 1]}>
<mesh>
<planeGeometry args={[6, 6]} />
<Mark />
Expand Down
1 change: 0 additions & 1 deletion apps/frontend/src/features/chess/compomemt/ChessPieces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ function MoveCommand(
});
}


const ChessPieces = ({ command }: { command: VoiceInput | null }) => {
const [pieces, setPieces] = useState(createInitialPieces());
const { startAnimation } = useAnimationStore();
Expand Down
1 change: 1 addition & 0 deletions packages/schema/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from "./aiResponse";
export * from "./personality";
export * from "./backend-chess";
export * from "./resolve-action";
export * from "./initGame";
16 changes: 16 additions & 0 deletions packages/schema/src/initGame.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { z } from "zod";
import { personalitySchema } from "./personality";

export const initGameSchema = z.object({
player_id: z.uuid(),
enemy_id: z.uuid(),
first_player: z.uuid(),
});

export type initGame = z.infer<typeof initGameSchema>;

export const initGameResponseSchema = z.object({
response: z.array(personalitySchema).length(32),
});

export type initGameResponse = z.infer<typeof initGameResponseSchema>;
6 changes: 3 additions & 3 deletions packages/schema/src/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export const CreateUserSchema = UserSchema.omit({ id: true });
export type CreateUser = z.infer<typeof CreateUserSchema>;

export const UserCreatedInputSchema = z.object({
name: z.string().min(2)
})
name: z.string().min(2),
});
export type UserCreatedInput = z.infer<typeof UserCreatedInputSchema>;

export const UsersResponseSchema = z.object({
Expand All @@ -21,7 +21,7 @@ export const UsersResponseSchema = z.object({

export const UserCreatedResponseSchema = z.object({
userId: z.uuid(),
success: z.boolean()
success: z.boolean(),
});

export type UsersResponse = z.infer<typeof UsersResponseSchema>;
Expand Down