Compare commits
No commits in common. "118ae220ee326cc17e1e9dba1e33ac2edf540a04" and "e8d1a8afded1df4a74677884b02414bc5aeceaef" have entirely different histories.
118ae220ee
...
e8d1a8afde
|
|
@ -17,9 +17,9 @@ import {
|
||||||
upsertCollection,
|
upsertCollection,
|
||||||
} from "../repositories/collectionRepository";
|
} from "../repositories/collectionRepository";
|
||||||
import { getWeight, lootboxes } from "../../shared/lootboxes";
|
import { getWeight, lootboxes } from "../../shared/lootboxes";
|
||||||
import { round, weightedPickRandom } from "../../shared/utils";
|
import { weightedPickRandom } from "../../shared/utils";
|
||||||
import { emit } from "../events";
|
import { emit } from "../events";
|
||||||
import { Game, Gems } from "../schema";
|
import { Game } from "../schema";
|
||||||
import { and, count, eq, gt, max, not, sum } from "drizzle-orm";
|
import { and, count, eq, gt, max, not, sum } from "drizzle-orm";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
|
@ -222,19 +222,10 @@ export const userController = createController({
|
||||||
})
|
})
|
||||||
.from(Game)
|
.from(Game)
|
||||||
.where(and(eq(Game.user, id), not(eq(Game.finished, 0))));
|
.where(and(eq(Game.user, id), not(eq(Game.finished, 0))));
|
||||||
const [{ totalGems, currentGems }] = await db
|
|
||||||
.select({
|
|
||||||
totalGems: Gems.totalCount,
|
|
||||||
currentGems: Gems.count,
|
|
||||||
})
|
|
||||||
.from(Gems)
|
|
||||||
.where(eq(Gems.user, id));
|
|
||||||
return {
|
return {
|
||||||
totalGames,
|
totalGames,
|
||||||
highestStage,
|
highestStage,
|
||||||
averageStage: round(Number(totalStages) / totalGames, 3),
|
averageStage: Number(totalStages) / totalGames,
|
||||||
totalGems,
|
|
||||||
currentGems,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,6 @@ export const removeGems = async (
|
||||||
if (count - gems < 0) throw new Error("Not enough gems");
|
if (count - gems < 0) throw new Error("Not enough gems");
|
||||||
await db
|
await db
|
||||||
.update(Gems)
|
.update(Gems)
|
||||||
.set({ count: count - gems, totalCount: totalCount })
|
.set({ count: count - gems, totalCount: totalCount - gems })
|
||||||
.where(eq(Gems.user, user));
|
.where(eq(Gems.user, user));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,3 @@ export const weightedPickRandom = <T>(
|
||||||
}
|
}
|
||||||
return arr[arr.length - 1];
|
return arr[arr.length - 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const round = (value: number, digits: number) => {
|
|
||||||
const factor = Math.pow(10, digits);
|
|
||||||
return Math.round(value * factor) / factor;
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,7 @@ const Shell: React.FC<PropsWithChildren> = ({ children }) => {
|
||||||
animate={{ x }}
|
animate={{ x }}
|
||||||
transition={{ type: "tween" }}
|
transition={{ type: "tween" }}
|
||||||
>
|
>
|
||||||
<div
|
<div className="w-full p-2 flex flex-col gap-6">
|
||||||
className="w-full p-2 flex flex-col gap-6"
|
|
||||||
onClick={() => {
|
|
||||||
if (isMobile) {
|
|
||||||
setIsOpen(false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h2 className="[background:var(--bg-brand)] [-webkit-text-fill-color:transparent] font-black [-webkit-background-clip:text!important] font-mono text-3xl">
|
<h2 className="[background:var(--bg-brand)] [-webkit-text-fill-color:transparent] font-black [-webkit-background-clip:text!important] font-mono text-3xl">
|
||||||
Business
|
Business
|
||||||
<br />
|
<br />
|
||||||
|
|
@ -108,10 +101,7 @@ const Shell: React.FC<PropsWithChildren> = ({ children }) => {
|
||||||
<Button
|
<Button
|
||||||
className="absolute left-4 bg-black border-white/10 border-y-1 border-r-1 rounded-l-none"
|
className="absolute left-4 bg-black border-white/10 border-y-1 border-r-1 rounded-l-none"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={(e) => {
|
onClick={() => setIsOpen((isOpen) => !isOpen)}
|
||||||
e.stopPropagation();
|
|
||||||
setIsOpen((isOpen) => !isOpen);
|
|
||||||
}}
|
|
||||||
aria-label="Menu"
|
aria-label="Menu"
|
||||||
>
|
>
|
||||||
<Menu />
|
<Menu />
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
} from "../../components/DropdownMenu";
|
} from "../../components/DropdownMenu";
|
||||||
import { cn } from "../../lib/utils";
|
import { cn } from "../../lib/utils";
|
||||||
import { useWSMutation, useWSQuery } from "../../hooks";
|
import { useWSMutation, useWSQuery } from "../../hooks";
|
||||||
import { Suspense } from "react";
|
|
||||||
|
|
||||||
const Collection = () => {
|
const Collection = () => {
|
||||||
const { data: collection, refetch } = useWSQuery(
|
const { data: collection, refetch } = useWSQuery(
|
||||||
|
|
@ -76,7 +75,6 @@ const Collection = () => {
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Suspense>
|
|
||||||
<Board
|
<Board
|
||||||
game={testBoard(theme.id)}
|
game={testBoard(theme.id)}
|
||||||
onLeftClick={() => {}}
|
onLeftClick={() => {}}
|
||||||
|
|
@ -88,7 +86,6 @@ const Collection = () => {
|
||||||
selected && "outline-primary outline-4 rounded-md",
|
selected && "outline-primary outline-4 rounded-md",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useAtom } from "jotai";
|
||||||
import { gameIdAtom } from "../../atoms";
|
import { gameIdAtom } from "../../atoms";
|
||||||
import { Button } from "../../components/Button";
|
import { Button } from "../../components/Button";
|
||||||
import LeaderboardButton from "../../components/LeaderboardButton";
|
import LeaderboardButton from "../../components/LeaderboardButton";
|
||||||
import { Fragment, startTransition, Suspense, useEffect } from "react";
|
import { Fragment, useEffect } from "react";
|
||||||
import { Board } from "../../components/LazyBoard";
|
import { Board } from "../../components/LazyBoard";
|
||||||
|
|
||||||
interface EndlessProps {
|
interface EndlessProps {
|
||||||
|
|
@ -41,7 +41,6 @@ const Endless: React.FC<EndlessProps> = (props) => {
|
||||||
<div className="grow" />
|
<div className="grow" />
|
||||||
<LeaderboardButton label="View Leaderboard" />
|
<LeaderboardButton label="View Leaderboard" />
|
||||||
</div>
|
</div>
|
||||||
<Suspense>
|
|
||||||
<Board
|
<Board
|
||||||
game={game}
|
game={game}
|
||||||
restartGame={async () => {
|
restartGame={async () => {
|
||||||
|
|
@ -67,7 +66,6 @@ const Endless: React.FC<EndlessProps> = (props) => {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full grid md:grid-cols-[350px_1fr]">
|
<div className="w-full grid md:grid-cols-[350px_1fr]">
|
||||||
|
|
@ -78,9 +76,7 @@ const Endless: React.FC<EndlessProps> = (props) => {
|
||||||
variant="primary"
|
variant="primary"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const gameId = await startGame.mutateAsync(null);
|
const gameId = await startGame.mutateAsync(null);
|
||||||
startTransition(() => {
|
|
||||||
setGameId(gameId.uuid);
|
setGameId(gameId.uuid);
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Start Game
|
Start Game
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import {
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "../../components/Tooltip";
|
} from "../../components/Tooltip";
|
||||||
import PastMatch from "../../components/PastMatch";
|
import PastMatch from "../../components/PastMatch";
|
||||||
import GemsIcon from "../../components/GemIcon";
|
|
||||||
|
|
||||||
const Profile: React.FC = () => {
|
const Profile: React.FC = () => {
|
||||||
const { data: username } = useWSQuery("user.getSelf", null);
|
const { data: username } = useWSQuery("user.getSelf", null);
|
||||||
|
|
@ -44,11 +43,6 @@ const Profile: React.FC = () => {
|
||||||
<p>
|
<p>
|
||||||
Average Stage: {Math.round(profile?.averageStage ?? 1 * 100) / 100}
|
Average Stage: {Math.round(profile?.averageStage ?? 1 * 100) / 100}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
Gems Spend:{" "}
|
|
||||||
{(profile?.totalGems ?? 0) - (profile?.currentGems ?? 0)}{" "}
|
|
||||||
<GemsIcon />
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,6 @@ const createWSClient = () => {
|
||||||
let reconnectAttempts = 0;
|
let reconnectAttempts = 0;
|
||||||
const maxReconnectAttempts = 5;
|
const maxReconnectAttempts = 5;
|
||||||
|
|
||||||
const tryReconnect = () => {
|
|
||||||
if (reconnectAttempts < maxReconnectAttempts) {
|
|
||||||
setTimeout(() => {
|
|
||||||
reconnectAttempts++;
|
|
||||||
connect();
|
|
||||||
}, 1000 * reconnectAttempts);
|
|
||||||
} else {
|
|
||||||
console.error("Max reconnect attempts reached");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const connect = () => {
|
const connect = () => {
|
||||||
ws = new WebSocket(connectionString);
|
ws = new WebSocket(connectionString);
|
||||||
|
|
||||||
|
|
@ -53,7 +42,16 @@ const createWSClient = () => {
|
||||||
|
|
||||||
ws.onmessage = emitMessage;
|
ws.onmessage = emitMessage;
|
||||||
|
|
||||||
ws.onclose = tryReconnect;
|
ws.onclose = () => {
|
||||||
|
if (reconnectAttempts < maxReconnectAttempts) {
|
||||||
|
setTimeout(() => {
|
||||||
|
reconnectAttempts++;
|
||||||
|
connect();
|
||||||
|
}, 1000 * reconnectAttempts);
|
||||||
|
} else {
|
||||||
|
console.error("Max reconnect attempts reached");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ws.onerror = (err) => {
|
ws.onerror = (err) => {
|
||||||
console.error("WebSocket error", err);
|
console.error("WebSocket error", err);
|
||||||
|
|
@ -62,11 +60,6 @@ const createWSClient = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
connect();
|
connect();
|
||||||
document.addEventListener("focus", () => {
|
|
||||||
if (ws.readyState != ws.OPEN) {
|
|
||||||
tryReconnect();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addMessageListener((event: MessageEvent) => {
|
addMessageListener((event: MessageEvent) => {
|
||||||
const data = JSON.parse(event.data) as Events;
|
const data = JSON.parse(event.data) as Events;
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,12 @@ import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react-swc";
|
import react from "@vitejs/plugin-react-swc";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import { imagetools } from "vite-imagetools";
|
import { imagetools } from "vite-imagetools";
|
||||||
// import { analyzer } from "vite-bundle-analyzer";
|
import { analyzer } from "vite-bundle-analyzer";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
server: {
|
server: {
|
||||||
port: 3003,
|
port: 3003,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [react(), tailwindcss(), imagetools(), analyzer()],
|
||||||
react(),
|
|
||||||
tailwindcss(),
|
|
||||||
imagetools(),
|
|
||||||
// analyzer()
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue