feedback7 stats: a match left right away stays in the history but does not count; bounded storage, corrupt-data handling, the page reworked as 干员调配-style tabs, the settlement re-view without the app store (PR #323 by @2321Robin, owner's decision of 2026-10-08); golden: unchanged
Counting rule (ui/stats.js countsTowardStats, the owner's decision of 2026-10-08: do not count the matches entered and left right away, but keep them in the history): a settled match (m.result arrived) always counts; a match given up (放弃模拟) counts once at least one of the player's battles had finished — a round cleared (the server's own rule, platform.js _quit: leaving while round k runs has passed k - 1, in its settlement k) or already eliminated. Anything earlier is history only: marked 中途退出 and 不计入统计, dimmed, listed in 对局记录, left out of every aggregate (games, wins, win rate, strategy table, titles, rounds, time, combat totals); 总览 says how many were left out. - A leaver gets no m.result, so the page records the match itself: quitMatch (放弃模拟) → recordQuit builds an `end: 'quit'` record from the app state and a tracker (observeMatch, installed in main.js) that remembers when the page first saw the match and the last round the player was seen alive in. No record for a spectator seat, a match with its settlement already there, a match the page never saw; matches the server ended and closed tabs are not recorded. Defects of PR #323 as submitted, reproduced (scratchpad/w7-stats-notes/repro-pr-bugs.mjs, loads-check*.mjs) and fixed: - the title screen loaded all 16 game data files (5.3 MB) at boot: <StatsHost/> called useGameData() at mount; now the host renders nothing until opened, the overview reads config / bands / assets and the settlement re-view loads the rest when opened (the title screen loads the same 3 files as before); - importing a file put the list oldest first (the page shows the first 20 as the newest and the cap would drop the newest); the list is newest first everywhere, also when loaded from storage; - recordResult wrote over the envelope of a NEWER build (a downgrade, against the PR's own rule); it refuses now, as saveStats does; - 1000 four-player records are ~7.2 M characters (the PR's ~1.5 kB/record is a solo match) against a ~2.5 M-character quota: MAX_RECORDS 1000 stays, plus a 800 000-character budget (the oldest go first), and only the newest 30 records keep their rows (lineup, bonds, teammates' names; the replay needs them) — older ones are compacted to the player's own summary row (~620 characters), a refused write retries with half the history; unknown fields and oversized values are dropped (a strict schema), import files are bounded (8 MB); - the re-view clobbered the app store (match.public / match.result, the route, the music); ResultScreen is split into ResultScreen (the store) and ResultView (props: result, myId, back label), so the stats page renders a stored match itself; a 自选 pick and a 补位 stand-in were dropped from the stored lineup (the replayed card drew the plain operator); DIFFICULTY_NAMES were not translated; a band cell was a display:flex <td>; the overlay stayed open when a co-op match started; the 清空 two-step blink was replaced by the shared confirm dialog. - Corrupt storage: unreadable data is moved to sp.pref.stats.damaged and the page says so; damaged rows are dropped and counted; duplicates, an oversized or unsorted list are repaired on load; a pre-`end` (PR-era) envelope reads as settled. UI: a full-screen overlay in the grammar of 干员调配 (top bar with 返回 / four tabs 总览 · 策略 · 战斗累计 · 对局记录 / 导出 导入 清空, a note line saying the data stays in this browser and that teammates' names are stored too), text sizes with max(.xxrem, N px) for phones in landscape, a 50-row history page with 显示更多, a pass-rate bar, a per-difficulty table in order; the entries use a new `chart` icon (not the ping bars), the title screen's sits beside the language menu (the connection row has no room: it squeezed the gear and wrapped the status text), the lobby / room buttons show the icon alone below 700 px (the room's title ran under the label at 640 px). docs/PLAYING.md §12, README row; 41 + 25 UI strings in en / ja / ko / zh-TW (the PR's four unused ones removed). Tests: test/ui/stats.test.js 44 / 44 (counting rule per phase, quit records, bounds, corrupt / old / newer storage, import order, aggregation, the replay payload); test/ui/stats.e2e.test.js (opt-in SP_E2E=1, real server, headless Chrome: seeded history on 1920×1080 and 844×390, the re-view, export / import / clear, corrupt and newer storage, and the real flows: a solo match given up in the briefing is history only, one given up after round 1 counts, a settled match is recorded once and not again after a reload) 6 / 6; lint 0 errors, i18n extract 0 / check --all --strict clean, check:imports, typecheck, docs and version tests, golden unchanged.
This commit is contained in:
1 parent
438a6b521a
commit
51e0e60b6e
20 files changed
+1808
-530
No files matched your search
+29
-8
@@ -1058,7 +1058,6 @@
|
||||
"开发版 · 不稳定,请勿用于公开服务器": "Development build · unstable, not for public servers",
|
||||
"统计数据": "Statistics",
|
||||
"统计": "Stats",
|
||||
"对局进行中,暂不能回看历史结算": "A match is running — replays are unavailable right now",
|
||||
"总览": "Overview",
|
||||
"总局数": "Games",
|
||||
"胜场": "Wins",
|
||||
@@ -1076,7 +1075,6 @@
|
||||
"通过率": "Clear rate",
|
||||
"称号": "Titles",
|
||||
"战斗累计": "Combat totals",
|
||||
"最近对局": "Recent matches",
|
||||
"时间": "Time",
|
||||
"模式": "Mode",
|
||||
"结果": "Result",
|
||||
@@ -1085,16 +1083,39 @@
|
||||
"同盟": "Co-op",
|
||||
"胜": "Win",
|
||||
"负": "Loss",
|
||||
"点击任意一行,回看该局结算。": "Click a row to re-view that match's settlement.",
|
||||
"已导出 {n} 条对局记录": "Exported {n} match records",
|
||||
"已导入 {added} 条记录{tail}": "Imported {added} records{tail}",
|
||||
"(跳过重复 {skipped} 条)": " ({skipped} duplicates skipped)",
|
||||
"已导出 {n} 条对局记录": "Exported {n} match {n|record|records}",
|
||||
"已导入 {added} 条记录{tail}": "Imported {added} {added|record|records}{tail}",
|
||||
"(跳过重复 {skipped} 条)": " ({skipped} {skipped|duplicate|duplicates} skipped)",
|
||||
"没有新记录(全部与现有数据重复)": "Nothing new (everything already exists)",
|
||||
"导入失败:不是有效的统计导出文件": "Import failed: not a valid stats export file",
|
||||
"已清空本机统计数据": "Local stats cleared",
|
||||
"确认清空?": "Clear for sure?",
|
||||
"本机数据 · 仅记录本浏览器中你参与的对局": "Local data · only matches you took part in, in this browser",
|
||||
"检测到更新版本的统计数据,请先升级客户端再查看,以免覆盖数据。": "Stats data from a newer version detected — upgrade the client before viewing, or the data could be overwritten.",
|
||||
"还没有记录 —— 完成一局对局后,这里会开始积累。": "No records yet — finish a match and the page starts filling in.",
|
||||
"未知": "Unknown"
|
||||
"未知": "Unknown",
|
||||
"对局记录": "Match history",
|
||||
"{n} 小时": "{n} h",
|
||||
"计入统计:打到结算的对局,以及中途退出前至少清完 1 个回合的对局;更早退出的对局只留在对局记录里。": "Counted: matches played to the settlement, and matches given up after clearing at least 1 round. Matches given up earlier stay in the match history only.",
|
||||
"另有 {n} 局未计入统计": "{n} more {n|match|matches} not counted",
|
||||
"没有清完第一个回合就退出,不计入统计": "Left before clearing the first round — not counted",
|
||||
"中途退出的对局没有结算可看": "A match given up has no settlement to view",
|
||||
"较早的对局只保留汇总,不能回看结算": "Older matches keep only their summary — no settlement to view",
|
||||
"中途退出": "Left early",
|
||||
"不计入统计": "Not counted",
|
||||
"显示更多(还有 {n} 局)": "Show more ({n} left)",
|
||||
"点击一行,回看该局结算;中途退出的对局只留记录。": "Click a row to re-view that match's settlement; a match given up only leaves its entry.",
|
||||
"最多保留最近 {max} 局,只有最新的 {full} 局能回看结算。": "Only the latest {max} matches are kept, and only the newest {full} can show their settlement again.",
|
||||
"返回统计": "Back to Stats",
|
||||
"文件过大,无法导入": "File too large to import",
|
||||
"无法写入本机存储,可能已满": "Could not write to local storage — it may be full",
|
||||
"({n} 条无法读取)": " ({n} unreadable)",
|
||||
"导入失败:这份文件由更新版本的客户端导出,请先升级客户端": "Import failed: this file was exported by a newer client — upgrade the client first",
|
||||
"清空统计数据": "Clear Statistics",
|
||||
"将删除本机保存的 {n} 条对局记录,无法恢复。": "This deletes the {n} match {n|record|records} stored on this device. It cannot be undone.",
|
||||
"导出为文件(可在别的设备上导入)": "Export to a file (import it on another device)",
|
||||
"从导出的文件导入(与现有记录合并)": "Import from an exported file (merged with the current records)",
|
||||
"清空本机的统计数据": "Clear the statistics stored on this device",
|
||||
"本机数据:只保存在这个浏览器里,不会上传到服务器;同盟对局里队友的代号也会存在本机(导出文件里也有)。": "Local data: kept only in this browser, never uploaded to the server. Teammates' names from Team Simulations are stored here too (and appear in an export file).",
|
||||
"本机保存的统计数据无法读取,已另存为备份,从现在起重新记录。": "The stats stored on this device could not be read. They were set aside as a backup and recording starts afresh.",
|
||||
"有 {n} 条记录已损坏,已忽略。": "{n} damaged {n|record was|records were} ignored."
|
||||
}
|
||||
Reference in new issue
Block a user