combining league jsons
This commit is contained in:
@@ -1087,7 +1087,21 @@ def results_display():
|
||||
translations=get_translations(),
|
||||
current_language=get_current_language())
|
||||
|
||||
# Priority 1.5: Check if current results are from a finished league (even if league state was archived)
|
||||
# Priority 1.5: Check if results contain league_data (from league preview/combiner)
|
||||
elif results and results.get('league_data'):
|
||||
league_data = results.get('league_data')
|
||||
calculate_league_final_scores(league_data)
|
||||
participants = get_league_final_rankings(league_data)
|
||||
|
||||
return render_template('league_scoreboard_display.html',
|
||||
league=league_data,
|
||||
participants=participants,
|
||||
results=None,
|
||||
preview_mode=True,
|
||||
translations=get_translations(),
|
||||
current_language=get_current_language())
|
||||
|
||||
# Priority 1.6: Check if current results are from a finished league (even if league state was archived)
|
||||
elif results and results.get('league_tournament_number'):
|
||||
# This is a league tournament result, but league state was archived
|
||||
# Try to find the archived league data
|
||||
@@ -1697,7 +1711,327 @@ def get_league():
|
||||
return jsonify(league_state)
|
||||
else:
|
||||
return jsonify({'status': 'error', 'message': 'No league found'}), 404
|
||||
|
||||
|
||||
@app.route('/league/combine')
|
||||
def league_combine_page():
|
||||
"""Page for combining multiple league JSON files"""
|
||||
if is_mobile_device():
|
||||
return redirect('/mobile')
|
||||
|
||||
return render_template('league_combine.html',
|
||||
translations=get_translations(),
|
||||
current_language=get_current_language())
|
||||
|
||||
@app.route('/league/preview')
|
||||
def league_preview():
|
||||
"""Display league preview from session"""
|
||||
# Get league data from session
|
||||
league_data = session.get('preview_league')
|
||||
|
||||
if not league_data:
|
||||
return redirect('/league/combine')
|
||||
|
||||
# Calculate scores and get rankings
|
||||
calculate_league_final_scores(league_data)
|
||||
participants = get_league_final_rankings(league_data)
|
||||
|
||||
return render_template('league_scoreboard_display.html',
|
||||
league=league_data,
|
||||
participants=participants,
|
||||
results=None,
|
||||
preview_mode=True,
|
||||
translations=get_translations(),
|
||||
current_language=get_current_language())
|
||||
|
||||
@app.route('/league/set-preview', methods=['POST'])
|
||||
def set_league_preview():
|
||||
"""Store league data in session for preview"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
combined_league = data.get('league')
|
||||
|
||||
if not combined_league:
|
||||
return jsonify({'status': 'error', 'message': 'No league data provided'}), 400
|
||||
|
||||
# Store in session
|
||||
session['preview_league'] = combined_league
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'redirect_url': '/league/preview'
|
||||
})
|
||||
except Exception as e:
|
||||
print(f"Error setting league preview: {e}")
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
@app.route('/api/league/combine', methods=['POST'])
|
||||
def combine_leagues():
|
||||
"""API endpoint to combine multiple league files"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
leagues = data.get('leagues', [])
|
||||
|
||||
if len(leagues) < 1:
|
||||
return jsonify({'status': 'error', 'message': 'Need at least 1 league'}), 400
|
||||
|
||||
# If only one league, just return it for preview
|
||||
if len(leagues) == 1:
|
||||
league = leagues[0]
|
||||
calculate_league_final_scores(league)
|
||||
participants = get_league_final_rankings(league)
|
||||
|
||||
highest_score = max((p['final_score'] for p in participants), default=0)
|
||||
avg_score = sum(p['final_score'] for p in participants) / len(participants) if participants else 0
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'combined_league': league,
|
||||
'participants': participants,
|
||||
'source_count': 1,
|
||||
'tournament_type': league.get('tournament_type', '20_targets'),
|
||||
'total_participants': len(participants),
|
||||
'total_tournaments': league.get('total_tournaments', 5),
|
||||
'highest_score': highest_score,
|
||||
'avg_score': round(avg_score, 2)
|
||||
})
|
||||
|
||||
# Get tournament type from first league
|
||||
tournament_type = leagues[0].get('tournament_type', '20_targets')
|
||||
|
||||
# Create combined league structure
|
||||
combined_league = {
|
||||
'league_id': f'combined_{datetime.now().strftime("%Y%m%d_%H%M%S")}',
|
||||
'created_at': datetime.now().isoformat(),
|
||||
'tournament_type': tournament_type,
|
||||
'total_tournaments': sum(len(league.get('completed_tournaments', [])) for league in leagues),
|
||||
'current_tournament': 0,
|
||||
'participants': {},
|
||||
'completed_tournaments': [],
|
||||
'league_finished': True,
|
||||
'combined_from': len(leagues)
|
||||
}
|
||||
|
||||
# Build name-to-player mapping for combining by name
|
||||
name_to_combined_id = {} # Maps player name to their ID in combined league
|
||||
next_player_id = 1
|
||||
|
||||
# Combine tournament results from all leagues
|
||||
tournament_counter = 0
|
||||
for league_idx, league in enumerate(leagues):
|
||||
# Process each participant in this league
|
||||
for player_id, league_participant in league.get('participants', {}).items():
|
||||
player_name = league_participant.get('name', f'Player {player_id}')
|
||||
|
||||
# Check if we've seen this player name before
|
||||
if player_name in name_to_combined_id:
|
||||
# Use existing combined player
|
||||
combined_id = name_to_combined_id[player_name]
|
||||
else:
|
||||
# Create new combined player
|
||||
combined_id = str(next_player_id)
|
||||
next_player_id += 1
|
||||
name_to_combined_id[player_name] = combined_id
|
||||
|
||||
# Initialize new participant
|
||||
combined_league['participants'][combined_id] = {
|
||||
'name': player_name,
|
||||
'joker_used': False,
|
||||
'tournament_results': [],
|
||||
'total_score': 0,
|
||||
'final_score': 0,
|
||||
'tournaments_participated': 0
|
||||
}
|
||||
|
||||
combined_participant = combined_league['participants'][combined_id]
|
||||
|
||||
# Add all tournament results from this league
|
||||
for result in league_participant.get('tournament_results', []):
|
||||
combined_participant['tournament_results'].append({
|
||||
'tournament': tournament_counter + result.get('tournament', 0),
|
||||
'score': result.get('score', 0),
|
||||
'tens_count': result.get('tens_count', 0),
|
||||
'participated': result.get('participated', True),
|
||||
'source_league': league_idx + 1
|
||||
})
|
||||
|
||||
if result.get('participated', True):
|
||||
combined_participant['tournaments_participated'] += 1
|
||||
combined_participant['total_score'] += result.get('score', 0)
|
||||
|
||||
# Add completed tournaments
|
||||
for completed in league.get('completed_tournaments', []):
|
||||
combined_league['completed_tournaments'].append({
|
||||
**completed,
|
||||
'source_league': league_idx + 1
|
||||
})
|
||||
|
||||
tournament_counter += len(league.get('completed_tournaments', []))
|
||||
|
||||
# Calculate final scores
|
||||
calculate_league_final_scores(combined_league)
|
||||
|
||||
# Get rankings
|
||||
participants = get_league_final_rankings(combined_league)
|
||||
|
||||
# Calculate stats
|
||||
highest_score = max((p['final_score'] for p in participants), default=0)
|
||||
avg_score = sum(p['final_score'] for p in participants) / len(participants) if participants else 0
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'combined_league': combined_league,
|
||||
'participants': participants,
|
||||
'source_count': len(leagues),
|
||||
'tournament_type': tournament_type,
|
||||
'total_participants': len(participants),
|
||||
'total_tournaments': combined_league['total_tournaments'],
|
||||
'highest_score': highest_score,
|
||||
'avg_score': round(avg_score, 2)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error combining leagues: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 400
|
||||
|
||||
@app.route('/api/league/convert', methods=['POST'])
|
||||
def convert_tournaments_to_league():
|
||||
"""API endpoint to convert 1-5 tournament files into a league"""
|
||||
try:
|
||||
data = request.get_json()
|
||||
tournaments = data.get('tournaments', [])
|
||||
|
||||
if len(tournaments) < 1 or len(tournaments) > 5:
|
||||
return jsonify({'status': 'error', 'message': 'Need 1-5 tournament files'}), 400
|
||||
|
||||
# Sort tournaments by finished_at timestamp to maintain chronological order
|
||||
tournaments.sort(key=lambda t: t.get('results', {}).get('finished_at', ''))
|
||||
|
||||
# Get tournament type from first tournament
|
||||
tournament_type = tournaments[0].get('results', {}).get('tournament_type', '20_targets')
|
||||
num_tournaments = len(tournaments)
|
||||
|
||||
# Collect all unique participants
|
||||
all_player_ids = set()
|
||||
for tournament in tournaments:
|
||||
results = tournament.get('results', {})
|
||||
all_player_ids.update(results.get('participants', {}).keys())
|
||||
|
||||
# Create league structure
|
||||
created_league = {
|
||||
'league_id': f'converted_{datetime.now().strftime("%Y%m%d_%H%M%S")}',
|
||||
'created_at': datetime.now().isoformat(),
|
||||
'tournament_type': tournament_type,
|
||||
'total_tournaments': 5, # Always 5 for a full league
|
||||
'current_tournament': num_tournaments, # How many completed so far
|
||||
'participants': {},
|
||||
'completed_tournaments': [],
|
||||
'league_finished': num_tournaments >= 5, # Only finished if all 5 uploaded
|
||||
'converted_from_tournaments': True,
|
||||
'is_partial': num_tournaments < 5
|
||||
}
|
||||
|
||||
# Initialize participants
|
||||
for player_id in all_player_ids:
|
||||
created_league['participants'][player_id] = {
|
||||
'name': '',
|
||||
'joker_used': False,
|
||||
'tournament_results': [],
|
||||
'total_score': 0,
|
||||
'final_score': 0,
|
||||
'tournaments_participated': 0
|
||||
}
|
||||
|
||||
# Process each tournament
|
||||
for tournament_idx, tournament in enumerate(tournaments):
|
||||
results = tournament.get('results', {})
|
||||
tournament_results_data = results.get('participants', {})
|
||||
|
||||
# Add completed tournament metadata
|
||||
created_league['completed_tournaments'].append({
|
||||
'tournament_number': tournament_idx + 1,
|
||||
'tournament_type': results.get('tournament_type', tournament_type),
|
||||
'finished_at': results.get('finished_at', datetime.now().isoformat()),
|
||||
'results_summary': {
|
||||
'participants': len(tournament_results_data),
|
||||
'tournament_id': tournament.get('tournament', {}).get('tournament_id', f'tournament_{tournament_idx + 1}')
|
||||
}
|
||||
})
|
||||
|
||||
# Add results for each participant
|
||||
for player_id in all_player_ids:
|
||||
league_participant = created_league['participants'][player_id]
|
||||
|
||||
if player_id in tournament_results_data:
|
||||
participant_data = tournament_results_data[player_id]
|
||||
|
||||
# Set name if not set
|
||||
if not league_participant['name']:
|
||||
league_participant['name'] = participant_data.get('name', f'Player {player_id}')
|
||||
|
||||
# Count tens
|
||||
tens_count = 0
|
||||
targets = participant_data.get('targets', {})
|
||||
for target in targets.values():
|
||||
for shot_key, shot_value in target.items():
|
||||
if shot_key.startswith('shot') and shot_value == 10:
|
||||
tens_count += 1
|
||||
|
||||
# Add tournament result
|
||||
score = participant_data.get('total_score', 0)
|
||||
league_participant['tournament_results'].append({
|
||||
'tournament': tournament_idx + 1,
|
||||
'score': score,
|
||||
'tens_count': tens_count,
|
||||
'participated': True
|
||||
})
|
||||
|
||||
league_participant['tournaments_participated'] += 1
|
||||
league_participant['total_score'] += score
|
||||
else:
|
||||
# Player didn't participate (used joker)
|
||||
league_participant['tournament_results'].append({
|
||||
'tournament': tournament_idx + 1,
|
||||
'score': 0,
|
||||
'tens_count': 0,
|
||||
'participated': False,
|
||||
'joker': True
|
||||
})
|
||||
|
||||
if tournament_idx == 0:
|
||||
# Set joker_used for players who didn't participate in first tournament
|
||||
league_participant['joker_used'] = True
|
||||
|
||||
# Calculate final scores using league rules
|
||||
calculate_league_final_scores(created_league)
|
||||
|
||||
# Get rankings
|
||||
participants = get_league_final_rankings(created_league)
|
||||
|
||||
# Calculate stats
|
||||
highest_score = max((p['final_score'] for p in participants), default=0)
|
||||
avg_score = sum(p['final_score'] for p in participants) / len(participants) if participants else 0
|
||||
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'combined_league': created_league,
|
||||
'participants': participants,
|
||||
'source_count': num_tournaments,
|
||||
'tournament_type': tournament_type,
|
||||
'total_participants': len(participants),
|
||||
'total_tournaments': num_tournaments,
|
||||
'is_partial': num_tournaments < 5,
|
||||
'highest_score': highest_score,
|
||||
'avg_score': round(avg_score, 2)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error converting tournaments to league: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 400
|
||||
|
||||
# Add this route to your Flask app (around line 850, with the other mobile routes)
|
||||
|
||||
@app.route('/mobile/remote')
|
||||
|
||||
Reference in New Issue
Block a user