feat(web): verify bot profile pages render per-bot JSON correctly

- All 6 strategy bot profiles (HunterBot, SwarmBot, GathererBot, GuardianBot, RusherBot, RandomBot) now have complete JSON files
- Bot profile pages display: name, owner, rating, rating deviation, matches played, win rate
- Match history section shows recent matches with 'Watch Replay' links
- Per-bot stats match leaderboard.json values
- Mobile layout verified - readable text, usable touch targets, no horizontal overflow

Bot IDs verified:
- b_457b876ca1c4 (HunterBot) - Rating: 1710±35, 162 matches, 66.7% win rate
- b_62beeb03c196 (SwarmBot) - Rating: 1680±38, 156 matches, 62.8% win rate
- b_2fa5681bf0ff (GathererBot) - Rating: 1640±42, 148 matches, 60.1% win rate
- b_f3af8d6177eb (GuardianBot) - Rating: 1590±40, 155 matches, 56.8% win rate
- b_ae1845729bbf (RusherBot) - Rating: 1520±45, 142 matches, 54.9% win rate
- b_656f050a7ed3 (RandomBot) - Rating: 1200±50, 180 matches, 25.0% win rate
This commit is contained in:
jedarden 2026-04-25 10:37:49 -04:00
parent 3938afd058
commit e6a52810c5
11 changed files with 1537 additions and 7 deletions

View file

@ -0,0 +1,51 @@
{
"id": "b_2fa5681bf0ff",
"name": "GathererBot",
"owner_id": "system",
"description": "Economic strategy bot that maximizes energy collection while avoiding combat",
"rating": 1640,
"rating_deviation": 42.0,
"rating_volatility": 0.05,
"matches_played": 148,
"matches_won": 89,
"win_rate": 60.1,
"health_status": "healthy",
"evolved": false,
"debug_public": true,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-18T16:00:00Z",
"rating_history": [
{"bot_id": "b_2fa5681bf0ff", "rating": 1500, "rating_deviation": 350.0, "recorded_at": "2024-01-15T10:00:00Z"},
{"bot_id": "b_2fa5681bf0ff", "rating": 1530, "rating_deviation": 180.0, "recorded_at": "2024-01-16T12:00:00Z"},
{"bot_id": "b_2fa5681bf0ff", "rating": 1590, "rating_deviation": 90.0, "recorded_at": "2024-01-17T14:00:00Z"},
{"bot_id": "b_2fa5681bf0ff", "rating": 1640, "rating_deviation": 42.0, "recorded_at": "2024-01-18T16:00:00Z"}
],
"recent_matches": [
{
"id": "m_test003",
"completed_at": "2024-01-18T12:00:00Z",
"participants": [
{"bot_id": "b_2fa5681bf0ff", "name": "GathererBot", "score": 4, "won": true},
{"bot_id": "b_656f050a7ed3", "name": "RandomBot", "score": 1, "won": false}
],
"winner_id": "b_2fa5681bf0ff",
"map_id": "map_2p_003",
"turns": 312,
"end_reason": "turn_limit",
"enriched": false
},
{
"id": "m_test004",
"completed_at": "2024-01-18T11:00:00Z",
"participants": [
{"bot_id": "b_2fa5681bf0ff", "name": "GathererBot", "score": 3, "won": false},
{"bot_id": "b_62beeb03c196", "name": "SwarmBot", "score": 5, "won": true}
],
"winner_id": "b_62beeb03c196",
"map_id": "map_2p_004",
"turns": 489,
"end_reason": "turn_limit",
"enriched": true
}
]
}

View file

@ -0,0 +1,38 @@
{
"id": "b_457b876ca1c4",
"name": "HunterBot",
"owner_id": "system",
"description": "Tactical bot that targets isolated enemy bots for efficient kills",
"rating": 1710,
"rating_deviation": 35.0,
"rating_volatility": 0.04,
"matches_played": 162,
"matches_won": 108,
"win_rate": 66.7,
"health_status": "healthy",
"evolved": false,
"debug_public": true,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-18T16:00:00Z",
"rating_history": [
{"bot_id": "b_457b876ca1c4", "rating": 1500, "rating_deviation": 350.0, "recorded_at": "2024-01-15T10:00:00Z"},
{"bot_id": "b_457b876ca1c4", "rating": 1580, "rating_deviation": 160.0, "recorded_at": "2024-01-16T12:00:00Z"},
{"bot_id": "b_457b876ca1c4", "rating": 1650, "rating_deviation": 75.0, "recorded_at": "2024-01-17T14:00:00Z"},
{"bot_id": "b_457b876ca1c4", "rating": 1710, "rating_deviation": 35.0, "recorded_at": "2024-01-18T16:00:00Z"}
],
"recent_matches": [
{
"id": "m_test005",
"completed_at": "2024-01-18T15:30:00Z",
"participants": [
{"bot_id": "b_457b876ca1c4", "name": "HunterBot", "score": 5, "won": true},
{"bot_id": "b_ae1845729bbf", "name": "RusherBot", "score": 2, "won": false}
],
"winner_id": "b_457b876ca1c4",
"map_id": "map_2p_005",
"turns": 278,
"end_reason": "dominance",
"enriched": true
}
]
}

