Commit Graph

931 Commits

Author SHA1 Message Date
gamer147
1e9693e56d feat(battle-xp): wire rank + AI-rank /finish through IBattleXpService
- RankBattleController.Finish (covers all 4 URLs: rotation, unlimited,
  ai_rotation, ai_unlimited) now grants win/loss XP via IBattleXpService
  with BattleXpMode.Rank. Uses req.ClassId from wire.
- Tests updated: AI-variant win asserts new XP values; consistency-loss
  asserts loss XP. Added persistence test on /unlimited_rank_battle/finish.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 08:59:01 -04:00
gamer147
c3da6079b2 feat(battle-xp): wire /practice/finish through IBattleXpService
- Practice finish now grants win/loss XP via IBattleXpService.GrantAsync
  with BattleXpMode.Practice. Response fields (get_class_experience,
  class_experience, class_level) reflect post-grant totals.
- Uses req.ClassId from wire; no BattleContext lookup needed.
- Test asserts default XpPerWin=100 crosses classexp.csv L1=50 threshold
  → Level=2 + Exp=50 carry, persists to Viewer.Classes.
- Added loss-XP test asserting default XpPerLoss=25 stays under threshold.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 08:56:59 -04:00
gamer147
f85f221bfa refactor(battle-xp): retire ArenaTwoPickConfig.ClassXpPerBattle for shared BattleXpService
- ArenaTwoPickService now delegates class-XP grants to IBattleXpService
  with BattleXpMode.ArenaTwoPick. Inline GrantClassXp/ResolveClassLevel
  helpers deleted.
- ClassXpPerBattle field removed from ArenaTwoPickConfig; TK2 XP now
  configurable via ArenaTwoPickXpPerWin/XpPerLoss overrides or the global
  BattleXpConfig defaults (100/25).
- Updated 5 test files (ArenaTwoPickService callers) for the new
  constructor arg. Added loss-XP assertion to Finish tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 08:54:52 -04:00
gamer147
81771bb0a0 feat(battle-xp): IBattleXpService with per-mode overrides and auto level-up
- IBattleXpService.GrantAsync mutates viewer.Classes in place; caller SaveChanges
- Resolves win/loss amount from per-mode override or global XpPerWin/XpPerLoss
- Story mode ignores isWin, uses StoryXpPerClear ?? XpPerWin
- Level-up loop consults curve[row.Level].NecessaryExp; carries overflow
- Saturates at max curve level (excess piles in Exp)
- Unknown classId → no-op returning (0, 0, 1), logs Warning
- 10 unit tests (Moq-backed curve stub); DI registered next to InventoryService
- GameConfigurationJsonbTests baseline updated (19 sections)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 08:51:43 -04:00
gamer147
4541378885 feat(battle-xp): config section + viewer loader for class XP grants
Adds BattleXpConfig ([ConfigSection("BattleXp")]) with global
XpPerWin/XpPerLoss plus per-mode nullable overrides. Adds BattleXpMode
enum and IViewerRepository.LoadForBattleXpGrantAsync — focused tracked
load with viewer.Classes + Class nav ref included, for the service
about to be introduced.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 08:44:11 -04:00
gamer147
57df329923 content: wire Serilog into SVSim.ContentServer
Calls UseSvSimSerilog("svsim-content") right after CreateBuilder and
wraps Main in try/catch/finally. No environment gate needed —
ContentServer has no test-suite path. The existing manual request-log
middleware (uses ILogger<Program>) now flows through Serilog
automatically; swapping it for UseSerilogRequestLogging() is a
follow-up per the spec.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 02:08:44 -04:00
gamer147
9a47ac8d90 app: wire Serilog into SVSim.EmulatedEntrypoint
Registers Serilog via SVSim.Hosting.UseSvSimSerilog("svsim-api") right
after CreateBuilder and wraps Main in try/catch/finally so a fatal
startup exception logs before CloseAndFlush.

