From 75ac46c23cbc7652ca7ab4e2f57fc10a8a9d865f Mon Sep 17 00:00:00 2001 From: Bl3kiiie <96978644+Bl3kiiie@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:53:24 +0200 Subject: [PATCH] Add files via upload --- TV_APP_V2/app.py | 2058 +++++++++++++++++ TV_APP_V2/camera_settings.json | 14 + TV_APP_V2/players.json | 224 ++ TV_APP_V2/static/logo.png | Bin 0 -> 139448 bytes TV_APP_V2/static/setting.png | Bin 0 -> 12862 bytes TV_APP_V2/templates/draft.html | 547 +++++ TV_APP_V2/templates/fullscreen.html | 766 ++++++ TV_APP_V2/templates/index.html | 875 +++++++ .../templates/league_results_display.html | 1112 +++++++++ .../templates/league_scoreboard_display.html | 1156 +++++++++ TV_APP_V2/templates/mobile_draft.html | 769 ++++++ .../templates/mobile_league_results.html | 934 ++++++++ TV_APP_V2/templates/mobile_menu.html | 382 +++ TV_APP_V2/templates/mobile_results.html | 696 ++++++ TV_APP_V2/templates/mobile_streams.html | 670 ++++++ TV_APP_V2/templates/modern_archive_index.html | 701 ++++++ .../templates/modern_player_analysis.html | 776 +++++++ TV_APP_V2/templates/modern_player_stats.html | 627 +++++ TV_APP_V2/templates/results_calculator.html | 1074 +++++++++ TV_APP_V2/templates/results_display.html | 872 +++++++ TV_APP_V2/templates/tournament.html | 1565 +++++++++++++ TV_APP_V2/tournament_results.json | 357 +++ 22 files changed, 16175 insertions(+) create mode 100644 TV_APP_V2/app.py create mode 100644 TV_APP_V2/camera_settings.json create mode 100644 TV_APP_V2/players.json create mode 100644 TV_APP_V2/static/logo.png create mode 100644 TV_APP_V2/static/setting.png create mode 100644 TV_APP_V2/templates/draft.html create mode 100644 TV_APP_V2/templates/fullscreen.html create mode 100644 TV_APP_V2/templates/index.html create mode 100644 TV_APP_V2/templates/league_results_display.html create mode 100644 TV_APP_V2/templates/league_scoreboard_display.html create mode 100644 TV_APP_V2/templates/mobile_draft.html create mode 100644 TV_APP_V2/templates/mobile_league_results.html create mode 100644 TV_APP_V2/templates/mobile_menu.html create mode 100644 TV_APP_V2/templates/mobile_results.html create mode 100644 TV_APP_V2/templates/mobile_streams.html create mode 100644 TV_APP_V2/templates/modern_archive_index.html create mode 100644 TV_APP_V2/templates/modern_player_analysis.html create mode 100644 TV_APP_V2/templates/modern_player_stats.html create mode 100644 TV_APP_V2/templates/results_calculator.html create mode 100644 TV_APP_V2/templates/results_display.html create mode 100644 TV_APP_V2/templates/tournament.html create mode 100644 TV_APP_V2/tournament_results.json diff --git a/TV_APP_V2/app.py b/TV_APP_V2/app.py new file mode 100644 index 0000000..11f67ac --- /dev/null +++ b/TV_APP_V2/app.py @@ -0,0 +1,2058 @@ +from flask import Flask, render_template, request, redirect, jsonify +import json +import os +import random +import glob +from collections import defaultdict +from datetime import datetime +import re + +app = Flask(__name__) + +def is_mobile_device(): + """Check if the request is coming from a mobile device""" + user_agent = request.headers.get('User-Agent', '').lower() + mobile_patterns = [ + r'android', r'iphone', r'ipad', r'ipod', r'blackberry', + r'iemobile', r'opera mini', r'mobile', r'tablet' + ] + return any(re.search(pattern, user_agent) for pattern in mobile_patterns) + +# Define streams globally so both routes can access them +STREAMS = [ + {'name': 'Target1', 'url': 'http://192.168.0.134:9081'}, + {'name': 'Target2', 'url': 'http://192.168.0.134:9082'}, + {'name': 'Target3', 'url': 'http://192.168.0.134:9083'}, + {'name': 'Target4', 'url': 'http://192.168.0.134:9084'}, + {'name': 'Target5', 'url': 'http://192.168.0.134:9085'}, + {'name': 'Target6', 'url': 'http://192.168.0.134:9086'}, +] + +# Settings file paths +SETTINGS_FILE = 'camera_settings.json' +PLAYERS_FILE = 'players.json' +TOURNAMENT_FILE = 'tournament_state.json' +RESULTS_FILE = 'tournament_results.json' +LEAGUE_FILE = 'league_state.json' +ARCHIVE_DIR = 'tournament_archives' +LEAGUE_ARCHIVE_DIR = 'league_archives' + +# Default settings +DEFAULT_SETTINGS = { + 'camera_titles': { + '1': 'Camera 1', + '2': 'Camera 2', + '3': 'Camera 3', + '4': 'Camera 4', + '5': 'Camera 5', + '6': 'Camera 6' + }, + 'display_options': { + 'show_titles': True, + 'title_size': 1.1 + } +} + +# Default players structure +DEFAULT_PLAYERS = { + 'players': [ + {'id': 1, 'name': 'Player 1', 'enabled': True}, + {'id': 2, 'name': 'Player 2', 'enabled': True}, + {'id': 3, 'name': 'Player 3', 'enabled': True}, + {'id': 4, 'name': 'Player 4', 'enabled': True}, + {'id': 5, 'name': 'Player 5', 'enabled': True}, + {'id': 6, 'name': 'Player 6', 'enabled': True}, + ] +} + +def load_settings(): + """Load settings from JSON file, create with defaults if not exists""" + try: + if os.path.exists(SETTINGS_FILE): + with open(SETTINGS_FILE, 'r') as f: + settings = json.load(f) + # Ensure all required keys exist (for backwards compatibility) + for key in DEFAULT_SETTINGS: + if key not in settings: + settings[key] = DEFAULT_SETTINGS[key] + for camera_id in DEFAULT_SETTINGS['camera_titles']: + if camera_id not in settings['camera_titles']: + settings['camera_titles'][camera_id] = DEFAULT_SETTINGS['camera_titles'][camera_id] + return settings + else: + return DEFAULT_SETTINGS.copy() + except (json.JSONDecodeError, IOError): + return DEFAULT_SETTINGS.copy() + +def save_settings(settings): + """Save settings to JSON file""" + try: + with open(SETTINGS_FILE, 'w') as f: + json.dump(settings, f, indent=2) + return True + except IOError: + return False + +def load_players(): + """Load players from JSON file, create with defaults if not exists""" + try: + if os.path.exists(PLAYERS_FILE): + with open(PLAYERS_FILE, 'r') as f: + return json.load(f) + else: + save_players(DEFAULT_PLAYERS) + return DEFAULT_PLAYERS.copy() + except (json.JSONDecodeError, IOError): + return DEFAULT_PLAYERS.copy() + +def save_players(players_data): + """Save players to JSON file""" + try: + with open(PLAYERS_FILE, 'w') as f: + json.dump(players_data, f, indent=2) + return True + except IOError: + return False + +def load_tournament_state(): + """Load tournament state from JSON file""" + try: + if os.path.exists(TOURNAMENT_FILE): + with open(TOURNAMENT_FILE, 'r') as f: + return json.load(f) + else: + return None + except (json.JSONDecodeError, IOError): + return None + +def save_tournament_state(tournament_data): + """Save tournament state to JSON file""" + try: + with open(TOURNAMENT_FILE, 'w') as f: + json.dump(tournament_data, f, indent=2) + return True + except IOError: + return False + +def load_league_state(): + """Load league state from JSON file""" + try: + if os.path.exists(LEAGUE_FILE): + with open(LEAGUE_FILE, 'r') as f: + return json.load(f) + else: + return None + except (json.JSONDecodeError, IOError): + return None + +def save_league_state(league_data): + """Save league state to JSON file""" + try: + with open(LEAGUE_FILE, 'w') as f: + json.dump(league_data, f, indent=2) + return True + except IOError: + return False + +def load_results(): + """Load results from JSON file""" + try: + if os.path.exists(RESULTS_FILE): + with open(RESULTS_FILE, 'r') as f: + return json.load(f) + else: + return None + except (json.JSONDecodeError, IOError): + return None + +def save_results(results_data): + """Save results to JSON file""" + try: + with open(RESULTS_FILE, 'w') as f: + json.dump(results_data, f, indent=2) + return True + except IOError: + return False + +def archive_tournament(tournament_data, results_data): + """Archive completed tournament data""" + try: + # Create archive directory if it doesn't exist + if not os.path.exists(ARCHIVE_DIR): + os.makedirs(ARCHIVE_DIR) + + # Create filename with timestamp + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + archive_filename = f"tournament_{timestamp}.json" + archive_path = os.path.join(ARCHIVE_DIR, archive_filename) + + # Combine tournament and results data + archive_data = { + 'tournament': tournament_data, + 'results': results_data, + 'archived_at': datetime.now().isoformat() + } + + # Save to archive + with open(archive_path, 'w') as f: + json.dump(archive_data, f, indent=2) + + print(f"Tournament archived to: {archive_path}") + return True + except Exception as e: + print(f"Error archiving tournament: {e}") + return False + +def archive_league(league_data): + """Archive completed league data""" + try: + if not os.path.exists(LEAGUE_ARCHIVE_DIR): + os.makedirs(LEAGUE_ARCHIVE_DIR) + + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + archive_filename = f"league_{timestamp}.json" + archive_path = os.path.join(LEAGUE_ARCHIVE_DIR, archive_filename) + + archive_data = { + 'league': league_data, + 'archived_at': datetime.now().isoformat() + } + + with open(archive_path, 'w') as f: + json.dump(archive_data, f, indent=2) + + print(f"League archived to: {archive_path}") + return True + except Exception as e: + print(f"Error archiving league: {e}") + return False + +def create_league(enabled_players, tournament_type): + """Create a new league with 6 tournaments""" + league_id = f"league_{datetime.now().strftime('%Y%m%d_%H%M%S')}" + + league_data = { + 'league_id': league_id, + 'created_at': datetime.now().isoformat(), + 'tournament_type': tournament_type, + 'total_tournaments': 6, + 'current_tournament': 0, # Will be 1 when first tournament starts + 'participants': {}, + 'completed_tournaments': [], + 'league_finished': False + } + + # Initialize participants + for player in enabled_players: + league_data['participants'][str(player['id'])] = { + 'name': player['name'], + 'joker_used': False, + 'tournament_results': [], + 'total_score': 0, + 'final_score': 0, # Best 5 tournaments + 'tournaments_participated': 0 + } + + return league_data + +def create_draft(enabled_players, tournament_type='20_targets', league_tournament_number=None): + """Create draft groups of 6 players and organize rounds""" + if len(enabled_players) < 1: + return None + + # Shuffle players for random grouping + players_copy = enabled_players.copy() + random.shuffle(players_copy) + + # Create groups of up to 6 + groups = [] + for i in range(0, len(players_copy), 6): + group = players_copy[i:i+6] + groups.append(group) + + # Create rounds + rounds = [] + for i, group in enumerate(groups): + rounds.append({ + 'round_number': i + 1, + 'players': group, + 'status': 'pending' if i == 0 else 'waiting' + }) + + tournament_data = { + 'rounds': rounds, + 'created_at': datetime.now().isoformat(), + 'total_players': len(enabled_players), + 'total_rounds': len(rounds), + 'current_round': 1, + 'tournament_type': tournament_type + } + + if league_tournament_number: + tournament_data['league_tournament_number'] = league_tournament_number + + return tournament_data + +def create_results_structure(tournament_data): + """Create results structure for a tournament""" + if not tournament_data: + return None + + tournament_type = tournament_data.get('tournament_type', '20_targets') + num_targets = 40 if tournament_type == '40_targets' else 20 + + results = { + 'tournament_id': tournament_data.get('created_at', datetime.now().isoformat()), + 'tournament_type': tournament_type, + 'participants': {}, + 'tournament_finished': False, + 'created_at': datetime.now().isoformat() + } + + # Add league info if present + if 'league_tournament_number' in tournament_data: + results['league_tournament_number'] = tournament_data['league_tournament_number'] + + # Create structure for each participant + all_players = [] + for round_data in tournament_data['rounds']: + all_players.extend(round_data['players']) + + for player in all_players: + player_id = str(player['id']) + results['participants'][player_id] = { + 'name': player['name'], + 'targets': {str(i): {'shot1': None, 'shot2': None} for i in range(1, num_targets + 1)}, + 'total_score': 0, + 'completed': False + } + + return results + +def calculate_total_score(targets): + """Calculate total score from targets, treating None as 0""" + total = 0 + for target in targets.values(): + shot1 = target.get('shot1') + shot2 = target.get('shot2') + total += (shot1 if shot1 is not None else 0) + total += (shot2 if shot2 is not None else 0) + return total + +def is_participant_completed(targets): + """Check if a participant has completed all targets (all shots entered, including 0s)""" + for target in targets.values(): + shot1 = target.get('shot1') + shot2 = target.get('shot2') + if shot1 is None or shot2 is None: + return False + return True + +def calculate_league_final_scores(league_data): + """Calculate final league scores using best 5 tournaments (joker system)""" + for participant_id, participant in league_data['participants'].items(): + tournament_scores = [] + + # Get all tournament scores where player participated + for result in participant['tournament_results']: + if result['participated']: + tournament_scores.append(result['score']) + + # Sort scores descending and take best 5 (or all if less than 6) + tournament_scores.sort(reverse=True) + best_scores = tournament_scores[:5] if len(tournament_scores) > 5 else tournament_scores + + participant['final_score'] = sum(best_scores) + participant['tournaments_participated'] = len(tournament_scores) + +def get_league_final_rankings(league_data): + """Get final league rankings sorted by final score""" + participants = [] + for player_id, data in league_data['participants'].items(): + participants.append({ + 'id': player_id, + 'name': data['name'], + 'final_score': data['final_score'], + 'total_score': data['total_score'], + 'tournaments_participated': data['tournaments_participated'], + 'joker_used': data['joker_used'], + 'tournament_results': data['tournament_results'] + }) + + # Sort by final score (best 5 tournaments) descending + participants.sort(key=lambda x: x['final_score'], reverse=True) + + # Add rankings + for i, participant in enumerate(participants): + participant['rank'] = i + 1 + + return participants + +def get_current_round_data(): + """Get current round data from tournament""" + tournament_state = load_tournament_state() + if not tournament_state: + return None + + current_round_num = tournament_state.get('current_round', 1) + + # Find the current round + for round_data in tournament_state['rounds']: + if round_data['round_number'] == current_round_num: + return round_data + + return None + +def calculate_current_league_standings(league_data): + """Calculate current league standings during active league""" + participants = [] + for player_id, data in league_data['participants'].items(): + # Calculate current standings based on completed tournaments + tournament_scores = [] + completed_tournaments = 0 + + for result in data['tournament_results']: + if result['participated']: + tournament_scores.append(result['score']) + completed_tournaments += 1 + + # Current score is sum of all completed tournaments + current_total = sum(tournament_scores) + + # For display, show what the final score would be if we took best 5 now + tournament_scores.sort(reverse=True) + projected_final = sum(tournament_scores[:5]) if len(tournament_scores) >= 5 else sum(tournament_scores) + + participants.append({ + 'id': player_id, + 'name': data['name'], + 'current_total': current_total, + 'projected_final': projected_final, + 'tournaments_completed': completed_tournaments, + 'joker_used': data['joker_used'], + 'tournament_results': data['tournament_results'] + }) + + # Sort by current total score (descending) + participants.sort(key=lambda x: x['current_total'], reverse=True) + + # Add rankings + for i, participant in enumerate(participants): + participant['rank'] = i + 1 + + return participants + +def get_league_current_standings(league_state): + """Get current league standings including in-progress tournament""" + if not league_state: + return [] + + # Start with current league participants + participants = [] + for player_id, data in league_state['participants'].items(): + participant = { + 'id': player_id, + 'name': data['name'], + 'total_score': data['total_score'], + 'final_score': data['final_score'], + 'tournaments_participated': data['tournaments_participated'], + 'joker_used': data['joker_used'], + 'tournament_results': data['tournament_results'], + 'current_tournament_score': 0, # Score from current tournament + 'current_tournament_participating': False + } + participants.append(participant) + + # Add current tournament scores if available + current_results = load_results() + if current_results and not current_results.get('tournament_finished', False): + for player_id, result_data in current_results['participants'].items(): + # Find this participant in our list + for participant in participants: + if participant['id'] == player_id: + participant['current_tournament_score'] = result_data['total_score'] + participant['current_tournament_participating'] = True + break + + # Sort by final score (best 5 tournaments) descending + participants.sort(key=lambda x: x['final_score'], reverse=True) + + # Add rankings + for i, participant in enumerate(participants): + participant['rank'] = i + 1 + + return participants + +# Add these functions after the existing helper functions in app.py + +def get_archived_tournaments(): + """Get list of standalone archived tournaments (excluding league tournaments)""" + try: + if not os.path.exists(ARCHIVE_DIR): + return [] + + archives = [] + for file_path in glob.glob(os.path.join(ARCHIVE_DIR, "tournament_*.json")): + try: + with open(file_path, 'r') as f: + data = json.load(f) + + # Extract metadata + filename = os.path.basename(file_path) + archived_at = data.get('archived_at', 'Unknown') + tournament_data = data.get('tournament', {}) + results_data = data.get('results', {}) + + # Skip tournaments that are part of a league + if tournament_data.get('league_tournament_number') or results_data.get('league_tournament_number'): + continue + + archive_info = { + 'filename': filename, + 'filepath': file_path, + 'archived_at': archived_at, + 'created_at': tournament_data.get('created_at', 'Unknown'), + 'tournament_type': tournament_data.get('tournament_type', '20_targets'), + 'total_players': tournament_data.get('total_players', 0), + 'total_rounds': tournament_data.get('total_rounds', 0), + 'tournament_finished': results_data.get('tournament_finished', False), + 'participants_count': len(results_data.get('participants', {})) + } + + archives.append(archive_info) + except (json.JSONDecodeError, IOError) as e: + print(f"Error reading archive {file_path}: {e}") + continue + + # Sort by archived date (newest first) + archives.sort(key=lambda x: x['archived_at'], reverse=True) + return archives + except Exception as e: + print(f"Error getting archived tournaments: {e}") + return [] + +def get_archived_leagues(): + """Get list of all archived leagues""" + try: + if not os.path.exists(LEAGUE_ARCHIVE_DIR): + return [] + + archives = [] + for file_path in glob.glob(os.path.join(LEAGUE_ARCHIVE_DIR, "league_*.json")): + try: + with open(file_path, 'r') as f: + data = json.load(f) + + filename = os.path.basename(file_path) + archived_at = data.get('archived_at', 'Unknown') + league_data = data.get('league', {}) + + archive_info = { + 'filename': filename, + 'filepath': file_path, + 'archived_at': archived_at, + 'created_at': league_data.get('created_at', 'Unknown'), + 'league_id': league_data.get('league_id', 'Unknown'), + 'tournament_type': league_data.get('tournament_type', '20_targets'), + 'total_tournaments': league_data.get('total_tournaments', 6), + 'participants_count': len(league_data.get('participants', {})), + 'league_finished': league_data.get('league_finished', False), + 'completed_tournaments': len(league_data.get('completed_tournaments', [])) + } + + archives.append(archive_info) + except (json.JSONDecodeError, IOError) as e: + print(f"Error reading league archive {file_path}: {e}") + continue + + # Sort by archived date (newest first) + archives.sort(key=lambda x: x['archived_at'], reverse=True) + return archives + except Exception as e: + print(f"Error getting archived leagues: {e}") + return [] + +def load_archive_file(filepath): + """Load a specific archive file""" + try: + with open(filepath, 'r') as f: + return json.load(f) + except (json.JSONDecodeError, IOError) as e: + print(f"Error loading archive file {filepath}: {e}") + return None + +def analyze_player_performance(player_id, archives_data): + """Analyze performance of a specific player across all archives""" + player_stats = { + 'total_tournaments': 0, + 'total_leagues': 0, + 'tournament_scores': [], + 'league_scores': [], + 'best_tournament_score': 0, + 'worst_tournament_score': float('inf'), + 'average_tournament_score': 0, + 'total_shots_fired': 0, + 'performance_trend': [], + 'tournament_history': [], + 'league_history': [] + } + + # 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 + targets = participant.get('targets', {}) + shots_in_tournament = 0 + for target in targets.values(): + if target.get('shot1') is not None: + shots_in_tournament += 1 + if target.get('shot2') is not None: + shots_in_tournament += 1 + + player_stats['total_shots_fired'] += shots_in_tournament + + # 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 + }) + except Exception as e: + print(f"Error analyzing tournament archive: {e}") + continue + + # Process league archives + for archive in archives_data.get('leagues', []): + try: + data = load_archive_file(archive['filepath']) + if not data: + continue + + league = data.get('league', {}) + participants = league.get('participants', {}) + + if str(player_id) in participants: + 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) + + 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', []) + }) + except Exception as e: + print(f"Error analyzing league archive: {e}") + continue + + # Calculate averages and trends + if player_stats['tournament_scores']: + player_stats['average_tournament_score'] = sum(player_stats['tournament_scores']) / len(player_stats['tournament_scores']) + + # Performance trend (simple moving average) + if len(player_stats['tournament_scores']) >= 3: + for i in range(2, len(player_stats['tournament_scores'])): + avg = sum(player_stats['tournament_scores'][i-2:i+1]) / 3 + player_stats['performance_trend'].append(avg) + + if player_stats['worst_tournament_score'] == float('inf'): + player_stats['worst_tournament_score'] = 0 + + # Sort histories by date (newest first) + player_stats['tournament_history'].sort(key=lambda x: x['date'], reverse=True) + player_stats['league_history'].sort(key=lambda x: x['date'], reverse=True) + + return player_stats + +def get_all_players_from_archives(): + """Get all players that appear in any archive""" + all_players = {} + + # Get current players first + current_players = load_players() + for player in current_players['players']: + all_players[str(player['id'])] = { + 'id': player['id'], + 'name': player['name'], + 'current_player': True + } + + # Add players from tournament archives + tournaments = get_archived_tournaments() + for archive in tournaments: + try: + data = load_archive_file(archive['filepath']) + if data and 'results' in data: + participants = data['results'].get('participants', {}) + for player_id, participant in participants.items(): + if player_id not in all_players: + all_players[player_id] = { + 'id': int(player_id), + 'name': participant.get('name', f'Player {player_id}'), + 'current_player': False + } + except Exception as e: + print(f"Error processing tournament archive: {e}") + continue + + # Add players from league archives + leagues = get_archived_leagues() + for archive in leagues: + try: + data = load_archive_file(archive['filepath']) + if data and 'league' in data: + participants = data['league'].get('participants', {}) + for player_id, participant in participants.items(): + if player_id not in all_players: + all_players[player_id] = { + 'id': int(player_id), + 'name': participant.get('name', f'Player {player_id}'), + 'current_player': False + } + except Exception as e: + print(f"Error processing league archive: {e}") + continue + + # Convert to list and sort by name + players_list = list(all_players.values()) + players_list.sort(key=lambda x: x['name']) + + return players_list + +# Add these routes after the existing routes in app.py + +# Add this to your app.py file to integrate the modern archive system + +# Replace your existing archive routes with these updated ones: + +@app.route('/archive') +def archive_index(): + """Archive index page with updated styling""" + if is_mobile_device(): + return redirect('/mobile/archive') + + tournaments = get_archived_tournaments() # Now only returns standalone tournaments + leagues = get_archived_leagues() + + # Calculate overview stats + total_tournaments = len(tournaments) + total_leagues = len(leagues) + + # Get total players from current players list + players_data = load_players() + total_players = len([p for p in players_data['players'] if p['enabled']]) + + # Calculate total competitions (standalone tournaments + completed leagues) + total_matches = total_tournaments + total_leagues + + stats = { + 'total_tournaments': total_tournaments, + 'total_leagues': total_leagues, + 'total_players': total_players, + 'total_matches': total_matches + } + + # Use the new template + return render_template('modern_archive_index.html', + tournaments=tournaments, + leagues=leagues, + stats=stats) + +@app.route('/archive/player-analysis') +def player_analysis(): + """Modern Player analysis page""" + if is_mobile_device(): + return redirect('/mobile/archive/player-analysis') + + all_players = get_all_players_from_archives() + + # Calculate overview stats + total_players = len(all_players) + active_players = len([p for p in all_players if p['current_player']]) + + # Get average tournaments and top score from archives + avg_tournaments = 0 + top_score = 0 + + if all_players: + total_tournament_count = 0 + max_score = 0 + + for player in all_players: + # Get basic stats for each player + archives_data = { + 'tournaments': get_archived_tournaments(), + 'leagues': get_archived_leagues() + } + player_stats = analyze_player_performance(player['id'], archives_data) + total_tournament_count += player_stats['total_tournaments'] + if player_stats['best_tournament_score'] > max_score: + max_score = player_stats['best_tournament_score'] + + avg_tournaments = total_tournament_count // total_players if total_players else 0 + top_score = max_score + + overview_stats = { + 'total_players': total_players, + 'active_players': active_players, + 'avg_tournaments': avg_tournaments, + 'top_score': top_score + } + + return render_template('modern_player_analysis.html', + players=all_players, + overview_stats=overview_stats) + +@app.route('/archive/player/') +def view_player_stats(player_id): + """Modern Player stats page""" + if is_mobile_device(): + return redirect(f'/mobile/archive/player/{player_id}') + + all_players = get_all_players_from_archives() + player_info = next((p for p in all_players if p['id'] == player_id), None) + + if not player_info: + return redirect('/archive/player-analysis') + + # Get archives data + archives_data = { + 'tournaments': get_archived_tournaments(), + 'leagues': get_archived_leagues() + } + + # Analyze player performance + player_stats = analyze_player_performance(player_id, archives_data) + + return render_template('modern_player_stats.html', + player=player_info, + stats=player_stats) + +# Enhanced API endpoints for the modern archive system + +@app.route('/api/archive/stats', methods=['GET']) +def api_get_archive_stats(): + """API endpoint to get archive overview statistics""" + try: + tournaments = get_archived_tournaments() + leagues = get_archived_leagues() + players_data = load_players() + + # Calculate activity over time (last 6 months) + activity_data = { + 'labels': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], + 'tournaments': [2, 4, 3, 5, 6, 4], # This should be calculated from actual data + 'leagues': [1, 1, 2, 1, 2, 1] + } + + # Calculate tournament type distribution + type_distribution = {'20_targets': 0, '40_targets': 0} + for tournament in tournaments: + tournament_type = tournament.get('tournament_type', '20_targets') + type_distribution[tournament_type] += 1 + + for league in leagues: + league_type = league.get('tournament_type', '20_targets') + type_distribution[league_type] += 1 + + stats = { + 'overview': { + 'total_tournaments': len(tournaments), + 'total_leagues': len(leagues), + 'total_players': len([p for p in players_data['players'] if p['enabled']]), + 'total_matches': len(tournaments) + sum(l.get('completed_tournaments', 0) for l in leagues) + }, + 'activity_data': activity_data, + 'type_distribution': { + 'labels': ['20 Targets', '40 Targets'], + 'data': [type_distribution['20_targets'], type_distribution['40_targets']] + } + } + + return jsonify({'status': 'success', 'stats': stats}) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 500 + +@app.route('/api/archive/player//performance', methods=['GET']) +def api_get_player_performance(player_id): + """API endpoint to get player performance data for charts""" + try: + archives_data = { + 'tournaments': get_archived_tournaments(), + 'leagues': get_archived_leagues() + } + + player_stats = analyze_player_performance(player_id, archives_data) + + # Prepare chart data + performance_data = { + 'trend': { + 'labels': [f'T{i+1}' for i in range(len(player_stats['tournament_scores']))], + 'data': player_stats['tournament_scores'] + }, + 'distribution': { + 'labels': ['0-50', '51-60', '61-70', '71-80', '81-90', '91-100'], + 'data': [0, 0, 0, 0, 0, 0] + } + } + + # Calculate score distribution + for score in player_stats['tournament_scores']: + if score <= 50: + performance_data['distribution']['data'][0] += 1 + elif score <= 60: + performance_data['distribution']['data'][1] += 1 + elif score <= 70: + performance_data['distribution']['data'][2] += 1 + elif score <= 80: + performance_data['distribution']['data'][3] += 1 + elif score <= 90: + performance_data['distribution']['data'][4] += 1 + else: + performance_data['distribution']['data'][5] += 1 + + return jsonify({'status': 'success', 'performance': performance_data}) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 500 + +@app.route('/api/archive/players/with-stats', methods=['GET']) +def api_get_players_with_stats(): + """API endpoint to get all players with their basic stats""" + try: + all_players = get_all_players_from_archives() + archives_data = { + 'tournaments': get_archived_tournaments(), + 'leagues': get_archived_leagues() + } + + players_with_stats = [] + for player in all_players: + player_stats = analyze_player_performance(player['id'], archives_data) + + players_with_stats.append({ + 'id': player['id'], + 'name': player['name'], + 'current_player': player['current_player'], + 'stats': { + 'total_tournaments': player_stats['total_tournaments'], + 'total_leagues': player_stats['total_leagues'], + 'best_tournament_score': player_stats['best_tournament_score'], + 'average_tournament_score': player_stats['average_tournament_score'], + 'total_shots_fired': player_stats['total_shots_fired'], + 'performance_trend': player_stats['tournament_scores'][-8:] if len(player_stats['tournament_scores']) >= 8 else player_stats['tournament_scores'] # Last 8 tournaments for mini chart + } + }) + + return jsonify({'status': 'success', 'players': players_with_stats}) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 500 + +# Add these routes to handle clicking on archived tournaments/leagues +# These will load the archive data and show it in your existing result page format + +@app.route('/archive/tournament/') +def view_archived_tournament(filename): + """View archived tournament in results format""" + if is_mobile_device(): + return redirect(f'/mobile/archive/tournament/{filename}') + + filepath = os.path.join(ARCHIVE_DIR, filename) + data = load_archive_file(filepath) + + if not data: + return redirect('/archive') + + tournament_data = data.get('tournament', {}) + results_data = data.get('results', {}) + + # Process results for display + participants = [] + for player_id, participant_data in results_data.get('participants', {}).items(): + participants.append({ + 'id': player_id, + 'name': participant_data['name'], + 'total_score': participant_data['total_score'], + 'completed': participant_data['completed'], + 'targets': participant_data.get('targets', {}) + }) + + # Sort by score (descending) + participants.sort(key=lambda x: x['total_score'], reverse=True) + + # Add rankings + for i, participant in enumerate(participants): + participant['rank'] = i + 1 + + # Use the existing results display template but with archived data + return render_template('results_display.html', + results=results_data, + participants=participants, + archived=True, + archive_info={ + 'filename': filename, + 'archived_at': data.get('archived_at'), + 'tournament_type': tournament_data.get('tournament_type', '20_targets') + }) + +@app.route('/archive/league/') +def view_archived_league(filename): + """View archived league in results format""" + if is_mobile_device(): + return redirect(f'/mobile/archive/league/{filename}') + + filepath = os.path.join(LEAGUE_ARCHIVE_DIR, filename) + data = load_archive_file(filepath) + + if not data: + return redirect('/archive') + + league_data = data.get('league', {}) + + # Process league results using your existing function + calculate_league_final_scores(league_data) + participants = get_league_final_rankings(league_data) + + # Use the existing league results display template but with archived data + return render_template('league_scoreboard_display.html', + league=league_data, + participants=participants, + archived=True, + archive_info={ + 'filename': filename, + 'archived_at': data.get('archived_at'), + 'tournament_type': league_data.get('tournament_type', '20_targets') + }) + +# Mobile versions +@app.route('/mobile/archive/tournament/') +def mobile_view_archived_tournament(filename): + """Mobile view of archived tournament""" + filepath = os.path.join(ARCHIVE_DIR, filename) + data = load_archive_file(filepath) + + if not data: + return redirect('/mobile/archive') + + tournament_data = data.get('tournament', {}) + results_data = data.get('results', {}) + + # Process results for display + participants = [] + for player_id, participant_data in results_data.get('participants', {}).items(): + participants.append({ + 'id': player_id, + 'name': participant_data['name'], + 'total_score': participant_data['total_score'], + 'completed': participant_data['completed'] + }) + + # Sort by score (descending) + participants.sort(key=lambda x: x['total_score'], reverse=True) + + # Add rankings + for i, participant in enumerate(participants): + participant['rank'] = i + 1 + + return render_template('mobile_results.html', + results=results_data, + participants=participants, + show_league_results=False, + show_tournament_results=True, + tournament_active=False, + league=None, + tournament_type=results_data.get('tournament_type', '20_targets'), + archived=True, + archive_info={ + 'filename': filename, + 'archived_at': data.get('archived_at') + }) + +@app.route('/mobile/archive/league/') +def mobile_view_archived_league(filename): + """Mobile view of archived league""" + filepath = os.path.join(LEAGUE_ARCHIVE_DIR, filename) + data = load_archive_file(filepath) + + if not data: + return redirect('/mobile/archive') + + league_data = data.get('league', {}) + + # Process league results + calculate_league_final_scores(league_data) + participants = get_league_final_rankings(league_data) + + return render_template('mobile_results.html', + league=league_data, + participants=participants, + show_league_results=True, + show_tournament_results=False, + tournament_active=False, + results=None, + archived=True, + archive_info={ + 'filename': filename, + 'archived_at': data.get('archived_at') + }) +# MAIN ROUTES +@app.route('/') +def index(): + # Redirect mobile users to mobile menu + if is_mobile_device(): + return redirect('/mobile') + + # Desktop users get the regular dashboard + settings = load_settings() + + # Check if tournament is active and get current round players + current_round_data = get_current_round_data() + + # If tournament is active, override camera titles with player names + if current_round_data: + tournament_titles = {} + players = current_round_data['players'] + + for i in range(6): # Always 6 positions + if i < len(players): + tournament_titles[str(i + 1)] = players[i]['name'] + else: + tournament_titles[str(i + 1)] = 'Empty' + + # Create a copy of settings with tournament titles + display_settings = settings.copy() + display_settings['camera_titles'] = tournament_titles + display_settings['tournament_active'] = True + + tournament_state = load_tournament_state() + display_settings['current_round'] = tournament_state.get('current_round', 1) + display_settings['total_rounds'] = tournament_state.get('total_rounds', 1) + + # Add league info if available + league_state = load_league_state() + if league_state: + display_settings['league_active'] = True + display_settings['league_tournament'] = league_state.get('current_tournament', 1) + display_settings['league_total'] = league_state.get('total_tournaments', 6) + else: + display_settings = settings.copy() + display_settings['tournament_active'] = False + display_settings['current_round'] = 1 + display_settings['total_rounds'] = 1 + display_settings['league_active'] = False + + return render_template('index.html', streams=STREAMS, settings=display_settings) + +# MOBILE ROUTES +@app.route('/mobile') +def mobile_menu(): + """Mobile main menu page""" + tournament_state = load_tournament_state() + league_state = load_league_state() + results = load_results() + + tournament_active = tournament_state is not None + league_active = league_state is not None and not league_state.get('league_finished', False) + results_available = results is not None and results.get('tournament_finished', False) + league_results_available = league_state is not None and league_state.get('league_finished', False) + + return render_template('mobile_menu.html', + tournament_active=tournament_active, + league_active=league_active, + tournament_state=tournament_state, + league_state=league_state, + results_available=results_available, + league_results_available=league_results_available) + +@app.route('/mobile/streams') +def mobile_streams(): + """Mobile streams page""" + settings = load_settings() + tournament_state = load_tournament_state() + + # Check if tournament is active + tournament_active = tournament_state is not None + current_round_data = get_current_round_data() if tournament_active else None + + return render_template('mobile_streams.html', + streams=STREAMS, + settings=settings, + tournament_active=tournament_active, + current_round_data=current_round_data, + tournament_state=tournament_state) + +@app.route('/mobile/draft') +def mobile_draft(): + """Mobile tournament draft page""" + tournament_state = load_tournament_state() + league_state = load_league_state() + if not tournament_state: + return redirect('/mobile') + + return render_template('mobile_draft.html', + tournament=tournament_state, + league=league_state) + + +@app.route('/mobile/results') +def mobile_results(): + """Mobile results page""" + league_state = load_league_state() + results = load_results() + + # Priority 1: Show league results if there's an active or finished league + if league_state: + if league_state.get('league_finished', False): + # Show final league results + calculate_league_final_scores(league_state) + participants = get_league_final_rankings(league_state) + + return render_template('mobile_results.html', + league=league_state, + participants=participants, + show_league_results=True, + show_tournament_results=False, + tournament_active=False, + results=None) # No individual tournament results + else: + # Show ongoing league scoreboard + calculate_league_final_scores(league_state) + participants = get_league_current_standings(league_state) + + # Check if there's a current tournament + tournament_state = load_tournament_state() + tournament_active = tournament_state is not None + current_tournament_results = results + + return render_template('mobile_league_results.html', + league=league_state, + participants=participants, + show_league_results=True, + show_tournament_results=False, + tournament_active=tournament_active, + tournament_state=tournament_state, + current_tournament_results=current_tournament_results) + + # Priority 2: Show individual tournament results (standalone tournament) + elif results and results.get('tournament_finished', False): + participants = [] + for player_id, data in results['participants'].items(): + participants.append({ + 'id': player_id, + 'name': data['name'], + 'total_score': data['total_score'], + 'completed': data['completed'] + }) + + # Sort by score (descending) + participants.sort(key=lambda x: x['total_score'], reverse=True) + + # Add rankings + for i, participant in enumerate(participants): + participant['rank'] = i + 1 + + return render_template('mobile_results.html', + results=results, # ← FIXED: Pass as 'results' + participants=participants, + show_league_results=False, + show_tournament_results=True, + tournament_active=False, + league=None, + tournament_type=results.get('tournament_type', '20_targets')) + else: + return redirect('/mobile') + +# DESKTOP ROUTES +@app.route('/fullscreen/') +def fullscreen(camera_id): + # Get the camera stream data + if 1 <= camera_id <= len(STREAMS): + settings = load_settings() + stream = STREAMS[camera_id - 1] + + # Check if tournament is active for title + current_round_data = get_current_round_data() + if current_round_data and camera_id <= len(current_round_data['players']): + camera_title = current_round_data['players'][camera_id - 1]['name'] + else: + camera_title = settings['camera_titles'].get(str(camera_id), f'Camera {camera_id}') + + custom_title = request.args.get('title', camera_title) + + return render_template('fullscreen.html', + stream=stream, + camera_id=camera_id, + title=custom_title, + settings=settings) + else: + return redirect('/') + +@app.route('/tournament') +def tournament(): + """Tournament management page""" + # Check if mobile device + if is_mobile_device(): + tournament_state = load_tournament_state() + league_state = load_league_state() + if tournament_state: + # Mobile users with active tournament go to draft view + return redirect('/mobile/draft') + else: + # Mobile users without tournament go to mobile menu + return redirect('/mobile') + + # Desktop users get full tournament management + players_data = load_players() + tournament_state = load_tournament_state() + league_state = load_league_state() + + return render_template('tournament.html', + players=players_data['players'], + tournament_state=tournament_state, + league_state=league_state) + +@app.route('/tournament/draft') +def tournament_draft(): + """Tournament draft page""" + # Redirect mobile users to mobile draft + if is_mobile_device(): + return redirect('/mobile/draft') + + tournament_state = load_tournament_state() + league_state = load_league_state() + if not tournament_state: + return redirect('/tournament') + + return render_template('draft.html', + tournament=tournament_state, + league=league_state) + +@app.route('/results/calculator') +def results_calculator(): + """Results calculator page (desktop only)""" + if is_mobile_device(): + return redirect('/mobile/streams') + + tournament_state = load_tournament_state() + if not tournament_state: + return redirect('/tournament') + + # Get or create results structure + results = load_results() + if not results: + results = create_results_structure(tournament_state) + save_results(results) + + return render_template('results_calculator.html', + tournament=tournament_state, + results=results) + +@app.route('/results') +def results_display(): + """Results display page""" + # Redirect mobile users to mobile results + if is_mobile_device(): + return redirect('/mobile/results') + + league_state = load_league_state() + results = load_results() + + # Priority 1: Show league results if there's an active or finished league + if league_state: + if league_state.get('league_finished', False): + # Show final league results + calculate_league_final_scores(league_state) + participants = get_league_final_rankings(league_state) + + return render_template('league_scoreboard_display.html', + league=league_state, + participants=participants) + else: + # Show ongoing league scoreboard + calculate_league_final_scores(league_state) # Calculate current standings + participants = get_league_current_standings(league_state) # Use the helper function + + # Add tournament information + tournament_state = load_tournament_state() + current_tournament_results = results + + return render_template('league_scoreboard_display.html', + league=league_state, + participants=participants, + tournament_state=tournament_state, + current_tournament_results=current_tournament_results) + + # Priority 2: Show individual tournament results (standalone tournament) + elif results and results.get('tournament_finished', False): + participants = [] + for player_id, data in results['participants'].items(): + participants.append({ + 'id': player_id, + 'name': data['name'], + 'total_score': data['total_score'], + 'completed': data['completed'] + }) + + # Sort by score (descending) + participants.sort(key=lambda x: x['total_score'], reverse=True) + + # Add rankings + for i, participant in enumerate(participants): + participant['rank'] = i + 1 + + return render_template('results_display.html', + results=results, + participants=participants) + else: + return redirect('/tournament') + +# API Routes +@app.route('/api/settings', methods=['GET']) +def get_settings(): + """API endpoint to get current settings""" + settings = load_settings() + return jsonify(settings) + +@app.route('/api/settings', methods=['POST']) +def update_settings(): + """API endpoint to update settings""" + try: + new_settings = request.get_json() + + # Load current settings + current_settings = load_settings() + + # Update only provided fields + if 'camera_titles' in new_settings: + current_settings['camera_titles'].update(new_settings['camera_titles']) + + if 'display_options' in new_settings: + current_settings['display_options'].update(new_settings['display_options']) + + # Save updated settings + if save_settings(current_settings): + return jsonify({'status': 'success', 'settings': current_settings}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save settings'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/players', methods=['GET']) +def get_players(): + """API endpoint to get all players""" + players_data = load_players() + return jsonify(players_data) + +@app.route('/api/players', methods=['POST']) +def update_players(): + """API endpoint to update players""" + try: + players_data = request.get_json() + + if save_players(players_data): + return jsonify({'status': 'success', 'players': players_data}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save players'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/players/add', methods=['POST']) +def add_player(): + """API endpoint to add a new player""" + try: + data = request.get_json() + name = data.get('name', '').strip() + + if not name: + return jsonify({'status': 'error', 'message': 'Player name is required'}), 400 + + players_data = load_players() + + # Find next available ID + existing_ids = [p['id'] for p in players_data['players']] + new_id = max(existing_ids) + 1 if existing_ids else 1 + + # Add new player + new_player = { + 'id': new_id, + 'name': name, + 'enabled': True + } + + players_data['players'].append(new_player) + + if save_players(players_data): + return jsonify({'status': 'success', 'player': new_player}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save player'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/players//delete', methods=['POST']) +def delete_player(player_id): + """API endpoint to delete a player""" + try: + players_data = load_players() + + # Find and remove the player + players_data['players'] = [p for p in players_data['players'] if p['id'] != player_id] + + if save_players(players_data): + return jsonify({'status': 'success'}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save players'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/players/', methods=['POST']) +def update_player(player_id): + """API endpoint to update a single player""" + try: + data = request.get_json() + players_data = load_players() + + # Find and update the player + for player in players_data['players']: + if player['id'] == player_id: + if 'name' in data: + player['name'] = data['name'] + if 'enabled' in data: + player['enabled'] = data['enabled'] + break + + if save_players(players_data): + return jsonify({'status': 'success', 'player': player}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save player'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +# LEAGUE API ROUTES +@app.route('/api/league/start', methods=['POST']) +def start_league(): + """API endpoint to start a new league""" + try: + data = request.get_json() + tournament_type = data.get('tournament_type', '20_targets') + + if tournament_type not in ['20_targets', '40_targets']: + return jsonify({'status': 'error', 'message': 'Invalid tournament type'}), 400 + + players_data = load_players() + enabled_players = [p for p in players_data['players'] if p['enabled']] + + if len(enabled_players) < 1: + return jsonify({'status': 'error', 'message': 'Need at least 1 enabled player'}), 400 + + league_data = create_league(enabled_players, tournament_type) + + if save_league_state(league_data): + return jsonify({'status': 'success', 'league': league_data}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save league'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/league/tournament/start', methods=['POST']) +def start_league_tournament(): + """API endpoint to start next tournament in league""" + try: + league_state = load_league_state() + if not league_state: + return jsonify({'status': 'error', 'message': 'No active league'}), 400 + + if league_state.get('league_finished', False): + return jsonify({'status': 'error', 'message': 'League already finished'}), 400 + + current_tournament = league_state.get('current_tournament', 0) + if current_tournament >= league_state['total_tournaments']: + return jsonify({'status': 'error', 'message': 'All tournaments completed'}), 400 + + # Get players for this tournament (excluding joker users for this round) + data = request.get_json() or {} + joker_players = data.get('joker_players', []) # List of player IDs using joker + + # Update joker usage in league + for player_id in joker_players: + player_id_str = str(player_id) + if player_id_str in league_state['participants']: + if league_state['participants'][player_id_str]['joker_used']: + return jsonify({'status': 'error', 'message': f'Player {player_id} already used joker'}), 400 + league_state['participants'][player_id_str]['joker_used'] = True + + # Create list of participating players (not using joker) + participating_players = [] + for player_id, participant in league_state['participants'].items(): + if int(player_id) not in joker_players: + participating_players.append({ + 'id': int(player_id), + 'name': participant['name'] + }) + + if len(participating_players) < 1: + return jsonify({'status': 'error', 'message': 'Need at least 1 participating player'}), 400 + + # Start next tournament + league_state['current_tournament'] = current_tournament + 1 + tournament_data = create_draft( + participating_players, + league_state['tournament_type'], + league_state['current_tournament'] + ) + + # Save states + save_league_state(league_state) + + if save_tournament_state(tournament_data): + # Create results structure + results = create_results_structure(tournament_data) + save_results(results) + + return jsonify({ + 'status': 'success', + 'tournament': tournament_data, + 'league': league_state + }) + else: + return jsonify({'status': 'error', 'message': 'Failed to save tournament'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/league/reset', methods=['POST']) +def reset_league(): + """API endpoint to reset/clear league""" + try: + # Archive current league if it exists + league_state = load_league_state() + if league_state: + archive_league(league_state) + + # Remove league, tournament, and results files + for file_path in [LEAGUE_FILE, TOURNAMENT_FILE, RESULTS_FILE]: + if os.path.exists(file_path): + os.remove(file_path) + + return jsonify({'status': 'success'}) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +# TOURNAMENT API ROUTES (Updated) +@app.route('/api/tournament/start', methods=['POST']) +def start_tournament(): + """API endpoint to start a standalone tournament""" + try: + data = request.get_json() or {} + tournament_type = data.get('tournament_type', '20_targets') + + if tournament_type not in ['20_targets', '40_targets']: + return jsonify({'status': 'error', 'message': 'Invalid tournament type'}), 400 + + players_data = load_players() + enabled_players = [p for p in players_data['players'] if p['enabled']] + + if len(enabled_players) < 1: + return jsonify({'status': 'error', 'message': 'Need at least 1 enabled player'}), 400 + + tournament_data = create_draft(enabled_players, tournament_type) + + if save_tournament_state(tournament_data): + # Create results structure when tournament starts + results = create_results_structure(tournament_data) + save_results(results) + + return jsonify({'status': 'success', 'tournament': tournament_data}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save tournament'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/tournament/round/', methods=['POST']) +def change_round(round_number): + """API endpoint to change current round""" + try: + tournament_state = load_tournament_state() + if not tournament_state: + return jsonify({'status': 'error', 'message': 'No active tournament'}), 400 + + if round_number < 1 or round_number > tournament_state['total_rounds']: + return jsonify({'status': 'error', 'message': 'Invalid round number'}), 400 + + tournament_state['current_round'] = round_number + + # Update round statuses + for round_data in tournament_state['rounds']: + if round_data['round_number'] < round_number: + round_data['status'] = 'completed' + elif round_data['round_number'] == round_number: + round_data['status'] = 'pending' + else: + round_data['status'] = 'waiting' + + if save_tournament_state(tournament_state): + return jsonify({'status': 'success', 'tournament': tournament_state}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save tournament'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/tournament/reset', methods=['POST']) +def reset_tournament(): + """API endpoint to reset/clear tournament""" + try: + if os.path.exists(TOURNAMENT_FILE): + os.remove(TOURNAMENT_FILE) + if os.path.exists(RESULTS_FILE): + os.remove(RESULTS_FILE) + return jsonify({'status': 'success'}) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +# RESULTS API Routes (Updated) +@app.route('/api/results/participant/', methods=['POST']) +def update_participant_scores(player_id): + """API endpoint to update participant scores""" + try: + data = request.get_json() + results = load_results() + + if not results: + return jsonify({'status': 'error', 'message': 'No results data found'}), 400 + + player_id_str = str(player_id) + if player_id_str not in results['participants']: + return jsonify({'status': 'error', 'message': 'Player not found'}), 400 + + # Update scores + if 'targets' in data: + results['participants'][player_id_str]['targets'].update(data['targets']) + + # Recalculate total score + targets = results['participants'][player_id_str]['targets'] + total_score = calculate_total_score(targets) + results['participants'][player_id_str]['total_score'] = total_score + + # Check if all targets are completed (all shots entered, including 0s) + all_completed = is_participant_completed(targets) + results['participants'][player_id_str]['completed'] = all_completed + + if save_results(results): + return jsonify({'status': 'success', 'participant': results['participants'][player_id_str]}) + else: + return jsonify({'status': 'error', 'message': 'Failed to save results'}), 500 + + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/results/finish', methods=['POST']) +def finish_tournament(): + """API endpoint to finish tournament""" + try: + results = load_results() + tournament_state = load_tournament_state() + league_state = load_league_state() + + if not results: + return jsonify({'status': 'error', 'message': 'No results data found'}), 400 + + if not tournament_state: + return jsonify({'status': 'error', 'message': 'No active tournament found'}), 400 + + # Check if all participants are completed + all_completed = all( + participant['completed'] + for participant in results['participants'].values() + ) + + if not all_completed: + return jsonify({'status': 'error', 'message': 'Not all participants have completed scores'}), 400 + + # Mark tournament as finished + results['tournament_finished'] = True + results['finished_at'] = datetime.now().isoformat() + + league_finished = False # Track if league finished + + # Update league state if this is a league tournament + if league_state and 'league_tournament_number' in results: + tournament_number = results['league_tournament_number'] + + # Update league with tournament results + for player_id, participant in results['participants'].items(): + if player_id in league_state['participants']: + league_participant = league_state['participants'][player_id] + + # Add tournament result + league_participant['tournament_results'].append({ + 'tournament': tournament_number, + 'score': participant['total_score'], + 'participated': True + }) + + # Update total score + league_participant['total_score'] += participant['total_score'] + + # Add results for players who used joker (didn't participate) + for player_id, participant in league_state['participants'].items(): + if player_id not in results['participants']: + # This player used joker + participant['tournament_results'].append({ + 'tournament': tournament_number, + 'score': 0, + 'participated': False, + 'joker': True + }) + + # Add to completed tournaments + league_state['completed_tournaments'].append({ + 'tournament_number': tournament_number, + 'finished_at': datetime.now().isoformat(), + 'results_summary': { + 'participants': len(results['participants']), + 'total_shots': len(results['participants']) * (40 if results.get('tournament_type') == '40_targets' else 20) * 2 + } + }) + + # Check if league is finished + if tournament_number >= league_state['total_tournaments']: + league_state['league_finished'] = True + league_state['finished_at'] = datetime.now().isoformat() + + # Calculate final scores + calculate_league_final_scores(league_state) + + league_finished = True + print("League finished!") + + save_league_state(league_state) + + # Archive the tournament (only if it's NOT part of a league) + archive_success = False + if not league_state: # Only archive standalone tournaments + archive_success = archive_tournament(tournament_state, results) + print(f"Standalone tournament archived: {archive_success}") + else: + print("League tournament - not archiving individual tournament") + + # Archive the league if it just finished + league_archive_success = False + if league_finished and league_state: + league_archive_success = archive_league(league_state) + print(f"League archived: {league_archive_success}") + + # Save final results + if save_results(results): + # End the tournament by removing tournament state + if os.path.exists(TOURNAMENT_FILE): + os.remove(TOURNAMENT_FILE) + + # If league finished, also remove league state file + if league_finished and os.path.exists(LEAGUE_FILE): + os.remove(LEAGUE_FILE) + + response_data = { + 'status': 'success', + 'results': results, + 'archived': archive_success, + 'league_archived': league_archive_success if league_finished else None + } + + if league_state: + response_data['league'] = league_state + response_data['league_finished'] = league_state.get('league_finished', False) + + return jsonify(response_data) + else: + return jsonify({'status': 'error', 'message': 'Failed to save results'}), 500 + + except Exception as e: + print(f"Error finishing tournament: {e}") + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/results', methods=['GET']) +def get_results(): + """API endpoint to get current results""" + results = load_results() + if results: + return jsonify(results) + else: + return jsonify({'status': 'error', 'message': 'No results found'}), 404 + +@app.route('/api/league', methods=['GET']) +def get_league(): + """API endpoint to get current league state""" + league_state = load_league_state() + if league_state: + return jsonify(league_state) + else: + return jsonify({'status': 'error', 'message': 'No league found'}), 404 + +# Add this route to your Flask app (around line 850, with the other mobile routes) + +@app.route('/mobile/remote') +def mobile_remote(): + """Mobile remote control page""" + # This page doesn't redirect mobile users - it's specifically for mobile control + tournament_state = load_tournament_state() + league_state = load_league_state() + results = load_results() + + return render_template('mobile_remote.html', + tournament_state=tournament_state, + league_state=league_state, + results=results) + +# Add these API endpoints for the remote control functionality + +@app.route('/api/tournament', methods=['GET']) +def get_tournament(): + """API endpoint to get current tournament state""" + tournament_state = load_tournament_state() + if tournament_state: + return jsonify(tournament_state) + else: + return jsonify({'status': 'error', 'message': 'No tournament found'}), 404 + +@app.route('/api/remote/refresh_dashboard', methods=['POST']) +def refresh_dashboard(): + """API endpoint to trigger dashboard refresh""" + try: + # You could add logic here to trigger refresh on connected clients + # For now, just return success + return jsonify({'status': 'success', 'message': 'Refresh signal sent'}) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/remote/system_info', methods=['GET']) +def get_system_info(): + """API endpoint to get comprehensive system information""" + try: + tournament_state = load_tournament_state() + league_state = load_league_state() + results = load_results() + players_data = load_players() + settings = load_settings() + + system_info = { + 'timestamp': datetime.now().isoformat(), + 'tournament': { + 'active': tournament_state is not None, + 'data': tournament_state + }, + 'league': { + 'active': league_state is not None and not league_state.get('league_finished', False), + 'finished': league_state is not None and league_state.get('league_finished', False), + 'data': league_state + }, + 'results': { + 'available': results is not None, + 'finished': results is not None and results.get('tournament_finished', False), + 'data': results + }, + 'players': { + 'total': len(players_data['players']) if players_data else 0, + 'enabled': len([p for p in players_data['players'] if p['enabled']]) if players_data else 0 + }, + 'settings': settings + } + + return jsonify(system_info) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/remote/emergency_reset', methods=['POST']) +def emergency_reset(): + """API endpoint for emergency system reset""" + try: + # Archive current states before reset + tournament_state = load_tournament_state() + league_state = load_league_state() + results = load_results() + + if tournament_state and results: + archive_tournament(tournament_state, results) + + if league_state: + archive_league(league_state) + + # Remove all state files + for file_path in [LEAGUE_FILE, TOURNAMENT_FILE, RESULTS_FILE]: + if os.path.exists(file_path): + os.remove(file_path) + + return jsonify({ + 'status': 'success', + 'message': 'Emergency reset completed', + 'archived': True + }) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +@app.route('/api/remote/camera_titles', methods=['GET']) +def get_camera_titles(): + """API endpoint to get camera titles""" + try: + settings = load_settings() + current_round_data = get_current_round_data() + + titles = {} + + if current_round_data: + # Tournament active - use player names + players = current_round_data['players'] + for i in range(6): + if i < len(players): + titles[str(i + 1)] = players[i]['name'] + else: + titles[str(i + 1)] = 'Empty' + else: + # No tournament - use configured titles + titles = settings['camera_titles'] + + return jsonify({ + 'status': 'success', + 'titles': titles, + 'tournament_active': current_round_data is not None + }) + except Exception as e: + return jsonify({'status': 'error', 'message': str(e)}), 400 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000, debug=True) \ No newline at end of file diff --git a/TV_APP_V2/camera_settings.json b/TV_APP_V2/camera_settings.json new file mode 100644 index 0000000..77f9c86 --- /dev/null +++ b/TV_APP_V2/camera_settings.json @@ -0,0 +1,14 @@ +{ + "camera_titles": { + "1": "Camera 1", + "2": "Camera 2", + "3": "Camera 3", + "4": "Camera 4", + "5": "Camera 5", + "6": "Camera 6" + }, + "display_options": { + "show_titles": true, + "title_size": 0.8 + } +} \ No newline at end of file diff --git a/TV_APP_V2/players.json b/TV_APP_V2/players.json new file mode 100644 index 0000000..4ba1638 --- /dev/null +++ b/TV_APP_V2/players.json @@ -0,0 +1,224 @@ +{ + "players": [ + { + "id": 1, + "name": "Domen Pleterski", + "enabled": true + }, + { + "id": 2, + "name": "Nik Pleterski", + "enabled": true + }, + { + "id": 3, + "name": "Ivan Tandler", + "enabled": true + }, + { + "id": 4, + "name": "Mateja Pleterski", + "enabled": true + }, + { + "id": 5, + "name": "Jo\u017ee Verhnjak", + "enabled": false + }, + { + "id": 6, + "name": "Mateja Senica", + "enabled": false + }, + { + "id": 7, + "name": "Branko Poker\u017enik", + "enabled": false + }, + { + "id": 8, + "name": "Franc \u017digart", + "enabled": false + }, + { + "id": 9, + "name": "Janez Bo\u017ei\u010d", + "enabled": false + }, + { + "id": 10, + "name": "Mitja \u010ceh", + "enabled": false + }, + { + "id": 11, + "name": "Rado Kefer", + "enabled": false + }, + { + "id": 12, + "name": "Matej Kvasnik", + "enabled": false + }, + { + "id": 13, + "name": "Angelca Mrak", + "enabled": false + }, + { + "id": 14, + "name": "Karli Proje", + "enabled": false + }, + { + "id": 15, + "name": "Jan Pleterski", + "enabled": false + }, + { + "id": 16, + "name": "Silvo Poro\u010dnik", + "enabled": false + }, + { + "id": 17, + "name": "Du\u0161an Onuk", + "enabled": false + }, + { + "id": 18, + "name": "Matja\u017e Pleterski", + "enabled": false + }, + { + "id": 19, + "name": "Franc Rizmal", + "enabled": false + }, + { + "id": 20, + "name": "Jo\u017ee Preglav", + "enabled": false + }, + { + "id": 21, + "name": "Marko Blimen", + "enabled": false + }, + { + "id": 22, + "name": "Doris Fesel", + "enabled": false + }, + { + "id": 23, + "name": "Robi Krautberger", + "enabled": false + }, + { + "id": 24, + "name": "Jo\u017ee Verdinek", + "enabled": false + }, + { + "id": 25, + "name": "Andrej Herman", + "enabled": false + }, + { + "id": 26, + "name": "Jakob Herman", + "enabled": false + }, + { + "id": 27, + "name": "Janez Mrak", + "enabled": false + }, + { + "id": 28, + "name": "An\u017ee Kolar", + "enabled": false + }, + { + "id": 29, + "name": "Alen Kolar", + "enabled": false + }, + { + "id": 30, + "name": "Maja Hirtl", + "enabled": false + }, + { + "id": 31, + "name": "Dejan Ku\u010dnik", + "enabled": false + }, + { + "id": 32, + "name": "David Strni\u0161a", + "enabled": false + }, + { + "id": 33, + "name": "Namir Uzunovi\u0107", + "enabled": false + }, + { + "id": 34, + "name": "Jo\u017ee Planin\u0161ec", + "enabled": false + }, + { + "id": 35, + "name": "Vanja Kolar", + "enabled": false + }, + { + "id": 36, + "name": "Klara Wankmuller", + "enabled": false + }, + { + "id": 37, + "name": "Milan Stramec", + "enabled": false + }, + { + "id": 38, + "name": "Bojan Sudar", + "enabled": false + }, + { + "id": 39, + "name": "Tia Sudar", + "enabled": false + }, + { + "id": 40, + "name": "Jaka Cvar", + "enabled": false + }, + { + "id": 41, + "name": "Tadej \u0160truc", + "enabled": false + }, + { + "id": 42, + "name": "Jure Glaser", + "enabled": false + }, + { + "id": 43, + "name": "Marko Pokr\u017enik", + "enabled": false + }, + { + "id": 44, + "name": "test", + "enabled": false + } + ] +} \ No newline at end of file diff --git a/TV_APP_V2/static/logo.png b/TV_APP_V2/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..da243c28dd00946fb0e5888215508a931c4d961d GIT binary patch literal 139448 zcmeFY^;cA37d8w6QqrlEfHVk*beFVrmvqelN;e`yha%l6-OP{!N=k#0Go*BP*LQfn z=Xw8xZ+$PB3d(E7#~)PhB1umal$R(_Ny(s! zwDyD{n2d#&J;Cr;&!+B$*T!Iz8T^o!iajPK=%~cMbfn(Azw&k?iZX?L`A2E-I#Lh= z%Z8;l7!=z4djr+|7s1O{6=n5;^PjFr*$YoT(SCAl*cdQtFs|fXPj?#@p1!>+Ymv*G zEZ=Au;qAMOKe$nUxIcKvMg^|)KQAeoz|ngA|8ry-I`hBxC?&CkRR8AyN@R)lzk^%> z8PNaUqfESu!291pFaoRg|NLhSDtdwceSqS~*!_5q{_~Oo|KF4R=SKYB+f{lWfF2~^ zP4U0X5dZ%?GlmcRwoywuJMJ%McZ-pY)7NtgUI#%Zh$sKe)h_H>RE@~3tu4?-dA0Ya z|7Lfvj|0mi3jF8wfAjgjH{$>1^M7vy%Ku-{GGp;#0*xnr%`iFE#!%qfLrfX>nRpe& zagdjd;d!4w*?p)lWI-Pu)8bbcqSO4ZL8npUX&LMc6X`jM11(JjKI`Hir!b%@+G)V>83Uic zE1k`7GAr4-1WvoSt?Os&J|p#3A|aJjK(8%i zD%poCwMf5qZ{RjaVvfSTJ{MhTUT;HkqBst_`cP2NdsqSCcV*XFPO{B${ltkwq^Wk( z065L&P3?@O=dqzIy?M zyPrBe{s058%wq5{g!R44ccbAkeB9%n!h4J&ntJj?ln(}aP9A3EU-<8i@XRj0dFl4a zDBpdCCJ{9rNynTqNDEp79GWni9pgQ(jpDv%i#`Y&Ic?sg2JFifb9L z)CqO<6SA0=)Q|N}8J-67xd#o+Mt!{0rpVuWViM`e9Liq{B{QeWGpFcO`Sd3_;nP-C zxyZP7DI~7Z&Kn9K6+Uqt7(e5+&&TJuc^Vde0x4X`Px$;2#pb!TF3i(I)zgtt1d&a< zjFAx8zLf4Lw}!J3!f}$*6<{Io8Mb&Pv$)QfZZ+|R!wL`7f!RgQ=RCFFOp|^pf-Nys zP!+Z6k>+~$rmn%~A$Q@z?_hE5%I&Si{m0eJ#m2yeRtbsB@L6Exr+sb1fi3aOw$LcF z{T$(f>$Qid7o?)287CG)Vn((XCXciXMi&*P9scj zA5Mbc8EWckb~opAzvF1d)9;RB1?w0U7Dg9lS}(ku{YIKMJS4i$;~#3SyzU#nzZYRM z{?wZ`i_MbxRV~wZJ1BH6nNwK&W-R=D#hMU_{SBIwVd%`Z;E>dHYX8YMPa%Su*n!v6 zlUHZyQ5a`9dDB!UIW#^Q2u&AVKQRP`X1FFUt87`5We2kr8W|(njPE1xUcTpUg0MnTlJ~Ai^&*cfh)U<LSuBtx7H&W8))OA#MeDZS1E%^)OFk@ z$bcvPoac6Fv8@VuPIAC1W9*AY?%y1`6+@Uo>bMQ4uGGxA+fcuVpa6#I!fyMP(zVHF zzQ3ToVQ&|L9u#3Ni%7nQ`SJ)FY7uwVo3lJwx~9E}iB`U84_+DFP5EevCPU_1mpn`N zn#+d2bp%=7GM=50EY^0}wbnue=a=NGx_MorvOZEUCoXAEEHeHP)^I`{7t~5Qh4F#g z*4BMtmFe!YO)U)zS+uy%+wNQGKYfzfhxWyw{MGlb#{`}Lds@Pt!6j*;X~`()16Kp; z{KZrTUmhF6VuN}aR`a{T`)G^rA*>9H=cvR!_VnjbYEAVtk1U;9$tNj(TF0#&q?1eQ z54I%i1%D@V&(q)Ipy_NlA3c;%PW032ow6V$q=Q%VP+*#0p`)gjIdrb`tnc#D+w=Ic zQ$%q3)KkNYf9Rdt+jhh~O6bhX{o8+t9|3x+Zb=?m^yRds*eq{hHBU&F#8f8V_X{p9 z%uv`Pt+Vssz(v29VQ*+OmgEeCeI!*YI!Sq*3iR8hD_!*Mue7O*Q0@rU+^fQ zOTl|pXQrJENG>>zKcW=adEs{9k@(DP4Yc6rK8SGXX!&jYyw}t1l+gRlW%4B^p1aJ+ zO>Mdp#9h+e`_y)DA{>pkqEMup7f|hYe zoRq9;FTU72F^#nN{Q$xA+>(VydW1dabZ(TBw>Zls3r~M`RSrIELpew-&LSwC) zglRMF+MpSnuvq*?&@xy)a9-f_(C8B1&+kEWb^-2ZOktqHd-LMe;1{qRm$;~?-`1a9 z#-KJ3WghIF2l;|zXe95;3-hP5X6EhC;?W@ZTLXvI;>eDsINR>!8$L*ucJm_w*J2v+&T0xnSe5Pbv63KUtHS*mJBe3 z7TY%urQnOeDGDRpXnMbk-TN#@lQ9zZ!@KoKeF>gTyf44gWx)WBrs1!D>EL=Agpx%R za6H>|6u5k=Xx;+SRgM5tZp;-9(@Of@_U{^J>{p*hTn6L5ZewlTaq=Sf(b8*p^|FD1 zKnoxISF`E8-`1MGU75v!?;Z5Le%C$*@?Q9%!!HjOpXK*{a{8tI`t)vw)|Un@A_3IO zc;SiRjE=?ap7<8LLmFY6UafWbe#_3zdXX}z0Heh9CZm$q=1KNC)x(CMl`JTnu~%$7 zdPmad{A!o(!NRSXAdCR3dhaUd(qQQOC*?p>qv_Y_o4>{;^-WFpzBQO!j?BThT1w3H zJ=NsnKX<*W3-U4gOZuXcNU8W<>Ztt=v#vlP=w`8A*1p%O6kE+4ZcT?vYD8w8i)$DBXq_lt3o4U3AK%`VA`bNkC+LRO>3^K}OG0bMSG+qBXt<_C&qt zXf3FU?D8N!!KG0ocBk(aNd80{bbhrrNsHG{Ji5gp;##R~xHfc;Qwqm%xXWt@aDmTm z#X58m_bQyke(SuQjARM4x5abw_ZJiO@wb@Qo%6*I@mzJw=>*}u>V6tiH|YVx#UuI5 z-O-}$r@=l==ZK4|Jos?Q$cNS$AGAAXap1nmJ>1Iwpl{9_JWj&@m(Wv~n0r?%roj(O zeJ3n&m@Z!OC^7OEJ}lVq}=^Nd4r>;%a?I(&;4D0C^Wy*jhtN~ zG$#rTyzIAWXP7LWWsZ#Re3!O~eOwcrl^5xZJ5B6lN$~fdS97P=zoMK6lRp7r7zTe5 z=RzcX$vk|02RL+V_06t*lIML@cImcsohxN^BEX(hB7yor87)|*sdi>G#x!p-C3P$c zF!BXE&v$g+`*~e!2#AY|*Gm^sBog1dq%2%t?oM-=9K1I3zaHwylTvULy(iAh85P8; z=l@Db#pCF!JDrbtW3vUtf>O$4b>2ANoQw|Nh9;X?pir_yv*7Lyy1K;ce-@qHz06D0 zJOqNr387x`)qPQgML3!T)5Cia-;%e&Lm|JDd|(vLCZk?P+z+zjET&l zzS^+XI4{^8u z59I6Xbgl-WA8DOpN~>oYdBOUFa^k&*^K^*v^6V)ZH(giUoivqEvt%w)pi%@JmCCQT zM+tSfoXn-iWjei3kHDiOgX);#qLmYx+-#k1s9BFG!apxbUg$d9Yzl8!=UiU;bRi}Q znMdh{zJQF6gYcf9BAhq{tm__vF`5k`Cq2s~;+++-iN$Y!TLBqMcc|~=%>KvI!b@2t zo!&Sro`3_p8nQi;H=u##kcw4p<{c;7I(|qZ@aMK4gTgxJexk?bZXV;xqh}RM#|BBn z=k-k^@4K+7ng^_9a(jj?zaRh;V`sVre`g5X{hqC->rMkrUVfbIuyq+RLWKe`reE?7^*ej0ccGBSN z-{AuX^b;`u**|5X>Xk!5?a8CsYy+B%^a8oVz1L+`@&x;sWXxRI0nRr=!H(?`i(_x^ zbP?^}Y-TYi%-#;c3M|IAdT;F%%sm895KJQCR+*$OOZ}?`B#)ucn|Nw!@K1i?fX*XB7>6zx!+5(s|TyQoQdlcxWcIeY5h*W?bdU!)IVJJ zM-L+8{+18Gd?%_|-V13m!K7aW-YYnu@``lBhK1X7mc>l1oqL+u)&8x=|B(TesS=Dn zoJE@##`x@D)ykWb(21-DxQSs?xwq7?iCk0DmZ{?A|9vuUwLA8P)OM%(HhYcCXVl2o z)ALB4LdUQO3>3AW7}{!~Gr8mI`#TpuB}RybPY659fnd?x<#^wHX$#{rTBpGt%-DtP zxUhm&1{XnU`_m8ICf|Y0 zLMn4;p)IrOZBZ9i`_o_-FNmvKpgK(VRWl&gelP^Vzt_KAd zD2w{k|H*r{>q|DBebdk93FSHV z{n9~?iIBnQxjBIhRbF)%#Xfm!e9BP06x4Qfbd;E(?@?v)O5?vLOgWcb z1i)k`X_W@K%=~=^&`RnUd`RTNdAp!Z2d|76uEj+8&#I;qU%{se?mol*14{hEBRU~2 zFM!0y)7w~19xx7bB*US5)&Tjum}BB9eI6N~qpx?9)6DssgCi^_{J3XWGba_rzPyCc zI8}#f0ciTHTv`h{i#=oqVh@l_wT}zG-+YnHuu>DQ#j&Gn&q=o^AO6ZJ^w6k8YN@5t z)HZy!$}FHKx37bpkVvz>K##F=0=@ zdkP*_K@&a#F|(%Ad=d9j#x80ne{))zDmEJQllJn&Tr1d-gaB7n<4?|cHr1W%!Oh;F z;SF%4`W)w=g?)uoCRI>)j?1cOGj(-k)nh_)3K*Qa>E7~Auk;iGl zd4Z~}-8;nA>6Z13TggL)&2>*yGZRB!L^O%Vl{olC9&5qlR-;+G$wTl zH8vQ;S+Pss+Z-=o>k}NHhn1XwDC=bneVx(?{0~}f^gfRsdkn5!QI~!9?*TC2N7`@9 zz4CJWYDiC``R<&<7{RwrJ0_q!3Op9F@@@V_x4?Thp6X|OL;b8M>*Vm?eB$DJY%!z= zZDwN;_TNON0?iRT zTZa=<;8_mtySaauq@)s}d7Lhn*tiElpMF7RgYH&)bfFH|;841u4!Y1;lx;E^%bPVS z7w=Mr*m!Q`W*@T3;{?QcIJ-gb_$2PjCPA8Ci=)9ap3B)oZOxA$uT)ydc8O;s1G>sOB#IJ2$urrX6 zSZZ;q9t^BmTTa{k8N3gOjv_K3DN}ZWYKYPSVVNOx`#22}-#t$tmCu9Hwj4%Pr(cY_=E`*M z%nvVf(un6#A}Onfpg3S9;2X#<8+3-;T>BHt+6V+MN2CXr)v#|U8a1%`9=GqZ2()Dj z_AUrzj&{wYJI>d6nkpM-Wz+D-hx_hj=;422u|Si<;tE*)!#&iH9BQTuBLs1l^h?7^ zlBF@)30RrSiayAy^*;U6)ofy4CiX?oqTIg9x{#?MFzPB!*QRB;Gc&Mr!`grzw#f^* z7`|npymH)%`ioe1ucAJ{LbJKanree%icK!%E`$D{PGT6!&w+ z*gj*M0*=wxc@!v5hH;4TTI8~{5-AqXgq<@eU0wr+n^V%uV^m`5PB?xxZ7ulHh#N*~ z9lejW9KhF+fJAE?mm3h7g@H$w!6$+K5nvtpEW6_3hTR`#^y-A`)G}VBs91GLsu6f4 z2!nPhJtgnT={Ik8rwDLqiEqYKEnZSS`H?qiuXML=M`DXsqIb$LdfI?pVqnJ=o82_Z zK(S(3sW`e8Z1+DeKxsNz+0N`Mt;*4g%%OJgEvC|-6<6919IeBk3bm_CjuxgpkcF!E z#&v5Qvcoq6A`!=CvJrmq8)Z*EgVH*>inR_X%H`t32oOV2l!>L2#5ym~%wh)m#-#my z1*7HU>i#j{4ktEl#%Js%KNHk35^MiYkm)m4_!!hC@r|SRXqcAq&BJ7$H%Or4m5h52 z4oy58ge@u%OKP+VQ=GaaMIcsXtZMLY?l<{J(jJ`Fnj7P=CwqkCEV4@t(~j;x-@qR? zo+n;y5{eXsT=)zz#S0OzzrW@{7q=S*_`js1TXGmgKXjS2Q^j`NR#BBJV;b5ylsZpb!ZMPG4gN`Vlc6_U& z`OE@_;|Y5`Shs6;B^S;^^>Zn|L#6nKG68FRMWnX6nvcCr7N>sk?kV1i3t3$m3AyV& zd}DuCmQIBC%*CIJVD%YNPNF@kYE{rU=#2j}juvEW1>w<1KL5;3`Tia(^Oeh2THwe; zI;TM4y9_!QBuoWIxsT2gEf-I~$JU*}$!rV?2b!t`V}i0b^TZYvsXTT7m32kw|bZVH^hVUS-d{V)KSZ2?jJky@& zbf#>4Uf!c(62nn$W9?1`JM@(}gdZfI+NBMOUo2=_)8FPzIQlXfW{0z-kilDdrnCcM zrQx++E}rwyX)^F6v_e{1AiW5D5ZON?phkbX<<}?{=;kXEjgU%f^f^pA}y$cX*O@596tSH564tDcND-{W!yHavJYsB zinvKmBr*@Y>Q#@?QNF79^h-!2k^WYwqx<}4!8xRvVJ+PR3l5K?_K{qhQ2@gkwr}c| zpw!RQSbq|UV28HJpc<1+u>vCq%5FKc`As{UOoHGE z>jv&u=Cb1i7@GqzxpV6Wy2)i}pLKU8wiq?6&YSkmL;wws#}0av1K68F@$ zf0tGsim^90L=ETRcBVj90`$(5`?ua<`tm>+`fQ2Dzke1PF>43QtmHoj-GBx^>67`v zd#9`WpgHOjD{1L(X!EZ+p%af=0K1Os_ZJW;Fft~E(&vyyWWN>7u4y7tb_)bb6jn7V zAH^0KWR`q&&EJb{3zv||_s!lIJ&8u`i10;QVn&K)Bv@7%Yin77mXEet(Rje zt3AKF%)eG|W95g8XWQkmDzdK|+dqQ5y||NK_SX)C%4uPam`vmTx57KHnv*wihaaLr zMM9*Ih&|8{gAPawAI zlv4(|7#o=BIQqMXG`^AAYN(xQF22JAg%;6t`oKSYtz^?(GFFJdQ{+!G7ptHvOj7N* zKQv+;#vZHg)_)TzRzbwn;Lh{9`kg`Oe9e6v!$p8D zUZwlgGvW`pd$KM74e$K=tOrFJhN)0{`M@ee6a;I7zQL)ua}Fpe9uQ&{Kvy#c@}o<@^6;B*`L){4zbARvk;?*F#A4n zTr_s^b&*pxiJ@x9vj0=n0jSZEOF34rA14Q%8(Ch3oQPAgM4Q=Uddbq|gL(5+iY|`@ zE~f{h8;!8nCLE*{>GjagGOm-zduR2Eg?@WuTI9O8KV8T1pHVoCGNHs58$J2VbmC7+ znxA%lZBiTu2%}khHV9C4p_(Pv)ZR2i zbo&!n_Omsd2gyHeW^U^gj^P98H=iX#JrvDn&h4ZeZF;=`4E1^!&X$Rh3QLT_6fd42B!%SXk79GT zpGMUhD(RV?+Z8S33@|zgY>s#y^{yx0Yy(xDdjD?a zSwfXzOpUZUHZ4VFe&RpI7GiA30*VzdzQ)nU;#a!=x%58uaMkOCx_+07=Lyj&_N)(!>7p4FMNQ2XrfNnLk%2 z?~ejj{e1I%Ra%xK(-xExD*EK*r#HiKC*Bsk`|S7(xRB2K^n zjbqwWdsSlkS#!WhdOj+Q4&>v#?n{vVYDhA43WfoC{z<;71OpLDJ`n?q(-bZqr7DiZ z5C0~#>(zs{|7jhZNcroMA5XuOcG#2CO>@o`Jl|Im{!u3j8n;4AnpscLn63M+JJY%T z5*0E2t%+F#XNO>1_s5UoVt{g%7+h8@G#%YfK!2Y&Z8nW51AW@)aoa%GU2Ut#28pMC z7DFvrmC^BmaWJ+9o zw`+UN)CBaMMT^A%rGVfTlndB=qe9V1b1ro?Q#W9Z!@qkMg`W}{M>NC*I#l9ehd)gz z)=`+o@o#t)W~5*-Pw$I=l;YB+x%cfSVQ6iCGMz-ib+~{JI1b3c-^bX9Y3-+f`-oq^ z>bT45$SDn54Z$l>F$g8VEz65NilZ=py~8@SLBi^(jABYGZrE{9DG29f(5;~qL>de@ zAJm}A4<;OgXKLt+z@X8;viM`6D9A7JfxMw#?t2(;@hBDw^77^LsltWU;~k%8X+T2_ z-?2sz)BMJo{u#3Mr92PwX7N60c9{vpKOzV{%$YpGC=FLu zqP1udfDoHsJt(Wsh(Z5u5KvW$#j-UYHD_5hHMlVl-q+g`tN0QBAQpq<(H>p`dVx*Y z+Evfb>o?gD9$xA)ItVu?m>Ekn^ReFWCDG%a7U!s>qTd*{8_Vbln+El zmynGvE|;!O$bg`W5KA z$=BnmW8g>iqoP6a>D?OtSa*#gvt`}0Z4$+5gqvlhPobvz*tODLXJys$Ng6roij?MV zduMzkUCfrj%s5H()$QBcY0BT2_M+M}fe;u0C|8{-X7k~7hDF|rkujl*hJG7310X`4 zy^(rE*5&|jizkHwdn@##PSg2Gb{_a~s9HLWTKue(-BO1Mwv_2MT7Ir*Uq@EU)!B99 z56q@~cri(hLd>tPMvLb9A4uF7t=8YtA0~_?i!&eQ54aBkY*>8&jn!@B^)~!uzX2!k z1elGU+E#VRw!JRX((-VhHi$v_Y%aovt`~HA`JIg*APw4c1q5}Gs29Mc8UvxZ6r6MY z@}^IUBUJfYo~8BYWEnTjB)rX#5{$p5elZwU5c%;0iWOUA;-?j$44W^hyK>rbnWoQs z?r_Ox=k$l<^)N6WFR8ji+c`V#ja&EirUM(aX0{%(4#dCuZtkc!%RiNu*WbErv{P=L z+H31qk;r*thHDXhlu8w+;fKsKXkabn@>69sNZLxqT^S=hkJMTJ=Q`2k?%N*k2+dPqimN&=Bp9RSR>{=;bY9Eo z4EmK7Uz)I0HW-FY@-6R^btKn2T^qD_x~CV2JXz1oJ|n>U!zQSn)kaV~J1|2P9yO3> z#I}YtDf8H5F%)BasOOGY{kO&C&btQIT>4<8w_$o_Eg& zzl>Vc;`?D^bwn4z1aQ_m zQ1e-GbxxvEnkZA=_;iR67|UT-Le;2~H_~^i)Jr+X>P3rsRIy=&Z3@2aJ{JM(u6%Dg zpDc@CFk^a`SM|ae*WV3}ni(BgjE(hlZJu;%8#n6uy`uRD^bx@M>j{C0+` zB;iW$Y2%&6DNn@9WQHPUTJ5|B(AWUgB7ja}rSBXQw?J~#@bj>VT0Mh}_IO3)lzxWj2`&95Do<1=!~LE) zoU7IC&UE(S*8Bkf8Y^XO*`k#-7#5vg!M*HPudQqrvqJ&YSdfO#lHcOq@t{Uo$K@cm z-Qygz)XT^F_heRQ_e@f0$E%;ctdB*zl*-^eFRYlEgl%~R7>qYhJ4odi3a34~STaAc zP+3xdyDn9Vvfk2NDW3Xzt1dC!kAP0?8x8>m^#vbFoH2S?%cY82E8l4BQnINbv+2Jo z8cswc9=_R{pqXqC3zjzX$pAcVAKt31QylcS?%qJSX9+j4e&M4zufv-^LokC4)zqR|-=q zB~*GH*i||6b?4QCC9mBBCDI&U;xuULusTlDR<2tCH8y2!8f83sZh4N}6XQ)&ee&z! zsY-bB@4E^m5SeJi;l1MfdH{ zFSt8~+yIbWrLq&o_8?exHw{=^-aROBj_1oORm-bV0?0>HC%D%dFy;u-+z7jfr=~d^ zje#A>uhhm@?^Vhbl-EEGsPYVL9Zqb$f#8tIF!~9^GBvPv?wq6CGcMGtM3B#JSk9p+ z;WU|2DG;U5gfgH9?&`^4aK;@Y9VfX9$EP{YmoNLk`+Be(P2S~$&*itim=hJ(KT0e% zUJE`7=XnHKslIkWDUUrB?e8;5Y{sn{nA z36a*j7mf0VpDJ2*N456t6z*qZt5Pk8GS|E8vXVaC{9&&xCH#vI7@OV;k4VdcG#7hr z2(Zd%Rhm4Nv9KHA0G$5_cLk4ZW~3{(EZ93m3{x|lVpEkqy6Sed^NThg!+TpXf_b4S z`Vhy2&M)(!tDEAdOOi>_UT@pB@?Xyjv>~SJ*6nHL+)utemA-@?FOZELct)#b?N1ogIc6D|G&Vz=7I^LZOr#cQQ=o{+r z-N>Ss$Umo|i?2c?%Evw8AN}%4B9FS@?@rfKyW368q?tII{^xc-=Guk>4E6h*d2qpd z<~~~+lXOH-6|sj#XjX}^T8#P=k)x~21!saC&&xSBRO?}N4ASh&8Z#p@;x;K@YTHmB|F!icbS5|JsWaUR&)G$w zquV{NUa-x3@>05*9r1ECe{0YX#%dmSYyyXyzI}uAnHq zcb)oEGz)HA&{}Oyr9QSCnwn6aUu?T+-;Hg6NKrmthUW;us`JY%RlS9c1JD29+`qk3 z|0tUsvw1O7Kgt3vwZKoQY!O>?5Ki^#+2pmYlETo<&`G0}j;y4N4x7pE8h+B#2eUqM zs1=+y?OIM^^8GGL>E+wu`b=$B;~Tr{LxV zqvYli-rw~u1_m%cqn7!Fwh5(}JfXEusGXtdZav3>cjKUzp!XTa;6@`i`WCX3j(=sj z|52KSU(A`V20AM{kQs#VvmL~81_j+lE2Fs2S;b2v9HVExSv~*hK6pH%R=#XBadGiM z#$X$mn+vT;*t#(A*jD}g*Hc_P=P)Fs($hvny1q`#o=Iv-8Fwu{30c?wWYfc(u2`CI z|99`nrs>JPySsOJEIq7t=4|^86JICj?bu6~-TCjIcw|5Uz~YEAALn*S?a4m2KBLY} z%TJ>XP?)eRmc|l<^Ilz=bjmMimy&s)u#-x5fmEOWNB19&_p*$XunWc5$85it{~QP3 zkqO?*_B-g8IL#x`&WQ{Uo0IVO+4g4OY=V4{a5ojoVbZhWXf3kWnc=Tpqu(Q?`Raef zL{{)L$pErub*O zPn+ia!GYO%VbG_n%qD2nilS2=w5SB*`4X4ca`E-g(cYXlmTk+rM}RZfL1@_YXX^g9 zZHcX^G^+8=npaNruvgLQ(E!;AfgH%sy$2#X1Dr03J|E;qkeWNZ3!;56`|*A@K{{KE zow}H!%+?%4OXU#(7IB(vsLw0(ef3&_%MPGFIDtUobMXF1yxnDP-$(4&5_h2JFouT8 z8hHOaC*e53reY!w7Ln)v{oK5l!-3bCv*?eW5DPfqIP#cQ4l`h@PPY^cJOaaSLeyMh zl#ExJk-gvSRgg6{#^O&)%)yy5tM%4*{5;d`yNqBcj<7-j$LcGnRn^b!nX3-hI6-`> zp;e|F_0l?D@2`XzWugw`Tt)zrrE-JGPTtK_O`EIuxR%lj;Px|J9va#e%_&hKBj4q; zLQxN@x_^R^QyBU2(=$o0MZQkGn{N34h}`K;oQq09LF0_izWf86yo;)Sl#>)FWfZTw zW$eBCqPYo<8@f=6;>hsZ~xJKeN;NIZ@)arm5(Aa9N)aW(Nb`vx_X9h3sNCD^=b9OB&kbY9y2 zjCIaR)Ie=)(92JY@~I@P@*u8K(FPO|-2O<^r1#J1=+u3hz|U&s^%wDV|Io`ItGM$= z>LW8CAFN+F)9UVt13uT`x5=24Rh+)=%m2W8EyjDhD3o3ceBR;7p@cVMK`nx(;X_kr91+ulo(R%m$J0$$S}pRH+8JQ2wQe zJDEU?#$uyu6@9;;SYa>Yr@ETdTp;!+fi$2gR&*xQte8+i?M21;O^*tmb6Gq~e#v}D zOe3eoTb)IWaOYC2a3!V*76Ux+=aS#ZgaN-{tyfzCIG&3jM*+%#4`SG^DlIMCiQYWO z4vQ$WzTIySmTO`A=syb^4YC2yz$bZwVo9m;!!_hQZ)d7XJDn`|9TSwoG)FzT{1D~Y zpaH0;`p#i(OtiAFr>XG6$@=i(!S!D=gOZU?C&Pk8ubnZ2QeLof{7O%B>eHz7TX}~n zkg8r{nU-5Yh~z03^n9;kg#HfjY^RNbZt;v47uK_3jO$l z(D*UKY&^_9bG688Nbbp^rWX~S=j*R;Je3ysK$-9LBO^H0Yuh1O+gW1TaxN;7eK=3; zi!yP~<0yT=Qe`wQQ9dR?wJ?mT@%E4?8sth{-FAACc9o4Stczs$(+R=VcE0bVelXV3*lLfZQW4sA zzAon%wAl#yXH^;>;H8X_MGRJM4t%!UtHDN|YEIeFajB(6XuuB}*Xmo(BdgVg%ly<5 zt@~y2@ydp+Bj^#1qhXQs10%-%2!~qrU&|2(YPvr}UuHIvuxAzmedh?K(Nj8Oj3ly* zSJyAZO~O4q7&WotPK=iW2-(*B%ACjh(r2{D-bE>g0>g&f=de|-6&!4`K$#*s(QVXp z4$c>g0Nd9t6B&ZNBoIi1Dn8|*;L>LQs=>dpME!uY9(XSXR*u3Y*)?xFO_*4e%*@FM zr;)%uh)${%#9tv;eixBqz*SH&*<6xT8SmfSo=ij<5PRV=Duz7UaD0hTRzp*+=6#B( z=`r^+wIa~kaR9|`tHXZ(2{$}k0UwLU;BY{EA| zxW{E#UC#PX-4!O#Cr}oxvfe(5@D`)G@lD+5|MLQDS!wTbhe!T;ESgo4^N>(ILG$MQ zbcT+WmN1Nz+QbX_j-*qj^e*=A*;MHNTR>)VxH@x+KxZH|Y zcQkz^Uo)Qb>9gb&`2i5D`vb{Ut7cjn-K7vuOOwS?XU(Lq2TIuVnH`fZEua7Xy6G_g zDYd*?n<$NG8o#fb1DYJoPJ4h$<0ifIRSel5pwa{+Z;;RrMo~)}qT~J zJwd=`_k{VqQL>Fkh2kqXcLNc`GCSaPspGrnlL-ZAwHuj!X4pYhqQvEW_6nS8D(efi5IL(*2;riIZHes45@7K>dgk2&wpO^4hnRtTQ~ z2=tZf{+;cUND1`}8K1t!BZRhBS~8h70&1;x_UDllvr!-$1<){N zItwQO5^M`t5=J<%#oiH%W`$F+do+?EnB0{YV50=|?o z@dTpA?K(*npWqW+3xHMszP!v&6nzaCsH1%LCi@tL*6jEnG@sX`MzF~B8NRzv1`vpDzd z53J12E4C6YSlGr5n6fN#^jTT`J;UYzVt{%9^pN~ZIr;R=3|*vrWRnYI>b~*@@;hPmXK=4~|7@#ZkeU28K%~loza!X~ z4<)o>nV3CqVi>2Aj0t~9WsO(!J+Na(9p#xJ<&uQKsrrAci7w!lMW?4cGM(1bP=JQb z``G2lpK?}jU&#cK^m4yyU9;NA`WswepIln%r5$HCv$q!=fxw~?n4XOw+IW<GSWX$*==hnVK(3Op|M^E5OP!9GvuW*;SJd zc*w2Mo)YmZkuzIGQj~GYZ;RI|O~N{NELd#P33(8YQ~3^G-Pnzp{zTIU!1^|OWBFS~ zkwI1DVXKEi@69rGr{FRRdYQ~wPch7yZ&?f-o}B;9qTA*w^yDSkq>fejVvT3J`a0M? zo`du4)qC!Jz`a;}yMI(xV^e$ZE!4Anm3Slva1oN7h_KSv__uxZn8<1qtt8v4eWj-d z`VyJA13Wb0;shjzdDCn588Beb3wwbiw2T(%-74MMj<=Qz9er_~>{ z*S+WGzHwXyCS7EU%Sx|>WQ87Xb^oy7V&ZYjsTgT(iD^;c_WKM$Ngjr3gA+*PdJXpS zxI$p6Df~K0*-P~zR6Y;s3}^B?9apG(R8Ql(PiCySJL>q>HuH_$=wx*?JSn58bY8dM zAl0)27Rog>0AZeY&qY=w z(oV%DOFzOh-WigrW>mlX$5y$jCnPBbIJtZuSk(#G^rES%;&G~UCTf+ueLnsA1i#xO z6redjy8rgJ-nOoEk=U$&Q&n&a*oiXn=s2bJGBGBT-I+_3ECaWaz&P8iqvrDZ%uT11 zw~jA#o-cvjGJ?faGv^Lz%Dr+{98Z&N?u)ciBK zZ~iT7;+B_2d?OuzpOX4^0W&e7d@Q^;IOHA=$BzFw9+Ua=IG4@Y5XgJJdj|xTe9;Mv z?5W;&C9%y@Wo!I6`e$9(_MtiHrtivjx#V1!_`k2X{^@$Mt>_bVK|MlUg8Gy3P*uXw zrGZ-cm~8y^&a|VE1;_icVFlqc`PxK0icF_c(Auk?pWcKejVf{MN~Uu>&LUaf_}X)e zOQoJYa!kPddBb<(iXqy%berj)t3PjETL342y6xZ8bzvVgRLQaZADjedfzvlh%NT_h z(K5bTzVd`;t=p8Dx}vp4--z!AJm((o$t%c>|M*PG8QN!g_Av1y7JN3KuHiNG8H zCcr00E^doc@GUN9R)+mQGtO8>*h&6LAr+NEXMl|>z+dvs;$7swzT1K&mvl;sD6-GV zC+2IK)}a#!>dLv<)W>IUFghK-bIw(H*$M2P+G@k8d?7SoYn31p^*NVE3WGGqa@jhU z-%)vGwZ~=cdTquAK6rEfrz~$H&(f1!r?e$(h9~-U3!Y8yLC;Adtg(mhNk35Yy8$qu zCh+YblyL@pg~8}qCY==P+Dwg-p5?^QLY;z*(BAWZ^y-6TwbL^ zS{b^31dQjGrkd$}f#vKiZ*Q&a=6>R4!4=H^2&^P>*P3YR)R3q7pQm6a8Miko4Vl=e zvTFjghl4j)XjxeF*z0`tFPuQoixC^@2$(cn0J*|1WXj@}&obv05T5e6jsra%mD%SE z;P9-qikfCWfb3d5}u)%3GZ=j8n9lt zKYXC4CsbfHmD%5^Vg?TfTE0C^>U3GtJDcM-sadKJ8u~{tBg{@0xi(C)G)y}3Z|VWH ze68BoETj2s=$x#QTshQRI`!?Ohoc##taBXKKz+C zkB_XVXGERqoju}nLV^4?6)B}znWup)5 zIwJ{UcH9$V<`0LPHN0K!qw7QO~4gGi;L3x}DE z@zt&{{ANQ$Q_pD?N%rmA~4M9!as7?Xb37NUT z_|y;Yez^urIpsr&B)0RpJf+1bc#t~Sna~b<`n9ZyH*RfCu}gxEe;m{7$0-Aafu2^* za?&Jigv5wf*Fh)mylceEH&g|f#|K2R1qmtxh@VL>@A!pEo@g*I+hUU}t-6N?9C|;n z3N-<#={(QNqn{sW6F;Hl6&E`m$=Vl3VUywRUt;zvVmkA()QiT~W>&e6qNl@4SV=&UP~YW^Q4^{7=AmFBm(5DJZm zZljt>2ghU68NUiPU${6lz)N0H)JR5tC*p8yJVpo6AdRo=FQ60ZoXvS_yavN!FL-t! zKWj~&cLID1klhmETJ7n0W!GyKIz>4WhSC1SN^Yec@50a6!4P=PJmdXv%f|2?%vLv) z{U7ojz4V-X$sL<4bc&Fng^gg86s2|L)sJTZVaeskp`fRJ?~lm-EKL?k$A1Z$$BbyK z+OCP2TN>{$kr4;_X4jTJe%(t5qNFsH|F=scsvnnB26T9bLd<-q-??l-CwE1HKKSGJyaT?U3W`?rv7!@VR;DzXtRHG|P*i|3rL_b+PM^ z@cK%dT-0ur(V*g)Z!mJGpm@5vze1dJCa&eL^g^~6UpZ*SdH zP8GVLnhXuv1qC)_zygjU5QXfV6aL+t*Yvo=@86fJ63~6Jp%ZeFaa)qFu6=J00(bWH zeQo>Uw{?RMO_|iQC-HaQRYMBlKhdQHA&Es{tDQex-snZ}y`qYGJv~MpY=fq_;cEFW z2&kw;!Zg>by!?Z5U)2pWNgWkY6iFZ#{C2hg+&DtY}=nb&z#X7pXVN1HHkj}X<(SoM8qhmeC$WjP~J2^k!fvNh~J?G3tB~e#kc%+c3P=o&E5Kf z*HW6{p9uiO^S+Yz`u>~>Y4NH~v^*f*q?w=Bex56FenBC^7l3VaK7}#A(juGBVm&>D zDR~AhoA?E%kuddA_~NM64J}>41m2RDV!Qn6K(LIH{+Pq<$T0QB1a^FJ`b-;WsSl0< zfUtJU*2_7|1!1{2MzPtZY%RLwr+CKR1xLR&&hPqjXF{&qSo{5;19YYGYZx3rXUi1j z1S}7~uk6==c<9%E@0x*;k3B=f6;Ef>NedJAx90dh%bMKtUWT^pMJgj-{n9uJ3VMgZvBCL~+Vlyr~tC6A@Bk&z) zF!eiuNW*Tlm>j~=@J*X`W@#}!TSzz)igSgUG@@NjGTtoQx*KhCKVD48v)NNQ!_N;| z;DR`LY|fP!x)vC)GV#J#$cYjmK$`m#8i{Dwf+T@K`~ee6Y8Tl{P3T7A>ytS`s_YOT zjoSNYLQHV5L_j*rUOSX+*shk{bxVIBstf!GK0Z6Y2fT+ zzJ33oy{O#=SmA2GigVPKk@hx>Fg7+sT;QjG!Jueyw+X$9t`)Y(iSklT6(o_zYan{54K^mJBiHqUWm}Zl;7?3f`?+0(h6i!lNi(iI3swGjqrUU0-(8*VIhe}a+B*KVaHyq(-h-vetys%8>uncMF zY+-bKumjv23kQ4>pIG(})YQ@yVhe{?OA@*auQeOxGAPB#sUnhG9Yp1TCjlvw(O+ql zyI)b#EgShdtov!Y5r~$JJ=0oc^erIkLQ<5ApT6|$!3n-!+j8}EKeM1dz&LYn`r3Nh z|GWnc_>^3L9si6tO?*t1{1pGM<y2KP^GHz9+%x+|ZadaCb!pd=QGFvf4-LhyolXv1S=|I%B0 zXx}i!1}8iYmoOdU%S{OWYZK45keYxY%Q!28`(!jq*Q%nTnp}zF)KWu>QB@%l_Mq|M zJ|=@s9M7b{KxFdc^d(xv_aQ7nw3ncJ)ey6JEd56gQ5s zdXz%2K|?K?=I|;(O{NEZ#mKw)uDP9$3Y4k}2eY8r{>{uzpk%!GHaknUm7)aFVQBT( zMJck|sK=2ww0*slWzX$~fG6&=_z8t2oja~RQ96IYSzrCmbjZ_xNDCdkW&vKz2+$0ee zhaG0=kp8ECMkXr*4_Zm_4l-4wPpDcV_&G~HDE8g24&1+po=vs=;fZlp9eHu4aD`>^ zj&J3Xbv)IMJkC|~iD25bq}(-YFsK|1X2HyLUz2xA-!3CbC3iX_i7$o7z+b;)%az%g z#A4TPNDWC&M1V=1Xp^=*)a|LV|awpOe*DvPf zr~f4751}vR8-Bk=UAQHjv@VRq%yDqXEXv_h#z9+)KRcLmb1(Jc2@x|MIXJc%-(=RJ z6)x2)*LElRhU{dz=7a27Z31ysMwLnPJ4T0CA(lea)`;7)S({y3=-raJ`)hDt8aaNP19y{EXLSj|>fR=MY-`_FhgG1D(~z$&>#z zCWr?UK_dnqhVW(L{MDxWznoFb4((+FFF&DG!Cr&bn}0RLE>5bYD+=vP+Z~$pHzN6h zl_Gy91`)3n_gJ^qZ8||1CnKW~#iH%!sOm%NF(o3wBu$;<3mgV4D<{{r-CC%6X_xwa z%O7sHi#2?gH_~aWR7X&9e*BS|Q54yl42Uqze1GWbiiE7db-?b(xGZ(KeRG=3M5|h0 zRCFy1QD7zBMq$Wl9$|%$cGx+LqfdWjCEJr7aJDBay;7XlKSTz)}m{iRp z$49BjoOtjMdEOC!w^9*HdnxD{wl%%YWO6hg^J^7do5-5H{S+1^wQl3J$#Ib2kNo_- z44Riq$yr{hCw{=I^5oOx!A`N$Vs?_$FRq z^eAVGt1`|;V3htnJt~Lj7xE7XyUjfC@p2f(0`Z_CXprDB?Z!xz??$3tGk?z+MHI%F zd#4ad9vdlr8Z|C@kGo3sTG^oc*rQg(rC`;q8^_p&S(QHm{O2aIZpLSM?(~-J)QedS zZJKJr$BE3bYaD`>dFB6|8CUu6f@!LGD1U|EgF*{oC)mp@YJ#6^h;jI{bf0*i&==t@ zQ(wtmCad~%vHKSDr|bmuv{xm+QKVbCRd@rQ4^O|tF-;jkRPgi=G;jpU|5ga^Ad(EM0(Zz@sobry5bRWlhU5d2$uPd|!If4Wx>Ax5TOJ+iz^{)p&i+pQ z{M+4b8s~;Ad(ha&1?j^AIpQj-I~m2L1qfbc>*|&wns{4|SASFYzP<9yFAdx2+=JEB zFjIpW!!F$mR#w)mkL%f84p@F$GEN)n!{=2F77?lqXuIUda?YS2m8^U+1?6N^H8>vh z7MpRxk%R+_gtM?YgJ-_X7=1}yrYqa1saDSE!>ZhJjbwdP zQe|LONWy6#P)uxADxpps!oGjqgp;VBwObmh;}eU0TWTdec!tyW^NC_(qpxB*LQN84 zV*qlyFjvH+JViCtH!8;R>^Bymp`j8(T7)@{SFkmOf%qhqsB@K5yEkjKFYy-aq0T?7 z#tVkJpvdbLoJ*5@U$SKIoc0-9w{uZ1zHNGp=f<72O{-HLQKHG!Hg!)zP2oyd=-aoQ zlb@czq%mm*U*^)fxqWI&3m2LCAL!)NO(;E%tj0vSg2-Rfv;NHGPumCrqxysFnK1@B z>C%{}z-v8MZ|KMOSlj(e1rt$mPG{Op+c_*ww80&>Y&?3XUAeCatBD^qVf#Bc=xQ6uk$E#C3Nx1eV zlI4Bw!~Jm=X6@>q&GDG@=Vdy}rX6x;w3P%NZi5%A5_xrT^IJMWSiLq5+-t1+@^C)H z2uPcluqZfS+-5aQ5*lHBW#J?)l1(NfOAdf==X|HMCgwxn;ZRN@fW@8tN+TJIp{B{0 zQ|2c^P*l|1T%|jOV;K2f;tM(6cwiPr#ZA71x~0i-S|iUWc0sX0Kpp&4L<=G7AG`BD>O5{&ZfL1tqz2v1mT*5vIJ}$|i=cpk3reJ&1`19~ACN zeh%h0feSL$Bppe?t*fHwXCtF3RTE?>t%?ba`I~+_$mx&heNK9*6@-uAD=ct%pu9Ox z!bdw2;%+g;v0HrMIewDVK^SdqCerOaXM#o?%_z&-d*V7iVM@@l=qWGrXHw#E8}(W- z6R(a<{_OVvB+4az_>@_7(2Nu_Q9(=1fmJld-g>hko#@>xrT_JxF_M_=SNp_-4E?xt zFtF4J$~W~4odE@@fdiVz&rT#iG+d3I>U7TI^bn|8ITansgn7{-^mSX8gz(yKr&PE< zm9pEc6@dIGKvI@KJse(h{?BXB%!DfX3oXB7vAFRC zelWUk$y@XLp(uJXDYrM=H||j_AFWGN^0~ubLa9vEi$>eb6Jj9U5_|fs%ait)>>nyB zl7&M{<6Y$~wf4TW&p*VaCzu z>^;W-r_1)Px|6Oszrx@x=ub^;JX?5Cw6%Qtg^3(giYiJQ3nD71L-)iVJT&)4zPhr! ztbdd~`6J+@cOrz<=UD1uKm-WKSU{@6(-@coU-JdHdi#=~(&we2P1elam+5Tf#N zpv>xnAwgs!&}-MI)FN_C#2L?GAxQxGC+Y=>Mae5MeeU~aS$7Up&m<@4|a~!3q?*3u7+k&kPWIHWh zx5o~nGklSGO4tL<%bhSZS2|ZUm>I__R8il_ezIi2QsT_Pn(Q{e0@@#DILo4m`SPy? zPs#9vP+q^FnfBVnCM?DlwCJDl9#$tm1}VoYD=Ks@JPEt^4V6E_OxY{~Z)Png!^u^P zLYnu~+$|}PfG;CS=LZsR%?5DsA-_&OtMKh~#5(2t5E69{J0XuNaEe@Cd5?;wGzoJ# zp^2mt^_7}D024Vg<44D&HWIj`ft5Hom<6SK`AdsaOdu8$Ge3{@R5BLAjeatWb7hO` zbL!!s{2tI|nC>i^P$4S>E>!2};? zzSjc^XG>D8dBIPJFK%j>OZ+Ee{F5k~1(BtHHM^T4CeKww{Jdceuhe8wlD2~7JpSUV zdm_YfDW)KY*$Fbq*fLePP=LPcDR?C--pdO`xu?bTjBn#0z}7X^E&!Aa2{tYH})XP3w$+2f!81M<};EnsvZwk zgq_wponTjykrXuagmAQ{PA7=N3F;}Q_%ZwK#1hH~mq4lA?&OR4F1OQ2!ZnSM@2g=T z=zD_!1quo@cse#CQ4Y|Gk_!-HU5Uve!w|csUtj4r3m%^eGE>@1D})B-Z=&bp_QyuM z$dvgCo-9dHoo-(B{6Xc=UnV_}0i}c4$7N0Wll4F*U4wxHm~NZ@5Q?*eO9d?#U?!0j z#AySy%rXbdlUYHAADGowmxXp}(+LbQZSXJ~PJYAi-L1Spn#Oz$h&J}^(Sj|n-l7t; z*k;o@+qq1}V{^@y_U&r1kk&pvDy_ydV_=r+tP!aculzif%w5p7MlNf^V*!b0D8oa_`S^TT^X$WHlozA_&>h!NhRw=3WQMId2* zFkpm0246rC;DZhWJ8jd`8mM(Ai8CIhsFu>1js@hdmaopX)Y{9g(8JsCexY8!Lu=uZ zh!Fa$v|k~(UZM%6@Tma;ZLd^AZ0ZbnN?c~Cq(-tS;^0z7H5q@pa2F7=R_n_6`0~U6 zGWb4KfoyLlmAH8-qK{cg=v5{=g>H$sP3t~hhZ7xX7O>Y=i5(}5{$FFIu(rbo={7k^ zL{J>|b#MagMbOt#Vpn7k*f@kmxbN)=Nm2IGJpqdd+X0EbW+1)^_jWEjdjtG19+M(2 z46Vq(U)}lQmJlnYLduThm4}>{C?&SdGaC*FE*b0qFHL6S#nr5lHHS~|Tg*THh}J;G z>@F`uGv4WjSXp-#Nc`EvFT4al<2$?29Yh36pLKQThO5-iGWb7BtweKZ!4x73KV*e9 zt0t^Ui<9tL_5pm8iegXSYkDVo@~ST^N*bXocGw*EL0}iSO+x@yRpVd3>8mr2R zK|S3f2`{d2$r(G| z1g33pSK6nmab{n|9pOD92#fRaXb7$lMqn`o?~Y*Mus=&ST4o9i@`g6t1Rf<{$8=L} z@Y2{~vdB+aVxcAu`*(;`yWi2-#Ha2Td6-V+ctrHicSkCnmWtR|?j~;lL5h(+!Xeim z6uN)0ww8E>N4jmqLQwNJyB*+T(UH@QJfrbqM$~|g^J$(#x3)j<$h|6wTnQ)hZ|kfG z|C(U?D1LzxsC=X=mvha^dn}nso$H%)$WpU$v$o+UlN|*RC@#~=b-$&wL;4tigy$b) z!y=^M=6f+FnI%CxyhWW%x&tKc^3Ft3a^(V)GSwg?oNzS;7gp3^^}kjnpFf;@)t#p? z98MC~3dbYZ;fvyOu3D3^o^lTN*uCf_Jq)AgiM6K2`)z1fy#(&{T>N`U{~OKJVt2Yl zqal#`<}*zPY?VrFsMIUz`pOo+CvtRAE0fb|zQ}k!t`ysgA$9)9x}I9`^c%?QtpYVw zGTO%?Bs#(GFV((c$6%{1ggO%WQ6uw8gN+CP&_D4Vp$FSV7W_B4A=f3tQw$xuFj%&qW*UlW+cZBXuu_Ao=s0`AFnGE47%OEIhRh)Qj^#QAvxccLHr*sDZDrDG$JC! zbl0Q)M!yj~O&RryQU`ZwhSx)ph2`bth2pX9?pM@B)&&UH7Wb7dHIwkGNj<$tNAHiZ zsX1VOb&e|1-$g|jPv_$%2S`P^CMvC;$l}9B5(9C^LKISuD3RqmFLqaMdig2ws7|jm z-r$bxm>{|2Hp(D8CC#|u6bD_r9tp#iG8GBAhM2%r!N9Z4GTKKNjv=YKx?-}X8en1w zTj{vGdJh@J+Y=O^*%1JFYPlIrUb~;QTFh*Ue@hU@BV0gm1KL;-w_EbuIVC8S;(DjH zvlBHob-YGX7EuFuz_AFTPD>3-ta1Um@uwLWqM#uBGdo#YXU0{88<+1w9J=*R#1GU1 z9{Lo+oTZiJrES%c>i4|FEzbmV;^sy1#L6_i40F~3eQy0-u8f(`0hrgu7J__pr@;}Y z}5hgwnjWmTVd#ZnuRd&D09~BqNS7gdl5z*;F zIy4Ean25kx)7Wa?Wl=-1vDaR@z8r8-`Xw_&N-#j?X?~*Zievq208|Qjm6_Y9j2tT~ zn|QU+Yc><7#hQn`9wW#PbltRM5B>u^P+??I>Pb{wjM_?9D=Z<418R1LxnWE%J*$a~StnpKU zm&Gf5NaysFgP4?;VI(5u3SC&(m5vC;@CBEyjkZi9*Aus|#8%v)>TcfIvT4^j=9g zN#{qezfG<1q9N!>^`C+iWPZoT#Q^;^(WZD}B4#LlaSfjf7I$&R~47-K3O~mjbgzqQ~Y|5UjC_yMah}s%QZ<5wL{#^X(?OFVGs8pIxefl*Z){@bv zmW@Pra$AaB^ZSdl!eD*F75_p%l$dCaQ@eRUdtmBc4txe5|3(Bclk-pQ1XF48WXPNt zm4gDVFs6zACeMh7env$+xh%`f%yu^??>yl(_6|AfqX$F_sk-X8YdtAYBYkf9LzkR0 z$JllgyZ%|q2w{{#^2XEI$V1lRNZTX@M(>P48eE9j!lN8Qn1u(n64sgx8)O@qv z9mQs<7dKiMMdq{y%^p@@951nX5Yz|DO0+gP^D}2?V02Bu8jbm~=7)rD1AL}RO<#h3 z4->Rp{TZkYn;0NrW3UJWY@H@Fp3bTDUzihKH5FWgj8jwsK&G_msVO%6Fgae(Z_P>KIg{=L zHf65L$}JR1S_^h8M$Qt04z0t+4pnBHWlPjBZcA*Ugz-gf2Ddj?n;O+wByq^sluBNl z*P05f3|95~A#<@~>RmSzl(yqLTS_R)whml&=+rzZU-5vGA4qhmBDyHa@yu%W;yt{& z2VfPg_hG_I!x>-858~oRp<5UoU*_GlP(ucMMWeMDX&iUs^@>AU{NoLV!;AK1ZqLcK*fM;H) zXoKa=V{7p|PjE=Zj7KAmSS(wYaLnA>_lSqr330BpQAR^;(6pWOzD-&PJB5 zJ|FrjB7}XI-P}KvETVrwX#&rEzRpquVQ`BHW1Jh%)|~--U&lrn&GdkXdR~DEovV5u&R+>AlJZPTRHN|9k-6`9l$+*blEDiLBOC@-SSWVzV8Uh~admHXQP*%}46o-bA9f*jDw<~al zZ@ugoxw)q=pH}E#UWYTWWI*-@zY1Eqs7DajXHIPPrnb60Q{0c-%M$ZDANGY*pcxxv zJIu+R1yIJz7rF$6{$QC;2mfv%1Vq*h4O>-3)lDWD#pRj}nBms)+PqUJ14szXC!Jta zbbE;D84Y_oMnL?PFDPo7#qZR5QIYGePd5nvInE&vS_kTKLfy;3aVZpRw?QR!$xAVE zjSQ~AdvnA>ML4a%FwJ+?4K#&JAOivgLJ7plcXU9W7l{D^TE-7j#2*%vRu36LzUfzV zNEKzJ*Pjpo2)Ft^L2rb_{YD2Nhkk&5`Jd@$Vy1ZsbY3Ni#2gObCXIa#p#MSr40rDn z;LisfW!)Y4VS`VJ zzQUpAq0#;)!9cVc3ZQC?6RAWJ6PdvKE`18U$8rINKiE{%d?Lh;Rb`BBdn~5%4xDPE zUWdI@1?}J7UVS^5OeH#Nw!r%(xF%#C^PBV>Q`g*$HDXvKa6oZ!`$VK6S@2K0Vzc^7 zVF?k|wpDi|_W(3C-O8E`wd0q%_DNYR2A4Z7^xsEFz^4^|Yvr#!4I`3^CgLfe_bj7$vH&KLl#nUTyfY$`Bex+sS#vBPgNd$PV;!5XR zj`2jfdV>51R|T9Z=(Yg0CIbLXN_rn`kgu_N(-sI~&h#pek#dIl=r&--DqY^EAe6 z%+f8zE7w_8trfc#PJ?yGI5~KT4z(n)1PZ$#EGDEdl4wEW-CFWQR{uj4Cwo!aF+4*} z)D0CddJmRCb4F+L#2W}uALiv|sI2@D(ZcE`t9HpBpNlcKHcxTGQzYvzIkqiE@2M93 z`?JOo<U9u><7A_R4hqhU^g=nfehc=fLTTJ2-N%f=koXIF}e-G0`-ds||WG%degr4)fkV5cgK53g1ly-}M>;4^jBW5)9# zxhv0{8sB2om(K!~Juonk17}#WjtP3mq~3s*9Dq_P&A za5kbabFO@zh)WH3^W#THHq|JX{eJz$SMeptNgSzKIhBb8x7&8g(P7)5U<|oeFFX#L zA&u!Zh331s^UYfk^>+GyR%U9@z~vLm`bbs_0dr*BGBXrNUZGAwS+J$T(`CstI?Q>4 zt`UTkU8?+t)0m=yMnYSQ79BJjLv#>X9iGc!8^o!f7OAev!>I(IRzCiBT>7g0Yfu zec9_kROld@fkKhKy0V=#wpcXu)A#)acGg8M zoCy^q*OcjaIG4Es7GgzgRz3AH>*`gv#WEXSOL&DQcWpUD&@BY)JCH1u{CY;LPw>=Y zb-@aIS{%esLg9%2$~<1XqcnOKC^;WwCh?8lP~vWidmD)4-o?Gz0af5HiC4{$kcAnS zGDra7O&^ScO?j=3~9`b{sRH zGlWNm!bJ0wPiUbB5)X~sdS;q~!=>GumXgg9Y2v8bQxUh943eSd zNbwN8rBBtUPPXVn<+9VlG1g{EC@@P>n9U6i8w2YC!B4>bp%okiJkSZnqK|fx^*;)o zy5g!MYUh8d-P6WpUMHR&60PA2F}RB&TY&b7iA7MvslIlB?Gc{ORlXknX$l(Q!v+<<~@A*GJmVZjGBeF005y4J5SH9S_RrE^jY0X6MEN zWu%j$(+4@PTl;AWdkJPgM;$So_SR>Uv@FZKmBK8BW zi`+BaP{Jq|EYIXwS(**Ypm?eCRxzVjA>}B%y+)p}90yc^nE&%9=Db;^3C;LJ8l|vQ zkVdN8m{V`XR?71^!-LJsbTN27*Up#M`Ig8}HrzLNq9T0bL8Foj+A=2bGFu33+j>+I zQ(*bXi###4_pH{wRMMLrQI{!{@S48b+QXX2=E}zU{DKq)nx?l>7?*RVoWnG!lJ!&^ zzd1y5L5%#aMO~I(%EK%mbULCpK} z3ZKyk@cUdE!>_=^PE>liVOyDs&BU?uL0^XpymS(PeYIQZjzs<`~&-J%#CDk$;xJpQg{Q z$=4Wsut?rzFsZ`k`D;k)e0xj|ge zzf~9J^2{Nonz^#feXj3O3?s?y_5D=r;DogkS*RJERd3IZ5f%WK<|2v!X=})Hb?8|0 zt!mR!7)z~g;Yw?gjiy+Wa_voP+##z7#q0Usq1})&u|osYot4CJ65XfYN|w}wp*pcr zKMz*THc8Szd40AqmvLCqn6}ems5w7UHLQGpwaFYgo>1}o9TM0KOu4aCRyx~#W-+yg zyYwTXO=G5CcY|y!x{J&{MF?>J%6YDo_)wn@Nj1Vi2W+Buqwn#-RCjzYcE29;9l%+Z zD6?e|_@DI0nB%R8+Z%8GeiW-hYV%3Ap^rlnVaELdBdsi@>=3A8*#D>Z z`3~El=gehZbf96+zeN#3|AtM60}V+C!>4!62#SAg7jS)*C{sLy zc4z`?n*ac@E$T7r-d_f1^Dh#pw3gTy)AXK5O@W17^uY7f0)D=-5>nr@4>`}MWIxxs zUs5DkY*4)o3pd45VIqSE?%Un9v!>@%mq~pQIh-lV3W`2kCtg>VKBg@io(UCEd`EUS zYdFmTP=}m3M|up3@BXD2O~9n6b$Uc1HTd|Wb$UvQRR>-b$g&M1{mBmxNpa!fOWlwX zgt1Qi%QXb;@deW0lQzYfLS-STyneVx{({fA13NDgL95GVJMa7f*$83>aU~=T)J}{% zz|nB{s%|peA!-o5@5p&fcnb1bCN0^$o0o%2Z2EO@tvk?_*3>9nFt)_Oqhv%i$gq~3qmZ-QsawLJYL%MIf@r#)8BS+WdJEml3IHCJXGu?~^N%`+ z3Rowl5r4M;Fn_Ef^YEiCZ3~^Z|MLPM2Z(VGh7eSctAUM6M;2;uUZKf354;5^!qej; zZ##ZcytCU;-pi`!7Xz};mG{wXKI;Vwh}ZpDaVG&Cx7KU!foR=Q62wS@n-DY!-62?p z@^}4R%k)K`)y1pTDp7SuFDzQ)pj7QT1!GMyQV<$$9gDQH#y3S4tLroADKqYJGL@2V zTE69sfSr*{_{(o}=9O`aZL)B%dXYq8cOlrcK!#LMGe~H1wu^ft-*EKo1H2IxF$0*3 zsU9-tkQHD^&7beA07C`ZCtS`axBcmsT?X!yVycvrw!8clS zUvH@UHKzwqiR(VugI zWFpy=@z@WiOLBt5MZsx!v)LR7=d9d0LFlXTY^eh(45ughM}jGY;TB36(@dYm^S<}juFYr7Ijy^ee$K$Ylqj< zxOu6b%z`_UhMHjYW4!g54g8M$hW!H}`v;Xk?NkZ^544LQDpnSpgiN>fc=UlYqKbqD z&6HVI5fxMs^cBSCgQ^jDU^5Qmvm{UxKwUO2lt&#+G6absLsrXThMgT5$_74i!i|;P z0`@vOY}K$giwb?{TrNxYT3pG&BIY3Ax!SiAn{vHo0c=nMB>bf;Nbm@w2J~OG5o!BG z-+cD#9@6~Z^W+_fHdM&!FYmXT3%-samhFC4XUq5gz!sWmA@VvI6#sT#|4#RBJFu0 z7HhHN8$!BY8*75Y*7DDgIawx^7(b2ovfruzE%>TI# z`EgUW&kwqjngv-M)->$&F}c_^^wX$2Te9pV`h3%n`m8Kc`q@YbNq1GSb*tgT074E% z!IL=DLO<(`=5p2)^&AcuLGa#0{%t)y2-tU&>Z(#V4-7UOCBS%eqK3us$ z&)=2S4sbF)zO~cEHoo4S95{>dSAHs`Ua)AH?xnTM!4_z0mi9hGe)cUFInY|UG?{A)O9jhoisMKS5n!=aXfn47Ej{|J$xd&|)a>bAu-H2( zf7p$)1awF1#OX1u9YPt{5daS%F6>5j9vL`c&7}zhLc`niJ2qJAyr{VD$z|xuUs>!z%zNwLzNI^>k%(Oxq)mlufw8rT)`!E zqU3+ZJ`X)mItrz8@w=;XPM+S=q<#c4MVyfL=)e-bwwnx7 z^B`9TGyr2?GyG35oqtGf2*bvlLIX;B7lOEV$zgJI`lj2*77Au=85sYws`-Mb2Q%oF~5RcygNiZZ3Z%sMUG!Ik& zH*%j^XsLB9^zz^pFw^9fQAFE9OggQQ{jXPG^6Z1c=Z9VR>umr>w22a=O8*T~VFb#~ zduEXp<;=egZS&_!V%C|?(|cmohULUSH?doXw;(_D)e+Fard3E^K0T1r!Hn@XXJFCl zr>@uxj*NEhsU_pBdgU5OMgwWNp!&D3_7CT1u^F(x37xKYXzz#!lcB-sP=E@AQC{Ia zzjmKypNI!sreV$OtkwI~R8wub>HzeA*kLpF`wcghJ?68%`nV#l&Bq^~?=k?G>hqoX zAx-YN)__4TfCpO`e(knb#R>W0>U?^S`#S4O7-0dza-jqcgZm1dV3{?>Y*?{V+#8&k zHwWw70k@yX4xFy3+p1$XsHsu|_q&E7YQf$-W{5csh?&_WA;}MbvQhDPD}BO1;9!vw z#2)kWkcX(goS9@yeSp_TC~8MH4$c8tFIh=QYLj~aurFt@ILOx@z^;Smrp3q`X`2fZ>UI3p~%sk z1LgU2yGc)s59(bl;DOkzBWYsBxCB5KRryql!;FFzYweP>6C-f=0Vpwmo{ksUMe zDLFAAfdd_-(j&=@sQKOQ*J=86`i`tl*INUl_Pe7 zl=8@PwUNqvzog`gs0KVwo|cJP-GYyyquV_S1wH-!p&b6VSuTTL$Eb0an(l)aWZjdy zy`1>QEZ@wF=Govf-qPDv5b%Z69w-ZG{C2>gx2bPVp?57-uX&j6jm1$3xj)J!pa3!8 z>u4fWmm)=2i0kH|(1v22s5Ijxcn6WR5PN0dm|qPQF=0K+9DZvbHw_TFw~a;X=u17SNv!mhU4S*_x$)LgQU_u7}TQ8 z?U7f`@QSfFJQy$}@U&dA=q<|nC_{-}Fc^sjAD95k_UvY#;nw2YMeQn)fPwO;+h7~4?5M;z%m3jP*k+8j2m4%CMZX{dIm-E=?CTc#0kOamr)D^Svd@> zLG@Gfz64=OEQD%|0`zsKLW9+3nN~0E@$pgPXEmKv*B>H<;pj%*7)z9O9NPb*>8qon z>b}2+p&4>W>6k&fyQCZGMp|;{P{5$Oq$E@tX~~gLB$Wn1VF(2j0qGDB0e#Or-{1Q` zYq8F~bI;!UQ=1ZJ4D7=81+vm4fI~kAo#xkT9+V)FNo3rm^-~*Pr6(KF8v_Sx$IS7b zrgcc+*B|-Vct9sLUnQlE+MT*$1Rt|V&b)nVm5~0%6A{fM8SgUqtB;DoYqRP4-6?wX@{SF!bT%vX3f{e|em#4wN~_nl2CLcL6f?aJ zsq-dkpoNtSx{h&UI9yvP@bev(I_2+g{A^!7V616;j6y($DQu@BK?jM{vMoe%q8Y)w z5J%Y-iaG&KEdI@AiceZrTX$^-rRujdR~ZQYTUCH>BX$wwYgmsJEeHh^!Z<)c;O zq+l%sXPB%z89qWxiEQ&NljLjV3v7e8^hMD{_5(x^L%;2!l35DdX(cl&j!`gr;<%Ia zT}A<){o_j!QC7<`fW_;jGD_+m_x%r^Ffr+;m$uZe9+af$Q48F&vcokGcrKm<6s5L| z@wcWQk}t0Tyu1&P(K6qg1HM_|geCugtis#096`tC>*3#MkR*a+(^LNmoM$_>;_vEu`$8omdUXFZ17jDR z1#bV(Q1L$SR!7VcV~0M|YC8OHP<>e$^n&4#CEEK#)urfCY0+_#)jv`S+Hbfej*9NW z4w_fc4xFDi{?8xa#|J|3@lXLWYB9|Jo!$8OEg|{e8#hPAtZ|Cm zeqYpTxXEr8L{vLo_3kMF(ITli-a6D7z2-Sj+j8yoF?w}O_?OpKb?BOf|<%o~T5hPF*X6&#S&J!pqAAK{aJ^ygm3sa&?Pss?>|joC-Z8X%y-wR^K`5%G zVH33Z8Shqvf4a{1%!kBj^5J9vog#PBK|SUzNDHMuv+nj)#6!99T2Q=|tFelQ;ZIlp zc^dtava!?9Vj3N>xl@o=-j7a#6C^Kqee?<-T2w^?W~t~xI2ILJ8lk>rPxO%+(&?n= z8XgfI@LPG^$R7>(bDilo+)+Vqa}|MeCn}|5>e3v|zvuq^IaZ$)kAK6-@n)jm)6Ne# z1ZI#(27RYT3K3w?`ywje*fMAgYBNwPa0#?IV1ZTbCQhBR8Ah1z3wHmP&%*`J<9dsD{AWiO6`N1v6F1Dr7tH}p74T`p&wAT$hI z%w6X6fUB;$oy1pa&5uKS{LJv~cY6xaCBe43 z%iveP(h#nf$J?|BK>^isZP583$rZ~9WhkK#-?!57mDijb;*=EFS$J1vo85|lT^L2R zl*>=)w56&Ngfj`y4M8Iu+`vA`_g8@4dx*_Q zv=knVPnpW};oe~@!(+GCaK#4|Lo<|D&SEx6avvs&Re+duV!-$ zUln$CaVx}mm_ns&zj;$;J?_K7qcR;csHRHzDj%Kp@-EPe$2A7tfTBysO(@>%RpFy( zV#Cg-*BnP?RtOB0E)aOA7s^p3ufIOv`u(HKfq&(kdVO9c61kh#U89!Ib4A_;7aaeF)I$m%q+3@^-d=S6|LzFc5jF5I)VHc~ zOQFre?C(NRc(1)XJLwi3SpOa3!qg5awxe;DRjnlaT81btTa7RjWhLRGpHeR-qi`?9 ztKjkYsP!InxUv$P3|2X>%hS0$e62*%l+}TY`A&c06^#{(KTyI$y%y8NuldJIx>iyE>Rh@f@)XyayaYrVuiEsgG4tP@ry_>?SRZ%o8sLG$jJ?4&NxMYhx41@cLx_ zGFDHS^d!Eez=E@m$$gQ@t;oH&sPm>dwKj5sUhYrr+gMX1YU$61@fZF53ZKgw&pXc9 zBXO|j-$v}4b>DlJlNKec| z;pw*o%63FwP+kudjKPgap2}HZ6w(NBIDfS(d5tuiNKnljK1kmRcS*wN>aGpCWdXA9 z`a+a0U*7On^?p!^xy(`+2+f_^OCJ=+gDy(F_r^?h33Et|>wU)SWKVN;kR$i)71q^T zIBzAR`X|tsC>d$XSHw2ebBlw^fDKxjuX9t%!uRBuR>39e4v&(iHwA2(^;(J6G8WCj z0dD)UGAk2N6&>$DBs7#AhpByF76L^d6jVyNO%+`k1+Lm$V7}kb5<=w8k`dFlHfWBd zO*Q5Fv;~r*G-2;a4MtV1@D>pWcc+r#);{w(Qd z#=`{e^px;3#Q@;Sk(nzrT1#fnXVu{U7|HM4nuDh;=wY14)@AtUtOOG$xc{4zA4mW8 z1&>g!s3%+ksU&tx;MRchCbD}_w(I|P@s73 ztkW$QK#h_;L_#`CpLMKRNqRC$k!@8Gzy~S(Ta?uk?J(rbSK^Z?NS^98Kzp(<6N)q(Rfsv zCvL*od?g z(&Q-^e^wP5z~~75{#=I7-Sg8t_hvM&p(`PrZ=PB+a65@GRV)Nc>2X${*%3E#c)QOn9y0^$^BM6ZlW>H>b<^O2z=Yh^JF`wRj z<#7%Q#O-hUbyLqXgcgb|%>3WPa>RxBysh3F5dx^>4`U|ctwxQ?0R%Kzk zC&oKTO`Pb5BC?0LZPfV2M#5CrMlFn(wR<6TAsWIImCIh@-jZGOIgx3D-gDuJ;fxfm35QR9F z$gcEI`Cc547dP)Q;ZXA79t!SWynyy8v#E?#D$zg3__9fk?rWPsWYMKazeiY%Z}F%P zpI++h1(mnk4b`<*qBpUq_Dg{IU%n0Yf{39O^dzXrdVNI&X``ZL|O_%daY>6p25sPrXI%0En0m=lz7ef87NRu802JV^J66y>!N^{;uh{{wtPIFfdoe!uwI%Juacp+VE;P63xVCHFGm;HsjHKt*X1?A{5BfSYMPl zavuS?PXGkAp-jEB9)es}17`gJ)R3P1>_KT|w!nNiWqXVwzmot>P9*b#Xp6G2(lYBs z7|j3fY^r1{a-YWu=Ki0bp$+GK8Vl358h3A!V0%tZ%RFUO9PX}roQOS9*= z)avV!b~%6YwZ#b1LGMR^z-~$!j!UB}s`iqgFel5F&m{2S4VBHWWDTz$JyXq;r|Wcm za$k^GMYwjn9J1az&5y0a<0e^50vGJ4jV@HozXdz zhgyzAV@;%PfqltEpWk#}zwU(9k^= ztx`{Avod88yL3J<}Ka5t-_clcx@ki1{O6 zZ(9GA3|dRfh92wmA zC?2mc++!ltI$@@s!|qtfu@&5n`e2&QgF3@1G3Iu$>I3ZRHu|li8ULVYE02NU3vGDT(GTLOe;)2(6%n$=!Skx zBRSRz-kX?(%kpYhwA^cX)_oGcI3!fAfT64xE(^(O{YqVD;Re0UQQ{To~LOp#2!Yy70FaDXT9mgg@KT#o|OFVc2eJbTV^T=r3guu82l zWwS<{p&&OVNwE!1Mu^;X31naE@2Zj{Vd{e@c_~H>JV_`F3qlI}1=aT^{x}{8*uh;f zH8J6nWn`veVm?t-4RE9eq?>Xo|6QV2ET*b|MVX@>gl~s&j<4llYrIn>o><6GoA90cvPg{>vt{%3_ti$K z|F9$ulaJivxA%3L+z(!?_Wpe>P7+Fl=~qdD1THVW@pL)tBRp`oX_|Ss$%yz>hq z^(bf8sk)M&#l;kp_TNe)OxhA1ZWG(7r%EEQ&Sv6#Vj#D;arIRZAj{-fKHAmDgO_B6 z)E+*WJI8BrQSt47&?XeQ_3HTPO7+N@r|5Yxh5YfpTl!C*(TOQ-OGOV{0A(1@SsJY~9IPV*IJU&~2zS(z%k?}?L) zX;hD6Vu-m<=!*2mt4#{#GA zW&f4EE@`GnBA#kvqNt9-=?t4ac{;04yuTm;0mg|#dU{)@K7lP<1~dEX zHYQ^fO>dAbvlS2DKh^oFJ`ZgV#s?Oi=80?sFGO2r*PEr0^Q=TQ8kk*w|2e5wb%r_t zcon0(=;&}lxe^<*5!h$n#Z?vBzI*V7r6DC~W@W|UaODo4Suk;O01>`mTH`g|K8%AP z&)8=4g?DN@oNP7UGBYa+?ozBlp31I>6}0}fF!g3PZYH4ZgsyTqoVFBuI%%LNlW|{` z=9N`&IYp~lP5}-izluQ!b#y#j&L6C<$HJ=zF|TnP85dzw-S@6zwf&*4oB~ZmTlHdiG~Bknm>B@LOh z)Ki;zh$FRy)W_Z{ieqK(7D3zBuJG>s%Tr1Vo31wrKSLc!dxhO}&YHlfUABKkAP+Le zoRY1SH1GU>Ex>aLIy4@x*W1{$olfijG1BC86D?<_{fak@(tqj8fCK}Ro% zrBE?;txjr^E5zF^}(7qhfKQ- z?Y+6Pf;<4&_tD->O(=0Ler{fF7M}ZH(;zY$ZRE;5~+HDwPgH^kxl&*}IVNJaJQc^bDxK0;*^AvE2yI&TxBN<-P-s)_5!Xxe)7f?x}+*PP9 zWl-+bHy)2ihOo!mhy znosm&k76rcnSRi=JFvCo=pn}4>%_m@?O}M1fi^nMRZwRb{`$4PV#xgOFs2Rc6(qWY z`NJIS1e;bGBS#`Dv!*0Bu-Qdd(5%F#IoZs*c~U=RbtS;Wq%5wcK3G@pIQvr36ZKSawbP>YBZA+D!#gW z7(CH)HHuzc`1gPtZ2-q7uD-L2MJm$mKh=sk^Zdrpjb*%^x>?)cTVdqv3MkX}U%hgq zI1!VGCvHTVwHFA%&*UL9-tmJe0V#A3)dtc81=FM0pEuze`EQEC6bEXW91m@nbyy#! zqZ9Shj68{FAhxN7oR2|aOK8gVcqW9x0f`hQBsbA^>$cP%zcLUXmri%Ny$}BQ0xeor zs-t`Pf!uMJv`{l)j+X6=oe5O`<*M*Txt9TM3nF{EoX&}hR(YW__q#f(5Yd(hy{!C^+x)q z`Dq)jaL+6&Q=`vD)J#ol{vpXEp3Yv8gy0?TYTby9iNr;z${3aYtzLKnX3WkAgz$)93zr zu#rA^nQ7`zUY`t9x9`R22B!dQjBru@`+@pV<{2&|wQt{=f?le1+O6&EH7Eb$GI?Y= zzWHcWgULBA5ZB58yganE+*x%qZ&Bjv>Sa*b)gm48kG$tFiGt@c!{KG?C!V9P^&<0d zLR|qP&Ib!KLj~)m%>6olCWT+w6VKIKKM%9;1@%3_Ifx!O8Y(uu7b;0a=C};swFQ+;xDp|BQE#&@|Qh#d%Pq3c=R<=xMd49*E z_-@jS33_WNA7+aMFlcC#7U#|bVq?s6X)WH9EJu?x7Q}`)@#oQaOT1Rb8TFez}Kld|baNq_?-9!=5}n{LzRM8YdU z3H~+M9aFRZ-fB04fUZ z{GkwVbG3fu`J`!PM4Nq=`krZ_qg&0&a4k0jDSqu-!(+MQQCr>LDdg3+jeVw^JeU5&34vyK98~F1+0a}%rHrc`1Z)Fr}hsxFh`4xB5bX8Us8H* z=I)sFW=w#F+d12rsLO)aiJzUUp-n~3NsuHWe437zw9S60B?PuqnUM9i9|18kYH9bx;)}pdvzyGvFu?Ua-UiL_Hp0)XBg0!G4wr*FyYiJG`ZvRsHyix zZ1bkbMV!t4Gkwu_-`O5feyf8V(mj6$ZbX7onc^%s+W$)aP~nH#BD}B5Pa+mI0xT<( zd7@c!bc7VUA8@1x3nl9+**-muu28)0dE4dp2+#um6|0%vTb~Ow z<&=854~H}?rls`SnZHypAEc^IrhIbCTb#(E);BYffAzsak(FB}pMZl2-$$KV{JCM^ zC%m=NFk8$S_@}E(sF%^evl?(L$&Rx$C-^E6A2rxkL!|ptb#fT`B(T!uwk?W~v4iU; z7fQYeLB(`uY%0islwL}FJh%Po-pIt8j1$i1gSv~9=o%d|ta|(E(;&#F@hC=W@?`xO zc{hFe;XuKmOj?9HGFW#pU>aO6H zcBIPdt_QFv7~W-;|H>Dp2%;ykkB2VwF3UnOC&ZBeuIPc7_F^IDEMU)x+{3a2kG+;z z7aVmWf9(b_iS66SjZ8ajneM3`m?bfW!WbQ6y}f)ZCVC$Lfo#ne0oij6-pI0xB0G{1 zW7BM1&QMdaNp>9?>x$y07Ux1(|)B^i2HDqI;_^6g(Nm-y3fK z?!7xMpQHA?#jG~%@8q58=4w*{en8;9SxO32H^E8}L2%u=TFZ`w#gX`4$~5_k0|3@{ z;zWc{t!DN4_~W9=i(7kpKmIzSgU%sV?zi_K0C zQC^9a$~_@UeU9e6k%68nBEJwgr~*T@&Pmxg2{c#!}mlbX=$QJDn4`^q<($fB0M10y1NrR|4ho-mk#nt5C_i__^dnBPFh@PrvYfBs%FOR7v=EoQ7rYsBdc^~C6dPK)jQb|M_=FI8np}ae~uy9S2c(94NIqCP#*H z=RkpUR>fpJq6(}p9eJzZ%X1Y@XX1W#{Z?m|=NSF>yFTp@D=}ff zkaKGlHcw07$f|f)Wz7ZF1yXDC0DeX@wKjPZWJS2fYR20p?3{|OTj)fNJ?!yT`V zw`kt{)H%AfQiC<>xIEtG1`kcQ+1l87mDrbf2n!C$f&)3 zok2uRFN9x%@eaZE#M^CKi~%3J>aA#1o0j)+X}uTFAt_&sEAdMC1B+rV{X=QBJb9Nf zfhuw79_FF^j6$f!djvcilg$fst&s@;6#|YD$}%KE{)wq%fJy8-BK1C=h3oq4dwh9= z-@Yz97D+B9iwq*dcg?y2VScvCtB(q)gMY56g+1ikppFDvzwkMwN?;MCVL%ovGfaRD z8htKR*0}V02d>+Ty%E$o9a~p>2#yMi8R%OzevWFIzv75PO}wyBTh1h@*m|S!qheDW z@r=IhIa691=^>;I+SIG~^({w0|UP7d*#AH6fUR(^@#}pZ!A;$Rhxg$x@8y7Cnx!4;vw#u$T_VocF`QRF`M1co63Xn6%9y% zMEg}S7PwQu;3|W7#I={p6y7(DX>JSY_&Wo%G^X{|TOGKO(nRx|U>J`5Mn~CEyn#1m zdSlb|h;9859I(;K38J-K&+%nXBmFb0*RVeIYf^`$#CW=xkM{{w1?5IBQyG^T?Dy&${XdG2Fn(~L&^V|qzh?|)|#oa*kIDY8I66%NF)** zdhwGNICLNtL5*F((!!-Ep5TB=0AW<3qLH^BJxKM&v8`M;Ky0hm50Sphx8&kw*bOqP z9+(uvo)|~x*tWDIPlUW6meU5vQh>w&2uKH-w(x~!2`K5bNFT*NTMwnnS0dAp>oGPN z{YtpA!GoECiG5J+BLEKhJ^Aj&-dqb+E3WKX-C*BLWo`nfX<8WTy_jQ0(2$Yu#zK*tI`Iv)Z1~nSgamf)Of2S9J!iV7ZVFzz*vKbZ(UU_Ln~;Df9bXa~!)~o7 zA$JvIMG?-#>9a}?K764SdR!;LeTnZkYTp0fZ-OK*C<%i(lBFJrSS0|LjNpxg+mTT$ z5izm^5DR6hdVF8$_29JorKyHl3k^6}k+gQrkF)xh+m5wvcz-ezqXtPCH-}$Km063@ z?<_JA5o3ni`?!G@vJb08v+3FRX5OB!uS&}gA{s&rS6)85XyXU~3HMAfVB$l|ZGkM; zf*1CeY0G$_C6k{=%`=u*j7ca-ej2CYW{vAlV%}|Q&?4zei+Uw>vR;-!1)=@^X6VLy zNbMo7c9-E1+0WB*Ig8}PBP0uDf&2UxJ72iEE^TG-3S6+c8%lLZ^__Yi$Dt^^bRG6e zqLdXopXMUiT;atrEy4#$gs-pp9Fyrdm7(19OxR*bsP;wVb(*xtZVWQj_&KFjFNhj5 zX3n_Wbv+2{?)lB^9y!9J#wj%jyPIiy^QTe1SsAtAG4_c#-3(heY=im+@+IeAmML_uiz$o2e@J*;ZC{k= z`VyC^%OyD*PcV{$_b(+@4ib)uhEDD?(0>?5mlTC!`z5Q1530`?xAhtiCbVr)7y6j)WPqF?WAMyc8#rq z(x$`6D@c>6|C|5InW*6dSpH1)oXQ1jSE8?~M=6|FUQCWie&)Mx#ceCn5cqktWV|Vr^7Oyh9WuLvfFf$P0QmO+&7lYBC;+u$rNG98U>{D^H)SFh@ z2O-P>{%Xqm_KcJEJqGZHDb7wKHvN1V77+@9?86U)g1D z9rs3E7lgg117*T6Os4owc3Tl_eG<4>RaF$hMUm9hdH^`3Z+POJFW=Z5AEUk{v>#T4 zluvB>G0Hrs&^YG5lfSg!{a~$~@OXNy9{!SjV=!o>NrZ5ns{{}m<%MmYO_ zk~NuNJv&e5Xh8&At|5}fxYe-~@&5DE5~u_^kqnUD_eM9UClyG5H8GRH+@FmePS!-ul z2vTr|;+>H_+WuwD)2`MMI7IT35Eb~QJ&rsLWRcvXU_tXamOJ+9J-#pd-Gequs@>n! zk`t$7|HN8_a-8D(sHRF4h-spDBs%p%MMs-s$^KOSVc8Sg5#3Dj*ol*D0&OG1{&4OS zM}9Im5%%g>whBG$@$3ClB z)b1Z})54zA>(zaV@G$+e;&o@NA)O7{PYUS_&XTZw{|!pVnV(&6oK^9-&Ip}e$A2V9p;f^H7cBy4YqgrEN%7mOY0&Lk zXGTQkuV&ri_&)vn)bV99(X1%~WVm2uvi%SAi@jj7V`^(0iRo^%tFRxVXXCTp;*HU0 zA`qs3hH?s1vpK>BZbg*q-~?YkX|jiy#jtyp&_?2e!O6#rfcqhasRU@NUH-<6Y%D%? zAOO>W_M;fs=RASe&^8w_!aZWi`C{A~4QCYy)k}9uynlw*?RA6utM5Wj4~lEgo1X2$ zRNh6+&EyYEwA>#t8QBcs7cJju8dC2+d(4i+W}mjrDrbGmLvo5*0x*(1Cg+3r_R;-v_^%9AJ=eYo0>sA?KCHgq;0GP2 zP-_RDkICDtKeSt|fj`P;&i_aq&DB~6aiU&Zaq!RIk$0GCb0$?u=qk>d3B>7`APZ4! zAO}C7#^`k+?c8~(k_wRf5Sqkgk@rNGhVpexvd(SY*aWkYli_k__uC?ofCoh;#IRW5 z_EK3Tv9>`oIjnZbNWZSElH_ik_$UU=_G5{%cc0?k!ug34LtEX5jkQIYb8EjWtllc; zQ-^!2_PVi>(W4PW7^seF7!8oI5%xoC9}@GAx;7LD+huNx&7?K?AU9Y0MW-M@DwjpU z8*K0E|J@R^f?zAvtE(6aPaAyFad8;&m)Q)W%DG!DvTTzeNb?Vf-KA95em9jg8Q%sn zfUI*6Ey)g0H9L&-*&3IiOf^TzT!8B3N2#^Mo+ESS-qdh7<@Dt5b6gq~zzXB=H6LdLJt-DFZ=Qn)0}@sCj9)yK6tUD@eiQm^)l~@9RZZyNa<$hK*1>Ws@=cg_6t_WUQ?YZ?CS) zK`l31{@z~O1|*BN#ZzQf{9Kjf4D}5-H(nIt!}ijLgJPi(1uS@OxikqkWJ2 zMr1;>UP66sOR3N)=@CVAH&Kul_UA3E3C>XJ!jgSM(7N6>6TVFeS%0A4;*Y47t((&}%?iAm*x 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 literal 0 HcmV?d00001 diff --git a/TV_APP_V2/static/setting.png b/TV_APP_V2/static/setting.png new file mode 100644 index 0000000000000000000000000000000000000000..bfbf3264460b3c879a96fd0a9985789e3f24880e GIT binary patch literal 12862 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�C5pnSvt}2I_X2~43~R?FZw3?=`v$E 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 VIwOAB5B%>3L@>2BDL+cQ`ajT>LWTeU literal 0 HcmV?d00001 diff --git a/TV_APP_V2/templates/draft.html b/TV_APP_V2/templates/draft.html new file mode 100644 index 0000000..8d30a46 --- /dev/null +++ b/TV_APP_V2/templates/draft.html @@ -0,0 +1,547 @@ + + + + + Tournament Draft + + + + + + +
+ {% if tournament %} +
+
🎯 Shooting Tournament
+
+ {{ tournament.total_players }} players • {{ tournament.total_rounds }} rounds + {% if tournament.current_round %} + • Currently on Round {{ tournament.current_round }} + {% endif %} +
+ + {% if tournament.current_round %} +
+ + Round {{ tournament.current_round }} of {{ tournament.total_rounds }} + +
+ {% endif %} +
+ +
+ {% for round in tournament.rounds %} + {% set is_current = tournament.current_round == round.round_number %} + {% set is_completed = tournament.current_round > round.round_number %} +
+
+
Round {{ round.round_number }}
+ {% if is_current %} +
Current
+ {% elif is_completed %} +
Done
+ {% else %} +
Wait
+ {% endif %} +
+ +
+ {% for position in range(1, 7) %} + {% set player = round.players[position-1] if position <= round.players|length else none %} +
+
{{ position }}
+ {% if player %} +
{{ player.name }}
+
ID: {{ player.id }}
+ {% else %} +
Empty
+ {% endif %} +
+ {% endfor %} +
+
+ {% endfor %} +
+ + {% else %} +
+

