π Project Statistics
31
Python files in models/
7
Subpackages
24
Classes (incl. abstract)
8
Route Blueprints
4
Flask Extensions
8
Utility Modules
π UML Class Diagram β All 24 Classes, Relationships & Inheritance
classDiagram
class BaseAvailability {
+int day_of_week
+time start_time
+time end_time
+datetime created_at
+datetime updated_at
}
class PlayerDisponibility {
+int id
+int player_id
}
class CoachAvailability {
+int id
+int coach_id
}
BaseAvailability <|-- PlayerDisponibility : extends
BaseAvailability <|-- CoachAvailability : extends
class BaseMatch {
+str title
+str description
+date date
+time start_time
+time end_time
+str location
+str status
+int created_by
+datetime created_at
}
class Match {
+int id
+int tryout_id
+str match_type
+int team1_id
+int team2_id
+get_participating_players()
}
class TeamMatch {
+int id
+int org_team_id
+str opponent
+get_confirmed_count()
}
BaseMatch <|-- Match : extends
BaseMatch <|-- TeamMatch : extends
class BaseParticipant {
+int player_id
+datetime added_at
}
class MatchParticipant {
+int id
+int match_id
+int team_side
+str position
+bool attendance_confirmed
}
class TeamMatchParticipant {
+int id
+int team_match_id
+bool is_confirmed
}
BaseParticipant <|-- MatchParticipant : extends
BaseParticipant <|-- TeamMatchParticipant : extends
class User {
+int id
+str username
+str password_hash
+str role
+str full_name
+str email
+str phone
+bool is_active_account
+datetime created_at
+int failed_login_attempts
+datetime locked_until
+str games
+str discord_username
+str discord_user_id
+str league_os_profile
+get_games_list()
+get_gamertags()
+get_org_teams()
+can_evaluate()
+can_manage_users()
+can_manage_teams()
+can_manage_tryouts()
+can_schedule_matches()
+can_manage_this_tryout()
+can_manage_this_org_team()
+get_visible_tryouts()
}
class Admin {
+all permissions = True
}
class Manager {
+can_manage_teams()
+can_manage_tryouts()
}
class Coach {
+can_evaluate()
+can_schedule_matches()
+can_manage_this_tryout()
+can_manage_this_org_team()
}
class Player {
+get_visible_tryouts()
}
class Scout {
+can_evaluate()
+get_visible_tryouts()
}
User <|-- Admin : polymorphic
User <|-- Manager : polymorphic
User <|-- Coach : polymorphic
User <|-- Player : polymorphic
User <|-- Scout : polymorphic
class UserGamertag {
+int id
+int user_id
+str game
+str gamertag
+str platform
+get_trn_url()
}
class OrgTeam {
+int id
+str name
+int created_by
+datetime created_at
+int coach_id
+int manager_id
+get_coaches()
+get_managers()
+players()
+get_players_with_status()
}
class TeamPlayer {
+int id
+int player_id
+int org_team_id
+str status
+str position
+datetime added_at
}
class Tryout {
+int id
+str title
+str description
+str game
+date date
+str location
+str status
+int max_players
+int created_by
+int target_org_team_id
+int manager_id
+int coach_id
+datetime created_at
}
class TryoutRegistration {
+int id
+int tryout_id
+int player_id
+datetime registered_at
+str status
+str notes
}
class Evaluation {
+int id
+int tryout_id
+int player_id
+int evaluator_id
+int mecanics_score
+int cohesion_score
+int communication_score
+int gamesense_score
+int versatility_score
+int discipline_score
+int analysis_score
+int sport_ethics_score
+int mental_score
+float overall_score
+str comments
+str position_recommendation
+datetime created_at
+datetime updated_at
}
class Team {
+int id
+int tryout_id
+str name
+int created_by
+datetime created_at
}
class TeamMember {
+int id
+int team_id
+int player_id
+str position
+datetime added_at
}
class Contract {
+int id
+int player_id
+int team_id
+int uploaded_by_id
+str original_filename
+str stored_filename
+str file_path
+str signed_filename
+str signed_file_path
+str status
+str notes
+datetime uploaded_at
+datetime signed_at
+can_view()
+can_upload_signed()
}
class TeamNote {
+int id
+int org_team_id
+int coach_id
+str content
+datetime created_at
+datetime updated_at
}
class PersonalNote {
+int id
+int player_id
+int coach_id
+str content
+datetime created_at
+datetime updated_at
+int match_id
+int team_id
+int tryout_id
}
class OneOnOneRequest {
+int id
+int player_id
+int coach_id
+int org_team_id
+date date
+time start_time
+time end_time
+str points
+str status
+datetime created_at
+datetime responded_at
+bigint discord_message_id
+str coach_rejection_message
}
class load_user {
+load_user(user_id)
}
User "1" --> "*" UserGamertag : gamertags
User "1" --> "*" Tryout : created_tryouts
User "1" --> "*" Tryout : managed_tryouts
User "1" --> "*" Tryout : coached_tryouts
User "1" --> "*" Evaluation : evaluations_given
User "1" --> "*" Evaluation : evaluations_received
User "1" --> "*" TryoutRegistration : registrations
User "1" --> "*" TeamMember : team_assignments
User "1" --> "*" TeamPlayer : team_placements
User "1" --> "*" Match : created_matches
User "1" --> "*" TeamMatch : created_team_matches
User "1" --> "*" PlayerDisponibility : disponibilities
User "1" --> "*" CoachAvailability : availabilities
User "1" --> "*" Team : created_teams
User "1" --> "*" Contract : contracts
User "1" --> "*" PersonalNote : personal_notes
User "1" --> "*" OneOnOneRequest : one_on_one_requests
OrgTeam "1" --> "*" TeamPlayer : team_players
OrgTeam "1" --> "*" Tryout : tryouts
OrgTeam "1" --> "*" TeamNote : team_notes
OrgTeam "1" --> "*" TeamMatch : team_matches
OrgTeam "1" --> "*" OneOnOneRequest : requests
OrgTeam "1" --> "*" Contract : contracts
Tryout "1" --> "*" TryoutRegistration : registrations
Tryout "1" --> "*" Evaluation : evaluations
Tryout "1" --> "*" Team : teams
Tryout "1" --> "*" Match : matches
Tryout "1" --> "*" PersonalNote : notes
Team "1" --> "*" TeamMember : members
Team "1" --> "*" Match : as_team1
Team "1" --> "*" Match : as_team2
Match "1" --> "*" MatchParticipant : participants
Match "1" --> "*" PersonalNote : notes
TeamMatch "1" --> "*" TeamMatchParticipant : participants
User .. load_user : loads
π¦ Model Package Structure β 7 Subpackages
graph TD
subgraph MODELS["app/models/ β 31 files"]
direction TB
INIT["__init__.py β master re-exporter"]
CONST["_constants.py β USER_TYPES, ESPORT_GAMES, GAME_POSITIONS, etc."]
LOADERS["_loaders.py β Flask-Login load_user()"]
ASSOC["_associations.py β M2M association tables"]
subgraph USER_PKG["user_model/ (7 files)"]
USER["user.py β User base (polymorphic)"]
ADMIN["admin.py β Admin(User)"]
MGR["manager.py β Manager(User)"]
COACH["coach.py β Coach(User)"]
PLAYER["player.py β Player(User)"]
SCOUT["scout.py β Scout(User)"]
end
subgraph AVAIL_PKG["availability/ (4 files)"]
BASE_AVAIL["base.py β BaseAvailability (abstract)"]
PD["player_disponibility.py β PlayerDisponibility"]
CA["coach_availability.py β CoachAvailability"]
end
subgraph MATCH_PKG["match_model/ (4 files)"]
BASE_M["base.py β BaseMatch (abstract)"]
MATCH["match.py β Match (tryout-scoped)"]
TM["team_match.py β TeamMatch (regular season)"]
end
subgraph PARTIC_PKG["participant/ (4 files)"]
BASE_P["base.py β BaseParticipant (abstract)"]
MP["match_participant.py β MatchParticipant"]
TMP["team_match_participant.py β TeamMatchParticipant"]
end
subgraph ORG_PKG["org_team/ (3 files)"]
ORG["org_team.py β OrgTeam"]
TP["team_player.py β TeamPlayer"]
end
subgraph TRYOUT_PKG["tryout/ (3 files)"]
TRY["tryout.py β Tryout"]
TR["tryout_registration.py β TryoutRegistration"]
end
subgraph TEAM_PKG["team/ (3 files)"]
TEAM["team.py β Team (tryout-specific)"]
TMEMBER["team_member.py β TeamMember"]
end
subgraph STANDALONE["6 Standalone Files"]
EVAL["evaluation.py"]
CONTRACT["contract.py"]
GT["user_gamertag.py"]
TN["team_note.py"]
PN["personal_note.py"]
OOO["one_on_one_request.py"]
end
end
INIT --> USER_PKG
INIT --> AVAIL_PKG
INIT --> MATCH_PKG
INIT --> PARTIC_PKG
INIT --> ORG_PKG
INIT --> TRYOUT_PKG
INIT --> TEAM_PKG
INIT --> STANDALONE
INIT --> CONST
INIT --> LOADERS
INIT --> ASSOC
π Functional Architecture β Request Flow & Component Graph
graph TD
subgraph CLIENT["Client Layer"]
BROWSER["Browser / User"]
DISCORD_APP["Discord App"]
MONITOR["Monitoring / LB"]
end
subgraph PROXY["Reverse Proxy"]
NGINX["Nginx
TLS termination
Static files
Rate limiting"] end subgraph APP["Flask Application β create_app()"] subgraph INGRESS["Incoming Middleware"] BEFORE_REQ["before_request
force_https()"] CSRF_CHECK["CSRF Validation"] LIMITER_CHECK["Rate Limiter
200/day | 50/hr"] LOGIN_CHECK["login_required
Permission checks"] end subgraph BLUEPRINTS["Route Blueprints (8)"] AUTH_BP["auth_bp /auth
login, register, logout"] MAIN_BP["main_bp /
dashboard, privacy, terms"] TRYOUTS_BP["tryouts_bp /tryouts
CRUD + register"] TEAMS_BP["teams_bp /teams
OrgTeam CRUD"] MATCHES_BP["matches_bp /matches
Tryout match CRUD"] TEAM_MATCHES_BP["team_matches_bp /team-matches
Season match CRUD"] USERS_BP["users_bp /users
User CRUD, contracts
disponibilities, one-on-one"] EVALS_BP["evaluations_bp /evaluations
9-score evaluations"] end subgraph EGRESS["Outgoing Middleware"] AFTER_REQ["after_request
Security headers"] ERRORS["Error Handlers
400 401 403 404 429 500"] HEALTH["GET /health"] end end subgraph EXTENSIONS["Flask Extensions"] DB_EXT["SQLAlchemy db"] LOGIN_EXT["LoginManager"] CSRF_EXT["CSRFProtect"] LIMITER_EXT["Flask-Limiter"] end subgraph MODELS["SQLAlchemy Models (7 subpackages)"] USER_M["user_model/ β User hierarchy
User, Admin, Manager, Coach, Player, Scout"] AVAIL_M["availability/ β BaseAvailability
PlayerDisponibility, CoachAvailability"] MATCH_M["match_model/ β BaseMatch
Match, TeamMatch"] PARTIC_M["participant/ β BaseParticipant
MatchParticipant, TeamMatchParticipant"] ORG_M["org_team/ β OrgTeam, TeamPlayer"] TRYOUT_M["tryout/ β Tryout, TryoutRegistration"] TEAM_M["team/ β Team, TeamMember"] STANDALONE_M["Standalone: Evaluation, Contract
UserGamertag, TeamNote, PersonalNote
OneOnOneRequest"] end subgraph DB["Database"] SQLITE["SQLite / PostgreSQL
DATABASE_URL"] end subgraph UTILS["Utility Modules"] VALIDATORS["validators.py
Input validation schemas"] LOGGING["logging_config.py
Structured logging"] DISCORD_BOT["discord_bot.py
Discord notifications
Reaction handling"] SECURITY["security_scan.py
Security audit"] SEED["seed.py
Database seeding"] BACKUP["backup.py
Database backup"] end subgraph TEMPLATES["Jinja2 Templates"] PAGES["templates/pages/
~30 HTML pages"] LAYOUTS["templates/layouts/
base, nav"] ERRORS_TPL["templates/errors/
400-500 errors"] end subgraph STATIC["Static Assets"] CSS_F["static/css/"] JS_F["static/js/"] end subgraph EXTERNAL["External APIs"] TRN_API["TRN / Tracker.gg
Gamertag profiles"] DISCORD_API["Discord API
Bot notifications"] end BROWSER --> NGINX NGINX --> BEFORE_REQ BEFORE_REQ --> CSRF_CHECK CSRF_CHECK --> LIMITER_CHECK LIMITER_CHECK --> LOGIN_CHECK LOGIN_CHECK --> BLUEPRINTS BLUEPRINTS --> AFTER_REQ AFTER_REQ --> BROWSER AUTH_BP -.-> USER_M TRYOUTS_BP -.-> TRYOUT_M EVALS_BP -.-> STANDALONE_M TEAMS_BP -.-> ORG_M MATCHES_BP -.-> MATCH_M TEAM_MATCHES_BP -.-> MATCH_M USERS_BP -.-> USER_M MODELS --> DB DB_EXT --> MODELS LOGIN_EXT --> USER_M CSRF_EXT --> BLUEPRINTS LIMITER_EXT --> BLUEPRINTS VALIDATORS -.-> AUTH_BP VALIDATORS -.-> USERS_BP LOGGING -.-> APP DISCORD_BOT --> DISCORD_API DISCORD_BOT -.-> MATCHES_BP DISCORD_BOT -.-> TEAM_MATCHES_BP DISCORD_BOT -.-> USERS_BP SEED -.-> DB BACKUP -.-> DB BLUEPRINTS --> TEMPLATES TEMPLATES --> STATIC USER_M -.-> TRN_API MONITOR --> HEALTH DISCORD_APP --> DISCORD_BOT
TLS termination
Static files
Rate limiting"] end subgraph APP["Flask Application β create_app()"] subgraph INGRESS["Incoming Middleware"] BEFORE_REQ["before_request
force_https()"] CSRF_CHECK["CSRF Validation"] LIMITER_CHECK["Rate Limiter
200/day | 50/hr"] LOGIN_CHECK["login_required
Permission checks"] end subgraph BLUEPRINTS["Route Blueprints (8)"] AUTH_BP["auth_bp /auth
login, register, logout"] MAIN_BP["main_bp /
dashboard, privacy, terms"] TRYOUTS_BP["tryouts_bp /tryouts
CRUD + register"] TEAMS_BP["teams_bp /teams
OrgTeam CRUD"] MATCHES_BP["matches_bp /matches
Tryout match CRUD"] TEAM_MATCHES_BP["team_matches_bp /team-matches
Season match CRUD"] USERS_BP["users_bp /users
User CRUD, contracts
disponibilities, one-on-one"] EVALS_BP["evaluations_bp /evaluations
9-score evaluations"] end subgraph EGRESS["Outgoing Middleware"] AFTER_REQ["after_request
Security headers"] ERRORS["Error Handlers
400 401 403 404 429 500"] HEALTH["GET /health"] end end subgraph EXTENSIONS["Flask Extensions"] DB_EXT["SQLAlchemy db"] LOGIN_EXT["LoginManager"] CSRF_EXT["CSRFProtect"] LIMITER_EXT["Flask-Limiter"] end subgraph MODELS["SQLAlchemy Models (7 subpackages)"] USER_M["user_model/ β User hierarchy
User, Admin, Manager, Coach, Player, Scout"] AVAIL_M["availability/ β BaseAvailability
PlayerDisponibility, CoachAvailability"] MATCH_M["match_model/ β BaseMatch
Match, TeamMatch"] PARTIC_M["participant/ β BaseParticipant
MatchParticipant, TeamMatchParticipant"] ORG_M["org_team/ β OrgTeam, TeamPlayer"] TRYOUT_M["tryout/ β Tryout, TryoutRegistration"] TEAM_M["team/ β Team, TeamMember"] STANDALONE_M["Standalone: Evaluation, Contract
UserGamertag, TeamNote, PersonalNote
OneOnOneRequest"] end subgraph DB["Database"] SQLITE["SQLite / PostgreSQL
DATABASE_URL"] end subgraph UTILS["Utility Modules"] VALIDATORS["validators.py
Input validation schemas"] LOGGING["logging_config.py
Structured logging"] DISCORD_BOT["discord_bot.py
Discord notifications
Reaction handling"] SECURITY["security_scan.py
Security audit"] SEED["seed.py
Database seeding"] BACKUP["backup.py
Database backup"] end subgraph TEMPLATES["Jinja2 Templates"] PAGES["templates/pages/
~30 HTML pages"] LAYOUTS["templates/layouts/
base, nav"] ERRORS_TPL["templates/errors/
400-500 errors"] end subgraph STATIC["Static Assets"] CSS_F["static/css/"] JS_F["static/js/"] end subgraph EXTERNAL["External APIs"] TRN_API["TRN / Tracker.gg
Gamertag profiles"] DISCORD_API["Discord API
Bot notifications"] end BROWSER --> NGINX NGINX --> BEFORE_REQ BEFORE_REQ --> CSRF_CHECK CSRF_CHECK --> LIMITER_CHECK LIMITER_CHECK --> LOGIN_CHECK LOGIN_CHECK --> BLUEPRINTS BLUEPRINTS --> AFTER_REQ AFTER_REQ --> BROWSER AUTH_BP -.-> USER_M TRYOUTS_BP -.-> TRYOUT_M EVALS_BP -.-> STANDALONE_M TEAMS_BP -.-> ORG_M MATCHES_BP -.-> MATCH_M TEAM_MATCHES_BP -.-> MATCH_M USERS_BP -.-> USER_M MODELS --> DB DB_EXT --> MODELS LOGIN_EXT --> USER_M CSRF_EXT --> BLUEPRINTS LIMITER_EXT --> BLUEPRINTS VALIDATORS -.-> AUTH_BP VALIDATORS -.-> USERS_BP LOGGING -.-> APP DISCORD_BOT --> DISCORD_API DISCORD_BOT -.-> MATCHES_BP DISCORD_BOT -.-> TEAM_MATCHES_BP DISCORD_BOT -.-> USERS_BP SEED -.-> DB BACKUP -.-> DB BLUEPRINTS --> TEMPLATES TEMPLATES --> STATIC USER_M -.-> TRN_API MONITOR --> HEALTH DISCORD_APP --> DISCORD_BOT
πΊοΈ Legend
Models (abstract) β BaseAvailability, BaseMatch, BaseParticipant
Subpackages β user_model, availability, match_model, participant, org_team, tryout, team
Blueprints β Flask route groups
Extensions β SQLAlchemy, Login, CSRF, Limiter
Utilities β Logging, validators, seed, backup, bot
External APIs β Discord API, TRN/Tracker.gg
Middleware β HTTPS redirect, security headers, errors
ββ Solid
= HTTP / data flow
β
β
Dashed
= Logical dependency