From b80c5b7aa29936d6b0072c623751ede519f19ff1 Mon Sep 17 00:00:00 2001 From: cedrick2711 Date: Wed, 29 Jul 2026 14:46:49 -0400 Subject: [PATCH] UML avec la derniere version du projet --- app/__init__.py | 1 - docs/architecture-v3.html | 799 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 799 insertions(+), 1 deletion(-) delete mode 100644 app/__init__.py create mode 100644 docs/architecture-v3.html diff --git a/app/__init__.py b/app/__init__.py deleted file mode 100644 index bd737e1..0000000 --- a/app/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# app package \ No newline at end of file diff --git a/docs/architecture-v3.html b/docs/architecture-v3.html new file mode 100644 index 0000000..8a32621 --- /dev/null +++ b/docs/architecture-v3.html @@ -0,0 +1,799 @@ + + + + + + Team Tryouts β€” Architecture v3 (Refactored) + + + + + +
+

πŸ† Team Tryouts β€” Architecture v3 (Refactored)

+

UML Class Diagram & Functional Graph β€” 7 Subpackages + 6 Standalone Models

+ +
+ +
+ + +
+

πŸ“Š 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 +
+ +
+
+ + +
+

πŸ—ΊοΈ 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 +
+
+
+ +
+ + + + + + + \ No newline at end of file