No Active Tournament

+

Go to Tournament Management to set up players and start a tournament.

+ 🏆 Set Up Tournament +
+ {% endif %} +
+ + +
+ 🔄 Updating... +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/fullscreen.html b/TV_APP_V2/templates/fullscreen.html new file mode 100644 index 0000000..4afde6c --- /dev/null +++ b/TV_APP_V2/templates/fullscreen.html @@ -0,0 +1,766 @@ + + + + + {{ title }} - Fullscreen + + + + +
+ + +
+ +
+
Loading stream...
+
+ {{ title }} +
+ +
+ +
1.0x
+ + +
+
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/index.html b/TV_APP_V2/templates/index.html new file mode 100644 index 0000000..ef1e364 --- /dev/null +++ b/TV_APP_V2/templates/index.html @@ -0,0 +1,875 @@ + + + + + Camera Dashboard + + + + + + +
+ +
+
+

Camera Settings

+ +
+ +
+ {% if settings.tournament_active %} +
+

🏆 Active Tournament

+ +
+

Current Round: {{ settings.current_round }} of {{ settings.total_rounds }}

+

Camera cards show current round players

+
+ + +
+ {% endif %} + +
+ {% if not settings.tournament_active %} +

Navigation

+ 🏆 Tournament Mode +

Data & Analysis