View file

@ -0,0 +1,37 @@
{
"id": "b_62beeb03c196",
"name": "SwarmBot",
"owner_id": "system",
"description": "Formation-based strategy bot that keeps units together",
"rating": 1680,
"rating_deviation": 38.0,
"rating_volatility": 0.05,
"matches_played": 156,
"matches_won": 98,
"win_rate": 62.8,
"health_status": "healthy",
"evolved": false,
"debug_public": true,
"created_at": "2024-01-15T10:00:00Z",
"rating_history": [
{"bot_id": "b_62beeb03c196", "rating": 1500, "rating_deviation": 350.0, "recorded_at": "2024-01-15T10:00:00Z"},
{"bot_id": "b_62beeb03c196", "rating": 1550, "rating_deviation": 150.0, "recorded_at": "2024-01-16T12:00:00Z"},
{"bot_id": "b_62beeb03c196", "rating": 1620, "rating_deviation": 80.0, "recorded_at": "2024-01-17T14:00:00Z"},
{"bot_id": "b_62beeb03c196", "rating": 1680, "rating_deviation": 38.0, "recorded_at": "2024-01-18T16:00:00Z"}
],
"recent_matches": [
{
"id": "m_test002",
"completed_at": "2024-01-18T13:00:00Z",
"participants": [
{"bot_id": "b_62beeb03c196", "name": "SwarmBot", "score": 5, "won": true},
{"bot_id": "b_ae1845729bbf", "name": "RusherBot", "score": 3, "won": false}
],
"winner_id": "b_62beeb03c196",
"map_id": "map_2p_002",
"turns": 456,
"end_reason": "turn_limit",
"enriched": true
}
]
}

View file

@ -0,0 +1,38 @@
{
"id": "b_656f050a7ed3",
"name": "RandomBot",
"owner_id": "system",
"description": "Makes uniformly random valid moves - the baseline for testing",
"rating": 1200,
"rating_deviation": 50.0,
"rating_volatility": 0.08,
"matches_played": 180,
"matches_won": 45,
"win_rate": 25.0,
"health_status": "healthy",
"evolved": false,
"debug_public": true,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-18T16:00:00Z",
"rating_history": [
{"bot_id": "b_656f050a7ed3", "rating": 1500, "rating_deviation": 350.0, "recorded_at": "2024-01-15T10:00:00Z"},
{"bot_id": "b_656f050a7ed3", "rating": 1350, "rating_deviation": 200.0, "recorded_at": "2024-01-16T12:00:00Z"},
{"bot_id": "b_656f050a7ed3", "rating": 1250, "rating_deviation": 100.0, "recorded_at": "2024-01-17T14:00:00Z"},
{"bot_id": "b_656f050a7ed3", "rating": 1200, "rating_deviation": 50.0, "recorded_at": "2024-01-18T16:00:00Z"}
],
"recent_matches": [
{
"id": "m_test006",
"completed_at": "2024-01-18T16:00:00Z",
"participants": [
{"bot_id": "b_656f050a7ed3", "name": "RandomBot", "score": 1, "won": false},
{"bot_id": "b_f3af8d6177eb", "name": "GuardianBot", "score": 4, "won": true}
],
"winner_id": "b_f3af8d6177eb",
"map_id": "map_2p_006",
"turns": 398,
"end_reason": "turn_limit",
"enriched": false
}
]
}

View file

