diff --git a/assets/sources/Card_back_01.svg b/assets/sources/Card_back_01.svg
new file mode 100644
index 0000000..33c9ab1
--- /dev/null
+++ b/assets/sources/Card_back_01.svg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a2780e41eb510b73fd3238f5e3328908aaff1a19b8b1e52ec30998d51b56be50
+size 123591
diff --git a/assets/views/back.svg b/assets/views/back.svg
new file mode 120000
index 0000000..3ea4d28
--- /dev/null
+++ b/assets/views/back.svg
@@ -0,0 +1 @@
+../sources/Card_back_01.svg
\ No newline at end of file
diff --git a/src/app.css b/src/app.css
index 3f1f248..54cbea7 100644
--- a/src/app.css
+++ b/src/app.css
@@ -28,6 +28,10 @@ body::before {
width: 100%;
}
+.w-full {
+ width: 100%;
+}
+
.center {
display: flex;
justify-content: center;
diff --git a/src/components/Card.tsx b/src/components/Card.tsx
index a75b487..3a2cd88 100644
--- a/src/components/Card.tsx
+++ b/src/components/Card.tsx
@@ -1,4 +1,4 @@
-import { Component, createResource, Suspense } from "solid-js";
+import { Component, createResource, JSX, Suspense } from "solid-js";
import { Card } from "../types/cards";
const cardToSvgFilename = (card: Card) => {
@@ -7,24 +7,43 @@ const cardToSvgFilename = (card: Card) => {
}
const value =
- { ace: 1, jack: 11, queen: 12, king: 13 }[card.rank] ??
- (card.rank as number);
+ { ace: 1, jack: 11, queen: 12, king: 13 }[
+ card.rank as "ace" | "jack" | "queen" | "king" // fuck you typescript
+ ] ?? (card.rank as number);
return `${card.suit.toUpperCase()}-${value}${
value >= 11 ? "-" + (card.rank as string).toUpperCase() : ""
}`;
};
export default ((props) => {
- const [svgPath] = createResource(
- () =>
- import(
- `~/../assets/views/cards/${cardToSvgFilename(props.card)}.svg`
- )
+ const [svgPath] = createResource(() =>
+ props.face == "down"
+ ? // @ts-ignore
+ import("~/../assets/views/back.svg")
+ : import(
+ `~/../assets/views/cards/${cardToSvgFilename(
+ props.card
+ )}.svg`
+ )
);
return (
-
+
);
-}) satisfies Component<{ card: Card }>;
+}) satisfies Component<{
+ class?: string;
+ style?: JSX.CSSProperties;
+ card: Card;
+ face?: "up" | "down";
+}>;
diff --git a/src/components/Game.tsx b/src/components/Game.tsx
index 0973c15..1dc4720 100644
--- a/src/components/Game.tsx
+++ b/src/components/Game.tsx
@@ -1,15 +1,40 @@
-import { JSX } from "solid-js";
+import { createContext, JSX } from "solid-js";
import Card from "./Card";
+import Hand from "./Hand";
+import Pile from "./Pile";
+import { newDeck, shuffle, Hand as THand } from "../types/cards";
+import { createStore, produce } from "solid-js/store";
+
+const GameContext = createContext();
export default () => {
+ const [gameState, setGameState] = createStore({
+ pile: shuffle(newDeck()),
+ hand: [] as THand,
+ });
+
return (
-
- games
-
- coming soon
-
+
+ {}}
+ class="full column"
+ style={{ "row-gap": "20px", "font-size": "32px" }}
+ >
+
+
+ setGameState(
+ produce((state) => {
+ state.hand.push(state.pile.pop()!);
+ })
+ )
+ }
+ />
+
+
+
+
);
};
diff --git a/src/components/Hand.tsx b/src/components/Hand.tsx
index e69de29..8277be1 100644
--- a/src/components/Hand.tsx
+++ b/src/components/Hand.tsx
@@ -0,0 +1,24 @@
+import { Component, For } from "solid-js";
+import Card from "./Card";
+import { Hand } from "../types/cards";
+
+export default ((props) => {
+ return (
+
+ {(card) => }
+
+ );
+}) satisfies Component<{ hand: Hand }>;
diff --git a/src/components/Pile.tsx b/src/components/Pile.tsx
index e69de29..f8b3c2d 100644
--- a/src/components/Pile.tsx
+++ b/src/components/Pile.tsx
@@ -0,0 +1,44 @@
+import { Component, For, JSX } from "solid-js";
+import Card from "./Card";
+import { Pile } from "../types/cards";
+
+export default ((props) => {
+ return (
+
+
+ {(card, i) => (
+
+ )}
+
+
+ );
+}) satisfies Component<{
+ pile: Pile;
+ style?: JSX.CSSProperties;
+ onClick?:
+ | JSX.EventHandlerUnion<
+ HTMLDivElement,
+ MouseEvent,
+ JSX.EventHandler
+ >
+ | undefined;
+}>;
diff --git a/src/types/cards.ts b/src/types/cards.ts
index 94f5970..029680d 100644
--- a/src/types/cards.ts
+++ b/src/types/cards.ts
@@ -1,6 +1,23 @@
-export type Suit = "heart" | "diamond" | "spade" | "club";
+const suits = ["heart", "diamond", "spade", "club"] as const;
+export type Suit = (typeof suits)[number];
+
+const ranks = [
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ "jack",
+ "queen",
+ "king",
+ "ace",
+] as const;
+export type Rank = (typeof ranks)[number];
-type Rank = number | "jack" | "queen" | "king" | "ace";
export type Card =
| {
kind: "normal";
@@ -13,3 +30,28 @@ export type Pile = Card[];
export type Stack = Card[];
export type Hand = Card[];
export type Board = Card[];
+
+export const newDeck = (withJokers = false): Pile =>
+ suits
+ .map((suit) =>
+ ranks.map((rank) => ({ kind: "normal", suit, rank } as Card))
+ )
+ .flat()
+ .concat(
+ withJokers
+ ? [
+ { kind: "joker", color: "red" },
+ { kind: "joker", color: "black" },
+ ]
+ : []
+ );
+
+export const shuffle = (cards: Card[]) => {
+ let i = cards.length;
+ while (i > 0) {
+ const j = Math.floor(Math.random() * i);
+ i--;
+ [cards[i], cards[j]] = [cards[j], cards[i]];
+ }
+ return cards;
+};
diff --git a/tsconfig.json b/tsconfig.json
index 7d5871a..3a1138c 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,19 +1,19 @@
{
- "compilerOptions": {
- "target": "ESNext",
- "module": "ESNext",
- "moduleResolution": "bundler",
- "allowSyntheticDefaultImports": true,
- "esModuleInterop": true,
- "jsx": "preserve",
- "jsxImportSource": "solid-js",
- "allowJs": true,
- "strict": true,
- "noEmit": true,
- "types": ["vinxi/types/client"],
- "isolatedModules": true,
- "paths": {
- "~/*": ["./src/*"]
- }
- }
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js",
+ "allowJs": true,
+ "strict": true,
+ "noEmit": true,
+ "types": ["vinxi/types/client"],
+ "isolatedModules": true,
+ "paths": {
+ "~/*": ["./src/*"]
+ }
+ }
}