+ 👤 Player Analysis + 📚 View Archive + {% endif %} +
+ + {% if not settings.tournament_active %} +
+

Display Options

+ +
+ +
+ +
+ + +
+
+
+

Camera Titles

+ {% for i in range(1, 7) %} +
+ + +
+ {% endfor %} +
+ {% endif %} +
+
+ +
+ {% for i in range(1, 7) %} +
+
{{ settings.camera_titles[i|string] }}
+
+ Camera Stream {{ i }} +
+
+ {% endfor %} +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/league_results_display.html b/TV_APP_V2/templates/league_results_display.html new file mode 100644 index 0000000..3c9cda2 --- /dev/null +++ b/TV_APP_V2/templates/league_results_display.html @@ -0,0 +1,1112 @@ + + + + + {% if league.league_finished %}League Final Results{% else %}League Scoreboard{% endif %} + + + + + + +
+ +
+ +
+ +
+ {% if league.league_finished %}League Championship{% else %}League Scoreboard{% endif %} +
+
+ {% if league.league_finished %} + Final Rankings - Best 5 of 6 Tournaments + {% else %} + Tournament {{ league.current_tournament }} of {{ league.total_tournaments }} - Live Updates + {% endif %} +
+
+
+ {{ participants|length }} + Participants +
+
+ {{ league.current_tournament if not league.league_finished else league.total_tournaments }} + {% if league.league_finished %}Total Tournaments{% else %}Current Tournament{% endif %} +
+
+ + {% if league.tournament_type == '40_targets' %}40{% else %}20{% endif %} + + Targets +
+
+ {% if participants and participants|length > 0 %}{{ participants[0].final_score if league.league_finished else participants[0].current_total }}{% else %}0{% endif %} + {% if league.league_finished %}Final Score{% else %}Leading Score{% endif %} +
+
+
+ + {% if participants and participants|length >= 3 %} + +
+
+ {% if league.league_finished %}🏆 Final Champions{% else %}🥇 Current Leaders{% endif %} +
+
+ {% for i in range(3) %} + {% set participant = participants[i] %} +
+
+
{{ participant.rank }}
+
+ {% if participant.rank == 1 %}st + {% elif participant.rank == 2 %}nd + {% elif participant.rank == 3 %}rd + {% else %}th + {% endif %} +
+
+ {% if participant.rank == 1 %}🥇 + {% elif participant.rank == 2 %}🥈 + {% elif participant.rank == 3 %}🥉 + {% endif %} +
+
+ +
+
{{ participant.name }}
+
+
ID: {{ participant.id }}
+ {% if participant.joker_used %} +
🃏 Joker Used
+ {% endif %} + {% if not league.league_finished and participant.current_tournament_participating %} +
🎯 Playing Now
+ {% endif %} +
+
+ +
+
{{ participant.final_score if league.league_finished else participant.current_total }}
+ {% if not league.league_finished %} +
+ {% if participant.current_tournament_participating %} + Current: +{{ participant.current_tournament_score }} + {% else %} + Final: {{ participant.final_score }} + {% endif %} +
+ {% else %} +
Total: {{ participant.total_score }}
+ {% endif %} +
{% if league.league_finished %}Final Score{% else %}Current Score{% endif %}
+
+
+ {% endfor %} +
+
+ {% endif %} +
+ + +
+
+