@ -0,0 +1,51 @@
{
"id": "b_ae1845729bbf",
"name": "RusherBot",
"owner_id": "system",
"description": "Aggressive strategy bot that rushes enemy cores",
"rating": 1520,
"rating_deviation": 45.0,
"rating_volatility": 0.06,
"matches_played": 142,
"matches_won": 78,
"win_rate": 54.9,
"health_status": "healthy",
"evolved": false,
"debug_public": true,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-18T16:00:00Z",
"rating_history": [
{"bot_id": "b_ae1845729bbf", "rating": 1500, "rating_deviation": 350.0, "recorded_at": "2024-01-15T10:00:00Z"},
{"bot_id": "b_ae1845729bbf", "rating": 1485, "rating_deviation": 200.0, "recorded_at": "2024-01-16T12:00:00Z"},
{"bot_id": "b_ae1845729bbf", "rating": 1510, "rating_deviation": 100.0, "recorded_at": "2024-01-17T14:00:00Z"},
{"bot_id": "b_ae1845729bbf", "rating": 1520, "rating_deviation": 45.0, "recorded_at": "2024-01-18T16:00:00Z"}
],
"recent_matches": [
{
"id": "m_test001",
"completed_at": "2024-01-18T14:30:00Z",
"participants": [
{"bot_id": "b_ae1845729bbf", "name": "RusherBot", "score": 5, "won": true},
{"bot_id": "b_656f050a7ed3", "name": "RandomBot", "score": 2, "won": false}
],
"winner_id": "b_ae1845729bbf",
"map_id": "map_2p_001",
"turns": 234,
"end_reason": "dominance",
"enriched": false
},
{
"id": "m_test002",
"completed_at": "2024-01-18T13:00:00Z",
"participants": [
{"bot_id": "b_ae1845729bbf", "name": "RusherBot", "score": 3, "won": false},
{"bot_id": "b_62beeb03c196", "name": "SwarmBot", "score": 5, "won": true}
],
"winner_id": "b_62beeb03c196",
"map_id": "map_2p_002",
"turns": 456,
"end_reason": "turn_limit",
"enriched": true
}
]
}

View file

@ -0,0 +1,51 @@
{
"id": "b_f3af8d6177eb",
"name": "GuardianBot",
"owner_id": "system",
"description": "Defensive strategy bot that protects its core and gathers nearby energy",
"rating": 1590,
"rating_deviation": 40.0,
"rating_volatility": 0.05,
"matches_played": 155,
"matches_won": 88,
"win_rate": 56.8,
"health_status": "healthy",
"evolved": false,
"debug_public": true,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-18T16:00:00Z",
"rating_history": [
{"bot_id": "b_f3af8d6177eb", "rating": 1500, "rating_deviation": 350.0, "recorded_at": "2024-01-15T10:00:00Z"},
{"bot_id": "b_f3af8d6177eb", "rating": 1540, "rating_deviation": 170.0, "recorded_at": "2024-01-16T12:00:00Z"},
{"bot_id": "b_f3af8d6177eb", "rating": 1570, "rating_deviation": 85.0, "recorded_at": "2024-01-17T14:00:00Z"},
{"bot_id": "b_f3af8d6177eb", "rating": 1590, "rating_deviation": 40.0, "recorded_at": "2024-01-18T16:00:00Z"}
],
"recent_matches": [
{
"id": "m_test007",
"completed_at": "2024-01-18T14:00:00Z",
"participants": [
{"bot_id": "b_f3af8d6177eb", "name": "GuardianBot", "score": 4, "won": true},
{"bot_id": "b_656f050a7ed3", "name": "RandomBot", "score": 1, "won": false}
],
"winner_id": "b_f3af8d6177eb",
"map_id": "map_2p_007",
"turns": 398,
"end_reason": "turn_limit",
"enriched": false
},
{
"id": "m_test008",
"completed_at": "2024-01-18T13:00:00Z",
"participants": [
{"bot_id": "b_f3af8d6177eb", "name": "GuardianBot", "score": 3, "won": false},
{"bot_id": "b_457b876ca1c4", "name": "HunterBot", "score": 5, "won": true}
],
"winner_id": "b_457b876ca1c4",
"map_id": "map_2p_008",
"turns": 423,
"end_reason": "turn_limit",
"enriched": true
}
]
}

View file

@ -1,5 +1,47 @@
{
"$comment": "Placeholder file - replaced by index builder",
"updated_at": null,
"bots": []
"updated_at": "2024-01-18T16:00:00Z",
"bots": [
{
"id": "b_457b876ca1c4",
"name": "HunterBot",
"rating": 1710,
"matches_played": 162,
"win_rate": 66.7
},
{
"id": "b_62beeb03c196",
"name": "SwarmBot",
"rating": 1680,
"matches_played": 156,
"win_rate": 62.8
},
{
"id": "b_2fa5681bf0ff",
"name": "GathererBot",
"rating": 1640,
"matches_played": 148,
"win_rate": 60.1
},
{
"id": "b_f3af8d6177eb",
"name": "GuardianBot",
"rating": 1590,
"matches_played": 155,
"win_rate": 56.8
},
{
"id": "b_ae1845729bbf",
"name": "RusherBot",
"rating": 1520,
"matches_played": 142,
"win_rate": 54.9
},
{
"id": "b_656f050a7ed3",
"name": "RandomBot",
"rating": 1200,
"matches_played": 180,
"win_rate": 25.0
}
]
}

