feat: add computed battery estimate to ReviewStep via hardware wattHours + tdpWatts (Tasks 4.1-4.3)
This commit is contained in:
@@ -52,6 +52,8 @@ export function GameEntryWizard({ gameId, gameVersions, defaultVersionId, editEn
|
|||||||
// Step 0: Setup — Hardware
|
// Step 0: Setup — Hardware
|
||||||
const [hardwareSlug, setHardwareSlug] = useState(editEntry?.hardwareSlug ?? "")
|
const [hardwareSlug, setHardwareSlug] = useState(editEntry?.hardwareSlug ?? "")
|
||||||
const [hardwareName, setHardwareName] = useState("")
|
const [hardwareName, setHardwareName] = useState("")
|
||||||
|
const [hardwareWattHours, setHardwareWattHours] = useState<number | null>(null)
|
||||||
|
const [hardwareDeviceType, setHardwareDeviceType] = useState<string | null>(null)
|
||||||
|
|
||||||
// Step 0: Setup — Game Version
|
// Step 0: Setup — Game Version
|
||||||
const [selectedVersionId, setSelectedVersionId] = useState(defaultVersionId)
|
const [selectedVersionId, setSelectedVersionId] = useState(defaultVersionId)
|
||||||
@@ -134,14 +136,20 @@ export function GameEntryWizard({ gameId, gameVersions, defaultVersionId, editEn
|
|||||||
setHardwareSlug(slug)
|
setHardwareSlug(slug)
|
||||||
if (!slug) {
|
if (!slug) {
|
||||||
setHardwareName("")
|
setHardwareName("")
|
||||||
|
setHardwareWattHours(null)
|
||||||
|
setHardwareDeviceType(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/performance/hardware")
|
const res = await fetch("/api/performance/hardware")
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json() as { data: Array<{ slug: string; name: string }> }
|
const data = await res.json() as { data: Array<{ slug: string; name: string; deviceType: string; wattHours: number | null; tdpMax: number | null }> }
|
||||||
const device = data.data.find((d) => d.slug === slug)
|
const device = data.data.find((d) => d.slug === slug)
|
||||||
if (device) setHardwareName(device.name)
|
if (device) {
|
||||||
|
setHardwareName(device.name)
|
||||||
|
setHardwareWattHours(device.wattHours ?? null)
|
||||||
|
setHardwareDeviceType(device.deviceType ?? null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
@@ -156,9 +164,13 @@ export function GameEntryWizard({ gameId, gameVersions, defaultVersionId, editEn
|
|||||||
try {
|
try {
|
||||||
const res = await fetch("/api/performance/hardware")
|
const res = await fetch("/api/performance/hardware")
|
||||||
if (res.ok && !cancelled) {
|
if (res.ok && !cancelled) {
|
||||||
const data = await res.json() as { data: Array<{ slug: string; name: string }> }
|
const data = await res.json() as { data: Array<{ slug: string; name: string; deviceType: string; wattHours: number | null; tdpMax: number | null }> }
|
||||||
const device = data.data.find((d) => d.slug === hardwareSlug)
|
const device = data.data.find((d) => d.slug === hardwareSlug)
|
||||||
if (device && !cancelled) setHardwareName(device.name)
|
if (device && !cancelled) {
|
||||||
|
setHardwareName(device.name)
|
||||||
|
setHardwareWattHours(device.wattHours ?? null)
|
||||||
|
setHardwareDeviceType(device.deviceType ?? null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
@@ -402,6 +414,8 @@ export function GameEntryWizard({ gameId, gameVersions, defaultVersionId, editEn
|
|||||||
data={{
|
data={{
|
||||||
hardwareSlug,
|
hardwareSlug,
|
||||||
hardwareName,
|
hardwareName,
|
||||||
|
hardwareWattHours,
|
||||||
|
hardwareDeviceType,
|
||||||
gameVersionLabel: getVersionLabel(),
|
gameVersionLabel: getVersionLabel(),
|
||||||
antiCheat,
|
antiCheat,
|
||||||
performance,
|
performance,
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { UPSCALER_TYPE_OPTIONS, FRAME_GEN_OPTIONS } from "./environment-step"
|
|||||||
export interface ReviewData {
|
export interface ReviewData {
|
||||||
hardwareSlug: string
|
hardwareSlug: string
|
||||||
hardwareName: string
|
hardwareName: string
|
||||||
|
hardwareWattHours: number | null
|
||||||
|
hardwareDeviceType: string | null
|
||||||
gameVersionLabel: string
|
gameVersionLabel: string
|
||||||
antiCheat: {
|
antiCheat: {
|
||||||
antiCheatRelevant: boolean
|
antiCheatRelevant: boolean
|
||||||
@@ -144,6 +146,19 @@ export function ReviewStep({
|
|||||||
<SummaryRow label="Load Time SSD" value={formatNumber(performance.loadTimeSsd)} />
|
<SummaryRow label="Load Time SSD" value={formatNumber(performance.loadTimeSsd)} />
|
||||||
<SummaryRow label="Load Time SD" value={formatNumber(performance.loadTimeSd)} />
|
<SummaryRow label="Load Time SD" value={formatNumber(performance.loadTimeSd)} />
|
||||||
<SummaryRow label="TDP (Watts)" value={formatNumber(performance.tdpWatts)} />
|
<SummaryRow label="TDP (Watts)" value={formatNumber(performance.tdpWatts)} />
|
||||||
|
<SummaryRow
|
||||||
|
label="Est. Battery"
|
||||||
|
value={(() => {
|
||||||
|
const wh = data.hardwareWattHours
|
||||||
|
const tdp = performance.tdpWatts
|
||||||
|
if (wh && tdp && tdp > 0 && data.hardwareDeviceType === "handheld") {
|
||||||
|
const hours = wh / tdp
|
||||||
|
const mins = Math.round(hours * 60)
|
||||||
|
return `~${hours.toFixed(1)}h (${mins} min)`
|
||||||
|
}
|
||||||
|
return "Not available — requires TDP and a handheld device"
|
||||||
|
})()}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Environment */}
|
{/* Environment */}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ export const performanceSubmitRoutes = new Elysia({ prefix: "/performance" })
|
|||||||
slug: hardware.slug,
|
slug: hardware.slug,
|
||||||
name: hardware.name,
|
name: hardware.name,
|
||||||
deviceType: hardware.deviceType,
|
deviceType: hardware.deviceType,
|
||||||
|
wattHours: hardware.wattHours,
|
||||||
|
tdpMax: hardware.tdpMax,
|
||||||
})
|
})
|
||||||
.from(hardware)
|
.from(hardware)
|
||||||
.orderBy(hardware.sortOrder)
|
.orderBy(hardware.sortOrder)
|
||||||
|
|||||||
Reference in New Issue
Block a user