+ {% if league.league_finished %} + 📊 Complete Tournament Breakdown & Final Calculation + {% else %} + 📊 League Standings - Tournament {{ league.current_tournament }} of {{ league.total_tournaments }} + {% endif %} +

+
+ +
+ + + + + + + + {% if not league.league_finished %} + + {% endif %} + + + + + + + + + + + + {% for participant in participants %} + + + + + + {% for tournament_num in range(1, 7) %} + + {% endfor %} + + + + {% if not league.league_finished %} + + {% endif %} + + {% endfor %} + +
RankParticipantIndividual Tournament Scores + {% if league.league_finished %} + Final Score
(Best 5) + {% else %} + Current
(Best 5) + {% endif %} +
Live
T{{ league.current_tournament }}
T1T2T3T4T5T6
+ {{ participant.rank }} + {% if participant.rank == 1 %}🏆 + {% elif participant.rank == 2 %}🥈 + {% elif participant.rank == 3 %}🥉 + {% endif %} + +
{{ participant.name }}
+
{{ participant.id }}
+
+ {% set found_result = false %} + {% for result in participant.tournament_results %} + {% if result.tournament == tournament_num %} + {% set found_result = true %} + {% if result.get('joker') or not result.participated %} + 🃏 + {% else %} + {% set all_scores = [] %} + {% for r in participant.tournament_results if r.participated %} + {% set _ = all_scores.append(r.score) %} + {% endfor %} + {% set sorted_scores = all_scores|sort(reverse=true) %} + {% set excluded_score = sorted_scores[-1] if sorted_scores|length > 5 else none %} + + {% if all_scores|length > 5 and result.score == excluded_score %} + {{ result.score }} + {% else %} + {{ result.score }} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% if not found_result %} + - + {% endif %} + + {% if league.league_finished %} + {{ participant.final_score }} + {% else %} + {{ participant.current_total }} + {% endif %} + + {% if participant.current_tournament_participating %} + {{ participant.current_tournament_score }} + {% else %} + - + {% endif %} +
+
+ +
+
📖 Scoring Legend:
+
+
+ + Counted Score +
+ {% if league.league_finished %} +
+ + Excluded (Worst) +
+ {% endif %} +
+ + Joker Used +
+
+ + {% if league.league_finished %}Final Score (Best 5){% else %}Current Score{% endif %} +
+ {% if not league.league_finished %} +
+ + Live Tournament +
+ {% endif %} +
+
+ + +
+
+ + +
+ 🔄 Updating... +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/league_scoreboard_display.html b/TV_APP_V2/templates/league_scoreboard_display.html new file mode 100644 index 0000000..57d61f4 --- /dev/null +++ b/TV_APP_V2/templates/league_scoreboard_display.html @@ -0,0 +1,1156 @@ + + + + + League Results + + + + + + +
+ +
+ +
+ +
League Championship
+
Final Rankings - Best 5 of 6 Tournaments
+
+
+ {{ participants|length }} + Participants +
+
+ {{ league.total_tournaments }} + Tournaments +
+
+ + {% if league.tournament_type == '40_targets' %}40{% else %}20{% endif %} + + Targets +
+
+ {% if participants and participants|length > 0 %}{{ participants[0].final_score }}{% else %}0{% endif %} + Highest Score +
+
+
+ + {% if participants and participants|length >= 3 %} + +
+
🏆 League Champions
+
+ {% for i in range(3) %} + {% set participant = participants[i] %} +
+
+
{{ participant.rank }}
+
+ {% if participant.rank == 1 %}st + {% elif participant.rank == 2 %}nd + {% elif participant.rank == 3 %}rd + {% else %}th + {% endif %} +
+
+ {% if participant.rank == 1 %}🥇 + {% elif participant.rank == 2 %}🥈 + {% elif participant.rank == 3 %}🥉 + {% endif %} +
+
+ +
+
{{ participant.name }}
+
+
ID: {{ participant.id }}
+ {% if participant.joker_used %} +
🃏 Joker Used
+ {% endif %} +
+
+ +
+
{{ participant.final_score }}
+
Total: {{ participant.total_score }}
+
Final Score
+
+
+ {% endfor %} +
+
+ {% endif %} +
+ + +
+
+

