Add shot accuracy data calculation and visualization to player stats page
- Implement calculate_shot_accuracy() function in tv_app.py to extract individual shot values from tournament participant data - Aggregate shot accuracy data (0-10) by tournament type (4_targets, 20_targets, 40_targets) in analyze_player_performance() - Update modern_player_stats.html to load shot accuracy data directly from template context instead of API - Add tournament type mapping between display names (40 Targets) and backend keys (40_targets) - Implement CSS-based bar chart visualization that displays shot distribution with proper color gradients - Remove unused async loadShotAccuracyData() API fetch and replace with direct template data access - Data is now properly aggregated across all tournaments for each player and format type 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -163,6 +163,56 @@ def get_archived_leagues():
|
||||
def load_archive_file(filepath):
|
||||
return ArchiveStorage.load_archive_file(filepath)
|
||||
|
||||
def calculate_shot_accuracy(participant):
|
||||
"""
|
||||
Extract shot accuracy breakdown from participant targets.
|
||||
Returns dict with counts for each shot value (0-10).
|
||||
"""
|
||||
accuracy_data = {
|
||||
'tens': 0,
|
||||
'nines': 0,
|
||||
'eights': 0,
|
||||
'sevens': 0,
|
||||
'sixes': 0,
|
||||
'fives': 0,
|
||||
'fours': 0,
|
||||
'threes': 0,
|
||||
'twos': 0,
|
||||
'ones': 0,
|
||||
'zeros': 0
|
||||
}
|
||||
|
||||
targets = participant.get('targets', {})
|
||||
for target_num, shots in targets.items():
|
||||
# Extract all shots from this target (shot1, shot2, etc.)
|
||||
for shot_key, shot_value in shots.items():
|
||||
shot_val = int(shot_value)
|
||||
if shot_val == 10:
|
||||
accuracy_data['tens'] += 1
|
||||
elif shot_val == 9:
|
||||
accuracy_data['nines'] += 1
|
||||
elif shot_val == 8:
|
||||
accuracy_data['eights'] += 1
|
||||
elif shot_val == 7:
|
||||
accuracy_data['sevens'] += 1
|
||||
elif shot_val == 6:
|
||||
accuracy_data['sixes'] += 1
|
||||
elif shot_val == 5:
|
||||
accuracy_data['fives'] += 1
|
||||
elif shot_val == 4:
|
||||
accuracy_data['fours'] += 1
|
||||
elif shot_val == 3:
|
||||
accuracy_data['threes'] += 1
|
||||
elif shot_val == 2:
|
||||
accuracy_data['twos'] += 1
|
||||
elif shot_val == 1:
|
||||
accuracy_data['ones'] += 1
|
||||
elif shot_val == 0:
|
||||
accuracy_data['zeros'] += 1
|
||||
|
||||
return accuracy_data
|
||||
|
||||
|
||||
def analyze_player_performance(player_id, archives_data):
|
||||
"""Analyze performance of a specific player across all archives"""
|
||||
player_stats = {
|
||||
@@ -176,46 +226,58 @@ def analyze_player_performance(player_id, archives_data):
|
||||
'total_shots_fired': 0,
|
||||
'performance_trend': [],
|
||||
'tournament_history': [],
|
||||
'league_history': []
|
||||
'league_history': [],
|
||||
'shot_accuracy': {
|
||||
'4_targets': {'tens': 0, 'nines': 0, 'eights': 0, 'sevens': 0, 'sixes': 0, 'fives': 0, 'fours': 0, 'threes': 0, 'twos': 0, 'ones': 0, 'zeros': 0},
|
||||
'20_targets': {'tens': 0, 'nines': 0, 'eights': 0, 'sevens': 0, 'sixes': 0, 'fives': 0, 'fours': 0, 'threes': 0, 'twos': 0, 'ones': 0, 'zeros': 0},
|
||||
'40_targets': {'tens': 0, 'nines': 0, 'eights': 0, 'sevens': 0, 'sixes': 0, 'fives': 0, 'fours': 0, 'threes': 0, 'twos': 0, 'ones': 0, 'zeros': 0}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Process tournament archives
|
||||
for archive in archives_data.get('tournaments', []):
|
||||
try:
|
||||
data = load_archive_file(archive['filepath'])
|
||||
if not data:
|
||||
continue
|
||||
|
||||
|
||||
results = data.get('results', {})
|
||||
participants = results.get('participants', {})
|
||||
|
||||
|
||||
if str(player_id) in participants:
|
||||
participant = participants[str(player_id)]
|
||||
score = participant.get('total_score', 0)
|
||||
completed = participant.get('completed', False)
|
||||
|
||||
|
||||
if completed:
|
||||
player_stats['total_tournaments'] += 1
|
||||
player_stats['tournament_scores'].append(score)
|
||||
|
||||
|
||||
if score > player_stats['best_tournament_score']:
|
||||
player_stats['best_tournament_score'] = score
|
||||
if score < player_stats['worst_tournament_score']:
|
||||
player_stats['worst_tournament_score'] = score
|
||||
|
||||
|
||||
# Count shots fired - NOW WITH PROPER COUNTING FOR ALL FORMATS
|
||||
tournament_type = archive.get('tournament_type', '20_targets')
|
||||
shots_in_tournament = count_shots_in_tournament(participant, tournament_type)
|
||||
|
||||
|
||||
player_stats['total_shots_fired'] += shots_in_tournament
|
||||
|
||||
|
||||
# Calculate and aggregate shot accuracy
|
||||
if tournament_type in player_stats['shot_accuracy']:
|
||||
shot_accuracy = calculate_shot_accuracy(participant)
|
||||
for key in shot_accuracy:
|
||||
player_stats['shot_accuracy'][tournament_type][key] += shot_accuracy[key]
|
||||
|
||||
# Add to history
|
||||
player_stats['tournament_history'].append({
|
||||
'date': archive['archived_at'],
|
||||
'score': score,
|
||||
'tournament_type': archive['tournament_type'],
|
||||
'completed': completed,
|
||||
'shots_fired': shots_in_tournament # NOW CORRECTLY CALCULATED
|
||||
'shots_fired': shots_in_tournament, # NOW CORRECTLY CALCULATED
|
||||
'filename': archive.get('filename', '')
|
||||
})
|
||||
except Exception as e:
|
||||
print(f"Error analyzing tournament archive: {e}")
|
||||
@@ -235,18 +297,22 @@ def analyze_player_performance(player_id, archives_data):
|
||||
participant = participants[str(player_id)]
|
||||
final_score = participant.get('final_score', 0)
|
||||
total_score = participant.get('total_score', 0)
|
||||
tournaments_participated = participant.get('tournaments_participated', 0)
|
||||
|
||||
tournament_results = participant.get('tournament_results', [])
|
||||
|
||||
# Count tournaments participated based on tournament_results array
|
||||
tournaments_participated = len([t for t in tournament_results if t.get('participated', False)])
|
||||
|
||||
player_stats['total_leagues'] += 1
|
||||
player_stats['league_scores'].append(final_score)
|
||||
|
||||
|
||||
player_stats['league_history'].append({
|
||||
'date': archive['archived_at'],
|
||||
'final_score': final_score,
|
||||
'total_score': total_score,
|
||||
'tournaments_participated': tournaments_participated,
|
||||
'joker_used': participant.get('joker_used', False),
|
||||
'tournament_results': participant.get('tournament_results', [])
|
||||
'tournament_results': tournament_results,
|
||||
'filename': archive.get('filename', '')
|
||||
})
|
||||
except Exception as e:
|
||||
print(f"Error analyzing league archive: {e}")
|
||||
|
||||
Reference in New Issue
Block a user