diff --git a/app/game/[id]/game-page-client.tsx b/app/game/[id]/game-page-client.tsx index 4a4cab3..1ed6689 100644 --- a/app/game/[id]/game-page-client.tsx +++ b/app/game/[id]/game-page-client.tsx @@ -73,7 +73,8 @@ interface Preset { fpsAvg: number | null fpsLow: number | null fpsHigh: number | null - fsrVersion: string | null + upscalerType: string | null + upscalerVersion: string | null frameGenMethod: string | null protonVersion: string | null osVersion: string | null @@ -89,6 +90,7 @@ interface StatsResponse { versionCount: number } isRawPerformer: boolean + isPoorPerformance: boolean boxplot: Array<{ hardwareSlug: string hardwareName: string @@ -107,7 +109,8 @@ interface StatsResponse { }> }> upscalerStats: Array<{ - fsrVersion: string + upscalerType: string + upscalerVersion?: string frameGenMethod: string hardwareSlug: string avgFps: number @@ -149,8 +152,8 @@ interface Props { gameId: string } -const FSR_OPTIONS = ["Any", "None", "FSR1", "FSR2", "FSR3"] -const FRAMEGEN_OPTIONS = ["Any", "None", "FSR FG", "DLSS FG"] +const UPSCALER_OPTIONS = ["Any", "None", "FSR", "DLSS", "XeSS", "LSFG", "Other"] +const FRAMEGEN_OPTIONS = ["Any", "None", "FSR FG", "DLSS FG", "LSFG", "Other"] function formatDate(value: string | null): string { if (!value) return "—" @@ -161,11 +164,15 @@ function isRawPerformerPreset(preset: Preset): boolean { return ( preset.fpsAvg !== null && preset.fpsAvg >= 60 && - preset.fsrVersion === "none" && + preset.upscalerType === "none" && preset.frameGenMethod === "none" ) } +function isPoorPerformancePreset(preset: Preset): boolean { + return preset.fpsAvg !== null && preset.fpsAvg < 30 +} + function getFpsColor(preset: Preset): string { if (preset.fpsAvg === null) return "text-text/60" if (isRawPerformerPreset(preset)) return "text-green-400" @@ -173,7 +180,7 @@ function getFpsColor(preset: Preset): string { if (preset.frameGenMethod === "dlss_fg") return "text-blue-400" return "text-orange-400" } - if (preset.fsrVersion && preset.fsrVersion !== "none") + if (preset.upscalerType && preset.upscalerType !== "none") return "text-orange-400" return "text-text/60" } @@ -192,7 +199,7 @@ export function GamePageClient({ const [filters, setFilters] = useState({ proton: "all", os: "all", - fsr: "all", + upscaler: "all", frameGen: "all", }) const [loading, setLoading] = useState(true) @@ -243,7 +250,7 @@ export function GamePageClient({ const filterUpscaler = (arr: StatsResponse["upscalerStats"]) => arr.filter((item) => { if (!deviceSet.has(item.hardwareSlug)) return false - if (filters.fsr !== "all" && item.fsrVersion !== filters.fsr) + if (filters.upscaler !== "all" && item.upscalerType !== filters.upscaler) return false if ( filters.frameGen !== "all" && @@ -282,7 +289,7 @@ export function GamePageClient({ if (filters.proton !== "all" && p.protonVersion !== filters.proton) return false if (filters.os !== "all" && p.osVersion !== filters.os) return false - if (filters.fsr !== "all" && p.fsrVersion !== filters.fsr) + if (filters.upscaler !== "all" && p.upscalerType !== filters.upscaler) return false if ( filters.frameGen !== "all" && @@ -351,6 +358,11 @@ export function GamePageClient({ Raw Performer )} + {stats?.isPoorPerformance && ( + + ⚠ Poor Performance + + )} {/* Subtitle */} @@ -636,11 +648,11 @@ export function GamePageClient({ } /> o.toLowerCase())} + label='Upscaler' + value={filters.upscaler} + options={UPSCALER_OPTIONS.map((o) => o.toLowerCase())} onChange={(v) => - setFilters((f) => ({ ...f, fsr: v })) + setFilters((f) => ({ ...f, upscaler: v })) } /> )} + {isPoorPerformancePreset(preset) && preset.fpsAvg !== null && ( + + ⚠ Slow + + )}

{preset.hardwareName} @@ -869,11 +886,12 @@ export function GamePageClient({ {/* Technology tags */}

- {preset.fsrVersion && - preset.fsrVersion !== + {preset.upscalerType && + preset.upscalerType !== "none" && ( - {preset.fsrVersion.toUpperCase()} + {preset.upscalerType.toUpperCase()} + {preset.upscalerVersion ? ` ${preset.upscalerVersion}` : ""} )} {preset.frameGenMethod && diff --git a/components/charts/UpscalerBarChart.tsx b/components/charts/UpscalerBarChart.tsx index f98f186..38cd451 100644 --- a/components/charts/UpscalerBarChart.tsx +++ b/components/charts/UpscalerBarChart.tsx @@ -5,17 +5,28 @@ import { EChartWrapper, CHART_THEME, getDeviceColor } from "./EChartWrapper" import type { EChartsOption } from "echarts" interface UpscalerStat { - fsrVersion: string + upscalerType: string + upscalerVersion?: string | null frameGenMethod: string hardwareSlug: string avgFps: number count: number } -function formatCombo(fsr: string, fg: string): string { +function formatCombo(upscalerType: string, upscalerVersion: string | null | undefined, fg: string): string { const parts: string[] = [] - if (fsr !== "none") parts.push(fsr.toUpperCase()) - if (fg !== "none") parts.push(fg === "fsr_fg" ? "FSR FG" : "DLSS FG") + if (upscalerType !== "none") { + const upscalerLabel = upscalerVersion + ? `${upscalerType.toUpperCase()} ${upscalerVersion}` + : upscalerType.toUpperCase() + parts.push(upscalerLabel) + } + if (fg !== "none") { + if (fg === "fsr_fg") parts.push("FSR FG") + else if (fg === "dlss_fg") parts.push("DLSS FG") + else if (fg === "lsfg") parts.push("LSFG") + else parts.push(fg.toUpperCase()) + } return parts.length > 0 ? parts.join(" + ") : "Native" } @@ -29,7 +40,7 @@ export function UpscalerBarChart({ const option = useMemo(() => { const combos = [ ...new Set( - data.map((d) => formatCombo(d.fsrVersion, d.frameGenMethod)), + data.map((d) => formatCombo(d.upscalerType, d.upscalerVersion, d.frameGenMethod)), ), ] const deviceSlugs = [...new Set(data.map((d) => d.hardwareSlug))] @@ -40,7 +51,7 @@ export function UpscalerBarChart({ data: combos.map((combo) => { const match = data.find( (d) => - formatCombo(d.fsrVersion, d.frameGenMethod) === combo && + formatCombo(d.upscalerType, d.upscalerVersion, d.frameGenMethod) === combo && d.hardwareSlug === slug, ) return match?.avgFps ?? 0