📊 Complete Tournament Breakdown & Final Calculation

+
+ +
+ + + + + + + + + + + + + + + + + + + {% for participant in participants %} + + + + + + {% for tournament_num in range(1, 7) %} + + {% endfor %} + + + + {% endfor %} + +
RankParticipantIndividual Tournament ScoresFinal Score
(Best 5)
T1T2T3T4T5T6
+ {{ participant.rank }} + {% if participant.rank == 1 %}🏆 + {% elif participant.rank == 2 %}🥈 + {% elif participant.rank == 3 %}🥉 + {% endif %} + +
{{ participant.name }}
+
+ {% set found_result = false %} + {% for result in participant.tournament_results %} + {% if result.tournament == tournament_num %} + {% set found_result = true %} + {% if result.get('joker') or not result.participated %} + 🃏 + {% else %} + {% set all_scores = [] %} + {% for r in participant.tournament_results if r.participated %} + {% set _ = all_scores.append(r.score) %} + {% endfor %} + {% set sorted_scores = all_scores|sort(reverse=true) %} + {% set excluded_score = sorted_scores[-1] if sorted_scores|length > 5 else none %} + + {% if all_scores|length > 5 and result.score == excluded_score %} + {{ result.score }} + {% else %} + {{ result.score }} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {{ participant.final_score }}
+
+ +
+
📖 Scoring Legend:
+
+
+ + Counted Score +
+
+ + Excluded (Worst) +
+
+ + Joker Used +
+
+ + Final Score (Best 5) +
+
+
+ + +
+
+ + +
+ 🔄 Updating... +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/mobile_draft.html b/TV_APP_V2/templates/mobile_draft.html new file mode 100644 index 0000000..663d0dc --- /dev/null +++ b/TV_APP_V2/templates/mobile_draft.html @@ -0,0 +1,769 @@ + + + + + 📱 Tournament Draft + + + + +
+ + +
+ +
+ {% if tournament %} +
+
🎯 Shooting Tournament
+
+ {{ tournament.total_players }} players • {{ tournament.total_rounds }} rounds + {% if tournament.current_round %} + • Currently on Round {{ tournament.current_round }} + {% endif %} +
+
+ +
+ {% for round in tournament.rounds %} + {% set is_current = tournament.current_round == round.round_number %} + {% set is_completed = tournament.current_round > round.round_number %} +
+
+
Round {{ round.round_number }}
+ {% if is_current %} +
Current
+ {% elif is_completed %} +
Completed
+ {% else %} +
Waiting
+ {% endif %} +
+ +
+ {% for position in range(1, 7) %} + {% set player = round.players[position-1] if position <= round.players|length else none %} +
+
{{ position }}
+ {% if player %} +
{{ player.name }}
+
ID: {{ player.id }}
+ {% else %} +
Empty
+ {% endif %} +
+ {% endfor %} +
+
+ {% endfor %} +
+ + +
+
📊 Tournament Summary
+
+
+ Total Players: + {{ tournament.total_players }} +
+
+ Total Rounds: + {{ tournament.total_rounds }} +
+
+ Current Round: + {{ tournament.current_round or 'Not set' }} +
+
+ Updates: + On Round Change +
+
+ Created: + {{ tournament.created_at[:10] if tournament.created_at else 'Unknown' }} +
+
+ Status: + Active +
+
+
+ {% else %} + +
+

