Compare commits

..

No commits in common. "118ae220ee326cc17e1e9dba1e33ac2edf540a04" and "e8d1a8afded1df4a74677884b02414bc5aeceaef" have entirely different histories.

9 changed files with 56 additions and 105 deletions

View File

@ -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,
}; };
}, },
), ),

View File

@ -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));
}; };

View File

@ -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;
};

View File

@ -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 />

View File

@ -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>
); );
})} })}

View File

@ -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

View File

@ -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">

View File

@ -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;

View File

@ -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()
],
}); });