2.0.0-rc1 : Profile and achievements update.

This commit is contained in:
2026-08-09 00:50:45 +08:00
parent 562775e5db
commit 3874bf57a9
31 changed files with 2618 additions and 108 deletions
+268 -13
View File
@@ -44,9 +44,12 @@ class ApplicationIntegrationTests(unittest.TestCase):
paths = [
'/',
'/matches/',
'/reports/',
'/awards/',
'/players/',
f'/players/{self.roster_ids[0]}',
'/teams/',
'/teams/performance',
'/tactics/',
'/opponents/',
]
@@ -56,6 +59,47 @@ class ApplicationIntegrationTests(unittest.TestCase):
self.assertEqual(response.status_code, 200)
self.assertGreater(len(response.data), 100)
def test_match_detail_contains_post_match_report(self):
l3 = sqlite3.connect(Config.DB_L3_PATH)
try:
match_id = l3.execute(
"""
SELECT match_id
FROM dm_match_reports
ORDER BY match_date DESC
LIMIT 1
"""
).fetchone()[0]
finally:
l3.close()
response = self.client.get(f'/matches/{match_id}')
self.assertEqual(response.status_code, 200)
self.assertIn('赛后报告'.encode('utf-8'), response.data)
self.assertIn('Form Improver'.encode('utf-8'), response.data)
def test_awards_and_professional_identity_render(self):
response = self.client.get('/awards/?type=monthly')
self.assertEqual(response.status_code, 200)
self.assertIn('周期最佳与荣誉榜'.encode('utf-8'), response.data)
self.assertIn('月度最佳'.encode('utf-8'), response.data)
response = self.client.get(f'/players/{self.roster_ids[0]}')
self.assertEqual(response.status_code, 200)
self.assertIn(b'Professional Identity', response.data)
self.assertIn('代表武器'.encode('utf-8'), response.data)
def test_team_performance_page_contains_beta_sections(self):
response = self.client.get('/teams/performance')
self.assertEqual(response.status_code, 200)
for label in (
'战队履历与阵容表现',
'二人组表现',
'实际阵容组合',
'Roster Version 历史',
):
with self.subTest(label=label):
self.assertIn(label.encode('utf-8'), response.data)
def test_admin_integrity_page_and_json_render(self):
with self.client.session_transaction() as session:
session['is_admin'] = True
@@ -93,19 +137,26 @@ class ApplicationIntegrationTests(unittest.TestCase):
"""
).fetchone()[0]
response = self.client.post(
'/admin/import-match',
data={
'capture': (
io.BytesIO(raw.encode('utf-8')),
'iframe_network.json',
),
},
content_type='multipart/form-data',
follow_redirects=True,
)
self.assertEqual(response.status_code, 200)
self.assertIn(b'already imported with identical data', response.data)
upload = io.BytesIO(raw.encode('utf-8'))
try:
response = self.client.post(
'/admin/import-match',
data={
'capture': (
upload,
'iframe_network.json',
),
},
content_type='multipart/form-data',
follow_redirects=True,
)
finally:
upload.close()
try:
self.assertEqual(response.status_code, 200)
self.assertIn(b'already imported with identical data', response.data)
finally:
response.close()
def test_player_search_works_across_l2_and_l3(self):
response = self.client.get('/players/?search=jAck')
@@ -238,11 +289,18 @@ class L3MartBuilderTests(unittest.TestCase):
)
l3.commit()
for table in (
'dm_duo_stats',
'dm_lineup_stats',
'dm_match_player_reports',
'dm_match_reports',
'dm_player_awards',
'dm_player_match_history',
'dm_player_map_stats',
'dm_player_period_stats',
'dm_player_record_events',
'dm_player_records',
'dm_player_weapon_stats',
'dm_team_season_stats',
):
count = l3.execute(
f'SELECT COUNT(*) FROM {table}'
@@ -615,6 +673,203 @@ class DatabaseGovernanceTests(unittest.TestCase):
l3.close()
l2.close()
def test_award_minimum_samples_and_unique_period_winner(self):
minimums = {
'daily': 1,
'weekly': 2,
'monthly': 5,
'quarterly': 10,
'yearly': 20,
}
l3 = sqlite3.connect(Config.DB_L3_PATH)
try:
rows = l3.execute(
"""
SELECT award_type, period_key, matches
FROM dm_player_awards
"""
).fetchall()
finally:
l3.close()
self.assertGreater(len(rows), 0)
seen = set()
for award_type, period_key, matches in rows:
with self.subTest(award_type=award_type, period_key=period_key):
self.assertGreaterEqual(matches, minimums[award_type])
self.assertNotIn((award_type, period_key), seen)
seen.add((award_type, period_key))
def test_seasons_only_include_team_matches(self):
l2 = sqlite3.connect(Config.DB_L2_PATH)
l3 = sqlite3.connect(Config.DB_L3_PATH)
web = sqlite3.connect(Config.DB_WEB_PATH)
try:
roster_ids = json.loads(
web.execute(
"""
SELECT player_ids_json
FROM team_lineups
WHERE is_active = 1
"""
).fetchone()[0]
)
placeholders = ','.join('?' for _ in roster_ids)
expected = {
str(row[0]): row[1]
for row in l2.execute(
f"""
SELECT
strftime('%Y', m.start_time, 'unixepoch') AS season,
COUNT(DISTINCT grouped.match_id)
FROM (
SELECT
match_id,
CASE
WHEN group_id IN (1, 2) THEN group_id
WHEN team_id IN (1, 2) THEN team_id
END AS team_key
FROM fact_match_players
WHERE steam_id_64 IN ({placeholders})
GROUP BY match_id, team_key
HAVING COUNT(DISTINCT steam_id_64) >= 2
AND team_key IS NOT NULL
) grouped
JOIN fact_matches m ON m.match_id = grouped.match_id
GROUP BY strftime('%Y', m.start_time, 'unixepoch')
""",
roster_ids,
)
}
actual = {
row[0]: row[1]
for row in l3.execute(
'SELECT season_key, matches FROM dm_team_season_stats'
)
}
finally:
l2.close()
l3.close()
web.close()
self.assertEqual(actual, expected)
def test_roster_version_snapshot_closes_previous_version(self):
from web.services.roster_version_service import RosterVersionService
with tempfile.TemporaryDirectory() as temp_dir:
web_path = Path(temp_dir) / 'Web.sqlite'
l2_path = Path(temp_dir) / 'L2.sqlite'
with sqlite3.connect(str(web_path)) as db:
with open(Config.DB_WEB_SCHEMA_PATH, 'r', encoding='utf-8') as schema:
db.executescript(schema.read())
db.execute(
"""
INSERT INTO team_lineups (
name, player_ids_json, is_active
) VALUES ('Test', '["1", "2"]', 1)
"""
)
with sqlite3.connect(str(l2_path)) as db:
db.executescript(
"""
CREATE TABLE fact_matches (
match_id TEXT PRIMARY KEY,
start_time INTEGER
);
CREATE TABLE fact_match_players (
match_id TEXT,
steam_id_64 TEXT
);
INSERT INTO fact_matches VALUES ('m1', 100);
INSERT INTO fact_match_players VALUES ('m1', '1');
INSERT INTO fact_match_players VALUES ('m1', '2');
"""
)
first_id = RosterVersionService.ensure_initial_version(
str(web_path),
str(l2_path),
)
second_id, created = RosterVersionService.snapshot_roster(
['1', '3'],
effective_from=200,
web_db_path=str(web_path),
)
RosterVersionService.update_current_member_role(
'1',
'starter',
web_db_path=str(web_path),
)
self.assertTrue(created)
self.assertNotEqual(first_id, second_id)
with sqlite3.connect(str(web_path)) as db:
old = db.execute(
"""
SELECT is_current, effective_to
FROM team_roster_versions
WHERE id = ?
""",
[first_id],
).fetchone()
current_ids = [
row[0] for row in db.execute(
"""
SELECT steam_id_64
FROM team_roster_members
WHERE roster_version_id = ?
ORDER BY position_order
""",
[second_id],
)
]
role = db.execute(
"""
SELECT member_role
FROM team_roster_members
WHERE roster_version_id = ? AND steam_id_64 = '1'
""",
[second_id],
).fetchone()[0]
self.assertEqual(old, (0, 199))
self.assertEqual(current_ids, ['1', '3'])
self.assertEqual(role, 'starter')
def test_team_marts_cover_active_roster_combinations(self):
import json
from math import comb
web = sqlite3.connect(Config.DB_WEB_PATH)
l3 = sqlite3.connect(Config.DB_L3_PATH)
try:
roster_ids = json.loads(
web.execute(
"""
SELECT player_ids_json
FROM team_lineups
WHERE is_active = 1
"""
).fetchone()[0]
)
duo_count = l3.execute(
'SELECT COUNT(*) FROM dm_duo_stats'
).fetchone()[0]
lineup_sizes = {
row[0]: row[1]
for row in l3.execute(
"""
SELECT player_count, COUNT(*)
FROM dm_lineup_stats
GROUP BY player_count
"""
)
}
finally:
web.close()
l3.close()
self.assertEqual(duo_count, comb(len(roster_ids), 2))
self.assertTrue(all(size in lineup_sizes for size in (2, 3, 4, 5)))
if __name__ == '__main__':
unittest.main()