📋 No Active Tournament

+

No tournament is currently running. Check the Results tab for completed tournaments or use the dashboard to start a new tournament.

+
+ {% endif %} +
+ + +
+ 🆕 New Round Starting... +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/mobile_league_results.html b/TV_APP_V2/templates/mobile_league_results.html new file mode 100644 index 0000000..199e1c8 --- /dev/null +++ b/TV_APP_V2/templates/mobile_league_results.html @@ -0,0 +1,934 @@ + + + + + 📱 League Results + + + + +
+ + +
+ +
+
+
🏆 League Championship
+
+ Final Results - Best 5 of 6 Tournaments +
+
+ {% if league.tournament_type == '40_targets' %} + 40 Targets Format + {% else %} + 20 Targets Format + {% endif %} +
+
+ +
+
+
{{ participants|length if participants else 0 }}
+
Participants
+
+
+
{{ league.total_tournaments }}
+
Tournaments
+
+
+
{% if participants and participants|length > 0 %}{{ participants[0].final_score }}{% else %}0{% endif %}
+
Highest Score
+
+
+
{{ league.finished_at[:10] if league.finished_at else 'Today' }}
+
Completed
+
+
+ + {% if participants and participants|length > 0 %} +
+
🎉 League Complete!
+
+ Congratulations to {{ participants[0].name }} for winning the league! +
+
+ +
+ {% for participant in participants %} +
+
+
{{ participant.rank }}
+
+ {% if participant.rank == 1 %}st + {% elif participant.rank == 2 %}nd + {% elif participant.rank == 3 %}rd + {% else %}th + {% endif %} +
+ {% if participant.rank == 1 %} +
🥇
+ {% elif participant.rank == 2 %} +
🥈
+ {% elif participant.rank == 3 %} +
🥉
+ {% endif %} +
+ +
+
{{ participant.name }}
+
+
ID: {{ participant.id }}
+
+
+ +
+
{{ participant.final_score }}
+
Total: {{ participant.total_score }}
+
Final Score
+
+
+ {% endfor %} +
+ + + + {% set max_breakdowns = 3 %} + {% if participants|length < 3 %} + {% set max_breakdowns = participants|length %} + {% endif %} + + {% for i in range(max_breakdowns) %} + {% set participant = participants[i] %} +
+
+ {% if participant.rank == 1 %}🥇{% elif participant.rank == 2 %}🥈{% elif participant.rank == 3 %}🥉{% endif %} + {{ participant.name }}'s Tournament History +
+
+ {% for tournament_num in range(1, 7) %} + {% set result = participant.tournament_results + | selectattr("tournament", "equalto", tournament_num) + | list + | first %} + + {% if result %} + {% if (result.joker is defined and result.joker) or (result.participated is defined and not result.participated) %} +
+
T{{ tournament_num }}
+
🃏 Joker
+
+ {% else %} + {% set all_participated_scores = participant.tournament_results + | selectattr("participated", "defined") + | selectattr("participated") + | selectattr("score", "defined") + | map(attribute="score") + | list %} + {% set sorted_scores = all_participated_scores | sort(reverse=true) %} + {% set is_excluded = sorted_scores | length > 5 and result.score == sorted_scores[-1] %} + + {% if is_excluded %} +
+
T{{ tournament_num }}
+
{{ result.score }} ❌
+
+ {% else %} +
+
T{{ tournament_num }}
+
{{ result.score }} ✅
+
+ {% endif %} + {% endif %} + {% else %} +
+
T{{ tournament_num }}
+
-
+
+ {% endif %} + {% endfor %} + +
+
+ {% endfor %} + + +
+
📖 How Final Scores Are Calculated
+
+
+ 🏆 League Rule: Best 5 out of 6 tournaments count toward final ranking +
+
+ 🃏 Joker System: Each player can skip 1 tournament without penalty +
+
+
+ + Counted toward final score +
+
+ + Excluded (worst score) +
+
+ 🃏 + Joker used (skipped) +
+
+
+
+ {% else %} +
+
+