Also updates the SVSim.Hosting extension to gate the file sink on entry
assembly rather than the ASP.NET environment name. WebApplicationFactory
sets the environment via a hook that resolves after both CreateBuilder
and the UseSerilog callback see their environment view, so
IsEnvironment("Testing") is unreliable in tests. The entry assembly
under `dotnet test` is always "testhost", which is a reliable signal.

appsettings.json grows a Serilog section mirroring the existing
Logging:LogLevel overrides; the Logging block itself is left in place
per the spec's follow-up cleanup note.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 02:07:41 -04:00
gamer147
a7843adfe6 hosting: add SVSim.Hosting with Serilog extension
Adds new SVSim.Hosting project carrying Serilog + Serilog.AspNetCore +
Serilog.Settings.Configuration + enricher package refs, and a single
IHostBuilder extension method UseSvSimSerilog(appName) that installs a
colored console sink and a plain-text file sink rolling daily with a
100 MB per-file cap and 7-file retention. ReadFrom.Configuration is
called last so appsettings can override minimum levels per category.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-04 01:55:58 -04:00
gamer147
87891f9896 cull(engine-cleanup): pass-9 cascade round 2 after UILabel stub 2026-07-03 23:46:27 -04:00
gamer147
773844165b cull(engine-cleanup): pass-9 cascade round 1 after UILabel stub 2026-07-03 23:45:28 -04:00
gamer147
ed6f6f1d68 cull(engine-cleanup): pass-9 — stub UILabel to live surface 2026-07-03 23:44:22 -04:00
gamer147
737f375ea7 cull(engine-cleanup): pass-9 cascade round 3 after NGUIText stub 2026-07-03 23:39:49 -04:00
gamer147
39ae2b0c0a cull(engine-cleanup): pass-9 cascade round 2 after NGUIText stub 2026-07-03 23:38:51 -04:00
gamer147
08c6bca58c cull(engine-cleanup): pass-9 cascade round 1 after NGUIText stub 2026-07-03 23:37:54 -04:00
gamer147
9183625ac2 cull(engine-cleanup): pass-9 — stub NGUIText to live surface 2026-07-03 23:36:53 -04:00
gamer147
699e78755b cull(engine-cleanup): pass-9 cascade round 6 after UIPanel stub 2026-07-03 23:34:56 -04:00
gamer147
c6319696f3 cull(engine-cleanup): pass-9 cascade round 5 after UIPanel stub 2026-07-03 23:33:54 -04:00
gamer147
01f9635d50 cull(engine-cleanup): pass-9 cascade round 4 after UIPanel stub 2026-07-03 23:32:57 -04:00
gamer147
0103050fe0 cull(engine-cleanup): pass-9 cascade round 3 after UIPanel stub 2026-07-03 23:31:57 -04:00
gamer147
18844b2233 cull(engine-cleanup): pass-9 cascade round 2 after UIPanel stub 2026-07-03 23:30:59 -04:00
gamer147
36bd90c2b3 cull(engine-cleanup): pass-9 cascade round 1 after UIPanel stub 2026-07-03 23:29:52 -04:00
gamer147
853b060f02 cull(engine-cleanup): pass-9 — stub UIPanel to live surface 2026-07-03 23:28:50 -04:00
gamer147
b54e79f1fb cull(engine-cleanup): pass-9 cascade round 3 after DialogBase stub 2026-07-03 23:25:54 -04:00
gamer147
6eb7d51d53 cull(engine-cleanup): pass-9 cascade round 2 after DialogBase stub 2026-07-03 23:24:59 -04:00
gamer147
4e3bb6f88f cull(engine-cleanup): pass-9 cascade round 1 after DialogBase stub 2026-07-03 23:23:59 -04:00
gamer147
6de5f03956 cull(engine-cleanup): pass-9 — stub DialogBase to live surface 2026-07-03 23:22:43 -04:00
gamer147
840ac27027 chore(engine-cleanup): pass-8 phase-2 — sync stub headers with post-cascade state 2026-07-03 22:38:17 -04:00
gamer147
0ee97cdd93 cull(engine-cleanup): pass-8 phase-2 cascade round 5 after CardDetailUI stub 2026-07-03 22:37:13 -04:00
gamer147
4950a57b11 cull(engine-cleanup): pass-8 phase-2 cascade round 4 after CardDetailUI stub 2026-07-03 22:36:16 -04:00
gamer147
0bf981ce4d cull(engine-cleanup): pass-8 phase-2 cascade round 3 after CardDetailUI stub 2026-07-03 22:35:21 -04:00
gamer147
99120ec858 cull(engine-cleanup): pass-8 phase-2 cascade round 2 after CardDetailUI stub 2026-07-03 22:34:23 -04:00
gamer147
3d641e9e35 cull(engine-cleanup): pass-8 phase-2 cascade round 1 after CardDetailUI stub 2026-07-03 22:33:26 -04:00
gamer147
8e6dbad56b cull(engine-cleanup): pass-8 phase-2 — stub CardDetailUI to live surface 2026-07-03 22:32:22 -04:00
gamer147
f26e8ceaec cull(engine-cleanup): pass-8 phase-2 cascade round 4 after GachaUI stub 2026-07-03 22:28:42 -04:00
gamer147
4e49a1236d cull(engine-cleanup): pass-8 phase-2 cascade round 3 after GachaUI stub 2026-07-03 22:27:45 -04:00
gamer147
78971adc46 cull(engine-cleanup): pass-8 phase-2 cascade round 2 after GachaUI stub 2026-07-03 22:26:45 -04:00
gamer147
e3b8b8dc0c cull(engine-cleanup): pass-8 phase-2 cascade round 1 after GachaUI stub 2026-07-03 22:25:44 -04:00
gamer147
a0533bf2e3 cull(engine-cleanup): pass-8 phase-2 — stub GachaUI to live surface 2026-07-03 22:24:38 -04:00
gamer147
59de7a8b86 cull(engine-cleanup): pass-8 phase-2 cascade round 5 after AreaSelectUI stub 2026-07-03 22:22:31 -04:00
gamer147
80abda90bf cull(engine-cleanup): pass-8 phase-2 cascade round 4 after AreaSelectUI stub 2026-07-03 22:21:26 -04:00
gamer147
9d4d5ff1ec cull(engine-cleanup): pass-8 phase-2 cascade round 3 after AreaSelectUI stub 2026-07-03 22:20:18 -04:00
gamer147
b148eb2968 cull(engine-cleanup): pass-8 phase-2 cascade round 2 after AreaSelectUI stub 2026-07-03 22:19:20 -04:00
gamer147
ad525456be cull(engine-cleanup): pass-8 phase-2 cascade round 1 after AreaSelectUI stub 2026-07-03 22:18:12 -04:00
gamer147
7aabb6a405 cull(engine-cleanup): pass-8 phase-2 — stub AreaSelectUI to live surface 2026-07-03 22:17:04 -04:00
gamer147
41ddba8fda cull(engine-cleanup): pass-8 phase-2 cascade round 7 after MyPageItemHome stub 2026-07-03 22:05:22 -04:00
gamer147
7938c6198c cull(engine-cleanup): pass-8 phase-2 cascade round 6 after MyPageItemHome stub 2026-07-03 22:04:24 -04:00
gamer147
4aa0ccaea7 cull(engine-cleanup): pass-8 phase-2 cascade round 5 after MyPageItemHome stub 2026-07-03 22:03:27 -04:00
gamer147
e07cacc55e cull(engine-cleanup): pass-8 phase-2 cascade round 4 after MyPageItemHome stub 2026-07-03 22:02:30 -04:00
gamer147
17b436d33d cull(engine-cleanup): pass-8 phase-2 cascade round 3 after MyPageItemHome stub 2026-07-03 22:01:31 -04:00
gamer147
e9b112d083 cull(engine-cleanup): pass-8 phase-2 cascade round 2 after MyPageItemHome stub 2026-07-03 22:00:30 -04:00