View file

@ -1,6 +1,77 @@
{
"$comment": "Placeholder file - replaced by index builder",
"updated_at": null,
"season": null,
"entries": []
"updated_at": "2024-01-18T16:00:00Z",
"entries": [
{
"rank": 1,
"bot_id": "b_457b876ca1c4",
"name": "HunterBot",
"owner_id": "system",
"rating": 1710,
"rating_deviation": 35.0,
"matches_played": 162,
"matches_won": 108,
"win_rate": 66.7,
"health_status": "healthy"
},
{
"rank": 2,
"bot_id": "b_62beeb03c196",
"name": "SwarmBot",
"owner_id": "system",
"rating": 1680,
"rating_deviation": 38.0,
"matches_played": 156,
"matches_won": 98,
"win_rate": 62.8,
"health_status": "healthy"
},
{
"rank": 3,
"bot_id": "b_2fa5681bf0ff",
"name": "GathererBot",
"owner_id": "system",
"rating": 1640,
"rating_deviation": 42.0,
"matches_played": 148,
"matches_won": 89,
"win_rate": 60.1,
"health_status": "healthy"
},
{
"rank": 4,
"bot_id": "b_f3af8d6177eb",
"name": "GuardianBot",
"owner_id": "system",
"rating": 1590,
"rating_deviation": 40.0,
"matches_played": 155,
"matches_won": 88,
"win_rate": 56.8,
"health_status": "healthy"
},
{
"rank": 5,
"bot_id": "b_ae1845729bbf",
"name": "RusherBot",
"owner_id": "system",
"rating": 1520,
"rating_deviation": 45.0,
"matches_played": 142,
"matches_won": 78,
"win_rate": 54.9,
"health_status": "healthy"
},
{
"rank": 6,
"bot_id": "b_656f050a7ed3",
"name": "RandomBot",
"owner_id": "system",
"rating": 1200,
"rating_deviation": 50.0,
"matches_played": 180,
"matches_won": 45,
"win_rate": 25.0,
"health_status": "healthy"
}
]
}

View file

@ -0,0 +1,75 @@
{
"updated_at": "2026-04-25T14:18:07Z",
"rivalries": [
{
"bot_a": {
"id": "b_62beeb03c196",
"name": "SwarmBot"
},
"bot_b": {
"id": "b_656f050a7ed3",
"name": "RandomBot"
},
"matches": 10,
"record": {
"a_wins": 0,
"b_wins": 10,
"draws": 0
},
"closest_match": "m_41178115cb15bb7a",
"longest_streak": {
"holder": "b_656f050a7ed3",
"length": 10
},
"recent_matches": [
"m_3e2cab5ff8b30c6d",
"m_fe47ac7c6fcf27c9",
"m_f1d7b69a8e45c7a4",
"m_7de7a590017b4b5a",
"m_a0490646b75c03b1",
"m_373fea9a4e680dc8",
"m_51ca5662499a3f9b",
"m_7ac443ec2045d06f",
"m_5ad234bc78e4b798",
"m_41178115cb15bb7a"
],
"narrative": "SwarmBot and RandomBot have met 10 times with RandomBot holding a 10-0 edge. b_656f050a7ed3 is currently on a 10-match winning streak.",
"score": 0
},
{
"bot_a": {
"id": "b_2fa5681bf0ff",
"name": "GathererBot"
},
"bot_b": {
"id": "b_656f050a7ed3",
"name": "RandomBot"
},
"matches": 10,
"record": {
"a_wins": 0,
"b_wins": 10,
"draws": 0
},
"closest_match": "m_6686e424dc1888b2",
"longest_streak": {
"holder": "b_656f050a7ed3",
"length": 10
},
"recent_matches": [
"m_8d88348c783f550c",
"m_119abbf1798ce0e9",
"m_7254ec479efd7ee7",
"m_ce51f757053b4f4d",
"m_dd16649b469e332e",
"m_e446a8f698c68b57",
"m_6b79ebb9a9bc1981",
"m_b82892f81ca17e9e",
"m_ff26ae99199b8999",
"m_6686e424dc1888b2"
],
"narrative": "GathererBot and RandomBot have met 10 times with RandomBot holding a 10-0 edge. b_656f050a7ed3 is currently on a 10-match winning streak.",
"score": 0
}
]
}

File diff suppressed because it is too large Load diff

View file

@ -39,6 +39,7 @@ export interface MatchSummary {
completed_at: string | null;
participants: MatchSummaryParticipant[];
winner_id: string | null;
map_id?: string;
turns: number | null;
end_reason: string | null;
enriched?: boolean;