No League Results Available

+

League results will appear here when the league is complete.

+
+
+ {% endif %} +
+ + +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/mobile_menu.html b/TV_APP_V2/templates/mobile_menu.html new file mode 100644 index 0000000..acf3382 --- /dev/null +++ b/TV_APP_V2/templates/mobile_menu.html @@ -0,0 +1,382 @@ + + + + + 📱 Camera Dashboard + + + + +
+ +
Camera Dashboard
+
Loading mobile interface...
+ +
+
Detecting tournament state...
+ + + + + + +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/mobile_results.html b/TV_APP_V2/templates/mobile_results.html new file mode 100644 index 0000000..96d0b85 --- /dev/null +++ b/TV_APP_V2/templates/mobile_results.html @@ -0,0 +1,696 @@ + + + + + 📱 Tournament Results + + + + +
+ + +
+ +
+ + {% if participants %} + {% if participants|length > 0 %} +
+
🎉 Tournament Complete!
+
+ Congratulations to {{ participants[0].name }} for winning! +
+
+ {% endif %} + +
+ {% for participant in participants %} +
+
+
{{ participant.rank }}
+
+ {% if participant.rank == 1 %}st + {% elif participant.rank == 2 %}nd + {% elif participant.rank == 3 %}rd + {% else %}th + {% endif %} +
+ {% if participant.rank == 1 %} +
🥇
+ {% elif participant.rank == 2 %} +
🥈
+ {% elif participant.rank == 3 %} +
🥉
+ {% endif %} +
+ +
+
{{ participant.name }}
+
ID: {{ participant.id }}
+
+ +
+
{{ participant.total_score }}
+
Points
+
+
+ {% endfor %} +
+ {% else %} +
+
+

