diff --git a/.envrc b/.envrc deleted file mode 100644 index 44610e5..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake; diff --git a/.gitignore b/.gitignore index f7852a6..c523f8d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,3 @@ node_modules .DS_Store **/.DS_Store -.direnv diff --git a/app/components/alert-timer.tsx b/app/components/alert-timer.tsx index b0b37e6..ac035e1 100644 --- a/app/components/alert-timer.tsx +++ b/app/components/alert-timer.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import type { MetagameWorld } from "../utils/metagame"; -import { humanTimeAgo } from "../utils/strings"; +import type { MetagameWorld } from "~/utils/metagame"; +import { humanTimeAgo } from "~/utils/strings"; import * as styles from "./alert-timer.css"; const endTime = (alert: Required["alert"]) => { @@ -51,7 +51,7 @@ export const AlertTimer = ({ }: { alert: MetagameWorld["zones"][0]["alert"]; }) => { - const [timeLeft, setTimeLeft] = useState(<>s); + const [timeLeft, setTimeLeft] = useState(timeLeftString(alert)); useEffect(() => { if (alert) { diff --git a/app/components/faction-bar-sxs.css.ts b/app/components/faction-bar-sxs.css.ts deleted file mode 100644 index a0b40cb..0000000 --- a/app/components/faction-bar-sxs.css.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { style } from "@vanilla-extract/css"; -import { background100, background200 } from "../utils/theme"; - -export const bar = style({ - backgroundColor: background200, - width: "0.3em", - height: "1em", - border: `1px solid ${background100}`, - // margin: 2 -}); - -export const container = style({ - display: "flex", -}); - diff --git a/app/components/faction-bar-sxs.tsx b/app/components/faction-bar-sxs.tsx deleted file mode 100644 index 5d8ff34..0000000 --- a/app/components/faction-bar-sxs.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { useMemo } from "react"; -import { Population } from "../utils/saerro"; -import * as styles from "./faction-bar-sxs.css"; -import { background200, ncFaction, trFaction, vsFaction } from "../utils/theme"; - -export const FactionBarSxS = ({ - population: { nc, vs, tr }, -}: { - population: Population; -}) => { - const { vsPercent, ncPercent, trPercent } = useMemo(() => { - const total = nc + vs + tr; - return { - vsPercent: Math.round((vs / total) * 100) || 0, - ncPercent: Math.round((nc / total) * 100) || 0, - trPercent: Math.round((tr / total) * 100) || 0, - }; - }, [vs, nc, tr]); - - return ( -
- - - -
- ); -}; - -const Bar = (props: { percent: number; color: string }) => ( -
-   -
-); diff --git a/app/components/faction-bar.css.ts b/app/components/faction-bar.css.ts index e3055f6..ef2609c 100644 --- a/app/components/faction-bar.css.ts +++ b/app/components/faction-bar.css.ts @@ -1,6 +1,5 @@ import type { ComplexStyleRule } from "@vanilla-extract/css"; import { style } from "@vanilla-extract/css"; -import { edge, ncFaction, trFaction, vsFaction } from "../utils/theme"; export const bar = style({ display: "flex", @@ -9,7 +8,7 @@ export const bar = style({ flexDirection: "row", overflow: "hidden", borderRadius: "0.4rem", - border: `2px solid ${edge}`, + border: "2px solid #4d4d4d", }); export const tinyBar = style({ @@ -28,16 +27,16 @@ const shared: ComplexStyleRule = { export const left = style({ ...shared, - backgroundColor: vsFaction, + backgroundColor: "#991cba", }); export const center = style({ ...shared, - backgroundColor: ncFaction, - borderLeft: `1px solid ${edge}`, - borderRight: `2px solid ${edge}`, + backgroundColor: "#1564cc", + borderLeft: "1px solid #4d4d4d", + borderRight: "2px solid #4d4d4d", boxShadow: "inset 0 0 0.5rem rgb(180 180 180 / 10%)", }); export const right = style({ ...shared, - backgroundColor: trFaction, + backgroundColor: "#d30101", }); diff --git a/app/components/faction-bar.tsx b/app/components/faction-bar.tsx index 1eb7d2a..727c65c 100644 --- a/app/components/faction-bar.tsx +++ b/app/components/faction-bar.tsx @@ -1,5 +1,5 @@ import { useMemo } from "react"; -import type { Population } from "../utils/saerro"; +import type { Population } from "~/utils/saerro"; import * as styles from "./faction-bar.css"; export const FactionBar = ({ diff --git a/app/components/faction-pie.tsx b/app/components/faction-pie.tsx index 4298994..2d9ed32 100644 --- a/app/components/faction-pie.tsx +++ b/app/components/faction-pie.tsx @@ -1,5 +1,4 @@ -import { background200, ncFaction, trFaction, vsFaction } from "../utils/theme"; -import type { Population } from "../utils/saerro"; +import type { Population } from "~/utils/saerro"; import { pieRoot } from "./faction-pie.css"; export const FactionPie = ({ @@ -25,11 +24,10 @@ export const FactionPie = ({ style={ { fontSize: size || "1em", - backgroundColor: background200, backgroundImage: `conic-gradient( - ${trFaction} 0% ${trPct}%, - ${vsFaction} ${trPct}% ${trPct + vsPct}%, - ${ncFaction} ${trPct + vsPct}% 100% + #d30101 0% ${trPct}%, + #991cba ${trPct}% ${trPct + vsPct}%, + #1564cc ${trPct + vsPct}% 100% )`, "--inner-margin": innerMargin ? `${innerMargin}px` : "0", "--inner-bg": innerBackground || "none", diff --git a/app/components/footer.css.ts b/app/components/footer.css.ts index 35177b7..f652d2e 100644 --- a/app/components/footer.css.ts +++ b/app/components/footer.css.ts @@ -1,5 +1,5 @@ import { style } from "@vanilla-extract/css"; -import footer from "../images/footer.jpg"; +import footer from "~/images/footer.jpg"; export const root = style({ height: 300, diff --git a/app/components/index-world-container.tsx b/app/components/index-world-container.tsx index 32d6b11..44ae6f0 100644 --- a/app/components/index-world-container.tsx +++ b/app/components/index-world-container.tsx @@ -1,7 +1,7 @@ import { IndexWorld } from "./index-world"; import * as styles from "./index-world-container.css"; -import type { MetagameWorld } from "../utils/metagame"; -import type { PopulationWorld } from "../utils/population"; +import type { MetagameWorld } from "~/utils/metagame"; +import type { PopulationWorld } from "~/utils/population"; export const WorldContainer = ({ metagame, diff --git a/app/components/index-world.tsx b/app/components/index-world.tsx index 54c2548..31a61f3 100644 --- a/app/components/index-world.tsx +++ b/app/components/index-world.tsx @@ -1,13 +1,19 @@ import { Link } from "@remix-run/react"; -import { snakeCaseToTitleCase, worlds, zones } from "../utils/strings"; +import { + humanTimeAgo, + snakeCaseToTitleCase, + worlds, + zones, +} from "~/utils/strings"; import * as styles from "./index-world.css"; -import vsLogo from "../images/vs-100.png"; -import ncLogo from "../images/nc-100.png"; -import trLogo from "../images/tr-100.png"; +import vsLogo from "~/images/vs-100.png"; +import ncLogo from "~/images/nc-100.png"; +import trLogo from "~/images/tr-100.png"; import { FactionBar } from "./faction-bar"; -import type { MetagameWorld } from "../utils/metagame"; -import type { PopulationWorld } from "../utils/population"; -import { c } from "../utils/classes"; +import type { MetagameWorld } from "~/utils/metagame"; +import type { PopulationWorld } from "~/utils/population"; +import { c } from "~/utils/classes"; +import { useEffect, useState } from "react"; import { AlertTimer } from "./alert-timer"; export type IndexWorldProps = { diff --git a/app/components/world-zone-container.css.ts b/app/components/world-zone-container.css.ts deleted file mode 100644 index 9dd9e8d..0000000 --- a/app/components/world-zone-container.css.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { style } from "@vanilla-extract/css"; - -export const zoneContainer = style({ - margin: "0.5em 1em", - backgroundColor: "#222", - padding: "1em", - boxSizing: "border-box", -}); - -export const zoneHeader = style({ - display: "flex", -}); - -export const chartTileTotal = style({ - textAlign: "center", - lineHeight: 1, - minWidth: "2em", - maxWidth: "2em", - fontSize: "3rem", - overflowY: "hidden", -}); - -export const chartTilePopLine = style({ - display: "flex", - fontSize: "1.5rem", - fontWeight: "bold", - alignItems: "center", - justifyContent: "center", - lineHeight: 1.1, - margin: 0, -}); - -export const chartTilePopImage = style({ - width: "1em", - // height: "1em", - marginRight: 4, -}); - -export const chartTile = style({ - fontSize: "4rem", - flex: "0 3 33%", - display: "flex", - marginTop: "0.2em", -}); - -export const classesContainer = style({ - display: "flex", - flex: "1 3 100%", - flexWrap: "wrap", - justifyContent: "space-evenly", -}); - -export const chartTileChart = style({ - display: "flex", - flexDirection: "column", - alignItems: "center", - justifyContent: "center", -}); diff --git a/app/components/world-zone-container.tsx b/app/components/world-zone-container.tsx deleted file mode 100644 index ac3c748..0000000 --- a/app/components/world-zone-container.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { - allClasses, - Population, - totalPopulation, - World, - Zone, -} from "../utils/saerro"; -import { headerFont } from "./world.css"; -import { - chartTile, - chartTileChart, - chartTilePopImage, - chartTilePopLine, - chartTileTotal, - classesContainer, - zoneContainer, - zoneHeader, -} from "./world-zone-container.css"; -import { classIconMap } from "../utils/class-icons"; -import { FactionBarSxS } from "./faction-bar-sxs"; -import { c } from "../utils/classes"; -import vsLogo from "../images/vs-100.png"; -import ncLogo from "../images/nc-100.png"; -import trLogo from "../images/tr-100.png"; - -export type WZCProps = { - world: World; - zone: Zone; -}; - -export const WorldZoneContainer = (props: WZCProps) => { - return ( -
-
-

{props.zone.name.toUpperCase()}

- {/* TODO: metagame */} -
-
-

CLASSES

-
- -
-   -
-
-   -
-
-
-
- ); -}; - -const Classes = (props: { classes: Zone["classes"] }) => { - if (props.classes === undefined) { - return null; - } - - return ( -
- {allClasses.map((name) => ( - )[name]} - /> - ))} -
- ); -}; - -const ChartTile = (props: { name: string; pop: Population }) => ( -
-
- - -
-
-
- {totalPopulation(props.pop)} -
-
-
- VS{" "} - {props.pop.vs} -
-
- NC{" "} - {props.pop.nc} -
-
- TR{" "} - {props.pop.tr} -
-
-
-
-); diff --git a/app/components/world.css.ts b/app/components/world.css.ts index 31d8909..edd9208 100644 --- a/app/components/world.css.ts +++ b/app/components/world.css.ts @@ -28,6 +28,7 @@ export const headerSub = style({ export const outer = style({ display: "flex", + justifyContent: "center", minHeight: "100vh", flexDirection: "column", maxWidth: "1920px", diff --git a/app/entry.client.tsx b/app/entry.client.tsx new file mode 100644 index 0000000..94d5dc0 --- /dev/null +++ b/app/entry.client.tsx @@ -0,0 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + +import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; + +startTransition(() => { + hydrateRoot( + document, + + + + ); +}); diff --git a/app/entry.server.tsx b/app/entry.server.tsx new file mode 100644 index 0000000..7fd5b88 --- /dev/null +++ b/app/entry.server.tsx @@ -0,0 +1,38 @@ +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.server + */ + +import type { EntryContext } from "@remix-run/cloudflare"; +import { RemixServer } from "@remix-run/react"; +import isbot from "isbot"; +import { renderToReadableStream } from "react-dom/server"; + +export default async function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + const body = await renderToReadableStream( + , + { + signal: request.signal, + onError(error: unknown) { + console.error(error); + responseStatusCode = 500; + }, + } + ); + + if (isbot(request.headers.get("user-agent"))) { + await body.allReady; + } + + responseHeaders.set("Content-Type", "text/html"); + return new Response(body, { + headers: responseHeaders, + status: responseStatusCode, + }); +} diff --git a/app/images/icon_engi.png b/app/images/icon_engi.png deleted file mode 100644 index 8a31388..0000000 Binary files a/app/images/icon_engi.png and /dev/null differ diff --git a/app/images/icon_heavy.png b/app/images/icon_heavy.png deleted file mode 100644 index 6860505..0000000 Binary files a/app/images/icon_heavy.png and /dev/null differ diff --git a/app/images/icon_infil.png b/app/images/icon_infil.png deleted file mode 100644 index ccd14f3..0000000 Binary files a/app/images/icon_infil.png and /dev/null differ diff --git a/app/images/icon_light.png b/app/images/icon_light.png deleted file mode 100644 index 2ea42e3..0000000 Binary files a/app/images/icon_light.png and /dev/null differ diff --git a/app/images/icon_max.png b/app/images/icon_max.png deleted file mode 100644 index 8cfebc3..0000000 Binary files a/app/images/icon_max.png and /dev/null differ diff --git a/app/images/icon_medic.png b/app/images/icon_medic.png deleted file mode 100644 index f44a6c3..0000000 Binary files a/app/images/icon_medic.png and /dev/null differ diff --git a/app/images/vehicles/ant.png b/app/images/vehicles/ant.png deleted file mode 100644 index 8e2126f..0000000 Binary files a/app/images/vehicles/ant.png and /dev/null differ diff --git a/app/images/vehicles/chimera.png b/app/images/vehicles/chimera.png deleted file mode 100644 index 22989f5..0000000 Binary files a/app/images/vehicles/chimera.png and /dev/null differ diff --git a/app/images/vehicles/corsair.png b/app/images/vehicles/corsair.png deleted file mode 100644 index d0c0609..0000000 Binary files a/app/images/vehicles/corsair.png and /dev/null differ diff --git a/app/images/vehicles/dervish.png b/app/images/vehicles/dervish.png deleted file mode 100644 index 8dbcee0..0000000 Binary files a/app/images/vehicles/dervish.png and /dev/null differ diff --git a/app/images/vehicles/flash.png b/app/images/vehicles/flash.png deleted file mode 100644 index 0f62482..0000000 Binary files a/app/images/vehicles/flash.png and /dev/null differ diff --git a/app/images/vehicles/galaxy.png b/app/images/vehicles/galaxy.png deleted file mode 100644 index 5bfabfe..0000000 Binary files a/app/images/vehicles/galaxy.png and /dev/null differ diff --git a/app/images/vehicles/harasser.png b/app/images/vehicles/harasser.png deleted file mode 100644 index 8c9dd87..0000000 Binary files a/app/images/vehicles/harasser.png and /dev/null differ diff --git a/app/images/vehicles/javelin.png b/app/images/vehicles/javelin.png deleted file mode 100644 index ba0068c..0000000 Binary files a/app/images/vehicles/javelin.png and /dev/null differ diff --git a/app/images/vehicles/liberator.png b/app/images/vehicles/liberator.png deleted file mode 100644 index 1d07c52..0000000 Binary files a/app/images/vehicles/liberator.png and /dev/null differ diff --git a/app/images/vehicles/lightning.png b/app/images/vehicles/lightning.png deleted file mode 100644 index 1d07c52..0000000 Binary files a/app/images/vehicles/lightning.png and /dev/null differ diff --git a/app/images/vehicles/magrider.png b/app/images/vehicles/magrider.png deleted file mode 100644 index 8144989..0000000 Binary files a/app/images/vehicles/magrider.png and /dev/null differ diff --git a/app/images/vehicles/mosquito.png b/app/images/vehicles/mosquito.png deleted file mode 100644 index 0f62482..0000000 Binary files a/app/images/vehicles/mosquito.png and /dev/null differ diff --git a/app/images/vehicles/prowler.png b/app/images/vehicles/prowler.png deleted file mode 100644 index 475e310..0000000 Binary files a/app/images/vehicles/prowler.png and /dev/null differ diff --git a/app/images/vehicles/reaver.png b/app/images/vehicles/reaver.png deleted file mode 100644 index 847f8c5..0000000 Binary files a/app/images/vehicles/reaver.png and /dev/null differ diff --git a/app/images/vehicles/scythe.png b/app/images/vehicles/scythe.png deleted file mode 100644 index 1e0148b..0000000 Binary files a/app/images/vehicles/scythe.png and /dev/null differ diff --git a/app/images/vehicles/sunderer.png b/app/images/vehicles/sunderer.png deleted file mode 100644 index 644c783..0000000 Binary files a/app/images/vehicles/sunderer.png and /dev/null differ diff --git a/app/images/vehicles/valkyrie.png b/app/images/vehicles/valkyrie.png deleted file mode 100644 index 4a64a15..0000000 Binary files a/app/images/vehicles/valkyrie.png and /dev/null differ diff --git a/app/images/vehicles/vanguard.png b/app/images/vehicles/vanguard.png deleted file mode 100644 index 1d1f1c2..0000000 Binary files a/app/images/vehicles/vanguard.png and /dev/null differ diff --git a/app/root.tsx b/app/root.tsx index 438f136..95c8baf 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,4 +1,4 @@ -import type { LinksFunction } from "@remix-run/node"; +import type { LinksFunction } from "@remix-run/cloudflare"; import { cssBundleHref } from "@remix-run/css-bundle"; import { Links, @@ -14,11 +14,17 @@ import "./reset.css"; export const links: LinksFunction = () => [ { rel: "preconnect", - href: "https://fonts.bunny.net", + href: "https://fonts.gstatic.com", + crossOrigin: "anonymous", + }, + { + rel: "preconnect", + href: "ttps://fonts.googleapis.com", + crossOrigin: "anonymous", }, { rel: "stylesheet", - href: "https://fonts.bunny.net/css?family=unbounded:700", + href: "https://fonts.googleapis.com/css2?family=Unbounded:wght@700&display=swap", }, ...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []), @@ -37,6 +43,7 @@ export default function App() { + ); diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index c57cdbd..24db3ce 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -1,10 +1,10 @@ -import { json, type MetaFunction } from "@remix-run/node"; +import { json, type V2_MetaFunction } from "@remix-run/cloudflare"; import { useLoaderData } from "@remix-run/react"; -import { Footer } from "../components/footer"; -import { WorldContainer } from "../components/index-world-container"; -import { outer } from "../components/index.css"; -import { fetchMetagameWorlds } from "../utils/metagame"; -import { fetchPopulationWorlds } from "../utils/population"; +import { Footer } from "~/components/footer"; +import { WorldContainer } from "~/components/index-world-container"; +import { outer } from "~/components/index.css"; +import { fetchMetagameWorlds } from "~/utils/metagame"; +import { fetchPopulationWorlds } from "~/utils/population"; export const loader = async () => { const [metagame, population] = await Promise.all([ @@ -15,7 +15,7 @@ export const loader = async () => { return json({ metagame: metagame.sort((a, b) => a.id - b.id), population }); }; -export const meta: MetaFunction = () => { +export const meta: V2_MetaFunction = () => { return [ { title: "PS2.LIVE" }, { diff --git a/app/routes/about.tsx b/app/routes/about.tsx index 5bcd385..1b0f3d7 100644 --- a/app/routes/about.tsx +++ b/app/routes/about.tsx @@ -1,4 +1,4 @@ -import { Footer } from "../components/footer"; +import { Footer } from "~/components/footer"; import { header, item, @@ -8,7 +8,7 @@ import { link, love, outer, -} from "../components/about.css"; +} from "~/components/about.css"; export default function About() { return ( diff --git a/app/routes/debug.components.tsx b/app/routes/debug.components.tsx index 3bb0a83..5d7b186 100644 --- a/app/routes/debug.components.tsx +++ b/app/routes/debug.components.tsx @@ -1,8 +1,7 @@ import { useState } from "react"; -import { FactionBar } from "../components/faction-bar"; -import { FactionPie } from "../components/faction-pie"; -import type { Population } from "../utils/saerro"; -import { FactionBarSxS } from "../components/faction-bar-sxs"; +import { FactionBar } from "~/components/faction-bar"; +import { FactionPie } from "~/components/faction-pie"; +import type { Population } from "~/utils/saerro"; export default function DebugComponents() { const [population, setPopulation] = useState({ @@ -67,10 +66,6 @@ export default function DebugComponents() { value={innerColor} onChange={(e) => setInnerColor(e.target.value)} /> -

Vertical Side-by-Side Bar Chart

-
- -
); diff --git a/app/routes/worlds.$id.tsx b/app/routes/worlds.$id.tsx index 97996c4..6476747 100644 --- a/app/routes/worlds.$id.tsx +++ b/app/routes/worlds.$id.tsx @@ -1,33 +1,32 @@ -import type { MetaFunction } from "@remix-run/node"; -import { json } from "@remix-run/node"; +import type { LoaderArgs, V2_MetaFunction } from "@remix-run/cloudflare"; +import { json } from "@remix-run/cloudflare"; import { useLoaderData } from "@remix-run/react"; -import { Footer } from "../components/footer"; -import type { MetagameWorld } from "../utils/metagame"; -import { fetchSingleMetagameWorld } from "../utils/metagame"; -import type { WorldResponse, Zone } from "../utils/saerro"; +import { Footer } from "~/components/footer"; +import type { MetagameWorld } from "~/utils/metagame"; +import { fetchSingleMetagameWorld } from "~/utils/metagame"; +import type { WorldResponse, Zone } from "~/utils/saerro"; import { allClasses, allVehicles, totalPopulation, worldQuery, -} from "../utils/saerro"; +} from "~/utils/saerro"; import { pascalCaseToTitleCase, toTitleCase, worlds, zones, -} from "../utils/strings"; -import * as styles from "../components/world.css"; -import { c } from "../utils/classes"; -import { FactionBar } from "../components/faction-bar"; -import { popImage } from "../components/index-world.css"; -import vsLogo from "../images/vs-100.png"; -import ncLogo from "../images/nc-100.png"; -import trLogo from "../images/tr-100.png"; -import { FactionPie } from "../components/faction-pie"; -import { AlertTimer } from "../components/alert-timer"; -import { contPrioritySort, zonePopulationSort } from "../utils/sorting"; -import { WorldZoneContainer } from "../components/world-zone-container"; +} from "~/utils/strings"; +import * as styles from "~/components/world.css"; +import { c } from "~/utils/classes"; +import { FactionBar } from "~/components/faction-bar"; +import { popImage } from "~/components/index-world.css"; +import vsLogo from "~/images/vs-100.png"; +import ncLogo from "~/images/nc-100.png"; +import trLogo from "~/images/tr-100.png"; +import { FactionPie } from "~/components/faction-pie"; +import { AlertTimer } from "~/components/alert-timer"; +import { contPrioritySort } from "~/utils/sorting"; type LoaderData = { saerro: WorldResponse; @@ -35,7 +34,7 @@ type LoaderData = { id: string; }; -export async function loader({ params }) { +export async function loader({ params }: LoaderArgs) { const [saerro, metagame] = await Promise.all([ worldQuery(params.id as string), fetchSingleMetagameWorld(params.id as string), @@ -43,7 +42,7 @@ export async function loader({ params }) { return json({ saerro, metagame, id: params.id } as LoaderData); } -export const meta: MetaFunction = ({ data }) => { +export const meta: V2_MetaFunction = ({ data }) => { const { saerro, id } = data as LoaderData; const date = new Date(); const worldInfo = worlds[String(id || "default")]; @@ -169,13 +168,10 @@ export default function World() {
-

WARZONES

-
- {world.zones.all.sort(zonePopulationSort).map((zone) => ( - - // - ))} -
+

Continents

+ {world.zones.all.map((zone) => ( + + ))}
@@ -187,8 +183,8 @@ export default function World() { const ZoneInfo = ({ zone }: { zone: Zone }) => { const zoneInfo = zones[String(zone.id)]; return ( -
-

{zoneInfo.name.toUpperCase()}

+
+

{zoneInfo.name}

{totalPopulation(zone.population)} players ({zone.population.vs} VS,{" "} {zone.population.nc} NC, {zone.population.tr} TR) diff --git a/app/utils/class-icons.ts b/app/utils/class-icons.ts deleted file mode 100644 index 345014f..0000000 --- a/app/utils/class-icons.ts +++ /dev/null @@ -1,17 +0,0 @@ -import combatMedic from "../images/icon_medic.png"; -import engineer from "../images/icon_engi.png"; -import heavyAssault from "../images/icon_heavy.png"; -import infiltrator from "../images/icon_infil.png"; -import lightAssault from "../images/icon_light.png"; -import max from "../images/icon_max.png"; - -export { combatMedic, engineer, heavyAssault, infiltrator, lightAssault, max }; - -export const classIconMap = { - combatMedic, - engineer, - heavyAssault, - infiltrator, - lightAssault, - max, -}; diff --git a/app/utils/saerro.ts b/app/utils/saerro.ts index 210d90d..6760946 100644 --- a/app/utils/saerro.ts +++ b/app/utils/saerro.ts @@ -1,6 +1,11 @@ export const saerroFetch = async (query: string): Promise => { const response = await fetch( - `https://saerro.ps2.live/graphql?query=${query}` + `https://saerro.ps2.live/graphql?query=${query}`, + { + cf: { + cacheTtl: 60, + }, + } ); const json: { data: T } = await response.json(); return json.data; @@ -17,10 +22,10 @@ export type Zone = { id: string; name: string; population: Population; - vehicles?: Record<(typeof allVehicles)[number], Population> & { + vehicles?: Record & { total: number; }; - classes?: Record<(typeof allClasses)[number], Population>; + classes?: Record; }; export type World = { @@ -78,7 +83,6 @@ export const worldQuery = async (worldID: string): Promise => { zones { all { id - name classes { ${allClasses.map((cls) => `${cls} { total nc tr vs }`).join(" ")} } diff --git a/app/utils/sorting.ts b/app/utils/sorting.ts index 0849152..89d2318 100644 --- a/app/utils/sorting.ts +++ b/app/utils/sorting.ts @@ -1,5 +1,4 @@ import type { MetagameWorld } from "./metagame"; -import { totalPopulation, type Zone } from "./saerro"; export const contPrioritySort = ( a: MetagameWorld["zones"][number], @@ -42,24 +41,3 @@ export const contPrioritySort = ( return 0; }; - -export const zonePopulationSort = (a: Zone, b: Zone): number => { - const total = ({ nc, vs, tr }: { nc: number; vs: number; tr: number }) => - nc + vs + tr; - const ap = total(a.population); - const bp = total(b.population); - - if (ap < bp) { - return 1; - } - - if (ap > bp) { - return -1; - } - - if (ap === bp) { - return a.id < b.id ? 1 : -1; - } - - return 0; -}; diff --git a/app/utils/theme.ts b/app/utils/theme.ts deleted file mode 100644 index a0fd6d0..0000000 --- a/app/utils/theme.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const trFaction = "#d30101"; -export const ncFaction = "#1564cc"; -export const vsFaction = "#991cba"; - -export const background100 = "#222"; -export const background200 = "#444"; - -export const edge = "#4d4d4d"; diff --git a/app/utils/vehicle-icons.ts b/app/utils/vehicle-icons.ts deleted file mode 100644 index c89cf47..0000000 --- a/app/utils/vehicle-icons.ts +++ /dev/null @@ -1,60 +0,0 @@ -import ant from "../images/vehicles/ant.png"; -import chimera from "../images/vehicles/chimera.png"; -import corsair from "../images/vehicles/corsair.png"; -import dervish from "../images/vehicles/dervish.png"; -import flash from "../images/vehicles/flash.png"; -import galaxy from "../images/vehicles/galaxy.png"; -import harasser from "../images/vehicles/harasser.png"; -import javelin from "../images/vehicles/javelin.png"; -import liberator from "../images/vehicles/liberator.png"; -import lightning from "../images/vehicles/lightning.png"; -import magrider from "../images/vehicles/magrider.png"; -import mosquito from "../images/vehicles/mosquito.png"; -import prowler from "../images/vehicles/prowler.png"; -import reaver from "../images/vehicles/reaver.png"; -import scythe from "../images/vehicles/scythe.png"; -import sunderer from "../images/vehicles/sunderer.png"; -import valkyrie from "../images/vehicles/valkyrie.png"; -import vanguard from "../images/vehicles/vanguard.png"; - -export { - ant, - chimera, - corsair, - dervish, - flash, - galaxy, - harasser, - javelin, - liberator, - lightning, - magrider, - mosquito, - prowler, - reaver, - scythe, - sunderer, - valkyrie, - vanguard, -}; - -export const vehicleIconMap = { - ant, - chimera, - corsair, - dervish, - flash, - galaxy, - harasser, - javelin, - liberator, - lightning, - magrider, - mosquito, - prowler, - reaver, - scythe, - sunderer, - valkyrie, - vanguard, -}; diff --git a/build/index.js b/build/index.js deleted file mode 100644 index ffe2fa0..0000000 --- a/build/index.js +++ /dev/null @@ -1,1904 +0,0 @@ -var __defProp = Object.defineProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: !0 }); -}; - -// node_modules/@remix-run/dev/dist/config/defaults/entry.server.node.tsx -var entry_server_node_exports = {}; -__export(entry_server_node_exports, { - default: () => handleRequest -}); -import { PassThrough } from "node:stream"; -import { createReadableStreamFromReadable } from "@remix-run/node"; -import { RemixServer } from "@remix-run/react"; -import * as isbotModule from "isbot"; -import { renderToPipeableStream } from "react-dom/server"; -import { jsxDEV } from "react/jsx-dev-runtime"; -var ABORT_DELAY = 5e3; -function handleRequest(request, responseStatusCode, responseHeaders, remixContext, loadContext) { - return isBotRequest(request.headers.get("user-agent")) || remixContext.isSpaMode ? handleBotRequest( - request, - responseStatusCode, - responseHeaders, - remixContext - ) : handleBrowserRequest( - request, - responseStatusCode, - responseHeaders, - remixContext - ); -} -function isBotRequest(userAgent) { - return userAgent ? "isbot" in isbotModule && typeof isbotModule.isbot == "function" ? isbotModule.isbot(userAgent) : "default" in isbotModule && typeof isbotModule.default == "function" ? isbotModule.default(userAgent) : !1 : !1; -} -function handleBotRequest(request, responseStatusCode, responseHeaders, remixContext) { - return new Promise((resolve, reject) => { - let shellRendered = !1, { pipe, abort } = renderToPipeableStream( - /* @__PURE__ */ jsxDEV( - RemixServer, - { - context: remixContext, - url: request.url, - abortDelay: ABORT_DELAY - }, - void 0, - !1, - { - fileName: "node_modules/@remix-run/dev/dist/config/defaults/entry.server.node.tsx", - lineNumber: 66, - columnNumber: 7 - }, - this - ), - { - onAllReady() { - shellRendered = !0; - let body = new PassThrough(), stream = createReadableStreamFromReadable(body); - responseHeaders.set("Content-Type", "text/html"), resolve( - new Response(stream, { - headers: responseHeaders, - status: responseStatusCode - }) - ), pipe(body); - }, - onShellError(error) { - reject(error); - }, - onError(error) { - responseStatusCode = 500, shellRendered && console.error(error); - } - } - ); - setTimeout(abort, ABORT_DELAY); - }); -} -function handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext) { - return new Promise((resolve, reject) => { - let shellRendered = !1, { pipe, abort } = renderToPipeableStream( - /* @__PURE__ */ jsxDEV( - RemixServer, - { - context: remixContext, - url: request.url, - abortDelay: ABORT_DELAY - }, - void 0, - !1, - { - fileName: "node_modules/@remix-run/dev/dist/config/defaults/entry.server.node.tsx", - lineNumber: 116, - columnNumber: 7 - }, - this - ), - { - onShellReady() { - shellRendered = !0; - let body = new PassThrough(), stream = createReadableStreamFromReadable(body); - responseHeaders.set("Content-Type", "text/html"), resolve( - new Response(stream, { - headers: responseHeaders, - status: responseStatusCode - }) - ), pipe(body); - }, - onShellError(error) { - reject(error); - }, - onError(error) { - responseStatusCode = 500, shellRendered && console.error(error); - } - } - ); - setTimeout(abort, ABORT_DELAY); - }); -} - -// app/root.tsx -var root_exports = {}; -__export(root_exports, { - default: () => App, - links: () => links -}); - -// css-bundle-plugin-ns:@remix-run/css-bundle -var cssBundleHref = "/build/css-bundle-RYSASN3C.css"; - -// app/root.tsx -import { - Links, - LiveReload, - Meta, - Outlet, - Scripts, - ScrollRestoration -} from "@remix-run/react"; - -// app/root.css.ts -var root = "root_root__o19f1u0"; - -// app/root.tsx -import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime"; -var links = () => [ - { - rel: "preconnect", - href: "https://fonts.gstatic.com", - crossOrigin: "anonymous" - }, - { - rel: "preconnect", - href: "ttps://fonts.googleapis.com", - crossOrigin: "anonymous" - }, - { - rel: "stylesheet", - href: "https://fonts.googleapis.com/css2?family=Unbounded:wght@700&display=swap" - }, - ...cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : [] -]; -function App() { - return /* @__PURE__ */ jsxDEV2("html", { lang: "en", children: [ - /* @__PURE__ */ jsxDEV2("head", { children: [ - /* @__PURE__ */ jsxDEV2("meta", { charSet: "utf-8" }, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 37, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV2("meta", { name: "viewport", content: "width=device-width,initial-scale=1" }, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 38, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV2(Meta, {}, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 39, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV2(Links, {}, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 40, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/root.tsx", - lineNumber: 36, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV2("body", { className: root, children: [ - /* @__PURE__ */ jsxDEV2(Outlet, {}, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 43, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV2(ScrollRestoration, {}, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 44, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV2(Scripts, {}, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 45, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV2(LiveReload, {}, void 0, !1, { - fileName: "app/root.tsx", - lineNumber: 46, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/root.tsx", - lineNumber: 42, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/root.tsx", - lineNumber: 35, - columnNumber: 5 - }, this); -} - -// app/routes/debug.components.tsx -var debug_components_exports = {}; -__export(debug_components_exports, { - default: () => DebugComponents -}); -import { useState } from "react"; - -// app/components/faction-bar.tsx -import { useMemo } from "react"; - -// app/components/faction-bar.css.ts -var bar = "faction-bar_bar__prieg10", tinyBar = "faction-bar_tinyBar__prieg11", left = "faction-bar_left__prieg12", center = "faction-bar_center__prieg13", right = "faction-bar_right__prieg14"; - -// app/components/faction-bar.tsx -import { Fragment, jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime"; -var FactionBar = ({ - population: { vs, nc, tr }, - tiny -}) => { - let { vsPercent, ncPercent, trPercent } = useMemo(() => { - let total = nc + vs + tr; - return { - vsPercent: Math.round(vs / total * 100) || 0, - ncPercent: Math.round(nc / total * 100) || 0, - trPercent: Math.round(tr / total * 100) || 0 - }; - }, [vs, nc, tr]); - return /* @__PURE__ */ jsxDEV3("div", { className: tiny ? tinyBar : bar, children: [ - /* @__PURE__ */ jsxDEV3("div", { className: left, style: { flexGrow: vs + 1 }, children: tiny ? /* @__PURE__ */ jsxDEV3(Fragment, { children: "\xA0" }, void 0, !1, { - fileName: "app/components/faction-bar.tsx", - lineNumber: 23, - columnNumber: 17 - }, this) : `${vsPercent}%` }, void 0, !1, { - fileName: "app/components/faction-bar.tsx", - lineNumber: 22, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV3("div", { className: center, style: { flexGrow: nc + 1 }, children: tiny ? /* @__PURE__ */ jsxDEV3(Fragment, { children: "\xA0" }, void 0, !1, { - fileName: "app/components/faction-bar.tsx", - lineNumber: 26, - columnNumber: 17 - }, this) : `${ncPercent}%` }, void 0, !1, { - fileName: "app/components/faction-bar.tsx", - lineNumber: 25, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV3("div", { className: right, style: { flexGrow: tr + 1 }, children: tiny ? /* @__PURE__ */ jsxDEV3(Fragment, { children: "\xA0" }, void 0, !1, { - fileName: "app/components/faction-bar.tsx", - lineNumber: 29, - columnNumber: 17 - }, this) : `${trPercent}%` }, void 0, !1, { - fileName: "app/components/faction-bar.tsx", - lineNumber: 28, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/components/faction-bar.tsx", - lineNumber: 21, - columnNumber: 5 - }, this); -}; - -// app/components/faction-pie.css.ts -var pieRoot = "faction-pie_pieRoot__15tar860"; - -// app/components/faction-pie.tsx -import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime"; -var FactionPie = ({ - population: population3, - innerMargin, - innerBackground, - size -}) => { - let { nc, tr, vs } = population3, total = nc + tr + vs, trPct = tr / total * 100, vsPct = vs / total * 100; - return /* @__PURE__ */ jsxDEV4( - "div", - { - className: pieRoot, - style: { - fontSize: size || "1em", - backgroundImage: `conic-gradient( - #d30101 0% ${trPct}%, - #991cba ${trPct}% ${trPct + vsPct}%, - #1564cc ${trPct + vsPct}% 100% - )`, - "--inner-margin": innerMargin ? `${innerMargin}px` : "0", - "--inner-bg": innerBackground || "none" - }, - children: "\xA0" - }, - void 0, - !1, - { - fileName: "app/components/faction-pie.tsx", - lineNumber: 22, - columnNumber: 5 - }, - this - ); -}; - -// app/routes/debug.components.tsx -import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime"; -function DebugComponents() { - let [population3, setPopulation] = useState({ - nc: 33, - tr: 33, - vs: 33 - }), [innerMargin, setInnerMargin] = useState(10), [innerColor, setInnerColor] = useState("black"); - return /* @__PURE__ */ jsxDEV5("div", { children: [ - /* @__PURE__ */ jsxDEV5("h1", { children: "Debug Components" }, void 0, !1, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 17, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV5("h2", { children: "Faction Viz" }, void 0, !1, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 18, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV5("div", { children: [ - "NC", - " ", - /* @__PURE__ */ jsxDEV5( - "input", - { - type: "number", - value: population3.nc, - onChange: (e) => setPopulation((p) => ({ ...p, nc: Number(e.target.value) })) - }, - void 0, - !1, - { - fileName: "app/routes/debug.components.tsx", - lineNumber: 21, - columnNumber: 9 - }, - this - ), - " ", - "|| TR", - " ", - /* @__PURE__ */ jsxDEV5( - "input", - { - type: "number", - value: population3.tr, - onChange: (e) => setPopulation((p) => ({ ...p, tr: Number(e.target.value) })) - }, - void 0, - !1, - { - fileName: "app/routes/debug.components.tsx", - lineNumber: 29, - columnNumber: 9 - }, - this - ), - " ", - "|| VS", - " ", - /* @__PURE__ */ jsxDEV5( - "input", - { - type: "number", - value: population3.vs, - onChange: (e) => setPopulation((p) => ({ ...p, vs: Number(e.target.value) })) - }, - void 0, - !1, - { - fileName: "app/routes/debug.components.tsx", - lineNumber: 37, - columnNumber: 9 - }, - this - ) - ] }, void 0, !0, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 19, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV5("div", { children: [ - /* @__PURE__ */ jsxDEV5("h3", { children: "Horizontal Stacked Bar Chart" }, void 0, !1, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 46, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV5(FactionBar, { population: population3 }, void 0, !1, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 47, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV5("h3", { children: "Pie Chart" }, void 0, !1, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 48, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV5("div", { style: { fontSize: "5rem" }, children: [ - /* @__PURE__ */ jsxDEV5(FactionPie, { population: population3 }, void 0, !1, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 50, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV5( - FactionPie, - { - population: population3, - innerBackground: innerColor, - innerMargin - }, - void 0, - !1, - { - fileName: "app/routes/debug.components.tsx", - lineNumber: 51, - columnNumber: 11 - }, - this - ) - ] }, void 0, !0, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 49, - columnNumber: 9 - }, this), - "Inner margin", - " ", - /* @__PURE__ */ jsxDEV5( - "input", - { - type: "number", - value: innerMargin, - onChange: (e) => setInnerMargin(Number(e.target.value)) - }, - void 0, - !1, - { - fileName: "app/routes/debug.components.tsx", - lineNumber: 58, - columnNumber: 9 - }, - this - ), - "Inner color", - " ", - /* @__PURE__ */ jsxDEV5( - "input", - { - type: "color", - value: innerColor, - onChange: (e) => setInnerColor(e.target.value) - }, - void 0, - !1, - { - fileName: "app/routes/debug.components.tsx", - lineNumber: 64, - columnNumber: 9 - }, - this - ) - ] }, void 0, !0, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 45, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/debug.components.tsx", - lineNumber: 16, - columnNumber: 5 - }, this); -} - -// app/routes/worlds.$id.tsx -var worlds_id_exports = {}; -__export(worlds_id_exports, { - default: () => World, - loader: () => loader, - meta: () => meta -}); -import { json } from "@remix-run/cloudflare"; -import { useLoaderData } from "@remix-run/react"; - -// app/components/footer.tsx -import { Link } from "@remix-run/react"; - -// app/components/footer.css.ts -var root2 = "footer_root__1a7dndp0", background = "footer_background__1a7dndp1", logo = "footer_logo__1a7dndp2"; -var logoLive = "footer_logoLive__1a7dndp4", logoDot = "footer_logoDot__1a7dndp5", lowerLogo = "footer_lowerLogo__1a7dndp6", link = "footer_link__1a7dndp7"; - -// app/components/footer.tsx -import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime"; -var Footer = ({ isMainPage }) => /* @__PURE__ */ jsxDEV6("footer", { children: /* @__PURE__ */ jsxDEV6("div", { className: root2, children: [ - /* @__PURE__ */ jsxDEV6("div", { className: background }, void 0, !1, { - fileName: "app/components/footer.tsx", - lineNumber: 7, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV6("div", { className: logo, children: [ - "PS2", - /* @__PURE__ */ jsxDEV6("div", { className: logoDot }, void 0, !1, { - fileName: "app/components/footer.tsx", - lineNumber: 10, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV6("span", { className: logoLive, children: "LIVE" }, void 0, !1, { - fileName: "app/components/footer.tsx", - lineNumber: 11, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV6("div", { className: lowerLogo, children: [ - /* @__PURE__ */ jsxDEV6("div", { children: isMainPage ? /* @__PURE__ */ jsxDEV6(Link, { className: link, to: "/about", children: "more stuff \xBB" }, void 0, !1, { - fileName: "app/components/footer.tsx", - lineNumber: 15, - columnNumber: 11 - }, this) : /* @__PURE__ */ jsxDEV6(Link, { className: link, to: "/", children: "less stuff \xBB" }, void 0, !1, { - fileName: "app/components/footer.tsx", - lineNumber: 19, - columnNumber: 11 - }, this) }, void 0, !1, { - fileName: "app/components/footer.tsx", - lineNumber: 13, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV6("div", { children: [ - "\xA9 ", - (/* @__PURE__ */ new Date()).getFullYear() - ] }, void 0, !0, { - fileName: "app/components/footer.tsx", - lineNumber: 24, - columnNumber: 11 - }, this) - ] }, void 0, !0, { - fileName: "app/components/footer.tsx", - lineNumber: 12, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/components/footer.tsx", - lineNumber: 8, - columnNumber: 7 - }, this) -] }, void 0, !0, { - fileName: "app/components/footer.tsx", - lineNumber: 6, - columnNumber: 5 -}, this) }, void 0, !1, { - fileName: "app/components/footer.tsx", - lineNumber: 5, - columnNumber: 1 -}, this); - -// app/utils/metagame.ts -var fetchMetagameWorlds = async () => await (await fetch("https://metagame.ps2.live/all")).json(), fetchSingleMetagameWorld = async (id) => await (await fetch(`https://metagame.ps2.live/${id}`)).json(); - -// app/utils/saerro.ts -var saerroFetch = async (query) => (await (await fetch( - `https://saerro.ps2.live/graphql?query=${query}`, - { - cf: { - cacheTtl: 60 - } - } -)).json()).data, allVehicles = [ - "flash", - "sunderer", - "lightning", - "scythe", - "vanguard", - "prowler", - "reaver", - "mosquito", - "galaxy", - "valkyrie", - "liberator", - "ant", - "harasser", - "dervish", - "chimera", - "javelin", - "corsair", - "magrider" -], allClasses = [ - "infiltrator", - "lightAssault", - "combatMedic", - "engineer", - "heavyAssault", - "max" -], worldQuery = async (worldID) => { - let query = `{ - world(by: {id: ${Number(worldID)}}) { - id - population { - nc - tr - vs - } - zones { - all { - id - classes { - ${allClasses.map((cls) => `${cls} { total nc tr vs }`).join(" ")} - } - vehicles { - total - ${allVehicles.map((vehicle) => `${vehicle} { total nc tr vs }`).join(" ")} - } - population { - nc - tr - vs - } - } - } - } - }`; - return await saerroFetch(query); -}, totalPopulation = ({ nc, vs, tr }) => nc + vs + tr; - -// app/utils/strings.ts -var toTitleCase = (str) => str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()), pascalCaseToTitleCase = (str) => toTitleCase(str.replace(/([A-Z])/g, " $1")), snakeCaseToTitleCase = (str) => toTitleCase(str.replace(/_/g, " ")), humanTimeAgo = (ms, full) => { - let millis = Math.floor(ms % 1e3), seconds = Math.floor(ms / 1e3), minutes = Math.floor(seconds / 60), hours = Math.floor(minutes / 60); - return hours > 0 ? full ? `${hours}h ${minutes % 60}m ${seconds % 60}s` : `${hours}h` : minutes > 0 ? full ? `${minutes}m ${seconds % 60}s` : `${minutes}m` : seconds > 0 ? `${seconds}s` : `${millis}ms`; -}, worlds = { - 1: { - name: "Connery", - timeZone: "America/Los_Angeles", - locale: "en-US", - location: "US-W", - platform: "PC" - }, - 10: { - name: "Miller", - timeZone: "UTC", - locale: "en-GB", - location: "EU", - platform: "PC" - }, - 13: { - name: "Cobalt", - timeZone: "UTC", - locale: "en-GB", - location: "EU", - platform: "PC" - }, - 17: { - name: "Emerald", - timeZone: "America/New_York", - locale: "en-US", - location: "US-E", - platform: "PC" - }, - 19: { - name: "Jaeger", - timeZone: "America/New_York", - locale: "en-US", - location: "US-E", - platform: "PC" - }, - 40: { - name: "SolTech", - timeZone: "Asia/Tokyo", - locale: "en-GB", - location: "JP", - platform: "PC" - }, - 1e3: { - name: "Genudine", - timeZone: "America/New_York", - locale: "en-US", - location: "US-E", - platform: "PS4" - }, - 2e3: { - name: "Ceres", - timeZone: "UTC", - locale: "en-GB", - location: "EU", - platform: "PS4" - }, - default: { - name: "Unknown", - timeZone: "UTC", - locale: "en-US", - location: "???", - platform: "???" - } -}, zones = { - 2: { - name: "Indar", - colors: ["#edb96b", "#964c2f"] - }, - 4: { - name: "Hossin", - colors: ["#47570d", "#7b9c05"] - }, - 6: { - name: "Amerish", - colors: ["#87a12a", "#5f634f"] - }, - 8: { - name: "Esamir", - colors: ["#d5f3f5", "#a1c7e6"] - }, - 344: { - name: "Oshur", - colors: ["#00c2bf", "#174185"] - }, - default: { - name: "Unknown", - colors: ["#111111", "#cccccc"] - } -}; - -// app/components/world.css.ts -var headerFont = "world_headerFont__cpwhdm0", header = "world_header__cpwhdm1", headerName = "world_headerName__cpwhdm2", headerSub = "world_headerSub__cpwhdm3", outer = "world_outer__cpwhdm4", population = "world_population__cpwhdm5", populationHead = "world_populationHead__cpwhdm6", popNumbers = "world_popNumbers__cpwhdm7", popItem = "world_popItem__cpwhdm8", totalPop = "world_totalPop__cpwhdm9", headerConts = "world_headerConts__cpwhdma"; -var cont = "world_cont__cpwhdmc", contSub = "world_contSub__cpwhdmd"; - -// app/utils/classes.ts -var c = (...args) => args.filter((x) => !!x).join(" "); - -// app/components/index-world.css.ts -var container = "index-world_container__1e3z7iu0", header2 = "index-world_header__1e3z7iu1", headerName2 = "index-world_headerName__1e3z7iu2", headerDetailsLink = "index-world_headerDetailsLink__1e3z7iu3", headerMarkers = "index-world_headerMarkers__1e3z7iu4"; -var details = "index-world_details__1e3z7iu6", population2 = "index-world_population__1e3z7iu7", popFaction = "index-world_popFaction__1e3z7iu8", popImage = "index-world_popImage__1e3z7iu9", totalPop2 = "index-world_totalPop__1e3z7iua", continent = "index-world_continent__1e3z7iub", contBars = "index-world_contBars__1e3z7iuc", contBarTitle = "index-world_contBarTitle__1e3z7iud", barSeparator = "index-world_barSeparator__1e3z7iue", contCircle = "index-world_contCircle__1e3z7iuf", contName = "index-world_contName__1e3z7iug", jaegerConts = "index-world_jaegerConts__1e3z7iuh"; -var nextCont = "index-world_nextCont__1e3z7ium", nextContText = "index-world_nextContText__1e3z7iun", oopsies = "index-world_oopsies__1e3z7iuo", oopsiesSpin = "index-world_oopsiesSpin__1e3z7iuq"; - -// app/images/vs-100.png -var vs_100_default = "/build/_assets/vs-100-5TO3XQQ2.png"; - -// app/images/nc-100.png -var nc_100_default = "/build/_assets/nc-100-22JVQEND.png"; - -// app/images/tr-100.png -var tr_100_default = "/build/_assets/tr-100-MTGS5ODT.png"; - -// app/components/alert-timer.tsx -import { useEffect, useState as useState2 } from "react"; - -// app/components/alert-timer.css.ts -var alertDot = "alert-timer_alertDot__eh4xj51", timer = "alert-timer_timer__eh4xj52"; - -// app/components/alert-timer.tsx -import { Fragment as Fragment2, jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime"; -var endTime = (alert) => { - let alertDurationMins = 90; - switch (alert.alert_type) { - case "air": - alertDurationMins = 30; - break; - case "sudden_death": - case "max": - alertDurationMins = 15; - break; - default: - break; - } - return new Date(alert.start_time).getTime() + alertDurationMins * 60 * 1e3; -}, timeLeftString = (alert) => { - if (alert) { - let time = endTime(alert) - Date.now(); - if (time < 2e3) - return /* @__PURE__ */ jsxDEV7(Fragment2, { children: "JUST ENDED" }, void 0, !1, { - fileName: "app/components/alert-timer.tsx", - lineNumber: 30, - columnNumber: 14 - }, this); - let speed = time < 1e3 * 60 * 15 ? "1s" : "4s"; - return /* @__PURE__ */ jsxDEV7(Fragment2, { children: [ - humanTimeAgo(time, !0).toUpperCase(), - " LEFT", - " ", - /* @__PURE__ */ jsxDEV7( - "div", - { - className: alertDot, - style: { "--speed": speed } - }, - void 0, - !1, - { - fileName: "app/components/alert-timer.tsx", - lineNumber: 38, - columnNumber: 9 - }, - this - ) - ] }, void 0, !0, { - fileName: "app/components/alert-timer.tsx", - lineNumber: 36, - columnNumber: 7 - }, this); - } else - return /* @__PURE__ */ jsxDEV7(Fragment2, {}, void 0, !1, { - fileName: "app/components/alert-timer.tsx", - lineNumber: 45, - columnNumber: 12 - }, this); -}, AlertTimer = ({ - alert -}) => { - let [timeLeft, setTimeLeft] = useState2(timeLeftString(alert)); - return useEffect(() => { - if (alert) { - let interval = setInterval(() => { - setTimeLeft(timeLeftString(alert)); - }, 1e3); - return () => clearInterval(interval); - } - }, [alert]), /* @__PURE__ */ jsxDEV7("div", { className: timer, children: timeLeft }, void 0, !1, { - fileName: "app/components/alert-timer.tsx", - lineNumber: 65, - columnNumber: 10 - }, this); -}; - -// app/utils/sorting.ts -var contPrioritySort = (a, b) => a.locked && !b.locked ? 1 : !a.locked && b.locked ? -1 : a.alert && b.alert ? Date.parse(a.alert.start_time) - Date.parse(b.alert.start_time) : a.alert ? -1 : b.alert ? 1 : a.locked_since && b.locked_since ? Date.parse(a.locked_since) - Date.parse(b.locked_since) : a.locked_since ? -1 : b.locked_since ? 1 : 0; - -// app/routes/worlds.$id.tsx -import { Fragment as Fragment3, jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime"; -async function loader({ params }) { - let [saerro, metagame] = await Promise.all( - [ - worldQuery(params.id), - fetchSingleMetagameWorld(params.id) - ] - ); - return json({ saerro, metagame, id: params.id }); -} -var meta = ({ data }) => { - let { saerro, id } = data, date = /* @__PURE__ */ new Date(), worldInfo = worlds[String(id || "default")], datetimeHumanFriendly = date.toLocaleString(worldInfo.locale, { - timeZone: worldInfo.timeZone, - dateStyle: "medium", - timeStyle: "short" - }); - return [ - { - title: `${worldInfo.name || "Unknown world"} | PlanetSide 2 Live Population Stats` - }, - { - name: "description", - content: `${worldInfo.name} currently has ${totalPopulation( - saerro.world.population - )} players online as of ${datetimeHumanFriendly} ${worldInfo.name} time. VS: ${saerro.world.population.vs}, NC: ${saerro.world.population.nc}, TR: ${saerro.world.population.tr} -- See more detailed stats on ps2.live.` - } - ]; -}; -function World() { - let { - saerro: { world }, - id, - metagame - } = useLoaderData(), worldInfo = worlds[String(id || "default")], nextZoneID = metagame.zones.length !== 0 ? metagame.zones.sort( - (a, b) => new Date(a.locked_since ?? Date.now()).getTime() - new Date(b.locked_since ?? Date.now()).getTime() - )[0].id : 0; - return /* @__PURE__ */ jsxDEV8(Fragment3, { children: [ - /* @__PURE__ */ jsxDEV8("div", { className: outer, children: /* @__PURE__ */ jsxDEV8("div", { children: [ - /* @__PURE__ */ jsxDEV8("div", { className: header, children: [ - /* @__PURE__ */ jsxDEV8("div", { className: c(headerName, headerFont), children: [ - /* @__PURE__ */ jsxDEV8("div", { children: worldInfo.name.toUpperCase() }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 98, - columnNumber: 15 - }, this), - /* @__PURE__ */ jsxDEV8("div", { className: headerSub, children: [ - "[", - worldInfo.location, - "] [", - worldInfo.platform, - "]" - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 99, - columnNumber: 15 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 97, - columnNumber: 13 - }, this), - /* @__PURE__ */ jsxDEV8("div", { className: populationHead, children: [ - /* @__PURE__ */ jsxDEV8("div", { className: headerFont, children: [ - /* @__PURE__ */ jsxDEV8("div", { className: totalPop, children: totalPopulation(world.population).toLocaleString() }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 105, - columnNumber: 17 - }, this), - "PLAYERS" - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 104, - columnNumber: 15 - }, this), - /* @__PURE__ */ jsxDEV8("div", { className: population, children: [ - /* @__PURE__ */ jsxDEV8("div", { className: popNumbers, children: [ - /* @__PURE__ */ jsxDEV8( - "div", - { - className: popItem, - style: { flex: world.population.vs + 1 }, - children: [ - /* @__PURE__ */ jsxDEV8("img", { className: popImage, src: vs_100_default, alt: "VS" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 116, - columnNumber: 21 - }, this), - " ", - world.population.vs - ] - }, - void 0, - !0, - { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 112, - columnNumber: 19 - }, - this - ), - /* @__PURE__ */ jsxDEV8( - "div", - { - className: popItem, - style: { flex: world.population.nc + 1 }, - children: [ - /* @__PURE__ */ jsxDEV8("img", { className: popImage, src: nc_100_default, alt: "NC" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 123, - columnNumber: 21 - }, this), - " ", - world.population.nc - ] - }, - void 0, - !0, - { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 119, - columnNumber: 19 - }, - this - ), - /* @__PURE__ */ jsxDEV8( - "div", - { - className: popItem, - style: { flex: world.population.tr + 1 }, - children: [ - /* @__PURE__ */ jsxDEV8("img", { className: popImage, src: tr_100_default, alt: "TR" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 130, - columnNumber: 21 - }, this), - " ", - world.population.tr - ] - }, - void 0, - !0, - { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 126, - columnNumber: 19 - }, - this - ) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 111, - columnNumber: 17 - }, this), - /* @__PURE__ */ jsxDEV8(FactionBar, { population: world.population }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 134, - columnNumber: 17 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 110, - columnNumber: 15 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 103, - columnNumber: 13 - }, this), - /* @__PURE__ */ jsxDEV8("div", { className: headerConts, children: [ - /* @__PURE__ */ jsxDEV8("div", { className: headerSub, children: "CONTINENT CONTROL" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 138, - columnNumber: 15 - }, this), - metagame.zones.sort(contPrioritySort).map((zone, idx) => { - let zoneInfo = zones[String(zone.id)]; - return /* @__PURE__ */ jsxDEV8("div", { className: cont, children: [ - /* @__PURE__ */ jsxDEV8("div", { style: { flex: 0 }, children: zoneInfo.name.toUpperCase() }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 143, - columnNumber: 21 - }, this), - /* @__PURE__ */ jsxDEV8("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsxDEV8( - FactionPie, - { - size: "4rem", - population: zone.alert?.percentages ?? zone.territory, - innerBackground: `linear-gradient(45deg, ${zoneInfo.colors[0]}, ${zoneInfo.colors[1]})`, - innerMargin: 10 - }, - void 0, - !1, - { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 145, - columnNumber: 23 - }, - this - ) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 144, - columnNumber: 21 - }, this), - /* @__PURE__ */ jsxDEV8("div", { className: contSub, children: zone.alert ? /* @__PURE__ */ jsxDEV8(AlertTimer, { alert: zone.alert }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 154, - columnNumber: 23 - }, this) : zone.locked ? nextZoneID == zone.id ? /* @__PURE__ */ jsxDEV8(Fragment3, { children: "NEXT UP \xBB" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 157, - columnNumber: 23 - }, this) : /* @__PURE__ */ jsxDEV8(Fragment3, { children: "LOCKED" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 159, - columnNumber: 23 - }, this) : /* @__PURE__ */ jsxDEV8(Fragment3, { children: "UNLOCKED" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 162, - columnNumber: 23 - }, this) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 152, - columnNumber: 21 - }, this) - ] }, idx, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 142, - columnNumber: 19 - }, this); - }) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 137, - columnNumber: 13 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 96, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV8("div", { children: [ - /* @__PURE__ */ jsxDEV8("h2", { children: "Continents" }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 171, - columnNumber: 13 - }, this), - world.zones.all.map( - (zone) => /* @__PURE__ */ jsxDEV8(ZoneInfo, { zone }, zone.id, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 173, - columnNumber: 13 - }, this) - ) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 170, - columnNumber: 11 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 95, - columnNumber: 9 - }, this) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 94, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV8(Footer, { isMainPage: !0 }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 178, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 93, - columnNumber: 5 - }, this); -} -var ZoneInfo = ({ zone }) => { - let zoneInfo = zones[String(zone.id)]; - return /* @__PURE__ */ jsxDEV8("section", { children: [ - /* @__PURE__ */ jsxDEV8("h3", { children: zoneInfo.name }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 187, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV8("p", { children: [ - totalPopulation(zone.population), - " players (", - zone.population.vs, - " VS,", - " ", - zone.population.nc, - " NC, ", - zone.population.tr, - " TR)" - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 188, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV8("p", { children: /* @__PURE__ */ jsxDEV8("ul", { children: allClasses.map( - (cls, idx) => /* @__PURE__ */ jsxDEV8("li", { children: [ - /* @__PURE__ */ jsxDEV8("b", { children: pascalCaseToTitleCase(cls) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 196, - columnNumber: 15 - }, this), - ": ", - zone.classes?.[cls].total, - " ", - "total, ", - zone.classes?.[cls].vs, - " VS, ", - zone.classes?.[cls].nc, - " NC,", - " ", - zone.classes?.[cls].tr, - " TR" - ] }, idx, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 195, - columnNumber: 11 - }, this) - ) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 193, - columnNumber: 9 - }, this) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 192, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV8("p", { children: [ - totalPopulation(zone.vehicles), - " vehicles...", - /* @__PURE__ */ jsxDEV8("ul", { children: allVehicles.map( - (vehicle, idx) => /* @__PURE__ */ jsxDEV8("li", { children: [ - /* @__PURE__ */ jsxDEV8("b", { children: toTitleCase(vehicle) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 208, - columnNumber: 15 - }, this), - ":", - " ", - totalPopulation(zone.vehicles?.[vehicle]), - " total,", - " ", - zone.vehicles?.[vehicle].vs, - " VS, ", - zone.vehicles?.[vehicle].nc, - " ", - "NC, ", - zone.vehicles?.[vehicle].tr, - " TR" - ] }, idx, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 207, - columnNumber: 11 - }, this) - ) }, void 0, !1, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 205, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 203, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/worlds.$id.tsx", - lineNumber: 186, - columnNumber: 5 - }, this); -}; - -// app/routes/_index.tsx -var index_exports = {}; -__export(index_exports, { - default: () => Index, - loader: () => loader2, - meta: () => meta2 -}); -import { json as json2 } from "@remix-run/cloudflare"; -import { useLoaderData as useLoaderData2 } from "@remix-run/react"; - -// app/components/index-world.tsx -import { Link as Link2 } from "@remix-run/react"; -import { Fragment as Fragment4, jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime"; -var IndexWorld = ({ metagame, population: population3 }) => { - let worldId = metagame.id, { platform, location, name } = worlds[String(worldId || "default")]; - if (metagame.zones.length === 0) - return /* @__PURE__ */ jsxDEV9(BrokenWorld, { worldId }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 29, - columnNumber: 12 - }, this); - let nextZone = metagame.zones.sort( - (a, b) => new Date(a.locked_since ?? Date.now()).getTime() - new Date(b.locked_since ?? Date.now()).getTime() - )[0], nextZoneStrings = zones[nextZone.id]; - return /* @__PURE__ */ jsxDEV9("div", { className: container, children: [ - /* @__PURE__ */ jsxDEV9(Link2, { to: `/worlds/${worldId}`, className: header2, children: [ - /* @__PURE__ */ jsxDEV9("div", { className: headerName2, children: name }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 42, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: headerMarkers, children: [ - "[", - location, - "] [", - platform, - "]", - " " - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 43, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: headerDetailsLink, children: "DETAILS \u21E8" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 46, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 41, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: details, children: [ - /* @__PURE__ */ jsxDEV9("div", { className: population2, children: [ - /* @__PURE__ */ jsxDEV9("div", { className: totalPop2, children: population3.factions.vs + population3.factions.nc + population3.factions.tr }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 50, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: popFaction, children: [ - /* @__PURE__ */ jsxDEV9("img", { className: popImage, src: vs_100_default, alt: "VS" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 56, - columnNumber: 13 - }, this), - " ", - population3.factions.vs - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 55, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: popFaction, children: [ - /* @__PURE__ */ jsxDEV9("img", { className: popImage, src: nc_100_default, alt: "NC" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 60, - columnNumber: 13 - }, this), - " ", - population3.factions.nc - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 59, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: popFaction, children: [ - /* @__PURE__ */ jsxDEV9("img", { className: popImage, src: tr_100_default, alt: "TR" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 64, - columnNumber: 13 - }, this), - " ", - population3.factions.tr - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 63, - columnNumber: 11 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 49, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV9(FactionBar, { population: population3.factions }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 68, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 48, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: c(worldId === 19 && jaegerConts), children: [ - metagame.zones.filter((zone) => !zone.locked).sort((a, b) => a.alert && !b.alert ? -1 : b.alert && !a.alert ? 1 : 0).map((zone) => worldId !== 19 ? /* @__PURE__ */ jsxDEV9(Continent, { zone }, zone.id, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 78, - columnNumber: 11 - }, this) : /* @__PURE__ */ jsxDEV9(JaegerContinent, { zone }, zone.id, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 80, - columnNumber: 11 - }, this)), - worldId !== 19 && /* @__PURE__ */ jsxDEV9("div", { className: nextCont, children: [ - /* @__PURE__ */ jsxDEV9("div", { className: nextContText, children: "Next continent \xBB" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 85, - columnNumber: 13 - }, this), - " ", - /* @__PURE__ */ jsxDEV9("div", { className: contName, children: [ - /* @__PURE__ */ jsxDEV9( - "div", - { - className: contCircle, - style: { - "--upper-color": nextZoneStrings.colors[0], - "--lower-color": nextZoneStrings.colors[1] - } - }, - void 0, - !1, - { - fileName: "app/components/index-world.tsx", - lineNumber: 87, - columnNumber: 15 - }, - this - ), - /* @__PURE__ */ jsxDEV9("div", { children: nextZoneStrings.name }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 96, - columnNumber: 15 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 86, - columnNumber: 13 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 84, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 70, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 40, - columnNumber: 5 - }, this); -}, JaegerContinent = ({ zone }) => { - let { - name, - colors: [upper, lower] - } = zones[zone.id]; - return /* @__PURE__ */ jsxDEV9("div", { className: contName, children: [ - /* @__PURE__ */ jsxDEV9( - "div", - { - className: contCircle, - style: { - "--upper-color": upper, - "--lower-color": lower - } - }, - void 0, - !1, - { - fileName: "app/components/index-world.tsx", - lineNumber: 112, - columnNumber: 7 - }, - this - ), - /* @__PURE__ */ jsxDEV9("div", { children: name }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 121, - columnNumber: 7 - }, this) - ] }, zone.id, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 111, - columnNumber: 5 - }, this); -}, Continent = ({ zone }) => { - let { - name, - colors: [upper, lower] - } = zones[zone.id]; - return /* @__PURE__ */ jsxDEV9("div", { className: c(continent), children: [ - /* @__PURE__ */ jsxDEV9("div", { className: contName, children: [ - /* @__PURE__ */ jsxDEV9( - "div", - { - className: contCircle, - style: { - "--upper-color": upper, - "--lower-color": lower - } - }, - void 0, - !1, - { - fileName: "app/components/index-world.tsx", - lineNumber: 135, - columnNumber: 9 - }, - this - ), - /* @__PURE__ */ jsxDEV9("div", { children: name }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 144, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 134, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: contBars, children: [ - /* @__PURE__ */ jsxDEV9("div", { children: [ - /* @__PURE__ */ jsxDEV9("div", { className: contBarTitle, children: "TERRITORY CONTROL" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 148, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV9(FactionBar, { population: zone.territory }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 149, - columnNumber: 11 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 147, - columnNumber: 9 - }, this), - zone.alert && /* @__PURE__ */ jsxDEV9(Fragment4, { children: [ - /* @__PURE__ */ jsxDEV9("div", { className: barSeparator }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 153, - columnNumber: 13 - }, this), - /* @__PURE__ */ jsxDEV9("div", { children: [ - /* @__PURE__ */ jsxDEV9("div", { className: contBarTitle, children: [ - /* @__PURE__ */ jsxDEV9("div", { children: [ - snakeCaseToTitleCase(zone.alert.alert_type).toUpperCase(), - " ", - "ALERT PROGRESS" - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 156, - columnNumber: 17 - }, this), - " ", - /* @__PURE__ */ jsxDEV9("div", { children: [ - /* @__PURE__ */ jsxDEV9(AlertTimer, { alert: zone.alert }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 161, - columnNumber: 19 - }, this), - " " - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 160, - columnNumber: 17 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 155, - columnNumber: 15 - }, this), - /* @__PURE__ */ jsxDEV9(FactionBar, { population: zone.alert.percentages }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 164, - columnNumber: 15 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 154, - columnNumber: 13 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 152, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 146, - columnNumber: 7 - }, this) - ] }, zone.id, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 133, - columnNumber: 5 - }, this); -}, BrokenWorld = ({ worldId }) => { - let { platform, location, name } = worlds[String(worldId || "default")]; - return /* @__PURE__ */ jsxDEV9("div", { className: container, children: [ - /* @__PURE__ */ jsxDEV9(Link2, { to: `/worlds/${worldId}`, className: header2, children: [ - /* @__PURE__ */ jsxDEV9("div", { className: headerName2, children: name }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 179, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: headerMarkers, children: [ - "[", - location, - "] [", - platform, - "]", - " " - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 180, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: headerDetailsLink, children: "DETAILS \u21E8" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 183, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 178, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: details, children: /* @__PURE__ */ jsxDEV9("div", { className: oopsies, children: [ - "Daybreak made an oopsie.", - /* @__PURE__ */ jsxDEV9("br", {}, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 188, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV9("div", { className: oopsiesSpin, children: "\u{1F642}" }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 189, - columnNumber: 11 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 186, - columnNumber: 9 - }, this) }, void 0, !1, { - fileName: "app/components/index-world.tsx", - lineNumber: 185, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/components/index-world.tsx", - lineNumber: 177, - columnNumber: 5 - }, this); -}; - -// app/components/index-world-container.css.ts -var container2 = "index-world-container_container__1ib388g0"; - -// app/components/index-world-container.tsx -import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime"; -var WorldContainer = ({ - metagame, - population: population3 -}) => /* @__PURE__ */ jsxDEV10("div", { className: container2, children: metagame.map( - (world) => /* @__PURE__ */ jsxDEV10( - IndexWorld, - { - metagame: world, - population: population3.find((p) => p.id === world.id) - }, - world.id, - !1, - { - fileName: "app/components/index-world-container.tsx", - lineNumber: 15, - columnNumber: 3 - }, - this - ) -) }, void 0, !1, { - fileName: "app/components/index-world-container.tsx", - lineNumber: 13, - columnNumber: 1 -}, this); - -// app/components/index.css.ts -var outer2 = "components_outer__8hh0bp0"; - -// app/utils/population.ts -var fetchPopulationWorlds = async () => (await (await fetch("https://agg.ps2.live/population/all")).json()).map(({ id, average, factions }) => ({ id, average, factions })); - -// app/routes/_index.tsx -import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime"; -var loader2 = async () => { - let [metagame, population3] = await Promise.all( - [ - fetchMetagameWorlds(), - fetchPopulationWorlds() - ] - ); - return json2({ metagame: metagame.sort((a, b) => a.id - b.id), population: population3 }); -}, meta2 = () => [ - { title: "PS2.LIVE" }, - { - name: "description", - content: "PlanetSide 2 Live Population Stats" - } -]; -function Index() { - let data = useLoaderData2(); - return /* @__PURE__ */ jsxDEV11("div", { children: [ - /* @__PURE__ */ jsxDEV11("div", { className: outer2, children: /* @__PURE__ */ jsxDEV11(WorldContainer, { metagame: data.metagame, population: data.population }, void 0, !1, { - fileName: "app/routes/_index.tsx", - lineNumber: 33, - columnNumber: 9 - }, this) }, void 0, !1, { - fileName: "app/routes/_index.tsx", - lineNumber: 32, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV11(Footer, { isMainPage: !0 }, void 0, !1, { - fileName: "app/routes/_index.tsx", - lineNumber: 35, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/_index.tsx", - lineNumber: 31, - columnNumber: 5 - }, this); -} - -// app/routes/about.tsx -var about_exports = {}; -__export(about_exports, { - default: () => About -}); - -// app/components/about.css.ts -var header3 = "about_header__wg0hcp0", outer3 = "about_outer__wg0hcp1", link2 = "about_link__wg0hcp2", itemContainer = "about_itemContainer__wg0hcp3", item = "about_item__wg0hcp4", itemLink = "about_itemLink__wg0hcp5", itemGithubLink = "about_itemGithubLink__wg0hcp6", love = "about_love__wg0hcp7"; - -// app/routes/about.tsx -import { jsxDEV as jsxDEV12 } from "react/jsx-dev-runtime"; -function About() { - return /* @__PURE__ */ jsxDEV12("div", { children: [ - /* @__PURE__ */ jsxDEV12("div", { className: outer3, children: [ - /* @__PURE__ */ jsxDEV12("div", { children: [ - /* @__PURE__ */ jsxDEV12("p", { className: header3, children: [ - /* @__PURE__ */ jsxDEV12("b", { children: "PS2.LIVE" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 19, - columnNumber: 13 - }, this), - " is a network of services that report on the ongoing war on Auraxis." - ] }, void 0, !0, { - fileName: "app/routes/about.tsx", - lineNumber: 18, - columnNumber: 11 - }, this), - /* @__PURE__ */ jsxDEV12("p", { style: { fontStyle: "italic" }, children: [ - "hat tips:", - " ", - /* @__PURE__ */ jsxDEV12("a", { className: link2, href: "https://ps2.fisu.pw/", children: "fisu" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 24, - columnNumber: 13 - }, this), - ",", - " ", - /* @__PURE__ */ jsxDEV12("a", { className: link2, href: "https://wt.honu.pw/", children: "honu & varunda" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 28, - columnNumber: 13 - }, this), - ",", - " ", - /* @__PURE__ */ jsxDEV12("a", { className: link2, href: "https://voidwell.com/", children: "Voidwell & Lampjaw" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 32, - columnNumber: 13 - }, this), - ",", - " ", - /* @__PURE__ */ jsxDEV12("a", { className: link2, href: "https://census.lithafalcon.cc/", children: "Sanctuary & Falcon" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 36, - columnNumber: 13 - }, this), - ",", - " ", - /* @__PURE__ */ jsxDEV12("a", { className: link2, href: "https://ps2alerts.com/", children: "PS2Alerts team" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 40, - columnNumber: 13 - }, this), - ",", - " ", - /* @__PURE__ */ jsxDEV12("a", { className: link2, href: "https://discord.gg/yVzGEg3RKV", children: "PS2devs Discord" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 44, - columnNumber: 13 - }, this), - ", Daybreak Census Team \u{1F496}" - ] }, void 0, !0, { - fileName: "app/routes/about.tsx", - lineNumber: 22, - columnNumber: 11 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/about.tsx", - lineNumber: 17, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV12("div", { children: /* @__PURE__ */ jsxDEV12("ul", { className: itemContainer, children: [ - { - name: "Saerro", - url: "https://saerro.ps2.live", - github: "https://github.com/genudine/saerro", - description: "Population GraphQL API focussing on deep granularity." - }, - { - name: "Metagame API", - url: "https://metagame.ps2.live", - github: "https://github.com/genudine/metagame", - description: "World states, contininent locks, alerts, etc." - }, - { - name: "Population API", - url: "https://agg.ps2.live/population", - github: "https://github.com/genudine/agg-population", - description: "Population as seen by many services, averaged." - }, - { - name: "Census Playground", - url: "https://try.ps2.live", - github: "https://github.com/genudine/try.ps2.live", - description: "Explore and share the Census API." - }, - { - name: "ps2.live", - url: "https://ps2.live", - github: "https://github.com/genudine/ps2.live", - description: "This website. It's pretty cool." - }, - { - name: "Medkit", - url: "https://github.com/genudine/medkit2", - github: "https://github.com/genudine/medkit2", - description: "PS2 Discord bot for population/continents in channel names." - } - ].map( - ({ name, url, github, description }, i) => /* @__PURE__ */ jsxDEV12("li", { className: item, children: [ - /* @__PURE__ */ jsxDEV12("a", { href: url, className: itemLink, children: name }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 93, - columnNumber: 17 - }, this), - /* @__PURE__ */ jsxDEV12("div", { children: [ - description, - " " - ] }, void 0, !0, { - fileName: "app/routes/about.tsx", - lineNumber: 96, - columnNumber: 17 - }, this), - /* @__PURE__ */ jsxDEV12("a", { href: github, className: itemGithubLink, children: "github" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 97, - columnNumber: 17 - }, this) - ] }, i, !0, { - fileName: "app/routes/about.tsx", - lineNumber: 92, - columnNumber: 13 - }, this) - ) }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 51, - columnNumber: 11 - }, this) }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 50, - columnNumber: 9 - }, this), - /* @__PURE__ */ jsxDEV12("p", { className: love, children: "Built with \u{1F496} by Doll" }, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 104, - columnNumber: 9 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/about.tsx", - lineNumber: 16, - columnNumber: 7 - }, this), - /* @__PURE__ */ jsxDEV12(Footer, {}, void 0, !1, { - fileName: "app/routes/about.tsx", - lineNumber: 106, - columnNumber: 7 - }, this) - ] }, void 0, !0, { - fileName: "app/routes/about.tsx", - lineNumber: 15, - columnNumber: 5 - }, this); -} - -// server-assets-manifest:@remix-run/dev/assets-manifest -var assets_manifest_default = { entry: { module: "/build/entry.client-ZTY5EYA2.js", imports: ["/build/_shared/chunk-O4BRYNJ4.js", "/build/_shared/chunk-Q3VAUTNA.js", "/build/_shared/chunk-U4FRFQSK.js", "/build/_shared/chunk-D6I44YFN.js", "/build/_shared/chunk-UWV35TSL.js", "/build/_shared/chunk-XGOTYLZ5.js", "/build/_shared/chunk-7M6SC7J5.js", "/build/_shared/chunk-PNG5AS42.js"] }, routes: { root: { id: "root", parentId: void 0, path: "", index: void 0, caseSensitive: void 0, module: "/build/root-LK675L7D.js", imports: void 0, hasAction: !1, hasLoader: !1, hasClientAction: !1, hasClientLoader: !1, hasErrorBoundary: !1 }, "routes/_index": { id: "routes/_index", parentId: "root", path: void 0, index: !0, caseSensitive: void 0, module: "/build/routes/_index-QVFHENLU.js", imports: ["/build/_shared/chunk-RPE3GBUS.js", "/build/_shared/chunk-UFMODTTP.js", "/build/_shared/chunk-AKBCVZVU.js"], hasAction: !1, hasLoader: !0, hasClientAction: !1, hasClientLoader: !1, hasErrorBoundary: !1 }, "routes/about": { id: "routes/about", parentId: "root", path: "about", index: void 0, caseSensitive: void 0, module: "/build/routes/about-NZRSS7UU.js", imports: ["/build/_shared/chunk-AKBCVZVU.js"], hasAction: !1, hasLoader: !1, hasClientAction: !1, hasClientLoader: !1, hasErrorBoundary: !1 }, "routes/debug.components": { id: "routes/debug.components", parentId: "root", path: "debug/components", index: void 0, caseSensitive: void 0, module: "/build/routes/debug.components-JC3GMEKW.js", imports: ["/build/_shared/chunk-YKZC3E7O.js", "/build/_shared/chunk-UFMODTTP.js"], hasAction: !1, hasLoader: !1, hasClientAction: !1, hasClientLoader: !1, hasErrorBoundary: !1 }, "routes/worlds.$id": { id: "routes/worlds.$id", parentId: "root", path: "worlds/:id", index: void 0, caseSensitive: void 0, module: "/build/routes/worlds.$id-S4Z76SWU.js", imports: ["/build/_shared/chunk-YKZC3E7O.js", "/build/_shared/chunk-RPE3GBUS.js", "/build/_shared/chunk-UFMODTTP.js", "/build/_shared/chunk-AKBCVZVU.js"], hasAction: !1, hasLoader: !0, hasClientAction: !1, hasClientLoader: !1, hasErrorBoundary: !1 } }, version: "918ff520", hmr: { runtime: "/build/_shared/chunk-D6I44YFN.js", timestamp: 1718514722630 }, url: "/build/manifest-918FF520.js" }; - -// server-entry-module:@remix-run/dev/server-build -var mode = "development", assetsBuildDirectory = "public/build", future = { v3_fetcherPersist: !1, v3_relativeSplatPath: !1, v3_throwAbortReason: !1, unstable_singleFetch: !1 }, publicPath = "/build/", entry = { module: entry_server_node_exports }, routes = { - root: { - id: "root", - parentId: void 0, - path: "", - index: void 0, - caseSensitive: void 0, - module: root_exports - }, - "routes/debug.components": { - id: "routes/debug.components", - parentId: "root", - path: "debug/components", - index: void 0, - caseSensitive: void 0, - module: debug_components_exports - }, - "routes/worlds.$id": { - id: "routes/worlds.$id", - parentId: "root", - path: "worlds/:id", - index: void 0, - caseSensitive: void 0, - module: worlds_id_exports - }, - "routes/_index": { - id: "routes/_index", - parentId: "root", - path: void 0, - index: !0, - caseSensitive: void 0, - module: index_exports - }, - "routes/about": { - id: "routes/about", - parentId: "root", - path: "about", - index: void 0, - caseSensitive: void 0, - module: about_exports - } -}; -export { - assets_manifest_default as assets, - assetsBuildDirectory, - entry, - future, - mode, - publicPath, - routes -}; -//# sourceMappingURL=index.js.map diff --git a/build/index.js.map b/build/index.js.map deleted file mode 100644 index 15a29a2..0000000 --- a/build/index.js.map +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": 3, - "sources": ["../node_modules/@remix-run/dev/dist/config/defaults/entry.server.node.tsx", "../app/root.tsx", "css-bundle-plugin-ns:@remix-run/css-bundle", "../app/root.css.ts", "../app/routes/debug.components.tsx", "../app/components/faction-bar.tsx", "../app/components/faction-bar.css.ts", "../app/components/faction-pie.css.ts", "../app/components/faction-pie.tsx", "../app/routes/worlds.$id.tsx", "../app/components/footer.tsx", "../app/components/footer.css.ts", "../app/utils/metagame.ts", "../app/utils/saerro.ts", "../app/utils/strings.ts", "../app/components/world.css.ts", "../app/utils/classes.ts", "../app/components/index-world.css.ts", "../app/components/alert-timer.tsx", "../app/components/alert-timer.css.ts", "../app/utils/sorting.ts", "../app/routes/_index.tsx", "../app/components/index-world.tsx", "../app/components/index-world-container.css.ts", "../app/components/index-world-container.tsx", "../app/components/index.css.ts", "../app/utils/population.ts", "../app/routes/about.tsx", "../app/components/about.css.ts", "server-assets-manifest:@remix-run/dev/assets-manifest", "server-entry-module:@remix-run/dev/server-build"], - "sourcesContent": ["import { PassThrough } from \"node:stream\";\n\nimport type { AppLoadContext, EntryContext } from \"@remix-run/node\";\nimport { createReadableStreamFromReadable } from \"@remix-run/node\";\nimport { RemixServer } from \"@remix-run/react\";\nimport * as isbotModule from \"isbot\";\nimport { renderToPipeableStream } from \"react-dom/server\";\n\nconst ABORT_DELAY = 5_000;\n\nexport default function handleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n remixContext: EntryContext,\n loadContext: AppLoadContext\n) {\n let prohibitOutOfOrderStreaming =\n isBotRequest(request.headers.get(\"user-agent\")) || remixContext.isSpaMode;\n\n return prohibitOutOfOrderStreaming\n ? handleBotRequest(\n request,\n responseStatusCode,\n responseHeaders,\n remixContext\n )\n : handleBrowserRequest(\n request,\n responseStatusCode,\n responseHeaders,\n remixContext\n );\n}\n\n// We have some Remix apps in the wild already running with isbot@3 so we need\n// to maintain backwards compatibility even though we want new apps to use\n// isbot@4. That way, we can ship this as a minor Semver update to @remix-run/dev.\nfunction isBotRequest(userAgent: string | null) {\n if (!userAgent) {\n return false;\n }\n\n // isbot >= 3.8.0, >4\n if (\"isbot\" in isbotModule && typeof isbotModule.isbot === \"function\") {\n return isbotModule.isbot(userAgent);\n }\n\n // isbot < 3.8.0\n if (\"default\" in isbotModule && typeof isbotModule.default === \"function\") {\n return isbotModule.default(userAgent);\n }\n\n return false;\n}\n\nfunction handleBotRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n remixContext: EntryContext\n) {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const { pipe, abort } = renderToPipeableStream(\n ,\n {\n onAllReady() {\n shellRendered = true;\n const body = new PassThrough();\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set(\"Content-Type\", \"text/html\");\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n })\n );\n\n pipe(body);\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n console.error(error);\n }\n },\n }\n );\n\n setTimeout(abort, ABORT_DELAY);\n });\n}\n\nfunction handleBrowserRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n remixContext: EntryContext\n) {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const { pipe, abort } = renderToPipeableStream(\n ,\n {\n onShellReady() {\n shellRendered = true;\n const body = new PassThrough();\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set(\"Content-Type\", \"text/html\");\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n })\n );\n\n pipe(body);\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n console.error(error);\n }\n },\n }\n );\n\n setTimeout(abort, ABORT_DELAY);\n });\n}\n", "import type { LinksFunction } from \"@remix-run/node\";\nimport { cssBundleHref } from \"@remix-run/css-bundle\";\nimport {\n Links,\n LiveReload,\n Meta,\n Outlet,\n Scripts,\n ScrollRestoration } from\n\"@remix-run/react\";\nimport * as styles from \"./root.css\";\nimport \"./reset.css?__remix_sideEffect__\";\n\nexport const links: LinksFunction = () => [\n{\n rel: \"preconnect\",\n href: \"https://fonts.gstatic.com\",\n crossOrigin: \"anonymous\"\n},\n{\n rel: \"preconnect\",\n href: \"ttps://fonts.googleapis.com\",\n crossOrigin: \"anonymous\"\n},\n{\n rel: \"stylesheet\",\n href: \"https://fonts.googleapis.com/css2?family=Unbounded:wght@700&display=swap\"\n},\n\n...(cssBundleHref ? [{ rel: \"stylesheet\", href: cssBundleHref }] : [])];\n\n\nexport default function App() {\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n\n}", "export const cssBundleHref = \"/build/css-bundle-RYSASN3C.css\";", "export var root = 'root_root__o19f1u0';", "import { useState } from \"react\";\nimport { FactionBar } from \"~/components/faction-bar\";\nimport { FactionPie } from \"~/components/faction-pie\";\nimport type { Population } from \"~/utils/saerro\";\n\nexport default function DebugComponents() {\n const [population, setPopulation] = useState({\n nc: 33,\n tr: 33,\n vs: 33,\n });\n\n const [innerMargin, setInnerMargin] = useState(10);\n const [innerColor, setInnerColor] = useState(\"black\");\n return (\n

\n

Debug Components

\n

Faction Viz

\n
\n NC{\" \"}\n \n setPopulation((p) => ({ ...p, nc: Number(e.target.value) }))\n }\n />{\" \"}\n || TR{\" \"}\n \n setPopulation((p) => ({ ...p, tr: Number(e.target.value) }))\n }\n />{\" \"}\n || VS{\" \"}\n \n setPopulation((p) => ({ ...p, vs: Number(e.target.value) }))\n }\n />\n
\n
\n

Horizontal Stacked Bar Chart

\n \n

Pie Chart

\n
\n \n \n
\n Inner margin{\" \"}\n setInnerMargin(Number(e.target.value))}\n />\n Inner color{\" \"}\n setInnerColor(e.target.value)}\n />\n
\n
\n );\n}\n", "import { useMemo } from \"react\";\nimport type { Population } from \"~/utils/saerro\";\nimport * as styles from \"./faction-bar.css\";\n\nexport const FactionBar = ({\n population: { vs, nc, tr },\n tiny\n\n\n\n}: {population: Population;tiny?: boolean;}) => {\n const { vsPercent, ncPercent, trPercent } = useMemo(() => {\n const total = nc + vs + tr;\n return {\n vsPercent: Math.round(vs / total * 100) || 0,\n ncPercent: Math.round(nc / total * 100) || 0,\n trPercent: Math.round(tr / total * 100) || 0\n };\n }, [vs, nc, tr]);\n return (\n
\n
\n {tiny ? <>  : `${vsPercent}%`}\n
\n
\n {tiny ? <>  : `${ncPercent}%`}\n
\n
\n {tiny ? <>  : `${trPercent}%`}\n
\n
);\n\n};", "export var bar = 'faction-bar_bar__prieg10';\nexport var tinyBar = 'faction-bar_tinyBar__prieg11';\nexport var left = 'faction-bar_left__prieg12';\nexport var center = 'faction-bar_center__prieg13';\nexport var right = 'faction-bar_right__prieg14';", "export var pieRoot = 'faction-pie_pieRoot__15tar860';", "import type { Population } from \"~/utils/saerro\";\nimport { pieRoot } from \"./faction-pie.css\";\n\nexport const FactionPie = ({\n population,\n innerMargin,\n innerBackground,\n size\n\n\n\n\n\n}: {population: Population;innerMargin?: number;innerBackground?: string;size?: string;}) => {\n const { nc, tr, vs } = population;\n const total = nc + tr + vs;\n\n const trPct = tr / total * 100;\n const vsPct = vs / total * 100;\n\n return (\n \n\n\n  \n );\n\n};", "import type { LoaderArgs, V2_MetaFunction } from \"@remix-run/cloudflare\";\nimport { json } from \"@remix-run/cloudflare\";\nimport { useLoaderData } from \"@remix-run/react\";\nimport { Footer } from \"~/components/footer\";\nimport type { MetagameWorld } from \"~/utils/metagame\";\nimport { fetchSingleMetagameWorld } from \"~/utils/metagame\";\nimport type { WorldResponse, Zone } from \"~/utils/saerro\";\nimport {\n allClasses,\n allVehicles,\n totalPopulation,\n worldQuery } from\n\"~/utils/saerro\";\nimport {\n pascalCaseToTitleCase,\n toTitleCase,\n worlds,\n zones } from\n\"~/utils/strings\";\nimport * as styles from \"~/components/world.css\";\nimport { c } from \"~/utils/classes\";\nimport { FactionBar } from \"~/components/faction-bar\";\nimport { popImage } from \"~/components/index-world.css\";\nimport vsLogo from \"~/images/vs-100.png\";\nimport ncLogo from \"~/images/nc-100.png\";\nimport trLogo from \"~/images/tr-100.png\";\nimport { FactionPie } from \"~/components/faction-pie\";\nimport { AlertTimer } from \"~/components/alert-timer\";\nimport { contPrioritySort } from \"~/utils/sorting\";\n\ntype LoaderData = {\n saerro: WorldResponse;\n metagame: MetagameWorld;\n id: string;\n};\n\nexport async function loader({ params }: LoaderArgs) {\n const [saerro, metagame] = await Promise.all([\n worldQuery((params.id as string)),\n fetchSingleMetagameWorld((params.id as string))]\n );\n return json(({ saerro, metagame, id: params.id } as LoaderData));\n}\n\nexport const meta: V2_MetaFunction = ({ data }) => {\n const { saerro, id } = (data as LoaderData);\n const date = new Date();\n const worldInfo = worlds[String(id || \"default\")];\n const datetimeHumanFriendly = date.toLocaleString(worldInfo.locale, {\n timeZone: worldInfo.timeZone,\n dateStyle: \"medium\",\n timeStyle: \"short\"\n });\n return [\n {\n title: `${\n worldInfo.name || \"Unknown world\"} | PlanetSide 2 Live Population Stats`\n\n },\n {\n name: \"description\",\n content: `${worldInfo.name} currently has ${totalPopulation(\n saerro.world.population\n )} players online as of ${datetimeHumanFriendly} ${\n worldInfo.name} time. VS: ${\n saerro.world.population.vs}, NC: ${\n saerro.world.population.nc}, TR: ${\n\n saerro.world.population.tr} -- See more detailed stats on ps2.live.`\n\n }];\n\n};\n\nexport default function World() {\n const {\n saerro: { world },\n id,\n metagame\n } = useLoaderData();\n\n const worldInfo = worlds[String(id || \"default\")];\n const nextZoneID =\n metagame.zones.length !== 0 ?\n metagame.zones.sort(\n (a, b) =>\n new Date(a.locked_since ?? Date.now()).getTime() -\n new Date(b.locked_since ?? Date.now()).getTime()\n )[0].id :\n 0;\n\n return (\n <>\n
\n
\n
\n
\n
{worldInfo.name.toUpperCase()}
\n
\n [{worldInfo.location}] [{worldInfo.platform}]\n
\n
\n
\n
\n
\n {totalPopulation(world.population).toLocaleString()}\n
\n PLAYERS\n
\n
\n
\n \n\n \"VS\"{\" \"}\n {world.population.vs}\n
\n \n\n \"NC\"{\" \"}\n {world.population.nc}\n
\n \n\n \"TR\"{\" \"}\n {world.population.tr}\n
\n
\n \n
\n
\n
\n
CONTINENT CONTROL
\n {metagame.zones.sort(contPrioritySort).map((zone, idx) => {\n const zoneInfo = zones[String(zone.id)];\n return (\n
\n
{zoneInfo.name.toUpperCase()}
\n
\n \n\n
\n
\n {zone.alert ?\n :\n zone.locked ?\n nextZoneID == zone.id ?\n <>NEXT UP \u00BB :\n\n <>LOCKED :\n\n\n <>UNLOCKED}\n\n
\n
);\n\n })}\n
\n \n
\n

Continents

\n {world.zones.all.map((zone) =>\n \n )}\n
\n \n \n