328 lines
10 KiB
Python
328 lines
10 KiB
Python
import json
|
|
|
|
from web.database import query_db
|
|
|
|
|
|
class NarrativeService:
|
|
AWARD_TYPE_LABELS = {
|
|
'daily': '单日最佳',
|
|
'weekly': '星期最佳',
|
|
'monthly': '月度最佳',
|
|
'quarterly': '季度最佳',
|
|
'yearly': '年度最佳',
|
|
}
|
|
|
|
PERFORMANCE_LABELS = {
|
|
'surge': '状态爆发',
|
|
'above_form': '高于近期',
|
|
'stable': '稳定发挥',
|
|
'below_form': '低于近期',
|
|
'slump': '状态低迷',
|
|
'insufficient_sample': '样本不足',
|
|
}
|
|
|
|
RECORD_LABELS = {
|
|
'highest_rating': '最高 Rating',
|
|
'most_kills': '最多击杀',
|
|
'highest_adr': '最高 ADR',
|
|
'highest_kd': '最高 K/D',
|
|
'most_headshots': '最多爆头',
|
|
}
|
|
|
|
@staticmethod
|
|
def _identity_map(steam_ids):
|
|
steam_ids = sorted({str(value) for value in steam_ids if value})
|
|
if not steam_ids:
|
|
return {}
|
|
placeholders = ','.join('?' for _ in steam_ids)
|
|
rows = query_db(
|
|
'l2',
|
|
f"""
|
|
SELECT steam_id_64, username, avatar_url
|
|
FROM dim_players
|
|
WHERE steam_id_64 IN ({placeholders})
|
|
""",
|
|
steam_ids,
|
|
)
|
|
return {str(row['steam_id_64']): dict(row) for row in rows}
|
|
|
|
@staticmethod
|
|
def get_match_report(match_id):
|
|
report = query_db(
|
|
'l3',
|
|
'SELECT * FROM dm_match_reports WHERE match_id = ?',
|
|
[match_id],
|
|
one=True,
|
|
)
|
|
if not report:
|
|
return None
|
|
result = dict(report)
|
|
player_rows = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT *
|
|
FROM dm_match_player_reports
|
|
WHERE match_id = ?
|
|
ORDER BY rating DESC
|
|
""",
|
|
[match_id],
|
|
)
|
|
player_reports = [dict(row) for row in player_rows]
|
|
steam_ids = [row['steam_id_64'] for row in player_reports]
|
|
steam_ids.extend([
|
|
result.get('mvp_steam_id'),
|
|
result.get('improver_steam_id'),
|
|
])
|
|
duo = json.loads(result.get('strongest_duo_json') or 'null')
|
|
if duo:
|
|
steam_ids.extend(duo.get('steam_ids') or [])
|
|
identities = NarrativeService._identity_map(steam_ids)
|
|
|
|
for player in player_reports:
|
|
player['identity'] = identities.get(
|
|
str(player['steam_id_64']),
|
|
{'username': player['steam_id_64']},
|
|
)
|
|
player['performance_text'] = NarrativeService.PERFORMANCE_LABELS.get(
|
|
player['performance_label'],
|
|
player['performance_label'],
|
|
)
|
|
record_keys = json.loads(player['record_keys_json'] or '[]')
|
|
player['record_labels'] = [
|
|
NarrativeService.RECORD_LABELS.get(key, key)
|
|
for key in record_keys
|
|
]
|
|
result['players'] = player_reports
|
|
result['mvp'] = identities.get(str(result.get('mvp_steam_id')), {})
|
|
result['improver'] = identities.get(
|
|
str(result.get('improver_steam_id')),
|
|
{},
|
|
)
|
|
if duo:
|
|
duo['players'] = [
|
|
identities.get(str(steam_id), {'username': steam_id})
|
|
for steam_id in duo.get('steam_ids', [])
|
|
]
|
|
result['strongest_duo'] = duo
|
|
return result
|
|
|
|
@staticmethod
|
|
def list_match_reports(limit=30):
|
|
rows = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT *
|
|
FROM dm_match_reports
|
|
ORDER BY match_date DESC, match_id DESC
|
|
LIMIT ?
|
|
""",
|
|
[limit],
|
|
)
|
|
identities = NarrativeService._identity_map(
|
|
[row['mvp_steam_id'] for row in rows]
|
|
)
|
|
result = []
|
|
for row in rows:
|
|
item = dict(row)
|
|
item['mvp'] = identities.get(str(item['mvp_steam_id']), {})
|
|
result.append(item)
|
|
return result
|
|
|
|
@staticmethod
|
|
def list_awards(award_type=None, limit=100):
|
|
args = []
|
|
where = ''
|
|
if award_type in NarrativeService.AWARD_TYPE_LABELS:
|
|
where = 'WHERE award_type = ?'
|
|
args.append(award_type)
|
|
args.append(limit)
|
|
rows = query_db(
|
|
'l3',
|
|
f"""
|
|
SELECT *
|
|
FROM dm_player_awards
|
|
{where}
|
|
ORDER BY period_start DESC,
|
|
CASE award_type
|
|
WHEN 'yearly' THEN 1
|
|
WHEN 'quarterly' THEN 2
|
|
WHEN 'monthly' THEN 3
|
|
WHEN 'weekly' THEN 4
|
|
ELSE 5
|
|
END
|
|
LIMIT ?
|
|
""",
|
|
args,
|
|
)
|
|
identities = NarrativeService._identity_map(
|
|
[row['steam_id_64'] for row in rows]
|
|
)
|
|
result = []
|
|
for row in rows:
|
|
item = dict(row)
|
|
item['identity'] = identities.get(str(item['steam_id_64']), {})
|
|
item['award_label'] = NarrativeService.AWARD_TYPE_LABELS.get(
|
|
item['award_type'],
|
|
item['award_type'],
|
|
)
|
|
result.append(item)
|
|
return result
|
|
|
|
@staticmethod
|
|
def get_award_summary():
|
|
rows = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT
|
|
steam_id_64,
|
|
COUNT(*) AS awards,
|
|
SUM(CASE WHEN award_type = 'daily' THEN 1 ELSE 0 END) AS daily,
|
|
SUM(CASE WHEN award_type = 'weekly' THEN 1 ELSE 0 END) AS weekly,
|
|
SUM(CASE WHEN award_type = 'monthly' THEN 1 ELSE 0 END) AS monthly,
|
|
SUM(CASE WHEN award_type = 'quarterly' THEN 1 ELSE 0 END) AS quarterly,
|
|
SUM(CASE WHEN award_type = 'yearly' THEN 1 ELSE 0 END) AS yearly
|
|
FROM dm_player_awards
|
|
GROUP BY steam_id_64
|
|
ORDER BY yearly DESC, quarterly DESC, monthly DESC,
|
|
weekly DESC, daily DESC
|
|
""",
|
|
)
|
|
identities = NarrativeService._identity_map(
|
|
[row['steam_id_64'] for row in rows]
|
|
)
|
|
result = []
|
|
for row in rows:
|
|
item = dict(row)
|
|
item['identity'] = identities.get(str(item['steam_id_64']), {})
|
|
result.append(item)
|
|
return result
|
|
|
|
@staticmethod
|
|
def get_seasons():
|
|
rows = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT *
|
|
FROM dm_team_season_stats
|
|
ORDER BY season_key DESC
|
|
""",
|
|
)
|
|
identities = NarrativeService._identity_map(
|
|
[row['top_player_steam_id'] for row in rows]
|
|
)
|
|
result = []
|
|
for row in rows:
|
|
item = dict(row)
|
|
item['top_player'] = identities.get(
|
|
str(item['top_player_steam_id']),
|
|
{},
|
|
)
|
|
result.append(item)
|
|
return result
|
|
|
|
@staticmethod
|
|
def get_player_honors(steam_id, limit=20):
|
|
rows = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT *
|
|
FROM dm_player_awards
|
|
WHERE steam_id_64 = ?
|
|
ORDER BY period_start DESC
|
|
LIMIT ?
|
|
""",
|
|
[steam_id, limit],
|
|
)
|
|
awards = []
|
|
for row in rows:
|
|
item = dict(row)
|
|
item['award_label'] = NarrativeService.AWARD_TYPE_LABELS.get(
|
|
item['award_type'],
|
|
item['award_type'],
|
|
)
|
|
awards.append(item)
|
|
record_rows = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT *
|
|
FROM dm_player_record_events
|
|
WHERE steam_id_64 = ?
|
|
ORDER BY match_date DESC
|
|
LIMIT ?
|
|
""",
|
|
[steam_id, limit],
|
|
)
|
|
record_events = []
|
|
for row in record_rows:
|
|
item = dict(row)
|
|
item['record_label'] = NarrativeService.RECORD_LABELS.get(
|
|
item['record_key'],
|
|
item['record_key'],
|
|
)
|
|
record_events.append(item)
|
|
return {
|
|
'awards': awards,
|
|
'award_count': len(awards),
|
|
'record_events': record_events,
|
|
}
|
|
|
|
@staticmethod
|
|
def get_player_identity(steam_id):
|
|
feature = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT
|
|
total_matches,
|
|
first_match_date,
|
|
last_match_date,
|
|
core_top_weapon,
|
|
meta_map_best_map,
|
|
tier_percentile
|
|
FROM dm_player_features
|
|
WHERE steam_id_64 = ?
|
|
""",
|
|
[steam_id],
|
|
one=True,
|
|
)
|
|
roster = query_db(
|
|
'web',
|
|
"""
|
|
SELECT
|
|
member.member_role,
|
|
version.name AS roster_version,
|
|
(
|
|
SELECT MIN(history_version.effective_from)
|
|
FROM team_roster_members history_member
|
|
JOIN team_roster_versions history_version
|
|
ON history_version.id = history_member.roster_version_id
|
|
WHERE history_member.steam_id_64 = member.steam_id_64
|
|
) AS effective_from
|
|
FROM team_roster_members member
|
|
JOIN team_roster_versions version
|
|
ON version.id = member.roster_version_id
|
|
WHERE member.steam_id_64 = ?
|
|
ORDER BY version.is_current DESC, version.effective_from DESC
|
|
LIMIT 1
|
|
""",
|
|
[steam_id],
|
|
one=True,
|
|
)
|
|
awards = query_db(
|
|
'l3',
|
|
"""
|
|
SELECT award_type, COUNT(*) AS count
|
|
FROM dm_player_awards
|
|
WHERE steam_id_64 = ?
|
|
GROUP BY award_type
|
|
""",
|
|
[steam_id],
|
|
)
|
|
result = dict(feature) if feature else {}
|
|
if roster:
|
|
result.update(dict(roster))
|
|
result['awards_by_type'] = {
|
|
row['award_type']: row['count'] for row in awards
|
|
}
|
|
result['award_count'] = sum(result['awards_by_type'].values())
|
|
return result
|