No Results Available

+

Tournament results will appear here when scoring is complete.

+
+
+ {% endif %} + + +
+
📊 Tournament Information
+
+
+ Total Participants: + {{ participants|length if participants else 0 }} +
+
+ Tournament ID: + {{ results.tournament_id[:10] if results.tournament_id else 'Unknown' }}... +
+
+ Created: + {{ results.created_at[:10] if results.created_at else 'Unknown' }} +
+
+ Status: + Completed +
+ {% if participants and participants|length > 0 %} +
+ Highest Score: + {{ participants[0].total_score }} points +
+
+ Winner: + {{ participants[0].name }} +
+ {% endif %} +
+
+
+ + +
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/mobile_streams.html b/TV_APP_V2/templates/mobile_streams.html new file mode 100644 index 0000000..6da9457 --- /dev/null +++ b/TV_APP_V2/templates/mobile_streams.html @@ -0,0 +1,670 @@ + + + + + 📱 Camera Streams + + + + +
+ + +
+ +
+
+ {% for i in range(1, 7) %} + {% set camera_id = i %} +
+
+
Loading...
+ Camera {{ camera_id }} +
+
+
+ {% if tournament_active and current_round_data and (i-1) < current_round_data.players|length %} + {{ current_round_data.players[i-1].name }} + {% else %} + {{ settings.camera_titles[camera_id|string] }} + {% endif %} +
+
+
+ {% endfor %} +
+
+ + + + + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/modern_archive_index.html b/TV_APP_V2/templates/modern_archive_index.html new file mode 100644 index 0000000..dd05a5e --- /dev/null +++ b/TV_APP_V2/templates/modern_archive_index.html @@ -0,0 +1,701 @@ + + + + + Tournament Archive + + + + + + +
+ +
+
+ 🏆 +
{{ stats.total_tournaments }}
+
Standalone Tournaments
+
+
+ 🎖️ +
{{ stats.total_leagues }}
+
Completed Leagues
+
+
+ 👥 +
{{ stats.total_players }}
+
Active Players
+
+
+ 📊 +
{{ stats.total_matches }}
+
Total Competitions
+
+
+ + + {% if leagues %} +
+

🎖️ League Championships

+
+ {% for league in leagues %} +
+
+
+
League Championship
+
{{ league.created_at[:10] if league.created_at != 'Unknown' else 'Unknown Date' }}
+
+ League +
+
+
+
+ 👥 + {{ league.participants_count }} players +
+
+ 🎯 + {{ league.tournament_type.replace('_', ' ')|title }} +
+
+ 📅 + {{ league.archived_at[:10] if league.archived_at != 'Unknown' else 'Unknown Date' }} +
+
+ + {{ league.completed_tournaments }}/{{ league.total_tournaments }} tournaments +
+
+
+ 🏆 View Results + +
+
+
+ {% endfor %} +
+
+ {% endif %} + + + {% if tournaments %} +
+

🏆 Standalone Tournaments

+
+ {% for tournament in tournaments %} +
+
+
+
Single Tournament
+
{{ tournament.created_at[:10] if tournament.created_at != 'Unknown' else 'Unknown Date' }}
+
+ Tournament +
+
+
+
+ 👥 + {{ tournament.participants_count }} players +
+
+ 🎯 + {{ tournament.tournament_type.replace('_', ' ')|title }} +
+
+ 📅 + {{ tournament.archived_at[:10] if tournament.archived_at != 'Unknown' else 'Unknown Date' }} +
+
+ 🏁 + {{ 'Finished' if tournament.tournament_finished else 'Incomplete' }} +
+
+
+ 📊 View Results + +
+
+
+ {% endfor %} +
+
+ {% endif %} + + + {% if not leagues and not tournaments %} +
+
+
📚
+

No Archives Found

+

Complete some tournaments or leagues to see them archived here

+ 🏆 Start Tournament +
+
+ {% endif %} +
+ + + + + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/modern_player_analysis.html b/TV_APP_V2/templates/modern_player_analysis.html new file mode 100644 index 0000000..c8a8643 --- /dev/null +++ b/TV_APP_V2/templates/modern_player_analysis.html @@ -0,0 +1,776 @@ + + + + + + Player Analysis - Camera Dashboard + + + + + + + +
+ +
+
+ 👥 +
{{ players|length }}
+
Total Players
+
+
+ +
{{ players|selectattr('current_player')|list|length }}
+
Active Players
+
+
+ 📊 +
{{ overview_stats.avg_tournaments if overview_stats else 0 }}
+
Avg Tournaments
+
+
+ 🏆 +
{{ overview_stats.top_score if overview_stats else 0 }}
+
Highest Score
+
+
+ +
+
Select a Player to Analyze
+ + +
+ + + + +
+ + + +
+
+ + +
+
+
+

Loading players...

+
+
+
+
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/modern_player_stats.html b/TV_APP_V2/templates/modern_player_stats.html new file mode 100644 index 0000000..8913b92 --- /dev/null +++ b/TV_APP_V2/templates/modern_player_stats.html @@ -0,0 +1,627 @@ + + + + + + {{ player.name }} - Player Stats + + + + + + + +
+ +
+ +
+
📊 Statistics
+
+
+
{{ stats.total_tournaments }}
+
Tournaments
+
+
+
{{ stats.total_leagues }}
+
Leagues
+
+
+
{{ stats.best_tournament_score }}
+
Best Score
+
+
+
{{ stats.average_tournament_score|round|int if stats.average_tournament_score > 0 else 0 }}
+
Average
+
+
+
{{ stats.total_shots_fired|default(0) }}
+
Total Shots
+
+
+
{{ stats.worst_tournament_score if stats.worst_tournament_score > 0 else 0 }}
+
Worst Score
+
+
+
+ + +
+
📈 Performance Trend
+
+ +
+
+
+ + +
+ +
+
🎯 Tournament History
+ {% if stats.tournament_history %} +
+ {% for tournament in stats.tournament_history[:10] %} +
+
+
{{ tournament.date[:10] if tournament.date != 'Unknown' else 'Unknown Date' }}
+
{{ tournament.tournament_type.replace('_', ' ')|title }} • {{ tournament.shots_fired }} shots
+
+
{{ tournament.score }}
+
+ {% endfor %} + {% if stats.tournament_history|length > 10 %} +
+ ... and {{ stats.tournament_history|length - 10 }} more +
+ {% endif %} +
+ {% else %} +
+
🎯
+
No tournament history
+
+ {% endif %} +
+ + +
+
🏆 League History
+ {% if stats.league_history %} +
+ {% for league in stats.league_history %} +
+
+
+
{{ league.date[:10] if league.date != 'Unknown' else 'Unknown Date' }}
+
+ League Championship • {{ league.tournaments_participated }}/6 tournaments + {% if league.joker_used %} • 🃏 Joker Used{% endif %} +
+
+
{{ league.final_score }}
+
+ +
+
+ Final Score: {{ league.final_score }} + Total: {{ league.total_score }} +
+
+ {% for result in league.tournament_results %} + + T{{ result.tournament }}: {{ result.score if result.participated else 'Joker' }} + + {% endfor %} +
+
+
+ {% endfor %} +
+ {% else %} +
+
🏆
+
No league history
+
+ {% endif %} +
+
+
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/results_calculator.html b/TV_APP_V2/templates/results_calculator.html new file mode 100644 index 0000000..647ccb5 --- /dev/null +++ b/TV_APP_V2/templates/results_calculator.html @@ -0,0 +1,1074 @@ + + + + + Results Calculator + + + + + + +
+
+
🎯 Tournament Scoring
+
Enter scores for each participant (20 targets, 2 shots each). Score 0 = miss.
+ +
+
+
0
+
Completed
+
+
+
{{ results.participants|length }}
+
Total
+
+
+
0
+
Total Shots
+
+
+
+ +
+ {% for player_id, participant in results.participants.items() %} +
+
+
+
{{ participant.name }}
+
ID: {{ player_id }}
+
+
+
+
{{ participant.total_score }}
+
Points
+
+
+ {% if participant.completed %} + Completed + {% else %} + Not Started + {% endif %} +
+
+
+
+ +
+
+
+ {% for i in range(1, 21) %} +
+
{{ i }}
+
+ + +
+
+ {% endfor %} +
+ +
+ + + +
+
+
+
+ {% endfor %} +
+ +
+
🏁 Finish Tournament
+
+ Complete scoring for all participants and finalize tournament results. +
+ + +
+
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/results_display.html b/TV_APP_V2/templates/results_display.html new file mode 100644 index 0000000..15d0799 --- /dev/null +++ b/TV_APP_V2/templates/results_display.html @@ -0,0 +1,872 @@ + + + + + Tournament Results + + + + + + +
+ +
+ +
+ +
Tournament Results
+
Final Rankings & Scores
+
+
+ {{ participants|length }} + Participants +
+
+ {{ (participants|length * 40) if participants else 0 }} + Total Shots +
+
+ {% if participants and participants|length > 0 %}{{ participants[0].total_score }}{% else %}0{% endif %} + Highest Score +
+
+
+ + {% if participants and participants|length >= 3 %} + +
+
🏆 Top 3 Winners
+
+ {% for i in range(3) %} + {% set participant = participants[i] %} +
+
+
{{ participant.rank }}
+
+ {% if participant.rank == 1 %}st + {% elif participant.rank == 2 %}nd + {% elif participant.rank == 3 %}rd + {% else %}th + {% endif %} +
+
+ {% if participant.rank == 1 %}🥇 + {% elif participant.rank == 2 %}🥈 + {% elif participant.rank == 3 %}🥉 + {% endif %} +
+
+ +
+
{{ participant.name }}
+
ID: {{ participant.id }}
+
+ +
+
{{ participant.total_score }}
+
Points
+
+
+ {% endfor %} +
+
+ {% endif %} +
+ + +
+
+

📊 Complete Rankings

+
+ +
+ + + + + + + + + + + + {% for participant in participants %} + + + + + + + + {% endfor %} + +
RankParticipantIDScoreStatus
+ {{ participant.rank }} + {% if participant.rank == 1 %}🥇 + {% elif participant.rank == 2 %}🥈 + {% elif participant.rank == 3 %}🥉 + {% endif %} + {{ participant.name }}{{ participant.id }}{{ participant.total_score }} + + ✓ + +
+
+ + +
+
+ + + + \ No newline at end of file diff --git a/TV_APP_V2/templates/tournament.html b/TV_APP_V2/templates/tournament.html new file mode 100644 index 0000000..4fc5b9d --- /dev/null +++ b/TV_APP_V2/templates/tournament.html @@ -0,0 +1,1565 @@ + + + + + Tournament Management + + + + + + +
+ + +
+ {% if league_state and not league_state.league_finished %} +

🏆 League Management

+
+
🏆 League Active
+
+
+
Tournament Type
+
+ {% if league_state.tournament_type == '40_targets' %} + 40 Targets + {% else %} + 20 Targets + {% endif %} +
+
+
+
Current Tournament
+
{{ league_state.current_tournament }} / {{ league_state.total_tournaments }}
+
+
+
Participants
+
{{ league_state.participants|length }}
+
+
+
Completed
+
{{ league_state.completed_tournaments|length }}
+
+
+
Created
+
{{ league_state.created_at[:10] }}
+
+
+ + {% if tournament_state %} + {% else %} + {% if league_state.current_tournament < league_state.total_tournaments %} + +
+
🃏 Joker Selection for Tournament {{ league_state.current_tournament + 1 }}
+

Select players who will use their joker (skip this tournament). Each player can only use their joker once per league.

+ +
+ {% for player_id, participant in league_state.participants.items() %} +
+ {{ participant.name }} + +
+ {% endfor %} +
+
+ +
+ +
+ {% else %} +
+ League Complete! All tournaments scheduled. Finish current one to see final results. +
+ {% endif %} + {% endif %} +
+ + {% elif league_state and league_state.league_finished %} +

🏁 League Completed

+
+
🏆 League Completed!
+
+
+
Tournament Type
+
{{ league_state.tournament_type == '40_targets' and '40 Targets' or '20 Targets' }}
+
+
+
Participants
+
{{ league_state.participants|length }}
+
+
+
Tournaments
+
{{ league_state.total_tournaments }}
+
+
+
Finished
+
{{ league_state.finished_at[:10] if league_state.finished_at else 'Today' }}
+
+
+ +
+ 🏆 View League Results + +
+
+ + {% elif not league_state and tournament_state %} +

🎯 Single Tournament Management

+
+
🎯 Tournament Active
+
+
+
Tournament Type
+
{{ tournament_state.tournament_type == '40_targets' and '40 Targets' or '20 Targets' }}
+
+
+
Players
+
{{ tournament_state.total_players }}
+
+
+
Rounds
+
{{ tournament_state.total_rounds }}
+
+
+
Current Round
+
{{ tournament_state.current_round }}
+
+
+
Created
+
{{ tournament_state.created_at[:10] if tournament_state.created_at else 'Today' }}
+
+
+ +
+ 📋 View Draft + 🎯 Score Tournament + 📺 Dashboard + +
+
+ + {% else %} +

🏁 Setup

+
No Active League or Tournament
+ + +
+
🎯 Select Tournament Type
+
+
+ +
20 Targets
+
Standard format with 20 targets, 2 shots each (40 shots total)
+
+
+ +
40 Targets
+
Extended format with 40 targets, 2 shots each (80 shots total)
+
+
+
+ +
+ 0 players enabled +
+ +
+ + +
+ + + {% endif %} +
+ + + + {% if tournament_state and league_state %} +
+

📋 Current Tournament

+ +
+
🎯 Tournament Active
+
+
+
Tournament Type
+
+ {% if tournament_state.tournament_type == '40_targets' %} + 40 Targets + {% else %} + 20 Targets + {% endif %} +
+
+
+
Total Players
+
{{ tournament_state.total_players }}
+
+
+
Total Rounds
+
{{ tournament_state.total_rounds }}
+
+
+
Current Round
+
{{ tournament_state.current_round }}
+
+ {% if league_state %} +
+
League Tournament
+
{{ tournament_state.league_tournament_number or 'N/A' }}
+
+ {% endif %} +
+ +
+ 📋 View Draft + 🎯 Score Tournament + 📺 Dashboard + +
+
+
+ {% endif %} + + + {% if not league_state and not tournament_state %} +
+

👥 Player Management

+ + +
+ + + +
+ + +
+ +
+
+ {% endif %} +
+ + + + + + + \ No newline at end of file diff --git a/TV_APP_V2/tournament_results.json b/TV_APP_V2/tournament_results.json new file mode 100644 index 0000000..63e99e4 --- /dev/null +++ b/TV_APP_V2/tournament_results.json @@ -0,0 +1,357 @@ +{ + "tournament_id": "2025-07-29T20:39:47.326034", + "tournament_type": "20_targets", + "participants": { + "4": { + "name": "Mateja Pleterski", + "targets": { + "1": { + "shot1": 0, + "shot2": 6 + }, + "2": { + "shot1": 7, + "shot2": 0 + }, + "3": { + "shot1": 3, + "shot2": 1 + }, + "4": { + "shot1": 1, + "shot2": 0 + }, + "5": { + "shot1": 10, + "shot2": 2 + }, + "6": { + "shot1": 10, + "shot2": 5 + }, + "7": { + "shot1": 2, + "shot2": 2 + }, + "8": { + "shot1": 7, + "shot2": 10 + }, + "9": { + "shot1": 1, + "shot2": 5 + }, + "10": { + "shot1": 5, + "shot2": 10 + }, + "11": { + "shot1": 1, + "shot2": 1 + }, + "12": { + "shot1": 2, + "shot2": 7 + }, + "13": { + "shot1": 7, + "shot2": 4 + }, + "14": { + "shot1": 9, + "shot2": 5 + }, + "15": { + "shot1": 0, + "shot2": 10 + }, + "16": { + "shot1": 8, + "shot2": 8 + }, + "17": { + "shot1": 2, + "shot2": 8 + }, + "18": { + "shot1": 10, + "shot2": 8 + }, + "19": { + "shot1": 6, + "shot2": 6 + }, + "20": { + "shot1": 4, + "shot2": 6 + } + }, + "total_score": 199, + "completed": true + }, + "2": { + "name": "Nik Pleterski", + "targets": { + "1": { + "shot1": 2, + "shot2": 5 + }, + "2": { + "shot1": 3, + "shot2": 7 + }, + "3": { + "shot1": 7, + "shot2": 7 + }, + "4": { + "shot1": 7, + "shot2": 2 + }, + "5": { + "shot1": 2, + "shot2": 4 + }, + "6": { + "shot1": 2, + "shot2": 6 + }, + "7": { + "shot1": 0, + "shot2": 5 + }, + "8": { + "shot1": 5, + "shot2": 4 + }, + "9": { + "shot1": 9, + "shot2": 7 + }, + "10": { + "shot1": 5, + "shot2": 8 + }, + "11": { + "shot1": 5, + "shot2": 8 + }, + "12": { + "shot1": 5, + "shot2": 4 + }, + "13": { + "shot1": 4, + "shot2": 7 + }, + "14": { + "shot1": 1, + "shot2": 10 + }, + "15": { + "shot1": 5, + "shot2": 3 + }, + "16": { + "shot1": 8, + "shot2": 5 + }, + "17": { + "shot1": 4, + "shot2": 9 + }, + "18": { + "shot1": 3, + "shot2": 1 + }, + "19": { + "shot1": 10, + "shot2": 10 + }, + "20": { + "shot1": 7, + "shot2": 0 + } + }, + "total_score": 206, + "completed": true + }, + "1": { + "name": "Domen Pleterski", + "targets": { + "1": { + "shot1": 6, + "shot2": 1 + }, + "2": { + "shot1": 6, + "shot2": 5 + }, + "3": { + "shot1": 7, + "shot2": 5 + }, + "4": { + "shot1": 7, + "shot2": 8 + }, + "5": { + "shot1": 10, + "shot2": 6 + }, + "6": { + "shot1": 7, + "shot2": 0 + }, + "7": { + "shot1": 1, + "shot2": 8 + }, + "8": { + "shot1": 3, + "shot2": 1 + }, + "9": { + "shot1": 6, + "shot2": 8 + }, + "10": { + "shot1": 3, + "shot2": 6 + }, + "11": { + "shot1": 1, + "shot2": 8 + }, + "12": { + "shot1": 0, + "shot2": 2 + }, + "13": { + "shot1": 1, + "shot2": 8 + }, + "14": { + "shot1": 5, + "shot2": 4 + }, + "15": { + "shot1": 1, + "shot2": 3 + }, + "16": { + "shot1": 1, + "shot2": 10 + }, + "17": { + "shot1": 0, + "shot2": 6 + }, + "18": { + "shot1": 6, + "shot2": 5 + }, + "19": { + "shot1": 8, + "shot2": 6 + }, + "20": { + "shot1": 4, + "shot2": 3 + } + }, + "total_score": 186, + "completed": true + }, + "3": { + "name": "Ivan Tandler", + "targets": { + "1": { + "shot1": 5, + "shot2": 8 + }, + "2": { + "shot1": 9, + "shot2": 3 + }, + "3": { + "shot1": 3, + "shot2": 1 + }, + "4": { + "shot1": 4, + "shot2": 8 + }, + "5": { + "shot1": 3, + "shot2": 1 + }, + "6": { + "shot1": 9, + "shot2": 5 + }, + "7": { + "shot1": 8, + "shot2": 0 + }, + "8": { + "shot1": 0, + "shot2": 2 + }, + "9": { + "shot1": 10, + "shot2": 6 + }, + "10": { + "shot1": 1, + "shot2": 3 + }, + "11": { + "shot1": 8, + "shot2": 3 + }, + "12": { + "shot1": 8, + "shot2": 8 + }, + "13": { + "shot1": 6, + "shot2": 3 + }, + "14": { + "shot1": 10, + "shot2": 2 + }, + "15": { + "shot1": 10, + "shot2": 2 + }, + "16": { + "shot1": 9, + "shot2": 2 + }, + "17": { + "shot1": 9, + "shot2": 4 + }, + "18": { + "shot1": 2, + "shot2": 10 + }, + "19": { + "shot1": 5, + "shot2": 9 + }, + "20": { + "shot1": 9, + "shot2": 5 + } + }, + "total_score": 213, + "completed": true + } + }, + "tournament_finished": true, + "created_at": "2025-07-29T20:39:47.326244", + "finished_at": "2025-07-29T20:39:58.449723" +} \ No newline at end of file