working e2e
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Component, createResource, JSX, Suspense } from "solid-js";
|
||||
import { Card, newDeck } from "../types/cards";
|
||||
|
||||
import { Clickable, Stylable } from "./toolbox";
|
||||
import { Card } from "../../../shared/cards";
|
||||
|
||||
const cardToSvgFilename = (card: Card) => {
|
||||
if (card.kind == "joker") {
|
||||
@@ -37,9 +38,13 @@ export default ((props) => {
|
||||
</Suspense>
|
||||
);
|
||||
}) satisfies Component<
|
||||
{
|
||||
(
|
||||
| {
|
||||
card: Card;
|
||||
face?: "up" | "down";
|
||||
} & Stylable &
|
||||
face?: "up";
|
||||
}
|
||||
| { card?: Card; face: "down" }
|
||||
) &
|
||||
Stylable &
|
||||
Clickable
|
||||
>;
|
||||
|
||||
@@ -3,46 +3,45 @@ import {
|
||||
GameState,
|
||||
Action,
|
||||
vGameState,
|
||||
PlayerView,
|
||||
} from "../../../server/src/games/simple";
|
||||
import api from "../api";
|
||||
import Hand from "./Hand";
|
||||
import Pile from "./Pile";
|
||||
|
||||
export const GameContext = createContext<{
|
||||
gameState: Accessor<GameState | undefined>;
|
||||
view: Accessor<PlayerView | undefined>;
|
||||
submitAction: (action: Action) => Promise<any>;
|
||||
}>();
|
||||
|
||||
export default (props: { instanceId: string }) => {
|
||||
const [gameState, { mutate }] = createResource(() =>
|
||||
const [view, { mutate }] = createResource(() =>
|
||||
api
|
||||
.simple(props)
|
||||
.get()
|
||||
.then((res) => res.data as GameState)
|
||||
.then((res) => res.data as PlayerView)
|
||||
);
|
||||
const submitAction = (action: Action) =>
|
||||
api
|
||||
.simple(props)
|
||||
.post({ action })
|
||||
.then((res) => res.status == 200 && mutate(res.data as vGameState));
|
||||
.then((res) => res.status == 200 && mutate(res.data as PlayerView));
|
||||
|
||||
return (
|
||||
<GameContext.Provider value={{ gameState, submitAction }}>
|
||||
<Show when={gameState.latest != undefined}>
|
||||
<GameContext.Provider value={{ view, submitAction }}>
|
||||
<Show when={view.latest != undefined}>
|
||||
<div
|
||||
class="full column center"
|
||||
style={{ "row-gap": "20px", "font-size": "32px" }}
|
||||
>
|
||||
<div class="full center">
|
||||
<Pile
|
||||
pile={gameState.latest!.deck}
|
||||
count={view.latest!.deckCount}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() =>
|
||||
api.simple({ instanceId: props.instanceId })
|
||||
}
|
||||
onClick={() => submitAction({ type: "draw" })}
|
||||
/>
|
||||
</div>
|
||||
<Hand hand={gameState.latest!.players["daniel"]} />
|
||||
<Hand hand={view.latest!.myHand} />
|
||||
</div>
|
||||
</Show>
|
||||
</GameContext.Provider>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { GameContext } from "./Game";
|
||||
import { produce } from "solid-js/store";
|
||||
|
||||
export default ((props) => {
|
||||
const { submitAction, gameState } = useContext(GameContext)!;
|
||||
const { submitAction, view } = useContext(GameContext)!;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, For, JSX } from "solid-js";
|
||||
import { Component, For, JSX, Show } from "solid-js";
|
||||
import Card from "./Card";
|
||||
import { Pile } from "../types/cards";
|
||||
import { type ComponentProps } from "solid-js";
|
||||
|
||||
import { Clickable, Stylable } from "./toolbox";
|
||||
|
||||
export default ((props) => {
|
||||
@@ -16,31 +15,14 @@ export default ((props) => {
|
||||
}}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<For each={props.pile}>
|
||||
{(card, i) => (
|
||||
<Card
|
||||
card={card}
|
||||
face="down"
|
||||
style={{
|
||||
position: "absolute",
|
||||
transform: `translate(${i() * 0.5}px, ${
|
||||
i() * 0.2
|
||||
}px)`,
|
||||
// "z-index": 100 - i(),
|
||||
border: `0.1px solid rgb(${
|
||||
10 + i() + Math.random() * 50
|
||||
}, ${10 + i() + Math.random() * 50}, ${
|
||||
10 + i() + Math.random() * 50
|
||||
});`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
<Show when={props.count > 0}>
|
||||
<Card face="down" />
|
||||
</Show>
|
||||
</div>
|
||||
);
|
||||
}) satisfies Component<
|
||||
{
|
||||
pile: Pile;
|
||||
count: number;
|
||||
} & Stylable &
|
||||
Clickable
|
||||
>;
|
||||
|
||||
@@ -47,7 +47,10 @@ export const newGame = (players: string[]) => {
|
||||
} as GameState;
|
||||
};
|
||||
|
||||
export const getKnowledge = (state: GameState, humanId: string) => ({
|
||||
export const getKnowledge = (
|
||||
state: GameState,
|
||||
humanId: string
|
||||
): vGameState => ({
|
||||
humanId,
|
||||
deck: state.deck.map((_) => null),
|
||||
players: Object.fromEntries(
|
||||
@@ -58,6 +61,17 @@ export const getKnowledge = (state: GameState, humanId: string) => ({
|
||||
),
|
||||
});
|
||||
|
||||
const getView = (state: vGameState, humanId: string): PlayerView => ({
|
||||
humanId,
|
||||
deckCount: state.deck.length,
|
||||
myHand: state.players[humanId] as Hand,
|
||||
playerHandCounts: Object.fromEntries(
|
||||
Object.entries(state.players)
|
||||
.filter(([id]) => id != humanId)
|
||||
.map(([id, hand]) => [id, hand.length])
|
||||
),
|
||||
});
|
||||
|
||||
export const resolveAction = (
|
||||
state: GameState,
|
||||
humanId: string,
|
||||
@@ -112,21 +126,31 @@ export const simpleApi = new Elysia({ prefix: "/simple" })
|
||||
)
|
||||
.group("/:instanceId", (app) =>
|
||||
app
|
||||
.get("/", ({ params: { instanceId } }) =>
|
||||
.get(
|
||||
"/",
|
||||
({ params: { instanceId }, headers: { human: humanId } }) =>
|
||||
prisma.instance
|
||||
.findUnique({
|
||||
where: {
|
||||
id: instanceId,
|
||||
},
|
||||
})
|
||||
.then((game) => game?.gameState)
|
||||
.then((game) =>
|
||||
getView(
|
||||
getKnowledge(
|
||||
game!.gameState as GameState,
|
||||
humanId!
|
||||
),
|
||||
humanId!
|
||||
)
|
||||
)
|
||||
)
|
||||
.post(
|
||||
"/",
|
||||
({
|
||||
params: { instanceId },
|
||||
body: { action },
|
||||
headers: { Human: humanId },
|
||||
headers: { human: humanId },
|
||||
}) =>
|
||||
prisma.instance
|
||||
.findUniqueOrThrow({
|
||||
@@ -134,20 +158,22 @@ export const simpleApi = new Elysia({ prefix: "/simple" })
|
||||
id: instanceId,
|
||||
},
|
||||
})
|
||||
.then((game) => {
|
||||
.then(async (game) => {
|
||||
const newState = resolveAction(
|
||||
game.gameState as GameState,
|
||||
humanId!,
|
||||
action
|
||||
);
|
||||
const knownState = getKnowledge(newState, humanId!);
|
||||
void prisma.instance.update({
|
||||
await prisma.instance.update({
|
||||
data: { gameState: newState },
|
||||
where: {
|
||||
id: instanceId,
|
||||
},
|
||||
});
|
||||
return knownState;
|
||||
return getView(
|
||||
getKnowledge(newState, humanId!),
|
||||
humanId!
|
||||
);
|
||||
}),
|
||||
{
|
||||
body: t.Object({
|
||||
|
||||
Reference in New Issue
Block a user