Files
yrtv/database/L3/Roadmap/IMPLEMENTATION_ROADMAP.md

610 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# L3 Implementation Roadmap & Checklist
> **Based on**: L3_ARCHITECTURE_PLAN.md v2.0
> **Start Date**: 2026-01-28
> **Estimated Duration**: 8-10 days
---
## Quick Start Checklist
### ✅ Pre-requisites
- [x] L1 database完整 (208 matches)
- [x] L2 database完整 (100% coverage, 51,860 rows)
- [x] L2 schema documented
- [x] Profile requirements analyzed
- [x] L3 architecture designed
### 🎯 Implementation Phases
---
## Phase 1: Schema & Infrastructure (Day 1-2)
### 1.1 Create L3 Database Schema
- [ ] Create `database/L3/schema.sql`
- [ ] dm_player_features (207 columns)
- [ ] dm_player_match_history
- [ ] dm_player_map_stats
- [ ] dm_player_weapon_stats
- [ ] All indexes
### 1.2 Initialize L3 Database
- [ ] Update `database/L3/L3_Builder.py` init_db()
- [ ] Run schema creation
- [ ] Verify tables created
### 1.3 Processor Base Classes
- [ ] Create `database/L3/processors/__init__.py`
- [ ] Create `database/L3/processors/base_processor.py`
- [ ] BaseFeatureProcessor interface
- [ ] SafeAggregator utility class
- [ ] Z-score normalization functions
**验收标准**
```bash
sqlite3 database/L3/L3.db ".tables"
# 应输出: dm_player_features, dm_player_match_history, dm_player_map_stats, dm_player_weapon_stats
```
---
## Phase 2: Tier 1 - Core Processors (Day 3-4)
### 2.1 BasicProcessor Implementation
- [ ] Create `database/L3/processors/basic_processor.py`
**Sub-tasks**:
- [ ] `calculate_basic_stats()` - 15 columns
- [ ] AVG(rating, rating2, kd, adr, kast, rws) from fact_match_players
- [ ] AVG(headshot_count), hs_rate = SUM(hs)/SUM(kills)
- [ ] total_kills, total_deaths, total_assists
- [ ] kpr, dpr, survival_rate
- [ ] `calculate_match_stats()` - 8 columns
- [ ] win_rate, wins, losses
- [ ] avg_match_duration from fact_matches
- [ ] avg_mvps, mvp_rate
- [ ] avg_elo_change, total_elo_gained from fact_match_teams
- [ ] `calculate_weapon_stats()` - 12 columns
- [ ] avg_awp_kills, awp_usage_rate
- [ ] avg_knife_kills, avg_zeus_kills, zeus_buy_rate
- [ ] top_weapon (GROUP BY weapon in fact_round_events)
- [ ] weapon_diversity (Shannon entropy)
- [ ] rifle/pistol/smg hs_rates
- [ ] `calculate_objective_stats()` - 6 columns
- [ ] avg_plants, avg_defuses, avg_flash_assists
- [ ] plant_success_rate, defuse_success_rate
- [ ] objective_impact (weighted score)
**测试用例**:
```python
features = BasicProcessor.calculate('76561198012345678', conn_l2)
assert 'core_avg_rating' in features
assert features['core_total_kills'] > 0
assert 0 <= features['core_hs_rate'] <= 1
```
---
## Phase 3: Tier 2 - Tactical Processors (Day 4-5)
### 3.1 TacticalProcessor Implementation
- [ ] Create `database/L3/processors/tactical_processor.py`
**Sub-tasks**:
- [ ] `calculate_opening_impact()` - 8 columns
- [ ] avg_fk, avg_fd from fact_match_players
- [ ] fk_rate, fd_rate
- [ ] fk_success_rate (team win when FK)
- [ ] entry_kill_rate, entry_death_rate
- [ ] opening_duel_winrate
- [ ] `calculate_multikill()` - 6 columns
- [ ] avg_2k, avg_3k, avg_4k, avg_5k
- [ ] multikill_rate
- [ ] ace_count (5k count)
- [ ] `calculate_clutch()` - 10 columns
- [ ] clutch_1v1/1v2_attempts/wins/rate
- [ ] clutch_1v3_plus aggregated
- [ ] clutch_impact_score (weighted)
- [ ] `calculate_utility()` - 12 columns
- [ ] util_X_per_round for flash/smoke/molotov/he
- [ ] util_usage_rate
- [ ] nade_dmg metrics
- [ ] flash_efficiency, smoke_timing_score
- [ ] util_impact_score
- [ ] `calculate_economy()` - 8 columns
- [ ] dmg_per_1k from fact_round_player_economy
- [ ] kpr/kd for eco/force/full rounds
- [ ] save_discipline, force_success_rate
- [ ] eco_efficiency_score
**测试**:
```python
features = TacticalProcessor.calculate('76561198012345678', conn_l2)
assert 'tac_fk_rate' in features
assert features['tac_multikill_rate'] >= 0
```
---
## Phase 4: Tier 3 - Intelligence Processors (Day 5-7)
### 4.1 IntelligenceProcessor Implementation
- [ ] Create `database/L3/processors/intelligence_processor.py`
**Sub-tasks**:
- [ ] `calculate_high_iq_kills()` - 8 columns
- [ ] wallbang/smoke/blind/noscope kills from fact_round_events flags
- [ ] Rates: X_kills / total_kills
- [ ] high_iq_score (weighted formula)
- [ ] `calculate_timing_analysis()` - 12 columns
- [ ] early/mid/late kills by event_time bins (0-30s, 30-60s, 60s+)
- [ ] timing shares
- [ ] avg_kill_time, avg_death_time
- [ ] aggression_index, patience_score
- [ ] first_contact_time (MIN(event_time) per round)
- [ ] `calculate_pressure_performance()` - 10 columns
- [ ] comeback_kd/rating (when down 4+ rounds)
- [ ] losing_streak_kd (3+ round loss streak)
- [ ] matchpoint_kpr/rating (at 15-X or 12-X)
- [ ] clutch_composure, entry_in_loss
- [ ] pressure_performance_index, big_moment_score
- [ ] tilt_resistance
- [ ] `calculate_position_mastery()` - 15 columns ⚠️ Complex
- [ ] site_a/b/mid_control_rate from xyz clustering
- [ ] favorite_position (most common cluster)
- [ ] position_diversity (entropy)
- [ ] rotation_speed (distance between kills)
- [ ] map_coverage, defensive/aggressive positioning
- [ ] lurk_tendency, site_anchor_score
- [ ] spatial_iq_score
- [ ] `calculate_trade_network()` - 8 columns
- [ ] trade_kill_count (kills within 5s of teammate death)
- [ ] trade_kill_rate
- [ ] trade_response_time (AVG seconds)
- [ ] trade_given (deaths traded by teammate)
- [ ] trade_balance, trade_efficiency
- [ ] teamwork_score
**Position Mastery特别注意**:
```python
# 需要使用sklearn DBSCAN聚类
from sklearn.cluster import DBSCAN
def cluster_player_positions(steam_id, conn_l2):
"""从fact_round_events提取xyz坐标并聚类"""
cursor = conn_l2.cursor()
cursor.execute("""
SELECT attacker_pos_x, attacker_pos_y, attacker_pos_z
FROM fact_round_events
WHERE attacker_steam_id = ?
AND attacker_pos_x IS NOT NULL
""", (steam_id,))
coords = cursor.fetchall()
# DBSCAN clustering...
```
**测试**:
```python
features = IntelligenceProcessor.calculate('76561198012345678', conn_l2)
assert 'int_high_iq_score' in features
assert features['int_timing_early_kill_share'] + features['int_timing_mid_kill_share'] + features['int_timing_late_kill_share'] <= 1.1 # Allow rounding
```
---
## Phase 5: Tier 4 - Meta Processors (Day 7-8)
### 5.1 MetaProcessor Implementation
- [ ] Create `database/L3/processors/meta_processor.py`
**Sub-tasks**:
- [ ] `calculate_stability()` - 8 columns
- [ ] rating_volatility (STDDEV of last 20 matches)
- [ ] recent_form_rating (AVG last 10)
- [ ] win/loss_rating
- [ ] rating_consistency (100 - volatility_norm)
- [ ] time_rating_correlation (CORR(duration, rating))
- [ ] map_stability, elo_tier_stability
- [ ] `calculate_side_preference()` - 14 columns
- [ ] side_ct/t_rating from fact_match_players_ct/t
- [ ] side_ct/t_kd, win_rate, fk_rate, kast
- [ ] side_rating_diff, side_kd_diff
- [ ] side_preference ('CT'/'T'/'Balanced')
- [ ] side_balance_score
- [ ] `calculate_opponent_adaptation()` - 12 columns
- [ ] vs_lower/similar/higher_elo_rating/kd
- [ ] Based on fact_match_teams.group_origin_elo差值
- [ ] elo_adaptation, stomping_score, upset_score
- [ ] consistency_across_elos, rank_resistance
- [ ] smurf_detection
- [ ] `calculate_map_specialization()` - 10 columns
- [ ] best/worst_map, best/worst_rating
- [ ] map_diversity (entropy)
- [ ] map_pool_size (maps with 5+ matches)
- [ ] map_specialist_score, map_versatility
- [ ] comfort_zone_rate, map_adaptation
- [ ] `calculate_session_pattern()` - 8 columns
- [ ] avg_matches_per_day
- [ ] longest_streak (consecutive days)
- [ ] weekend/weekday_rating
- [ ] morning/afternoon/evening/night_rating (based on timestamp)
**测试**:
```python
features = MetaProcessor.calculate('76561198012345678', conn_l2)
assert 'meta_rating_volatility' in features
assert features['meta_side_preference'] in ['CT', 'T', 'Balanced']
```
---
## Phase 6: Tier 5 - Composite Processors (Day 8)
### 6.1 CompositeProcessor Implementation
- [ ] Create `database/L3/processors/composite_processor.py`
**Sub-tasks**:
- [ ] `normalize_and_standardize()` helper
- [ ] Z-score normalization function
- [ ] Global mean/std calculation from all players
- [ ] Map Z-score to 0-100 range
- [ ] `calculate_radar_scores()` - 8 scores
- [ ] score_aim: 25% Rating + 20% KD + 15% ADR + 10% DuelWin + 10% HighEloKD + 20% MultiKill
- [ ] score_clutch: 25% 1v3+ + 20% MatchPtWin + 20% ComebackKD + 15% PressureEntry + 20% Rating
- [ ] score_pistol: 30% PistolKills + 30% PistolWin + 20% PistolKD + 20% PistolHS%
- [ ] score_defense: 35% CT_Rating + 35% T_Rating + 15% CT_FK + 15% T_FK
- [ ] score_utility: 35% UsageRate + 25% NadeDmg + 20% FlashEff + 20% FlashEnemy
- [ ] score_stability: 30% (100-Volatility) + 30% LossRating + 20% WinRating + 20% Consistency
- [ ] score_economy: 50% Dmg/$1k + 30% EcoKPR + 20% SaveRoundKD
- [ ] score_pace: 40% EntryTiming + 30% TradeSpeed + 30% AggressionIndex
- [ ] `calculate_overall_score()` - AVG of 8 scores
- [ ] `classify_tier()` - Performance tier
- [ ] Elite: overall > 75
- [ ] Advanced: 60-75
- [ ] Intermediate: 40-60
- [ ] Beginner: < 40
- [ ] `calculate_percentile()` - Rank among all players
**依赖**:
```python
def calculate(steam_id: str, conn_l2: sqlite3.Connection, pre_features: dict) -> dict:
"""
需要前面4个Tier的特征作为输入
Args:
pre_features: 包含Tier 1-4的所有特征
"""
pass
```
**测试**:
```python
# 需要先计算所有前置特征
features = {}
features.update(BasicProcessor.calculate(steam_id, conn_l2))
features.update(TacticalProcessor.calculate(steam_id, conn_l2))
features.update(IntelligenceProcessor.calculate(steam_id, conn_l2))
features.update(MetaProcessor.calculate(steam_id, conn_l2))
composite = CompositeProcessor.calculate(steam_id, conn_l2, features)
assert 0 <= composite['score_aim'] <= 100
assert composite['tier_classification'] in ['Elite', 'Advanced', 'Intermediate', 'Beginner']
```
---
## Phase 7: L3_Builder Integration (Day 8-9)
### 7.1 Main Builder Logic
- [ ] Update `database/L3/L3_Builder.py`
- [ ] Import all processors
- [ ] Main loop: iterate all players from dim_players
- [ ] Call processors in order
- [ ] _upsert_features() helper
- [ ] Batch commit every 100 players
- [ ] Progress logging
```python
def main():
logger.info("Starting L3 Builder...")
# 1. Init DB
init_db()
# 2. Connect
conn_l2 = sqlite3.connect(L2_DB_PATH)
conn_l3 = sqlite3.connect(L3_DB_PATH)
# 3. Get all players
cursor = conn_l2.cursor()
cursor.execute("SELECT DISTINCT steam_id_64 FROM dim_players")
players = cursor.fetchall()
logger.info(f"Processing {len(players)} players...")
for idx, (steam_id,) in enumerate(players, 1):
try:
# 4. Calculate features tier by tier
features = {}
features.update(BasicProcessor.calculate(steam_id, conn_l2))
features.update(TacticalProcessor.calculate(steam_id, conn_l2))
features.update(IntelligenceProcessor.calculate(steam_id, conn_l2))
features.update(MetaProcessor.calculate(steam_id, conn_l2))
features.update(CompositeProcessor.calculate(steam_id, conn_l2, features))
# 5. Upsert to L3
_upsert_features(conn_l3, steam_id, features)
# 6. Commit batch
if idx % 100 == 0:
conn_l3.commit()
logger.info(f"Processed {idx}/{len(players)} players")
except Exception as e:
logger.error(f"Error processing {steam_id}: {e}")
conn_l3.commit()
logger.info("Done!")
```
### 7.2 Auxiliary Tables Population
- [ ] Populate `dm_player_match_history`
- [ ] FROM fact_match_players JOIN fact_matches
- [ ] ORDER BY match date
- [ ] Calculate match_sequence, rolling averages
- [ ] Populate `dm_player_map_stats`
- [ ] GROUP BY steam_id, map_name
- [ ] FROM fact_match_players
- [ ] Populate `dm_player_weapon_stats`
- [ ] GROUP BY steam_id, weapon_name
- [ ] FROM fact_round_events
- [ ] TOP 10 weapons per player
### 7.3 Full Build Test
- [ ] Run: `python database/L3/L3_Builder.py`
- [ ] Verify: All players processed
- [ ] Check: Row counts in all L3 tables
- [ ] Validate: Sample features make sense
**验收标准**:
```sql
SELECT COUNT(*) FROM dm_player_features; -- 应该 = dim_players count
SELECT AVG(core_avg_rating) FROM dm_player_features; -- 应该接近1.0
SELECT COUNT(*) FROM dm_player_features WHERE score_aim > 0; -- 大部分玩家有评分
```
---
## Phase 8: Web Services Refactoring (Day 9-10)
### 8.1 Create PlayerService
- [ ] Create `web/services/player_service.py`
```python
class PlayerService:
@staticmethod
def get_player_features(steam_id: str) -> dict:
"""获取完整特征dm_player_features"""
pass
@staticmethod
def get_player_radar_data(steam_id: str) -> dict:
"""获取雷达图8维数据"""
pass
@staticmethod
def get_player_core_stats(steam_id: str) -> dict:
"""获取核心Dashboard数据"""
pass
@staticmethod
def get_player_history(steam_id: str, limit: int = 20) -> list:
"""获取历史趋势数据"""
pass
@staticmethod
def get_player_map_stats(steam_id: str) -> list:
"""获取各地图统计"""
pass
@staticmethod
def get_player_weapon_stats(steam_id: str, top_n: int = 10) -> list:
"""获取Top N武器"""
pass
@staticmethod
def get_players_ranking(order_by: str = 'core_avg_rating',
limit: int = 100,
offset: int = 0) -> list:
"""获取排行榜"""
pass
```
- [ ] Implement all methods
- [ ] Add error handling
- [ ] Add caching (optional)
### 8.2 Refactor Routes
- [ ] Update `web/routes/players.py`
- [ ] `/profile/<steam_id>` route
- [ ] Use PlayerService instead of direct DB queries
- [ ] Pass features dict to template
- [ ] Add API endpoints
- [ ] `/api/players/<steam_id>/features`
- [ ] `/api/players/ranking`
- [ ] `/api/players/<steam_id>/history`
### 8.3 Update feature_service.py
- [ ] Mark old rebuild methods as DEPRECATED
- [ ] Redirect to L3_Builder.py
- [ ] Keep query methods for backward compatibility
---
## Phase 9: Frontend Integration (Day 10-11)
### 9.1 Update profile.html Template
- [ ] Dashboard cards: use `features.core_*`
- [ ] Radar chart: use `features.score_*`
- [ ] Trend chart: use `history` data
- [ ] Core Performance section
- [ ] Gunfight section
- [ ] Opening Impact section
- [ ] Clutch section
- [ ] High IQ Kills section
- [ ] Map stats table
- [ ] Weapon stats table
### 9.2 JavaScript Integration
- [ ] Radar chart rendering (Chart.js)
- [ ] Trend chart rendering
- [ ] Dynamic data loading
### 9.3 UI Polish
- [ ] Responsive design
- [ ] Loading states
- [ ] Error handling
- [ ] Tooltips for complex metrics
---
## Phase 10: Testing & Validation (Day 11-12)
### 10.1 Unit Tests
- [ ] Test each processor independently
- [ ] Mock L2 data
- [ ] Verify calculation correctness
### 10.2 Integration Tests
- [ ] Full L3_Builder run
- [ ] Verify all tables populated
- [ ] Check data consistency
### 10.3 Performance Tests
- [ ] Benchmark L3_Builder runtime
- [ ] Profile slow queries
- [ ] Optimize if needed
### 10.4 Data Quality Checks
- [ ] Verify no NULL values where expected
- [ ] Check value ranges (e.g., 0 <= rate <= 1)
- [ ] Validate composite scores (0-100)
- [ ] Cross-check with L2 source data
---
## Success Criteria
### ✅ L3 Database
- [ ] All 4 tables created with correct schemas
- [ ] dm_player_features has 207 columns
- [ ] All players from L2 have corresponding L3 rows
- [ ] No critical NULL values
### ✅ Feature Calculation
- [ ] All 5 processors implemented and tested
- [ ] 207 features calculated correctly
- [ ] Composite scores in 0-100 range
- [ ] Tier classification working
### ✅ Services & Routes
- [ ] PlayerService provides all query methods
- [ ] Routes use services correctly
- [ ] API endpoints return valid JSON
- [ ] No direct DB queries in routes
### ✅ Frontend
- [ ] Profile page renders correctly
- [ ] Radar chart displays 8 dimensions
- [ ] Trend chart shows history
- [ ] All sections populated with data
### ✅ Performance
- [ ] L3_Builder completes in < 20 min for 1000 players
- [ ] Profile page loads in < 200ms
- [ ] No N+1 query problems
---
## Risk Mitigation
### 🔴 High Risk Items
1. **Position Mastery (xyz clustering)**
- Mitigation: Start with simple grid-based approach, defer ML clustering
2. **Composite Score Standardization**
- Mitigation: Use simple percentile-based normalization as fallback
3. **Performance at Scale**
- Mitigation: Implement incremental updates, add indexes
### 🟡 Medium Risk Items
1. **Time Window Calculations (trades)**
- Mitigation: Use efficient self-JOIN with time bounds
2. **Missing Data Handling**
- Mitigation: Comprehensive NULL handling, default values
### 🟢 Low Risk Items
1. Basic aggregations (AVG, SUM, COUNT)
2. Service layer refactoring
3. Template updates
---
## Next Actions
**Immediate (Today)**:
1. Create schema.sql
2. Initialize L3.db
3. Create processor base classes
**Tomorrow**:
1. Implement BasicProcessor
2. Test with sample player
3. Start TacticalProcessor
**This Week**:
1. Complete all 5 processors
2. Full L3_Builder run
3. Service refactoring
**Next Week**:
1. Frontend integration
2. Testing & validation
3. Documentation
---
## Notes
- 保持每个processor独立便于单元测试
- 使用动态SQL避免column count错误
- 所有rate/percentage使用0-1范围存储UI展示时乘100
- 时间戳统一使用Unix timestamp (INTEGER)
- 遵循"查询不计算"原则web层只SELECT不做聚合