Refactor change...
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
env/
|
||||
venv/
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Data files (generated at runtime)
|
||||
data/tournament_state.json
|
||||
data/tournament_results.json
|
||||
data/league_state.json
|
||||
data/players.json
|
||||
|
||||
# Archives (user-generated)
|
||||
data/tournament_archives/
|
||||
data/league_archives/
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Temporary launcher scripts
|
||||
_run_server.py
|
||||
app_runner.py
|
||||
@@ -0,0 +1,93 @@
|
||||
# TV_APP V1.0.0 - Tournament Management System
|
||||
|
||||
A Flask-based web application for managing tournaments with multi-camera streaming support.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- Python 3.7+
|
||||
|
||||
### Installation & Run
|
||||
|
||||
```bash
|
||||
# Create virtual environment
|
||||
python3 -m venv venv
|
||||
|
||||
# Activate venv
|
||||
source venv/bin/activate # Linux/Mac
|
||||
# or
|
||||
venv\Scripts\activate # Windows
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run the app
|
||||
python3 tv_app.py
|
||||
```
|
||||
|
||||
The app will be available at: **http://localhost:5000**
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
TV_APP_V1.0.0/
|
||||
├── tv_app.py # Main Flask application (2,364 lines)
|
||||
├── requirements.txt # Python dependencies
|
||||
├── README.md # This file
|
||||
│
|
||||
├── app/ # Support modules
|
||||
│ ├── __init__.py
|
||||
│ ├── config.py # Configuration
|
||||
│ ├── models.py # Data models
|
||||
│ ├── storage.py # Persistent storage
|
||||
│ └── utils.py # Utilities
|
||||
│
|
||||
├── templates/ # HTML templates
|
||||
├── static/ # CSS, JS, images
|
||||
├── data/ # Runtime data (JSON state)
|
||||
└── locales/ # Translations (EN, SL)
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
✅ Tournament management with live scoring
|
||||
✅ Multi-camera streaming integration
|
||||
✅ Mobile interface for remote access
|
||||
✅ Tournament archiving & history
|
||||
✅ League management
|
||||
✅ Multi-language support (English & Slovenian)
|
||||
✅ JSON-based persistent storage
|
||||
|
||||
## Key URLs
|
||||
|
||||
- **Main Dashboard**: http://localhost:5000/
|
||||
- **Mobile Interface**: http://localhost:5000/mobile
|
||||
- **Archive**: http://localhost:5000/archive
|
||||
- **Tournament View**: http://localhost:5000/tournament
|
||||
- **Results**: http://localhost:5000/results
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Flask 3.0.0
|
||||
- Flask-SocketIO 5.3.4
|
||||
- python-socketio 5.9.0
|
||||
- python-engineio 4.7.1
|
||||
- python-dotenv 1.0.0
|
||||
|
||||
## Development
|
||||
|
||||
The app structure is simple and maintainable:
|
||||
- All Flask routes in `tv_app.py`
|
||||
- Support modules in `app/` package
|
||||
- Ready to split into blueprints if needed
|
||||
|
||||
## Notes
|
||||
|
||||
- Real-time WebSocket synchronization is disabled (not working reliably)
|
||||
- Each instance operates independently
|
||||
- All data is saved to JSON files in `data/` folder
|
||||
- Fully functional and production-ready
|
||||
|
||||
## How to Stop
|
||||
|
||||
Press `Ctrl+C` in the terminal where the app is running.
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
"""
|
||||
TV_APP V1.0.0 - App Package
|
||||
|
||||
This package contains support modules for the main Flask application.
|
||||
All routes are in tv_app.py in the project root.
|
||||
"""
|
||||
@@ -0,0 +1,13 @@
|
||||
"""
|
||||
Configuration for TV_APP V1.0.0
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
|
||||
class Config:
|
||||
"""Base configuration class"""
|
||||
SECRET_KEY = os.getenv('SECRET_KEY', 'your-secret-key-for-sessions')
|
||||
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
|
||||
HOST = os.getenv('HOST', '0.0.0.0')
|
||||
PORT = int(os.getenv('PORT', 5000))
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
"""
|
||||
Data models and business logic for TV_APP
|
||||
Handles all calculations and data structure creation
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
import random
|
||||
|
||||
NUM_CAMERAS = 6
|
||||
|
||||
|
||||
class Tournament:
|
||||
"""Tournament creation and management"""
|
||||
|
||||
@staticmethod
|
||||
def create_league(enabled_players, tournament_type):
|
||||
"""Create a new league with 5 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': 5,
|
||||
'current_tournament': 0,
|
||||
'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,
|
||||
'tournaments_participated': 0
|
||||
}
|
||||
|
||||
return league_data
|
||||
|
||||
@staticmethod
|
||||
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), NUM_CAMERAS):
|
||||
group = players_copy[i:i + NUM_CAMERAS]
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
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')
|
||||
|
||||
# Determine target count and shots per target
|
||||
if tournament_type == '40_targets':
|
||||
num_targets = 40
|
||||
shots_per_target = 2
|
||||
elif tournament_type == '4_targets':
|
||||
num_targets = 4
|
||||
shots_per_target = 5
|
||||
else: # 20_targets (default)
|
||||
num_targets = 20
|
||||
shots_per_target = 2
|
||||
|
||||
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'])
|
||||
|
||||
# Create target structure based on tournament type
|
||||
targets = {}
|
||||
for i in range(1, num_targets + 1):
|
||||
target = {}
|
||||
for j in range(1, shots_per_target + 1):
|
||||
target[f'shot{j}'] = None
|
||||
targets[str(i)] = target
|
||||
|
||||
results['participants'][player_id] = {
|
||||
'name': player['name'],
|
||||
'targets': targets,
|
||||
'total_score': 0,
|
||||
'completed': False
|
||||
}
|
||||
|
||||
return results
|
||||
|
||||
|
||||
class Scoring:
|
||||
"""Score calculation and ranking"""
|
||||
|
||||
@staticmethod
|
||||
def calculate_total_score(targets):
|
||||
"""Calculate total score from targets, treating None as 0"""
|
||||
total = 0
|
||||
for target in targets.values():
|
||||
for shot_key, shot_value in target.items():
|
||||
if shot_key.startswith('shot') and shot_value is not None:
|
||||
total += shot_value
|
||||
return total
|
||||
|
||||
@staticmethod
|
||||
def is_participant_completed(targets):
|
||||
"""Check if a participant has completed all targets"""
|
||||
for target in targets.values():
|
||||
for shot_key, shot_value in target.items():
|
||||
if shot_key.startswith('shot') and shot_value is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def calculate_league_final_scores(league_data):
|
||||
"""Calculate final league scores using best 4 tournaments"""
|
||||
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 4
|
||||
tournament_scores.sort(reverse=True)
|
||||
best_scores = tournament_scores[:4] if len(tournament_scores) > 4 else tournament_scores
|
||||
|
||||
participant['final_score'] = sum(best_scores)
|
||||
participant['tournaments_participated'] = len(tournament_scores)
|
||||
|
||||
@staticmethod
|
||||
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():
|
||||
# Calculate total 10s across all tournaments
|
||||
total_tens = sum(
|
||||
result.get('tens_count', 0) for result in data['tournament_results']
|
||||
if result.get('participated', False)
|
||||
)
|
||||
|
||||
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'],
|
||||
'total_tens': total_tens
|
||||
})
|
||||
|
||||
# Sort by final score (best 4 tournaments) descending, then by total 10s
|
||||
participants.sort(key=lambda x: (x['final_score'], x['total_tens']), reverse=True)
|
||||
|
||||
# Add rankings
|
||||
for i, participant in enumerate(participants):
|
||||
participant['rank'] = i + 1
|
||||
|
||||
return participants
|
||||
|
||||
@staticmethod
|
||||
def calculate_current_league_standings(league_data):
|
||||
"""Calculate current league standings during active league"""
|
||||
participants = []
|
||||
for player_id, data in league_data['participants'].items():
|
||||
tournament_scores = []
|
||||
completed_tournaments = 0
|
||||
total_tens = 0
|
||||
|
||||
for result in data['tournament_results']:
|
||||
if result['participated']:
|
||||
tournament_scores.append(result['score'])
|
||||
completed_tournaments += 1
|
||||
total_tens += result.get('tens_count', 0)
|
||||
|
||||
# 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 4 now
|
||||
tournament_scores.sort(reverse=True)
|
||||
projected_final = sum(tournament_scores[:4]) if len(tournament_scores) >= 4 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'],
|
||||
'total_tens': total_tens
|
||||
})
|
||||
|
||||
# Sort by current total score (descending), then by total 10s
|
||||
participants.sort(key=lambda x: (x['current_total'], x['total_tens']), reverse=True)
|
||||
|
||||
# Add rankings
|
||||
for i, participant in enumerate(participants):
|
||||
participant['rank'] = i + 1
|
||||
|
||||
return participants
|
||||
|
||||
|
||||
class RoundManager:
|
||||
"""Tournament round management"""
|
||||
|
||||
@staticmethod
|
||||
def get_current_round_data(tournament_state):
|
||||
"""Get current round data from tournament"""
|
||||
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
|
||||
|
||||
@staticmethod
|
||||
def get_tournament_format_description(tournament_type):
|
||||
"""Get tournament format description"""
|
||||
formats = {
|
||||
'20_targets': '20 Targets, 2 Shots Per Target',
|
||||
'40_targets': '40 Targets, 2 Shots Per Target',
|
||||
'4_targets': '4 Targets, 5 Shots Per Target'
|
||||
}
|
||||
return formats.get(tournament_type, 'Unknown Format')
|
||||
+312
@@ -0,0 +1,312 @@
|
||||
"""
|
||||
File I/O and data persistence for TV_APP
|
||||
Handles all JSON file operations and data archiving
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import glob
|
||||
from datetime import datetime
|
||||
|
||||
# File paths - organized in data directory
|
||||
SETTINGS_FILE = 'data/camera_settings.json'
|
||||
PLAYERS_FILE = 'data/players.json'
|
||||
TOURNAMENT_FILE = 'data/tournament_state.json'
|
||||
RESULTS_FILE = 'data/tournament_results.json'
|
||||
LEAGUE_FILE = 'data/league_state.json'
|
||||
ARCHIVE_DIR = 'data/tournament_archives'
|
||||
LEAGUE_ARCHIVE_DIR = 'data/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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FileStorage:
|
||||
"""Handle JSON file read/write operations"""
|
||||
|
||||
@staticmethod
|
||||
def _ensure_directory(directory):
|
||||
"""Ensure directory exists"""
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
@staticmethod
|
||||
def _read_json(filepath):
|
||||
"""Read JSON file safely"""
|
||||
try:
|
||||
if os.path.exists(filepath):
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except (json.JSONDecodeError, IOError) as e:
|
||||
print(f"Error reading {filepath}: {e}")
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _write_json(filepath, data):
|
||||
"""Write JSON file safely"""
|
||||
try:
|
||||
directory = os.path.dirname(filepath)
|
||||
FileStorage._ensure_directory(directory)
|
||||
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
return True
|
||||
except IOError as e:
|
||||
print(f"Error writing {filepath}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
class SettingsStorage(FileStorage):
|
||||
"""Manage camera and display settings"""
|
||||
|
||||
@staticmethod
|
||||
def load_settings():
|
||||
"""Load settings from JSON file, create with defaults if not exists"""
|
||||
settings = FileStorage._read_json(SETTINGS_FILE)
|
||||
|
||||
if settings is None:
|
||||
return DEFAULT_SETTINGS.copy()
|
||||
|
||||
# Ensure all required keys exist (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.get('camera_titles', {}):
|
||||
settings['camera_titles'][camera_id] = DEFAULT_SETTINGS['camera_titles'][camera_id]
|
||||
|
||||
return settings
|
||||
|
||||
@staticmethod
|
||||
def save_settings(settings):
|
||||
"""Save settings to JSON file"""
|
||||
return FileStorage._write_json(SETTINGS_FILE, settings)
|
||||
|
||||
|
||||
class PlayerStorage(FileStorage):
|
||||
"""Manage player data"""
|
||||
|
||||
DEFAULT_PLAYERS = {
|
||||
'players': [
|
||||
{'id': i, 'name': f'Player {i}', 'enabled': True}
|
||||
for i in range(1, 7) # 6 cameras
|
||||
]
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def load_players():
|
||||
"""Load players from JSON file, create with defaults if not exists"""
|
||||
players = FileStorage._read_json(PLAYERS_FILE)
|
||||
|
||||
if players is None:
|
||||
PlayerStorage.save_players(PlayerStorage.DEFAULT_PLAYERS)
|
||||
return PlayerStorage.DEFAULT_PLAYERS.copy()
|
||||
|
||||
return players
|
||||
|
||||
@staticmethod
|
||||
def save_players(players_data):
|
||||
"""Save players to JSON file"""
|
||||
return FileStorage._write_json(PLAYERS_FILE, players_data)
|
||||
|
||||
|
||||
class TournamentStorage(FileStorage):
|
||||
"""Manage tournament state"""
|
||||
|
||||
@staticmethod
|
||||
def load_tournament_state():
|
||||
"""Load tournament state from JSON file"""
|
||||
return FileStorage._read_json(TOURNAMENT_FILE)
|
||||
|
||||
@staticmethod
|
||||
def save_tournament_state(tournament_data):
|
||||
"""Save tournament state to JSON file"""
|
||||
return FileStorage._write_json(TOURNAMENT_FILE, tournament_data)
|
||||
|
||||
|
||||
class ResultsStorage(FileStorage):
|
||||
"""Manage tournament results"""
|
||||
|
||||
@staticmethod
|
||||
def load_results():
|
||||
"""Load results from JSON file"""
|
||||
return FileStorage._read_json(RESULTS_FILE)
|
||||
|
||||
@staticmethod
|
||||
def save_results(results_data):
|
||||
"""Save results to JSON file"""
|
||||
return FileStorage._write_json(RESULTS_FILE, results_data)
|
||||
|
||||
|
||||
class LeagueStorage(FileStorage):
|
||||
"""Manage league state"""
|
||||
|
||||
@staticmethod
|
||||
def load_league_state():
|
||||
"""Load league state from JSON file"""
|
||||
return FileStorage._read_json(LEAGUE_FILE)
|
||||
|
||||
@staticmethod
|
||||
def save_league_state(league_data):
|
||||
"""Save league state to JSON file"""
|
||||
return FileStorage._write_json(LEAGUE_FILE, league_data)
|
||||
|
||||
|
||||
class ArchiveStorage(FileStorage):
|
||||
"""Manage tournament and league archives"""
|
||||
|
||||
@staticmethod
|
||||
def archive_tournament(tournament_data, results_data):
|
||||
"""Archive completed tournament data"""
|
||||
try:
|
||||
FileStorage._ensure_directory(ARCHIVE_DIR)
|
||||
|
||||
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)
|
||||
|
||||
archive_data = {
|
||||
'tournament': tournament_data,
|
||||
'results': results_data,
|
||||
'archived_at': datetime.now().isoformat()
|
||||
}
|
||||
|
||||
success = FileStorage._write_json(archive_path, archive_data)
|
||||
if success:
|
||||
print(f"Tournament archived to: {archive_path}")
|
||||
return success
|
||||
except Exception as e:
|
||||
print(f"Error archiving tournament: {e}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def archive_league(league_data):
|
||||
"""Archive completed league data"""
|
||||
try:
|
||||
FileStorage._ensure_directory(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()
|
||||
}
|
||||
|
||||
success = FileStorage._write_json(archive_path, archive_data)
|
||||
if success:
|
||||
print(f"League archived to: {archive_path}")
|
||||
return success
|
||||
except Exception as e:
|
||||
print(f"Error archiving league: {e}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_archived_tournaments():
|
||||
"""Get list of standalone archived 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:
|
||||
data = FileStorage._read_json(file_path)
|
||||
if not data:
|
||||
continue
|
||||
|
||||
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 []
|
||||
|
||||
@staticmethod
|
||||
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:
|
||||
data = FileStorage._read_json(file_path)
|
||||
if not data:
|
||||
continue
|
||||
|
||||
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', 5),
|
||||
'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 []
|
||||
|
||||
@staticmethod
|
||||
def load_archive_file(filepath):
|
||||
"""Load a specific archive file"""
|
||||
return FileStorage._read_json(filepath)
|
||||
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
Utility functions for TV_APP
|
||||
Helper functions for translations, device detection, and common calculations
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from flask import request, session
|
||||
|
||||
DEFAULT_LANGUAGE = 'sl'
|
||||
|
||||
|
||||
def load_translations(language='sl'):
|
||||
"""Load translations for the specified language"""
|
||||
try:
|
||||
locale_file = os.path.join('locales', f'{language}.json')
|
||||
if os.path.exists(locale_file):
|
||||
with open(locale_file, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Error loading translations for {language}: {e}")
|
||||
|
||||
# Fallback to default language
|
||||
try:
|
||||
default_file = os.path.join('locales', f'{DEFAULT_LANGUAGE}.json')
|
||||
with open(default_file, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Error loading default translations: {e}")
|
||||
return {}
|
||||
|
||||
|
||||
def get_current_language():
|
||||
"""Get current language from session or default"""
|
||||
return session.get('language', DEFAULT_LANGUAGE)
|
||||
|
||||
|
||||
def get_translations():
|
||||
"""Get translations for current language"""
|
||||
return load_translations(get_current_language())
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def calculate_tens_from_targets(targets):
|
||||
"""Calculate the number of 10s from a targets dictionary"""
|
||||
tens_count = 0
|
||||
if not targets:
|
||||
return 0
|
||||
|
||||
for target in targets.values():
|
||||
if isinstance(target, dict):
|
||||
for shot_key, shot_value in target.items():
|
||||
if shot_key.startswith('shot') and shot_value == 10:
|
||||
tens_count += 1
|
||||
|
||||
return tens_count
|
||||
|
||||
|
||||
def validate_player_data(player_data):
|
||||
"""Validate player data structure"""
|
||||
required_fields = ['id', 'name', 'enabled']
|
||||
return all(field in player_data for field in required_fields)
|
||||
|
||||
|
||||
def validate_settings(settings):
|
||||
"""Validate settings structure"""
|
||||
required_sections = ['camera_titles', 'display_options']
|
||||
return all(section in settings for section in required_sections)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,406 +0,0 @@
|
||||
{
|
||||
"league": {
|
||||
"league_id": "league_20251031_184134",
|
||||
"created_at": "2025-10-31T18:41:34.562185",
|
||||
"tournament_type": "4_targets",
|
||||
"total_tournaments": 5,
|
||||
"current_tournament": 0,
|
||||
"participants": {
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"2": {
|
||||
"name": "Nik Pleterski",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"6": {
|
||||
"name": "Mateja Senica",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"8": {
|
||||
"name": "Franc \u017digart",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"10": {
|
||||
"name": "Mitja \u010ceh",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"13": {
|
||||
"name": "Angelca Mrak",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"14": {
|
||||
"name": "Karli Proje",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"16": {
|
||||
"name": "Silvo Poro\u010dnik",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"18": {
|
||||
"name": "Matja\u017e Pleterski",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"19": {
|
||||
"name": "Franc Rizmal",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"22": {
|
||||
"name": "Doris Fesel",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"23": {
|
||||
"name": "Robi Krautberger",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"24": {
|
||||
"name": "Jo\u017ee Verdinek",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"25": {
|
||||
"name": "Andrej Herman",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"26": {
|
||||
"name": "Jakob Herman",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"27": {
|
||||
"name": "Janez Mrak",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"28": {
|
||||
"name": "An\u017ee Kolar",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"29": {
|
||||
"name": "Alen Kolar",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"30": {
|
||||
"name": "Maja Hirtl",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"31": {
|
||||
"name": "Dejan Ku\u010dnik",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"32": {
|
||||
"name": "David Strni\u0161a",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"33": {
|
||||
"name": "Namir Uzunovi\u0107",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"34": {
|
||||
"name": "Jo\u017ee Planin\u0161ec",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"35": {
|
||||
"name": "Vanja Kolar",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"36": {
|
||||
"name": "Klara Wankmuller",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"37": {
|
||||
"name": "Milan Stramec",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"38": {
|
||||
"name": "Bojan Sudar",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"39": {
|
||||
"name": "Tia Sudar",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"40": {
|
||||
"name": "Jaka Cvar",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"41": {
|
||||
"name": "Tadej \u0160truc",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"42": {
|
||||
"name": "Jure Glaser",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"43": {
|
||||
"name": "Marko Pokr\u017enik",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
},
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"joker_used": false,
|
||||
"tournament_results": [],
|
||||
"total_score": 0,
|
||||
"final_score": 0,
|
||||
"tournaments_participated": 0
|
||||
}
|
||||
},
|
||||
"completed_tournaments": [],
|
||||
"league_finished": false
|
||||
},
|
||||
"archived_at": "2025-10-31T18:41:38.976988"
|
||||
}
|
||||
-249
@@ -1,249 +0,0 @@
|
||||
{
|
||||
"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": true
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Mateja Senica",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Franc \u017digart",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Mitja \u010ceh",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"name": "Angelca Mrak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"name": "Karli Proje",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"name": "Silvo Poro\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"name": "Matja\u017e Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"name": "Franc Rizmal",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"name": "Doris Fesel",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"name": "Robi Krautberger",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"name": "Jo\u017ee Verdinek",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "Andrej Herman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"name": "Jakob Herman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"name": "Janez Mrak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"name": "An\u017ee Kolar",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"name": "Alen Kolar",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"name": "Maja Hirtl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"name": "Dejan Ku\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"name": "David Strni\u0161a",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"name": "Namir Uzunovi\u0107",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"name": "Jo\u017ee Planin\u0161ec",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"name": "Vanja Kolar",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 36,
|
||||
"name": "Klara Wankmuller",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"name": "Milan Stramec",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 38,
|
||||
"name": "Bojan Sudar",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 39,
|
||||
"name": "Tia Sudar",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"name": "Jaka Cvar",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 41,
|
||||
"name": "Tadej \u0160truc",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 42,
|
||||
"name": "Jure Glaser",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 43,
|
||||
"name": "Marko Pokr\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Flask==3.0.0
|
||||
python-dotenv==1.0.0
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"header_text_size": "14px"
|
||||
}
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
TV_APP V1.0.0 - One-Click Launcher
|
||||
Automatically installs dependencies and starts the web application
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import webbrowser
|
||||
import time
|
||||
import importlib.util
|
||||
|
||||
def check_python_version():
|
||||
"""Check if Python 3.7+ is available"""
|
||||
if sys.version_info < (3, 7):
|
||||
print("ERROR: Python 3.7+ is required")
|
||||
print(f"You have Python {sys.version}")
|
||||
return False
|
||||
return True
|
||||
|
||||
def check_and_install_flask():
|
||||
"""Check if Flask is installed, install if not"""
|
||||
flask_spec = importlib.util.find_spec("flask")
|
||||
|
||||
if flask_spec is not None:
|
||||
import flask
|
||||
print(f"✓ Flask is installed: v{flask.__version__}")
|
||||
return True
|
||||
|
||||
print("⚠ Flask not found. Installing...")
|
||||
try:
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "flask", "-q"])
|
||||
print("✓ Flask installed successfully")
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
print("ERROR: Failed to install Flask")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Main installation and startup routine"""
|
||||
print("\n" + "="*70)
|
||||
print(" TV_APP V1.0.0 - Installation & Launcher")
|
||||
print("="*70 + "\n")
|
||||
|
||||
# Check Python version
|
||||
print("[1/4] Checking Python version...")
|
||||
if not check_python_version():
|
||||
print("\nPlease install Python 3.7 or higher")
|
||||
input("Press Enter to exit...")
|
||||
return False
|
||||
|
||||
import flask
|
||||
print(f"✓ Python {sys.version.split()[0]} found\n")
|
||||
|
||||
# Check Flask
|
||||
print("[2/4] Checking Flask installation...")
|
||||
if not check_and_install_flask():
|
||||
input("Press Enter to exit...")
|
||||
return False
|
||||
print()
|
||||
|
||||
# Find the app directory (handle symlinks and copies)
|
||||
print("[3/4] Locating application directory...")
|
||||
|
||||
# Start with script location
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# Resolve symlinks
|
||||
if os.path.islink(__file__):
|
||||
script_dir = os.path.dirname(os.path.abspath(os.readlink(__file__)))
|
||||
|
||||
app_path = os.path.join(script_dir, "app.py")
|
||||
|
||||
# If app.py not found, search for it
|
||||
if not os.path.exists(app_path):
|
||||
print(f" Searching for app.py near {script_dir}...")
|
||||
|
||||
# Check parent directory
|
||||
parent_dir = os.path.dirname(script_dir)
|
||||
app_path = os.path.join(parent_dir, "app.py")
|
||||
if os.path.exists(app_path):
|
||||
script_dir = parent_dir
|
||||
else:
|
||||
print(f"ERROR: app.py not found")
|
||||
print(f" Checked: {script_dir}")
|
||||
print(f" Checked: {parent_dir}")
|
||||
input("Press Enter to exit...")
|
||||
return False
|
||||
|
||||
print(f"✓ Application found: {app_path}\n")
|
||||
|
||||
# Start the app
|
||||
print("[4/4] Starting web application...\n")
|
||||
print("="*70)
|
||||
print(" TV_APP is starting...")
|
||||
print("="*70)
|
||||
print("\nThe application will be available at: http://localhost:5000")
|
||||
print("Press Ctrl+C to stop the server\n")
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# Open browser
|
||||
try:
|
||||
webbrowser.open("http://localhost:5000", new=1)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Change to app directory and run
|
||||
os.chdir(script_dir)
|
||||
|
||||
try:
|
||||
# Import and run the Flask app
|
||||
import app
|
||||
app.app.run(host='0.0.0.0', port=5000, debug=True, use_reloader=False)
|
||||
except ImportError as e:
|
||||
print(f"ERROR: Could not import app.py: {e}")
|
||||
input("Press Enter to exit...")
|
||||
return False
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nServer stopped by user")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"ERROR: {e}")
|
||||
input("Press Enter to exit...")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* WebSocket Client - DEPRECATED
|
||||
* This file is no longer used. WebSocket/SocketIO support has been removed.
|
||||
*/
|
||||
|
||||
console.log('WebSocket support has been removed from this application.');
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"1": {
|
||||
"number": 1,
|
||||
"title": "Stream 1",
|
||||
"url": "http://192.168.0.103:9081",
|
||||
"active": true
|
||||
},
|
||||
"2": {
|
||||
"number": 2,
|
||||
"title": "Stream 2",
|
||||
"url": "http://192.168.0.103:9082",
|
||||
"active": true
|
||||
},
|
||||
"3": {
|
||||
"number": 3,
|
||||
"title": "Stream 3",
|
||||
"url": "http://192.168.0.103:9083",
|
||||
"active": true
|
||||
},
|
||||
"4": {
|
||||
"number": 4,
|
||||
"title": "Stream 4",
|
||||
"url": "http://192.168.0.103:9084",
|
||||
"active": true
|
||||
},
|
||||
"5": {
|
||||
"number": 5,
|
||||
"title": "Stream 5",
|
||||
"url": "http://192.168.0.103:9085",
|
||||
"active": true
|
||||
},
|
||||
"6": {
|
||||
"number": 6,
|
||||
"title": "Stream 6",
|
||||
"url": "http://192.168.0.103:9086",
|
||||
"active": true
|
||||
},
|
||||
"_last_updated": 1757351904.1407912
|
||||
}
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"git.ignoreLimitWarning": true
|
||||
}
|
||||
@@ -1,759 +0,0 @@
|
||||
{
|
||||
"tournament": {
|
||||
"rounds": [
|
||||
{
|
||||
"round_number": 1,
|
||||
"players": [
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Mateja Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Ivan Tandler",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"round_number": 2,
|
||||
"players": [
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
},
|
||||
{
|
||||
"round_number": 3,
|
||||
"players": [
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Domen Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-08-30T13:09:30.384521",
|
||||
"total_players": 18,
|
||||
"total_rounds": 3,
|
||||
"current_round": 1,
|
||||
"tournament_type": "4_targets"
|
||||
},
|
||||
"results": {
|
||||
"tournament_id": "2025-08-30T13:09:30.384521",
|
||||
"tournament_type": "4_targets",
|
||||
"participants": {
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 0,
|
||||
"completed": true
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 7,
|
||||
"shot3": 7,
|
||||
"shot4": 5,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 7,
|
||||
"shot4": 6,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 8,
|
||||
"shot3": 7,
|
||||
"shot4": 6,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 142,
|
||||
"completed": true
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 0,
|
||||
"completed": true
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 180,
|
||||
"completed": true
|
||||
},
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 10,
|
||||
"shot4": 9,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 10,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 179,
|
||||
"completed": true
|
||||
},
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 6,
|
||||
"shot4": 4,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 7,
|
||||
"shot3": 6,
|
||||
"shot4": 3,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 4,
|
||||
"shot3": 4,
|
||||
"shot4": 2,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 7,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 4,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 102,
|
||||
"completed": true
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 2,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 5,
|
||||
"shot3": 2,
|
||||
"shot4": 2,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 7,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 5,
|
||||
"shot3": 3,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 72,
|
||||
"completed": true
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 6,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 161,
|
||||
"completed": true
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 6,
|
||||
"shot4": 4,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 8,
|
||||
"shot3": 6,
|
||||
"shot4": 6,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 7,
|
||||
"shot3": 4,
|
||||
"shot4": 1,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 124,
|
||||
"completed": true
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 167,
|
||||
"completed": true
|
||||
},
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 7,
|
||||
"shot3": 6,
|
||||
"shot4": 4,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 3
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 3,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 4
|
||||
}
|
||||
},
|
||||
"total_score": 122,
|
||||
"completed": true
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 174,
|
||||
"completed": true
|
||||
},
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 8,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 144,
|
||||
"completed": true
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 0,
|
||||
"completed": true
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 10,
|
||||
"shot4": 1,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 4,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 7,
|
||||
"shot3": 2,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 71,
|
||||
"completed": true
|
||||
},
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 10,
|
||||
"shot4": 9,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 180,
|
||||
"completed": true
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 172,
|
||||
"completed": true
|
||||
},
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 9,
|
||||
"shot3": 7,
|
||||
"shot4": 6,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 155,
|
||||
"completed": true
|
||||
}
|
||||
},
|
||||
"tournament_finished": true,
|
||||
"created_at": "2025-08-30T13:09:30.386527",
|
||||
"finished_at": "2025-08-30T15:33:42.405404"
|
||||
},
|
||||
"archived_at": "2025-08-30T15:33:42.405434"
|
||||
}
|
||||
@@ -1,759 +0,0 @@
|
||||
{
|
||||
"tournament": {
|
||||
"rounds": [
|
||||
{
|
||||
"round_number": 1,
|
||||
"players": [
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Mateja Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Ivan Tandler",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"round_number": 2,
|
||||
"players": [
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
},
|
||||
{
|
||||
"round_number": 3,
|
||||
"players": [
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Domen Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-09-08T19:19:14.422360",
|
||||
"total_players": 18,
|
||||
"total_rounds": 3,
|
||||
"current_round": 1,
|
||||
"tournament_type": "4_targets"
|
||||
},
|
||||
"results": {
|
||||
"tournament_id": "2025-09-08T19:19:14.422360",
|
||||
"tournament_type": "4_targets",
|
||||
"participants": {
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 2,
|
||||
"shot4": 10,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 3,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 2,
|
||||
"shot3": 6,
|
||||
"shot4": 0,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 7,
|
||||
"shot2": 9,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 129,
|
||||
"completed": true
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 8,
|
||||
"shot4": 10,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 4,
|
||||
"shot3": 7,
|
||||
"shot4": 7,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 10,
|
||||
"shot3": 1,
|
||||
"shot4": 8,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 8,
|
||||
"shot3": 4,
|
||||
"shot4": 7,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 111,
|
||||
"completed": true
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 0,
|
||||
"shot3": 9,
|
||||
"shot4": 10,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 0,
|
||||
"shot3": 6,
|
||||
"shot4": 10,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 8,
|
||||
"shot3": 2,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 1,
|
||||
"shot3": 6,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 97,
|
||||
"completed": true
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 9,
|
||||
"shot3": 1,
|
||||
"shot4": 9,
|
||||
"shot5": 10
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 9,
|
||||
"shot3": 10,
|
||||
"shot4": 10,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 1,
|
||||
"shot3": 7,
|
||||
"shot4": 4,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 0,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 119,
|
||||
"completed": true
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 9,
|
||||
"shot3": 4,
|
||||
"shot4": 6,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 8,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 3
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 0,
|
||||
"shot3": 6,
|
||||
"shot4": 6,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 4,
|
||||
"shot3": 0,
|
||||
"shot4": 1,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 110,
|
||||
"completed": true
|
||||
},
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 9,
|
||||
"shot3": 10,
|
||||
"shot4": 7,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 4,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 1,
|
||||
"shot3": 6,
|
||||
"shot4": 2,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 134,
|
||||
"completed": true
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 6,
|
||||
"shot3": 4,
|
||||
"shot4": 3,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 5,
|
||||
"shot3": 1,
|
||||
"shot4": 1,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 4,
|
||||
"shot3": 0,
|
||||
"shot4": 8,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 1,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 101,
|
||||
"completed": true
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 4,
|
||||
"shot3": 1,
|
||||
"shot4": 2,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 0,
|
||||
"shot3": 1,
|
||||
"shot4": 2,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 10,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 7,
|
||||
"shot3": 4,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
}
|
||||
},
|
||||
"total_score": 79,
|
||||
"completed": true
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 6,
|
||||
"shot3": 7,
|
||||
"shot4": 2,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 4,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 3,
|
||||
"shot3": 8,
|
||||
"shot4": 3,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 10,
|
||||
"shot3": 2,
|
||||
"shot4": 9,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 101,
|
||||
"completed": true
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 10,
|
||||
"shot3": 7,
|
||||
"shot4": 10,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 6,
|
||||
"shot3": 0,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 6,
|
||||
"shot3": 8,
|
||||
"shot4": 9,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 1,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 110,
|
||||
"completed": true
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 7,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 1,
|
||||
"shot3": 6,
|
||||
"shot4": 4,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 7,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 4,
|
||||
"shot3": 8,
|
||||
"shot4": 9,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 89,
|
||||
"completed": true
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 9,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 5,
|
||||
"shot4": 4,
|
||||
"shot5": 5
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 6,
|
||||
"shot3": 1,
|
||||
"shot4": 9,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 2,
|
||||
"shot3": 1,
|
||||
"shot4": 2,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 107,
|
||||
"completed": true
|
||||
},
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 10,
|
||||
"shot3": 10,
|
||||
"shot4": 9,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 10,
|
||||
"shot3": 5,
|
||||
"shot4": 10,
|
||||
"shot5": 3
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 7,
|
||||
"shot3": 4,
|
||||
"shot4": 0,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 1,
|
||||
"shot3": 1,
|
||||
"shot4": 9,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 107,
|
||||
"completed": true
|
||||
},
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 9,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 3,
|
||||
"shot3": 7,
|
||||
"shot4": 2,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 4,
|
||||
"shot3": 4,
|
||||
"shot4": 5,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 95,
|
||||
"completed": true
|
||||
},
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 3,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 6,
|
||||
"shot2": 3,
|
||||
"shot3": 7,
|
||||
"shot4": 3,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 10,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 118,
|
||||
"completed": true
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 9,
|
||||
"shot3": 6,
|
||||
"shot4": 7,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 4,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 0,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 82,
|
||||
"completed": true
|
||||
},
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 7,
|
||||
"shot3": 1,
|
||||
"shot4": 0,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 0,
|
||||
"shot3": 3,
|
||||
"shot4": 3,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 2,
|
||||
"shot3": 0,
|
||||
"shot4": 3,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 0,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 9,
|
||||
"shot3": 4,
|
||||
"shot4": 9,
|
||||
"shot5": 2
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 9,
|
||||
"shot3": 0,
|
||||
"shot4": 4,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 90,
|
||||
"completed": true
|
||||
}
|
||||
},
|
||||
"tournament_finished": true,
|
||||
"created_at": "2025-09-08T19:19:14.422540",
|
||||
"finished_at": "2025-09-08T19:19:26.929175"
|
||||
},
|
||||
"archived_at": "2025-09-08T19:19:26.929203"
|
||||
}
|
||||
@@ -1,759 +0,0 @@
|
||||
{
|
||||
"tournament": {
|
||||
"rounds": [
|
||||
{
|
||||
"round_number": 1,
|
||||
"players": [
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Mateja Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Domen Pleterski",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"round_number": 2,
|
||||
"players": [
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
},
|
||||
{
|
||||
"round_number": 3,
|
||||
"players": [
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Ivan Tandler",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-09-08T19:23:24.597390",
|
||||
"total_players": 18,
|
||||
"total_rounds": 3,
|
||||
"current_round": 1,
|
||||
"tournament_type": "4_targets"
|
||||
},
|
||||
"results": {
|
||||
"tournament_id": "2025-09-08T19:23:24.597390",
|
||||
"tournament_type": "4_targets",
|
||||
"participants": {
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 2,
|
||||
"shot3": 4,
|
||||
"shot4": 6,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 4,
|
||||
"shot4": 3,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 4,
|
||||
"shot3": 3,
|
||||
"shot4": 3,
|
||||
"shot5": 2
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 7,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 67,
|
||||
"completed": true
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 10,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 9,
|
||||
"shot3": 5,
|
||||
"shot4": 4,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 2,
|
||||
"shot3": 8,
|
||||
"shot4": 0,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 3,
|
||||
"shot4": 5,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 85,
|
||||
"completed": true
|
||||
},
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 10,
|
||||
"shot3": 1,
|
||||
"shot4": 1,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 4,
|
||||
"shot3": 6,
|
||||
"shot4": 2,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 4,
|
||||
"shot3": 9,
|
||||
"shot4": 6,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 106,
|
||||
"completed": true
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 3,
|
||||
"shot2": 2,
|
||||
"shot3": 3,
|
||||
"shot4": 3,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 6,
|
||||
"shot3": 7,
|
||||
"shot4": 0,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 8,
|
||||
"shot3": 1,
|
||||
"shot4": 7,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 4,
|
||||
"shot3": 3,
|
||||
"shot4": 8,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 78,
|
||||
"completed": true
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 3,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 5,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 8,
|
||||
"shot3": 0,
|
||||
"shot4": 7,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 10,
|
||||
"shot3": 2,
|
||||
"shot4": 9,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 3,
|
||||
"shot4": 2,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 4,
|
||||
"shot3": 10,
|
||||
"shot4": 9,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 5,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 6,
|
||||
"shot3": 6,
|
||||
"shot4": 3,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 104,
|
||||
"completed": true
|
||||
},
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 8,
|
||||
"shot3": 6,
|
||||
"shot4": 9,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 0,
|
||||
"shot3": 9,
|
||||
"shot4": 2,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 0,
|
||||
"shot3": 4,
|
||||
"shot4": 10,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 4,
|
||||
"shot3": 2,
|
||||
"shot4": 7,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 99,
|
||||
"completed": true
|
||||
},
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 7,
|
||||
"shot4": 9,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 9,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 3,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 4,
|
||||
"shot2": 10,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 112,
|
||||
"completed": true
|
||||
},
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 4,
|
||||
"shot2": 9,
|
||||
"shot3": 2,
|
||||
"shot4": 4,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 9,
|
||||
"shot3": 4,
|
||||
"shot4": 3,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 7,
|
||||
"shot3": 9,
|
||||
"shot4": 0,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 0,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 106,
|
||||
"completed": true
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 10,
|
||||
"shot3": 4,
|
||||
"shot4": 2,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 9,
|
||||
"shot3": 2,
|
||||
"shot4": 7,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 8,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 10,
|
||||
"shot4": 0,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 116,
|
||||
"completed": true
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 6,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 6,
|
||||
"shot3": 7,
|
||||
"shot4": 6,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 8,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 2,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 125,
|
||||
"completed": true
|
||||
},
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 0,
|
||||
"shot3": 9,
|
||||
"shot4": 6,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 4,
|
||||
"shot3": 6,
|
||||
"shot4": 4,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 9,
|
||||
"shot3": 3,
|
||||
"shot4": 4,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 2,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 81,
|
||||
"completed": true
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 3,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 5,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 4,
|
||||
"shot3": 2,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 8,
|
||||
"shot3": 5,
|
||||
"shot4": 8,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 5,
|
||||
"shot3": 3,
|
||||
"shot4": 1,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 95,
|
||||
"completed": true
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 7,
|
||||
"shot4": 7,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 1,
|
||||
"shot4": 10,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 0,
|
||||
"shot3": 3,
|
||||
"shot4": 9,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 2,
|
||||
"shot3": 8,
|
||||
"shot4": 4,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 110,
|
||||
"completed": true
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 1,
|
||||
"shot3": 8,
|
||||
"shot4": 9,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 3,
|
||||
"shot3": 10,
|
||||
"shot4": 6,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 6,
|
||||
"shot3": 8,
|
||||
"shot4": 0,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 0,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 101,
|
||||
"completed": true
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 4,
|
||||
"shot2": 1,
|
||||
"shot3": 9,
|
||||
"shot4": 2,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 8,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 5
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 7,
|
||||
"shot3": 3,
|
||||
"shot4": 1,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 4,
|
||||
"shot2": 7,
|
||||
"shot3": 3,
|
||||
"shot4": 1,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 77,
|
||||
"completed": true
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 9,
|
||||
"shot3": 7,
|
||||
"shot4": 3,
|
||||
"shot5": 10
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 2,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 8,
|
||||
"shot3": 10,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 2,
|
||||
"shot3": 9,
|
||||
"shot4": 1,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 81,
|
||||
"completed": true
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 0,
|
||||
"shot3": 9,
|
||||
"shot4": 5,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 9,
|
||||
"shot3": 5,
|
||||
"shot4": 7,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 5,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 4
|
||||
}
|
||||
},
|
||||
"total_score": 83,
|
||||
"completed": true
|
||||
}
|
||||
},
|
||||
"tournament_finished": true,
|
||||
"created_at": "2025-09-08T19:23:24.597575",
|
||||
"finished_at": "2025-09-08T19:23:34.271264"
|
||||
},
|
||||
"archived_at": "2025-09-08T19:23:34.271291"
|
||||
}
|
||||
@@ -1,759 +0,0 @@
|
||||
{
|
||||
"tournament": {
|
||||
"rounds": [
|
||||
{
|
||||
"round_number": 1,
|
||||
"players": [
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Domen Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"round_number": 2,
|
||||
"players": [
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Mateja Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
},
|
||||
{
|
||||
"round_number": 3,
|
||||
"players": [
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Ivan Tandler",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-09-08T19:26:24.708355",
|
||||
"total_players": 18,
|
||||
"total_rounds": 3,
|
||||
"current_round": 1,
|
||||
"tournament_type": "4_targets"
|
||||
},
|
||||
"results": {
|
||||
"tournament_id": "2025-09-08T19:26:24.708355",
|
||||
"tournament_type": "4_targets",
|
||||
"participants": {
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 4,
|
||||
"shot3": 0,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 7,
|
||||
"shot3": 5,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 7,
|
||||
"shot3": 8,
|
||||
"shot4": 9,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 6,
|
||||
"shot3": 2,
|
||||
"shot4": 4,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 98,
|
||||
"completed": true
|
||||
},
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 7,
|
||||
"shot3": 10,
|
||||
"shot4": 4,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 5,
|
||||
"shot3": 5,
|
||||
"shot4": 0,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 1,
|
||||
"shot3": 3,
|
||||
"shot4": 4,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 3,
|
||||
"shot3": 3,
|
||||
"shot4": 10,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 94,
|
||||
"completed": true
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 8,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 4,
|
||||
"shot3": 4,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 2,
|
||||
"shot3": 5,
|
||||
"shot4": 0,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 4,
|
||||
"shot3": 2,
|
||||
"shot4": 4,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 98,
|
||||
"completed": true
|
||||
},
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 7,
|
||||
"shot3": 3,
|
||||
"shot4": 4,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 2,
|
||||
"shot3": 0,
|
||||
"shot4": 5,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 89,
|
||||
"completed": true
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 8,
|
||||
"shot3": 2,
|
||||
"shot4": 8,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 9,
|
||||
"shot3": 4,
|
||||
"shot4": 10,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 4,
|
||||
"shot3": 6,
|
||||
"shot4": 8,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 1,
|
||||
"shot3": 7,
|
||||
"shot4": 10,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 107,
|
||||
"completed": true
|
||||
},
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 3,
|
||||
"shot2": 10,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 7,
|
||||
"shot3": 9,
|
||||
"shot4": 7,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 8,
|
||||
"shot3": 3,
|
||||
"shot4": 7,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 7,
|
||||
"shot3": 9,
|
||||
"shot4": 7,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 115,
|
||||
"completed": true
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 1,
|
||||
"shot3": 4,
|
||||
"shot4": 8,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 6,
|
||||
"shot3": 4,
|
||||
"shot4": 3,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 9,
|
||||
"shot3": 10,
|
||||
"shot4": 6,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 87,
|
||||
"completed": true
|
||||
},
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 8,
|
||||
"shot3": 4,
|
||||
"shot4": 10,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 2,
|
||||
"shot3": 5,
|
||||
"shot4": 5,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 10,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 89,
|
||||
"completed": true
|
||||
},
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 10,
|
||||
"shot3": 1,
|
||||
"shot4": 7,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 9,
|
||||
"shot4": 2,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 1,
|
||||
"shot3": 4,
|
||||
"shot4": 1,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 6,
|
||||
"shot3": 8,
|
||||
"shot4": 4,
|
||||
"shot5": 4
|
||||
}
|
||||
},
|
||||
"total_score": 97,
|
||||
"completed": true
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 10,
|
||||
"shot3": 4,
|
||||
"shot4": 8,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 6,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 6,
|
||||
"shot2": 9,
|
||||
"shot3": 1,
|
||||
"shot4": 6,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 2,
|
||||
"shot3": 5,
|
||||
"shot4": 0,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 92,
|
||||
"completed": true
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 6,
|
||||
"shot3": 9,
|
||||
"shot4": 3,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 6,
|
||||
"shot4": 4,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 4,
|
||||
"shot4": 4,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 0,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 84,
|
||||
"completed": true
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 5,
|
||||
"shot3": 2,
|
||||
"shot4": 7,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 3,
|
||||
"shot3": 8,
|
||||
"shot4": 0,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 5,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 7,
|
||||
"shot3": 6,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 106,
|
||||
"completed": true
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 4,
|
||||
"shot3": 4,
|
||||
"shot4": 9,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 0,
|
||||
"shot3": 5,
|
||||
"shot4": 4,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 4,
|
||||
"shot3": 7,
|
||||
"shot4": 5,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 0,
|
||||
"shot4": 1,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 87,
|
||||
"completed": true
|
||||
},
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 10,
|
||||
"shot3": 5,
|
||||
"shot4": 8,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 8,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 5,
|
||||
"shot3": 2,
|
||||
"shot4": 6,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 2,
|
||||
"shot3": 1,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 90,
|
||||
"completed": true
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 10,
|
||||
"shot3": 0,
|
||||
"shot4": 8,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 9,
|
||||
"shot3": 3,
|
||||
"shot4": 6,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 8,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 7,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 126,
|
||||
"completed": true
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 7,
|
||||
"shot3": 3,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 5,
|
||||
"shot4": 3,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 3,
|
||||
"shot3": 5,
|
||||
"shot4": 2,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 0,
|
||||
"shot3": 3,
|
||||
"shot4": 1,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 84,
|
||||
"completed": true
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 7,
|
||||
"shot3": 8,
|
||||
"shot4": 2,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 10,
|
||||
"shot3": 5,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 1,
|
||||
"shot3": 0,
|
||||
"shot4": 4,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 0,
|
||||
"shot3": 7,
|
||||
"shot4": 4,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 7,
|
||||
"shot3": 3,
|
||||
"shot4": 1,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 1,
|
||||
"shot4": 3,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 5,
|
||||
"shot3": 3,
|
||||
"shot4": 9,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 68,
|
||||
"completed": true
|
||||
}
|
||||
},
|
||||
"tournament_finished": true,
|
||||
"created_at": "2025-09-08T19:26:24.708574",
|
||||
"finished_at": "2025-09-08T19:26:31.871139"
|
||||
},
|
||||
"archived_at": "2025-09-08T19:26:31.871173"
|
||||
}
|
||||
@@ -1,759 +0,0 @@
|
||||
{
|
||||
"tournament": {
|
||||
"rounds": [
|
||||
{
|
||||
"round_number": 1,
|
||||
"players": [
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"round_number": 2,
|
||||
"players": [
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Ivan Tandler",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Domen Pleterski",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
},
|
||||
{
|
||||
"round_number": 3,
|
||||
"players": [
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Mateja Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-09-08T19:27:18.397859",
|
||||
"total_players": 18,
|
||||
"total_rounds": 3,
|
||||
"current_round": 1,
|
||||
"tournament_type": "4_targets"
|
||||
},
|
||||
"results": {
|
||||
"tournament_id": "2025-09-08T19:27:18.397859",
|
||||
"tournament_type": "4_targets",
|
||||
"participants": {
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 0,
|
||||
"shot3": 1,
|
||||
"shot4": 2,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 9,
|
||||
"shot3": 1,
|
||||
"shot4": 4,
|
||||
"shot5": 3
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 6,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 7,
|
||||
"shot3": 8,
|
||||
"shot4": 1,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 85,
|
||||
"completed": true
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 3,
|
||||
"shot4": 5,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 6,
|
||||
"shot2": 3,
|
||||
"shot3": 8,
|
||||
"shot4": 2,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 4,
|
||||
"shot2": 6,
|
||||
"shot3": 2,
|
||||
"shot4": 9,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 69,
|
||||
"completed": true
|
||||
},
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 2,
|
||||
"shot4": 6,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 1,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 7,
|
||||
"shot4": 3,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 3,
|
||||
"shot3": 3,
|
||||
"shot4": 9,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 80,
|
||||
"completed": true
|
||||
},
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 0,
|
||||
"shot3": 6,
|
||||
"shot4": 7,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 7,
|
||||
"shot3": 10,
|
||||
"shot4": 10,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 3,
|
||||
"shot4": 9,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 9,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 118,
|
||||
"completed": true
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 8,
|
||||
"shot3": 3,
|
||||
"shot4": 0,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 9,
|
||||
"shot4": 10,
|
||||
"shot5": 3
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 4,
|
||||
"shot3": 8,
|
||||
"shot4": 10,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 4,
|
||||
"shot2": 8,
|
||||
"shot3": 1,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 118,
|
||||
"completed": true
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 3,
|
||||
"shot3": 4,
|
||||
"shot4": 9,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 8,
|
||||
"shot3": 1,
|
||||
"shot4": 3,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 6,
|
||||
"shot4": 9,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 6,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 7,
|
||||
"shot3": 2,
|
||||
"shot4": 10,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 10,
|
||||
"shot3": 1,
|
||||
"shot4": 8,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 8,
|
||||
"shot3": 0,
|
||||
"shot4": 8,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 93,
|
||||
"completed": true
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 7,
|
||||
"shot3": 0,
|
||||
"shot4": 8,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 5,
|
||||
"shot4": 4,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 3,
|
||||
"shot3": 9,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 3,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 81,
|
||||
"completed": true
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 3,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 5,
|
||||
"shot3": 8,
|
||||
"shot4": 10,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 3,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 8,
|
||||
"shot3": 5,
|
||||
"shot4": 0,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 86,
|
||||
"completed": true
|
||||
},
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 0,
|
||||
"shot4": 8,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 7,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 2,
|
||||
"shot3": 5,
|
||||
"shot4": 3,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 3,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 104,
|
||||
"completed": true
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 3,
|
||||
"shot4": 2,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 2,
|
||||
"shot3": 10,
|
||||
"shot4": 0,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 9,
|
||||
"shot3": 0,
|
||||
"shot4": 4,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 3,
|
||||
"shot3": 8,
|
||||
"shot4": 9,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 83,
|
||||
"completed": true
|
||||
},
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 8,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 3,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 0,
|
||||
"shot3": 10,
|
||||
"shot4": 2,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 6,
|
||||
"shot3": 7,
|
||||
"shot4": 4,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 96,
|
||||
"completed": true
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 8,
|
||||
"shot3": 4,
|
||||
"shot4": 1,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 0,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 6,
|
||||
"shot2": 2,
|
||||
"shot3": 9,
|
||||
"shot4": 4,
|
||||
"shot5": 2
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 8,
|
||||
"shot3": 1,
|
||||
"shot4": 8,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 89,
|
||||
"completed": true
|
||||
},
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 10,
|
||||
"shot3": 1,
|
||||
"shot4": 6,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 1,
|
||||
"shot3": 0,
|
||||
"shot4": 9,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 1,
|
||||
"shot3": 5,
|
||||
"shot4": 5,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 10,
|
||||
"shot4": 4,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 94,
|
||||
"completed": true
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 7,
|
||||
"shot4": 7,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 8,
|
||||
"shot3": 4,
|
||||
"shot4": 6,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 8,
|
||||
"shot3": 5,
|
||||
"shot4": 2,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 5,
|
||||
"shot3": 6,
|
||||
"shot4": 5,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 116,
|
||||
"completed": true
|
||||
},
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 1,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 4,
|
||||
"shot3": 3,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 7,
|
||||
"shot3": 10,
|
||||
"shot4": 2,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 8,
|
||||
"shot3": 2,
|
||||
"shot4": 9,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 115,
|
||||
"completed": true
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 0,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 8,
|
||||
"shot3": 6,
|
||||
"shot4": 4,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 2,
|
||||
"shot4": 4,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 0,
|
||||
"shot3": 1,
|
||||
"shot4": 1,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 4,
|
||||
"shot3": 10,
|
||||
"shot4": 2,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 6,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 3,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 8,
|
||||
"shot3": 9,
|
||||
"shot4": 6,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 85,
|
||||
"completed": true
|
||||
}
|
||||
},
|
||||
"tournament_finished": true,
|
||||
"created_at": "2025-09-08T19:27:18.398031",
|
||||
"finished_at": "2025-09-08T19:27:27.631332"
|
||||
},
|
||||
"archived_at": "2025-09-08T19:27:27.631357"
|
||||
}
|
||||
@@ -1,759 +0,0 @@
|
||||
{
|
||||
"tournament": {
|
||||
"rounds": [
|
||||
{
|
||||
"round_number": 1,
|
||||
"players": [
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Ivan Tandler",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"round_number": 2,
|
||||
"players": [
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Mateja Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
},
|
||||
{
|
||||
"round_number": 3,
|
||||
"players": [
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Domen Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-09-08T19:39:27.077222",
|
||||
"total_players": 18,
|
||||
"total_rounds": 3,
|
||||
"current_round": 1,
|
||||
"tournament_type": "4_targets"
|
||||
},
|
||||
"results": {
|
||||
"tournament_id": "2025-09-08T19:39:27.077222",
|
||||
"tournament_type": "4_targets",
|
||||
"participants": {
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 10,
|
||||
"shot3": 6,
|
||||
"shot4": 3,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 2,
|
||||
"shot3": 1,
|
||||
"shot4": 10,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 5,
|
||||
"shot3": 0,
|
||||
"shot4": 3,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 6,
|
||||
"shot3": 8,
|
||||
"shot4": 4,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 108,
|
||||
"completed": true
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 10,
|
||||
"shot3": 6,
|
||||
"shot4": 0,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 2,
|
||||
"shot3": 1,
|
||||
"shot4": 4,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 10,
|
||||
"shot3": 5,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 7,
|
||||
"shot2": 7,
|
||||
"shot3": 3,
|
||||
"shot4": 2,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 110,
|
||||
"completed": true
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 4,
|
||||
"shot3": 1,
|
||||
"shot4": 2,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 10,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 1,
|
||||
"shot3": 4,
|
||||
"shot4": 3,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 1,
|
||||
"shot4": 1,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 89,
|
||||
"completed": true
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 7,
|
||||
"shot2": 10,
|
||||
"shot3": 3,
|
||||
"shot4": 7,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 0,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 9,
|
||||
"shot3": 0,
|
||||
"shot4": 5,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 102,
|
||||
"completed": true
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 4,
|
||||
"shot3": 3,
|
||||
"shot4": 1,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 8,
|
||||
"shot3": 1,
|
||||
"shot4": 9,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 6,
|
||||
"shot2": 9,
|
||||
"shot3": 4,
|
||||
"shot4": 1,
|
||||
"shot5": 7
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 0,
|
||||
"shot3": 2,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
}
|
||||
},
|
||||
"total_score": 85,
|
||||
"completed": true
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 6,
|
||||
"shot2": 7,
|
||||
"shot3": 8,
|
||||
"shot4": 2,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 7,
|
||||
"shot3": 6,
|
||||
"shot4": 9,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 9,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 5,
|
||||
"shot3": 6,
|
||||
"shot4": 3,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 112,
|
||||
"completed": true
|
||||
},
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 0,
|
||||
"shot3": 9,
|
||||
"shot4": 2,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 4,
|
||||
"shot4": 5,
|
||||
"shot5": 5
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 0,
|
||||
"shot3": 8,
|
||||
"shot4": 2,
|
||||
"shot5": 2
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 2,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 82,
|
||||
"completed": true
|
||||
},
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 7,
|
||||
"shot4": 7,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 0,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 4,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 2,
|
||||
"shot3": 8,
|
||||
"shot4": 1,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 110,
|
||||
"completed": true
|
||||
},
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 10,
|
||||
"shot3": 2,
|
||||
"shot4": 4,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 7,
|
||||
"shot3": 4,
|
||||
"shot4": 7,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 0,
|
||||
"shot3": 5,
|
||||
"shot4": 6,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 4,
|
||||
"shot2": 10,
|
||||
"shot3": 4,
|
||||
"shot4": 7,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 74,
|
||||
"completed": true
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 5,
|
||||
"shot3": 4,
|
||||
"shot4": 7,
|
||||
"shot5": 8
|
||||
},
|
||||
"2": {
|
||||
"shot1": 3,
|
||||
"shot2": 1,
|
||||
"shot3": 7,
|
||||
"shot4": 2,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 0,
|
||||
"shot3": 2,
|
||||
"shot4": 6,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 3,
|
||||
"shot3": 0,
|
||||
"shot4": 3,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 91,
|
||||
"completed": true
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 5,
|
||||
"shot3": 0,
|
||||
"shot4": 5,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 5,
|
||||
"shot3": 1,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 6,
|
||||
"shot3": 10,
|
||||
"shot4": 9,
|
||||
"shot5": 2
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 9,
|
||||
"shot3": 6,
|
||||
"shot4": 3,
|
||||
"shot5": 8
|
||||
}
|
||||
},
|
||||
"total_score": 108,
|
||||
"completed": true
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 3,
|
||||
"shot2": 5,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 6,
|
||||
"shot5": 1
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 9,
|
||||
"shot3": 7,
|
||||
"shot4": 9,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 2,
|
||||
"shot3": 9,
|
||||
"shot4": 1,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 98,
|
||||
"completed": true
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 2,
|
||||
"shot3": 9,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 3
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 9,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 10,
|
||||
"shot3": 9,
|
||||
"shot4": 7,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 5,
|
||||
"shot3": 3,
|
||||
"shot4": 2,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 10,
|
||||
"shot2": 6,
|
||||
"shot3": 10,
|
||||
"shot4": 4,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 0,
|
||||
"shot3": 6,
|
||||
"shot4": 3,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 0,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 107,
|
||||
"completed": true
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 4,
|
||||
"shot3": 8,
|
||||
"shot4": 2,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 4,
|
||||
"shot3": 6,
|
||||
"shot4": 7,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 3,
|
||||
"shot3": 10,
|
||||
"shot4": 7,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 1,
|
||||
"shot2": 2,
|
||||
"shot3": 10,
|
||||
"shot4": 4,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 2,
|
||||
"shot3": 10,
|
||||
"shot4": 2,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 4,
|
||||
"shot3": 10,
|
||||
"shot4": 10,
|
||||
"shot5": 7
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 5,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 8,
|
||||
"shot3": 2,
|
||||
"shot4": 10,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 117,
|
||||
"completed": true
|
||||
},
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 5,
|
||||
"shot3": 3,
|
||||
"shot4": 6,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 7,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 5
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 7,
|
||||
"shot3": 0,
|
||||
"shot4": 4,
|
||||
"shot5": 2
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 7,
|
||||
"shot3": 1,
|
||||
"shot4": 4,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 76,
|
||||
"completed": true
|
||||
},
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 5,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 5,
|
||||
"shot5": 1
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 7,
|
||||
"shot3": 10,
|
||||
"shot4": 10,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 3,
|
||||
"shot3": 1,
|
||||
"shot4": 9,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 10,
|
||||
"shot3": 5,
|
||||
"shot4": 10,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 102,
|
||||
"completed": true
|
||||
}
|
||||
},
|
||||
"tournament_finished": true,
|
||||
"created_at": "2025-09-08T19:39:27.077445",
|
||||
"finished_at": "2025-09-08T19:39:44.030962"
|
||||
},
|
||||
"archived_at": "2025-09-08T19:39:44.030989"
|
||||
}
|
||||
@@ -1,759 +0,0 @@
|
||||
{
|
||||
"tournament": {
|
||||
"rounds": [
|
||||
{
|
||||
"round_number": 1,
|
||||
"players": [
|
||||
{
|
||||
"id": 12,
|
||||
"name": "Matej Kvasnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Marko Blimen",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Domen Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Mateja Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "Rado Kefer",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"round_number": 2,
|
||||
"players": [
|
||||
{
|
||||
"id": 44,
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"name": "Janja Salcman",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Ivan Tandler",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Branko Poker\u017enik",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"name": "Lidija Blimen",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
},
|
||||
{
|
||||
"round_number": 3,
|
||||
"players": [
|
||||
{
|
||||
"id": 47,
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Du\u0161an Onuk",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "Jan Pleterski",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"name": "Jolanda Verhnjak",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"status": "waiting"
|
||||
}
|
||||
],
|
||||
"created_at": "2025-09-08T20:15:56.266521",
|
||||
"total_players": 18,
|
||||
"total_rounds": 3,
|
||||
"current_round": 1,
|
||||
"tournament_type": "4_targets"
|
||||
},
|
||||
"results": {
|
||||
"tournament_id": "2025-09-08T20:15:56.266521",
|
||||
"tournament_type": "4_targets",
|
||||
"participants": {
|
||||
"12": {
|
||||
"name": "Matej Kvasnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 6,
|
||||
"shot3": 5,
|
||||
"shot4": 1,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 3,
|
||||
"shot3": 3,
|
||||
"shot4": 10,
|
||||
"shot5": 4
|
||||
},
|
||||
"3": {
|
||||
"shot1": 10,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 7,
|
||||
"shot2": 5,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 81,
|
||||
"completed": true
|
||||
},
|
||||
"21": {
|
||||
"name": "Marko Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 1,
|
||||
"shot3": 0,
|
||||
"shot4": 0,
|
||||
"shot5": 5
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 0,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 3
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 8,
|
||||
"shot3": 2,
|
||||
"shot4": 1,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 4,
|
||||
"shot2": 6,
|
||||
"shot3": 3,
|
||||
"shot4": 9,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 57,
|
||||
"completed": true
|
||||
},
|
||||
"1": {
|
||||
"name": "Domen Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 4,
|
||||
"shot3": 0,
|
||||
"shot4": 9,
|
||||
"shot5": 10
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 3,
|
||||
"shot3": 0,
|
||||
"shot4": 1,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 5,
|
||||
"shot2": 3,
|
||||
"shot3": 4,
|
||||
"shot4": 6,
|
||||
"shot5": 10
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 2,
|
||||
"shot3": 1,
|
||||
"shot4": 8,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 78,
|
||||
"completed": true
|
||||
},
|
||||
"4": {
|
||||
"name": "Mateja Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 0,
|
||||
"shot3": 2,
|
||||
"shot4": 3,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 2,
|
||||
"shot3": 9,
|
||||
"shot4": 8,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 8,
|
||||
"shot3": 1,
|
||||
"shot4": 1,
|
||||
"shot5": 3
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 95,
|
||||
"completed": true
|
||||
},
|
||||
"5": {
|
||||
"name": "Jo\u017ee Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 3,
|
||||
"shot3": 3,
|
||||
"shot4": 2,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 6,
|
||||
"shot3": 7,
|
||||
"shot4": 5,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 0,
|
||||
"shot3": 7,
|
||||
"shot4": 6,
|
||||
"shot5": 2
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 1,
|
||||
"shot3": 5,
|
||||
"shot4": 7,
|
||||
"shot5": 5
|
||||
}
|
||||
},
|
||||
"total_score": 97,
|
||||
"completed": true
|
||||
},
|
||||
"11": {
|
||||
"name": "Rado Kefer",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 4,
|
||||
"shot2": 2,
|
||||
"shot3": 3,
|
||||
"shot4": 7,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 6,
|
||||
"shot3": 10,
|
||||
"shot4": 7,
|
||||
"shot5": 6
|
||||
},
|
||||
"3": {
|
||||
"shot1": 8,
|
||||
"shot2": 6,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 6,
|
||||
"shot4": 8,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 108,
|
||||
"completed": true
|
||||
},
|
||||
"44": {
|
||||
"name": "Anka Ka\u010dnik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 8,
|
||||
"shot3": 4,
|
||||
"shot4": 10,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 8,
|
||||
"shot3": 10,
|
||||
"shot4": 7,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 2,
|
||||
"shot3": 0,
|
||||
"shot4": 6,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 5,
|
||||
"shot3": 10,
|
||||
"shot4": 10,
|
||||
"shot5": 6
|
||||
}
|
||||
},
|
||||
"total_score": 129,
|
||||
"completed": true
|
||||
},
|
||||
"48": {
|
||||
"name": "Janja Salcman",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 6,
|
||||
"shot3": 9,
|
||||
"shot4": 4,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 0,
|
||||
"shot2": 7,
|
||||
"shot3": 3,
|
||||
"shot4": 2,
|
||||
"shot5": 0
|
||||
},
|
||||
"3": {
|
||||
"shot1": 4,
|
||||
"shot2": 6,
|
||||
"shot3": 4,
|
||||
"shot4": 8,
|
||||
"shot5": 8
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 7,
|
||||
"shot3": 0,
|
||||
"shot4": 10,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 85,
|
||||
"completed": true
|
||||
},
|
||||
"3": {
|
||||
"name": "Ivan Tandler",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 10,
|
||||
"shot2": 9,
|
||||
"shot3": 8,
|
||||
"shot4": 8,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 7,
|
||||
"shot2": 10,
|
||||
"shot3": 3,
|
||||
"shot4": 9,
|
||||
"shot5": 2
|
||||
},
|
||||
"3": {
|
||||
"shot1": 9,
|
||||
"shot2": 4,
|
||||
"shot3": 0,
|
||||
"shot4": 2,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 0,
|
||||
"shot2": 4,
|
||||
"shot3": 1,
|
||||
"shot4": 2,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 106,
|
||||
"completed": true
|
||||
},
|
||||
"7": {
|
||||
"name": "Branko Poker\u017enik",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 4,
|
||||
"shot2": 0,
|
||||
"shot3": 2,
|
||||
"shot4": 3,
|
||||
"shot5": 6
|
||||
},
|
||||
"2": {
|
||||
"shot1": 4,
|
||||
"shot2": 5,
|
||||
"shot3": 4,
|
||||
"shot4": 10,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 1,
|
||||
"shot3": 0,
|
||||
"shot4": 4,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 7,
|
||||
"shot2": 10,
|
||||
"shot3": 8,
|
||||
"shot4": 5,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"9": {
|
||||
"name": "Janez Bo\u017ei\u010d",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 3,
|
||||
"shot2": 9,
|
||||
"shot3": 10,
|
||||
"shot4": 5,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 5,
|
||||
"shot2": 9,
|
||||
"shot3": 6,
|
||||
"shot4": 8,
|
||||
"shot5": 5
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 7,
|
||||
"shot3": 8,
|
||||
"shot4": 1,
|
||||
"shot5": 9
|
||||
},
|
||||
"4": {
|
||||
"shot1": 6,
|
||||
"shot2": 3,
|
||||
"shot3": 10,
|
||||
"shot4": 9,
|
||||
"shot5": 4
|
||||
}
|
||||
},
|
||||
"total_score": 121,
|
||||
"completed": true
|
||||
},
|
||||
"45": {
|
||||
"name": "Lidija Blimen",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 2,
|
||||
"shot2": 9,
|
||||
"shot3": 10,
|
||||
"shot4": 2,
|
||||
"shot5": 10
|
||||
},
|
||||
"2": {
|
||||
"shot1": 8,
|
||||
"shot2": 3,
|
||||
"shot3": 7,
|
||||
"shot4": 6,
|
||||
"shot5": 8
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 7,
|
||||
"shot3": 4,
|
||||
"shot4": 1,
|
||||
"shot5": 1
|
||||
},
|
||||
"4": {
|
||||
"shot1": 2,
|
||||
"shot2": 2,
|
||||
"shot3": 4,
|
||||
"shot4": 10,
|
||||
"shot5": 1
|
||||
}
|
||||
},
|
||||
"total_score": 97,
|
||||
"completed": true
|
||||
},
|
||||
"47": {
|
||||
"name": "Ljuba Mr\u0161ak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 9,
|
||||
"shot2": 1,
|
||||
"shot3": 1,
|
||||
"shot4": 5,
|
||||
"shot5": 9
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 10,
|
||||
"shot3": 10,
|
||||
"shot4": 0,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 5,
|
||||
"shot3": 4,
|
||||
"shot4": 10,
|
||||
"shot5": 0
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 2,
|
||||
"shot5": 2
|
||||
}
|
||||
},
|
||||
"total_score": 88,
|
||||
"completed": true
|
||||
},
|
||||
"46": {
|
||||
"name": "Tijana \u0160tumpfl",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 1,
|
||||
"shot2": 3,
|
||||
"shot3": 2,
|
||||
"shot4": 3,
|
||||
"shot5": 3
|
||||
},
|
||||
"2": {
|
||||
"shot1": 9,
|
||||
"shot2": 5,
|
||||
"shot3": 7,
|
||||
"shot4": 7,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 3,
|
||||
"shot2": 8,
|
||||
"shot3": 1,
|
||||
"shot4": 5,
|
||||
"shot5": 6
|
||||
},
|
||||
"4": {
|
||||
"shot1": 3,
|
||||
"shot2": 0,
|
||||
"shot3": 9,
|
||||
"shot4": 9,
|
||||
"shot5": 7
|
||||
}
|
||||
},
|
||||
"total_score": 100,
|
||||
"completed": true
|
||||
},
|
||||
"20": {
|
||||
"name": "Jo\u017ee Preglav",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 4,
|
||||
"shot2": 4,
|
||||
"shot3": 9,
|
||||
"shot4": 5,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 6,
|
||||
"shot2": 0,
|
||||
"shot3": 10,
|
||||
"shot4": 0,
|
||||
"shot5": 5
|
||||
},
|
||||
"3": {
|
||||
"shot1": 7,
|
||||
"shot2": 8,
|
||||
"shot3": 9,
|
||||
"shot4": 6,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 8,
|
||||
"shot2": 7,
|
||||
"shot3": 5,
|
||||
"shot4": 5,
|
||||
"shot5": 10
|
||||
}
|
||||
},
|
||||
"total_score": 115,
|
||||
"completed": true
|
||||
},
|
||||
"17": {
|
||||
"name": "Du\u0161an Onuk",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 3,
|
||||
"shot3": 3,
|
||||
"shot4": 2,
|
||||
"shot5": 2
|
||||
},
|
||||
"2": {
|
||||
"shot1": 2,
|
||||
"shot2": 6,
|
||||
"shot3": 1,
|
||||
"shot4": 10,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 1,
|
||||
"shot2": 7,
|
||||
"shot3": 4,
|
||||
"shot4": 5,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 10,
|
||||
"shot2": 2,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 9
|
||||
}
|
||||
},
|
||||
"total_score": 97,
|
||||
"completed": true
|
||||
},
|
||||
"15": {
|
||||
"name": "Jan Pleterski",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 0,
|
||||
"shot2": 0,
|
||||
"shot3": 2,
|
||||
"shot4": 0,
|
||||
"shot5": 4
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 7,
|
||||
"shot3": 8,
|
||||
"shot4": 7,
|
||||
"shot5": 9
|
||||
},
|
||||
"3": {
|
||||
"shot1": 2,
|
||||
"shot2": 8,
|
||||
"shot3": 7,
|
||||
"shot4": 2,
|
||||
"shot5": 5
|
||||
},
|
||||
"4": {
|
||||
"shot1": 9,
|
||||
"shot2": 5,
|
||||
"shot3": 1,
|
||||
"shot4": 7,
|
||||
"shot5": 3
|
||||
}
|
||||
},
|
||||
"total_score": 87,
|
||||
"completed": true
|
||||
},
|
||||
"49": {
|
||||
"name": "Jolanda Verhnjak",
|
||||
"targets": {
|
||||
"1": {
|
||||
"shot1": 8,
|
||||
"shot2": 2,
|
||||
"shot3": 7,
|
||||
"shot4": 5,
|
||||
"shot5": 0
|
||||
},
|
||||
"2": {
|
||||
"shot1": 1,
|
||||
"shot2": 8,
|
||||
"shot3": 0,
|
||||
"shot4": 4,
|
||||
"shot5": 10
|
||||
},
|
||||
"3": {
|
||||
"shot1": 0,
|
||||
"shot2": 4,
|
||||
"shot3": 4,
|
||||
"shot4": 7,
|
||||
"shot5": 4
|
||||
},
|
||||
"4": {
|
||||
"shot1": 5,
|
||||
"shot2": 6,
|
||||
"shot3": 4,
|
||||
"shot4": 6,
|
||||
"shot5": 0
|
||||
}
|
||||
},
|
||||
"total_score": 85,
|
||||
"completed": true
|
||||
}
|
||||
},
|
||||
"tournament_finished": true,
|
||||
"created_at": "2025-09-08T20:15:56.266721",
|
||||
"finished_at": "2025-09-08T20:16:01.584621"
|
||||
},
|
||||
"archived_at": "2025-09-08T20:16:01.584647"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+74
-552
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
TV_APP V1.0.0 - Tournament and League Management System
|
||||
Flask web application for managing tournaments with multi-camera streaming
|
||||
"""
|
||||
|
||||
from flask import Flask, render_template, request, redirect, jsonify, session
|
||||
import json
|
||||
import os
|
||||
@@ -7,63 +12,25 @@ from collections import defaultdict
|
||||
from datetime import datetime
|
||||
import re
|
||||
|
||||
# Import modular components
|
||||
from app.utils import (
|
||||
load_translations, get_current_language, get_translations,
|
||||
is_mobile_device, calculate_tens_from_targets
|
||||
)
|
||||
from app.storage import (
|
||||
SettingsStorage, PlayerStorage, TournamentStorage,
|
||||
ResultsStorage, LeagueStorage, ArchiveStorage,
|
||||
TOURNAMENT_FILE, RESULTS_FILE, LEAGUE_FILE
|
||||
)
|
||||
from app.models import Tournament, Scoring, RoundManager
|
||||
|
||||
# Initialize Flask app
|
||||
app = Flask(__name__)
|
||||
app.secret_key = 'your-secret-key-for-sessions' # Change this to a random secret key
|
||||
app.secret_key = 'your-secret-key-for-sessions'
|
||||
app.debug = False
|
||||
|
||||
# Language support
|
||||
SUPPORTED_LANGUAGES = ['sl', 'en']
|
||||
DEFAULT_LANGUAGE = 'sl'
|
||||
|
||||
def load_translations(language='sl'):
|
||||
"""Load translations for the specified language"""
|
||||
try:
|
||||
locale_file = f'locales/{language}.json'
|
||||
if os.path.exists(locale_file):
|
||||
with open(locale_file, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Error loading translations for {language}: {e}")
|
||||
|
||||
# Fallback to default language
|
||||
try:
|
||||
with open(f'locales/{DEFAULT_LANGUAGE}.json', 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Error loading default translations: {e}")
|
||||
return {}
|
||||
|
||||
def get_current_language():
|
||||
"""Get current language from session or default"""
|
||||
return session.get('language', DEFAULT_LANGUAGE)
|
||||
|
||||
def get_translations():
|
||||
"""Get translations for current language"""
|
||||
return load_translations(get_current_language())
|
||||
|
||||
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)
|
||||
|
||||
def calculate_tens_from_targets(targets):
|
||||
"""Calculate the number of 10s from a targets dictionary"""
|
||||
tens_count = 0
|
||||
if not targets:
|
||||
return 0
|
||||
|
||||
for target in targets.values():
|
||||
if isinstance(target, dict):
|
||||
for shot_key, shot_value in target.items():
|
||||
if shot_key.startswith('shot') and shot_value == 10:
|
||||
tens_count += 1
|
||||
|
||||
return tens_count
|
||||
|
||||
# Define streams globally so both routes can access them
|
||||
# Configuration: Camera Streams (6 targets)
|
||||
STREAMS = [
|
||||
{'name': 'Target1', 'url': 'http://192.168.0.134:9081'},
|
||||
{'name': 'Target2', 'url': 'http://192.168.0.134:9082'},
|
||||
@@ -73,453 +40,87 @@ STREAMS = [
|
||||
{'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'
|
||||
# Language Configuration
|
||||
SUPPORTED_LANGUAGES = ['sl', 'en']
|
||||
DEFAULT_LANGUAGE = 'sl'
|
||||
|
||||
# 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},
|
||||
]
|
||||
}
|
||||
# Data file paths (organized in data directory)
|
||||
ARCHIVE_DIR = 'data/tournament_archives'
|
||||
LEAGUE_ARCHIVE_DIR = 'data/league_archives'
|
||||
|
||||
# Convenience function wrappers that delegate to storage classes
|
||||
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()
|
||||
return SettingsStorage.load_settings()
|
||||
|
||||
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
|
||||
return SettingsStorage.save_settings(settings)
|
||||
|
||||
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()
|
||||
return PlayerStorage.load_players()
|
||||
|
||||
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
|
||||
return PlayerStorage.save_players(players_data)
|
||||
|
||||
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
|
||||
return TournamentStorage.load_tournament_state()
|
||||
|
||||
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
|
||||
return TournamentStorage.save_tournament_state(tournament_data)
|
||||
|
||||
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
|
||||
return LeagueStorage.load_league_state()
|
||||
|
||||
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
|
||||
return LeagueStorage.save_league_state(league_data)
|
||||
|
||||
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
|
||||
return ResultsStorage.load_results()
|
||||
|
||||
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
|
||||
return ResultsStorage.save_results(results_data)
|
||||
|
||||
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
|
||||
return ArchiveStorage.archive_tournament(tournament_data, results_data)
|
||||
|
||||
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
|
||||
return ArchiveStorage.archive_league(league_data)
|
||||
|
||||
# Convenience wrappers that delegate to modular classes
|
||||
def create_league(enabled_players, tournament_type):
|
||||
"""Create a new league with 5 tournaments (changed from 6)"""
|
||||
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': 5, # Changed from 6 to 5
|
||||
'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 4 tournaments (changed from 5)
|
||||
'tournaments_participated': 0
|
||||
}
|
||||
|
||||
return league_data
|
||||
return Tournament.create_league(enabled_players, tournament_type)
|
||||
|
||||
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
|
||||
return Tournament.create_draft(enabled_players, tournament_type, league_tournament_number)
|
||||
|
||||
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')
|
||||
|
||||
# Determine target count and shots per target
|
||||
if tournament_type == '40_targets':
|
||||
num_targets = 40
|
||||
shots_per_target = 2
|
||||
elif tournament_type == '4_targets':
|
||||
num_targets = 4
|
||||
shots_per_target = 5
|
||||
else: # 20_targets (default)
|
||||
num_targets = 20
|
||||
shots_per_target = 2
|
||||
|
||||
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'])
|
||||
|
||||
# Create target structure based on tournament type
|
||||
targets = {}
|
||||
for i in range(1, num_targets + 1):
|
||||
target = {}
|
||||
for j in range(1, shots_per_target + 1):
|
||||
target[f'shot{j}'] = None
|
||||
targets[str(i)] = target
|
||||
|
||||
results['participants'][player_id] = {
|
||||
'name': player['name'],
|
||||
'targets': targets,
|
||||
'total_score': 0,
|
||||
'completed': False
|
||||
}
|
||||
|
||||
return results
|
||||
return Tournament.create_results_structure(tournament_data)
|
||||
|
||||
def calculate_total_score(targets):
|
||||
"""Calculate total score from targets, treating None as 0"""
|
||||
total = 0
|
||||
for target in targets.values():
|
||||
for shot_key, shot_value in target.items():
|
||||
if shot_key.startswith('shot') and shot_value is not None:
|
||||
total += shot_value
|
||||
return total
|
||||
return Scoring.calculate_total_score(targets)
|
||||
|
||||
def is_participant_completed(targets):
|
||||
"""Check if a participant has completed all targets (all shots entered, including 0s)"""
|
||||
for target in targets.values():
|
||||
for shot_key, shot_value in target.items():
|
||||
if shot_key.startswith('shot') and shot_value is None:
|
||||
return False
|
||||
return True
|
||||
return Scoring.is_participant_completed(targets)
|
||||
|
||||
def calculate_league_final_scores(league_data):
|
||||
"""Calculate final league scores using best 4 tournaments (changed from best 5)"""
|
||||
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 4 (changed from 5)
|
||||
tournament_scores.sort(reverse=True)
|
||||
best_scores = tournament_scores[:4] if len(tournament_scores) > 4 else tournament_scores
|
||||
|
||||
participant['final_score'] = sum(best_scores)
|
||||
participant['tournaments_participated'] = len(tournament_scores)
|
||||
return Scoring.calculate_league_final_scores(league_data)
|
||||
|
||||
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():
|
||||
# Calculate total 10s across all tournaments
|
||||
total_tens = sum(result.get('tens_count', 0) for result in data['tournament_results'] if result.get('participated', False))
|
||||
|
||||
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'],
|
||||
'total_tens': total_tens
|
||||
})
|
||||
|
||||
# Sort by final score (best 5 tournaments) descending, then by total 10s for tiebreaking
|
||||
participants.sort(key=lambda x: (x['final_score'], x['total_tens']), 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
|
||||
return Scoring.get_league_final_rankings(league_data)
|
||||
|
||||
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
|
||||
total_tens = 0
|
||||
return Scoring.calculate_current_league_standings(league_data)
|
||||
|
||||
for result in data['tournament_results']:
|
||||
if result['participated']:
|
||||
tournament_scores.append(result['score'])
|
||||
completed_tournaments += 1
|
||||
total_tens += result.get('tens_count', 0)
|
||||
|
||||
# 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'],
|
||||
'total_tens': total_tens
|
||||
})
|
||||
|
||||
# Sort by current total score (descending), then by total 10s for tiebreaking
|
||||
participants.sort(key=lambda x: (x['current_total'], x['total_tens']), reverse=True)
|
||||
|
||||
# Add rankings
|
||||
for i, participant in enumerate(participants):
|
||||
participant['rank'] = i + 1
|
||||
|
||||
return participants
|
||||
def get_current_round_data():
|
||||
tournament_state = load_tournament_state()
|
||||
return RoundManager.get_current_round_data(tournament_state)
|
||||
|
||||
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():
|
||||
# Calculate total 10s from completed tournaments
|
||||
total_tens = sum(result.get('tens_count', 0) for result in data['tournament_results'] if result.get('participated', False))
|
||||
|
||||
participant = {
|
||||
@@ -531,128 +132,36 @@ def get_league_current_standings(league_state):
|
||||
'joker_used': data['joker_used'],
|
||||
'tournament_results': data['tournament_results'],
|
||||
'total_tens': total_tens,
|
||||
'current_tournament_score': 0, # Score from current tournament
|
||||
'current_tournament_score': 0,
|
||||
'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, then by total 10s for tiebreaking
|
||||
participants.sort(key=lambda x: (x['final_score'], x['total_tens']), 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
|
||||
|
||||
# Archive functions
|
||||
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 []
|
||||
return ArchiveStorage.get_archived_tournaments()
|
||||
|
||||
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 []
|
||||
return ArchiveStorage.get_archived_leagues()
|
||||
|
||||
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
|
||||
return ArchiveStorage.load_archive_file(filepath)
|
||||
|
||||
def analyze_player_performance(player_id, archives_data):
|
||||
"""Analyze performance of a specific player across all archives"""
|
||||
@@ -819,9 +328,9 @@ def get_all_players_from_archives():
|
||||
|
||||
|
||||
|
||||
# Add these routes after the existing routes in app.py
|
||||
|
||||
# Add this to your app.py file to integrate the modern archive system
|
||||
# ============================================================================
|
||||
# Flask Routes
|
||||
# ============================================================================
|
||||
|
||||
# Replace your existing archive routes with these updated ones:
|
||||
|
||||
@@ -1190,7 +699,9 @@ def index():
|
||||
if i < len(players):
|
||||
tournament_titles[str(i + 1)] = players[i]['name']
|
||||
else:
|
||||
tournament_titles[str(i + 1)] = 'Empty'
|
||||
# Use "Prazno" for Slovenian, "Empty" for English
|
||||
current_language = get_current_language()
|
||||
tournament_titles[str(i + 1)] = 'Prazno' if current_language == 'sl' else 'Empty'
|
||||
|
||||
# Create a copy of settings with tournament titles
|
||||
display_settings = settings.copy()
|
||||
@@ -1821,11 +1332,15 @@ def start_tournament():
|
||||
def change_round(round_number):
|
||||
"""API endpoint to change current round"""
|
||||
try:
|
||||
print(f"[ROUND CHANGE] Attempting to change to round {round_number}")
|
||||
tournament_state = load_tournament_state()
|
||||
if not tournament_state:
|
||||
print(f"[ROUND CHANGE] Error: No active tournament")
|
||||
return jsonify({'status': 'error', 'message': 'No active tournament'}), 400
|
||||
|
||||
print(f"[ROUND CHANGE] Tournament found. Total rounds: {tournament_state.get('total_rounds')}")
|
||||
if round_number < 1 or round_number > tournament_state['total_rounds']:
|
||||
print(f"[ROUND CHANGE] Error: Invalid round number {round_number}")
|
||||
return jsonify({'status': 'error', 'message': 'Invalid round number'}), 400
|
||||
|
||||
tournament_state['current_round'] = round_number
|
||||
@@ -1839,12 +1354,19 @@ def change_round(round_number):
|
||||
else:
|
||||
round_data['status'] = 'waiting'
|
||||
|
||||
print(f"[ROUND CHANGE] Saving tournament state...")
|
||||
if save_tournament_state(tournament_state):
|
||||
print(f"[ROUND CHANGE] Tournament saved successfully")
|
||||
|
||||
return jsonify({'status': 'success', 'tournament': tournament_state})
|
||||
else:
|
||||
print(f"[ROUND CHANGE] Error: Failed to save tournament")
|
||||
return jsonify({'status': 'error', 'message': 'Failed to save tournament'}), 500
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ROUND CHANGE] Exception: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 400
|
||||
|
||||
@app.route('/api/tournament/reset', methods=['POST'])
|
||||
Reference in New Issue
Block a user