diff --git a/api/backend/data_engineer/data_routes.py b/api/backend/data_engineer/data_routes.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/backend/games/games_routes.py b/api/backend/games/games_routes.py new file mode 100644 index 0000000000..2de6629af2 --- /dev/null +++ b/api/backend/games/games_routes.py @@ -0,0 +1,88 @@ +from flask import Blueprint, request, jsonify, make_response, current_app, redirect, url_for +import json +from backend.db_connection import db + +games_routes = Blueprint('games', __name__) + + +@games_routes.route('/games', methods=['GET']) +def get_games(): + try: + current_app.logger.info('GET /games handler') + cursor = db.get_db().cursor() + + cursor.execute('SELECT * FROM Game') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + except Exception as e: + current_app.logger.error(f'Error fetching games: {e}') + return make_response(jsonify({"error": "Failed to fetch games"}), 500) + +@games_routes.route('/games', methods=['POST']) +def create_game(): + try: + current_app.logger.info('POST /games handler') + cursor = db.get_db().cursor() + + new_game = request.get_json() + date = new_game.get('date') + season = new_game.get('season') + is_playoff = new_game.get('is_playoff') + home_team_id = new_game.get('home_team_id') + away_team_id = new_game.get('away_team_id') + home_score = new_game.get('home_score', 0) + away_score = new_game.get('away_score', 0) + + if not date or not season or not home_team_id or not away_team_id: + return make_response(jsonify({"error": "Missing required fields"}), 400) + + query = ''' + INSERT INTO Game (date, season, is_playoff, home_team_id, away_team_id, home_score, away_score) + VALUES (%s, %s, %s, %s, %s, %s, %s) + ''' + current_app.logger.info(f'Executing query: {query}') + + cursor.execute(query, (date, season, is_playoff, home_team_id, away_team_id, home_score, away_score)) + db.get_db().commit() + + the_response = make_response(jsonify(new_game), 201) + return the_response + except Exception as e: + current_app.logger.error(f'Error creating game: {e}') + return make_response(jsonify({"error": "Failed to create game"}), 500) + +@games_routes.route('/games/', methods=['PUT']) +def update_game(game_id): + try: + cursor = db.get_db().cursor() + current_app.logger.info(f'PUT /games/{game_id} handler') + + updated_game = request.get_json() + date = updated_game.get('date') + season = updated_game.get('season') + is_playoff = updated_game.get('is_playoff') + home_team_id = updated_game.get('home_team_id') + away_team_id = updated_game.get('away_team_id') + home_score = updated_game.get('home_score') + away_score = updated_game.get('away_score') + if not date or not season or not home_team_id or not away_team_id: + return make_response(jsonify({"error": "Missing required fields"}), 400) + + query = ''' + UPDATE Game + SET date = %s, season = %s, is_playoff = %s, home_team_id = %s, away_team_id = %s, home_score = %s, away_score = %s + WHERE game_id = %s + ''' + current_app.logger.info(f'Executing query: {query}') + + cursor.execute(query, (date, season, is_playoff, home_team_id, away_team_id, home_score, away_score, game_id)) + db.get_db().commit() + + the_response = make_response(jsonify(updated_game), 200) + return the_response + except Exception as e: + current_app.logger.error(f'Error updating game: {e}') + return make_response(jsonify({"error": "Failed to update game"}), 500) \ No newline at end of file diff --git a/api/backend/players/players_routes.py b/api/backend/players/players_routes.py new file mode 100644 index 0000000000..f8af94339d --- /dev/null +++ b/api/backend/players/players_routes.py @@ -0,0 +1,21 @@ +from flask import Blueprint, request, jsonify, make_response, current_app, redirect, url_for +import json +from backend.db_connection import db + +players = Blueprint('players', __name__) + +@players.route('/player-matchups', methods=['GET']) +def get_player_matchups(): + try: + current_app.logger.info('GET /player-matchups handler') + cursor = db.get_db().cursor() + + cursor.execute('SELECT * FROM PlayerMatchup') + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + except Exception as e: + current_app.logger.error(f'Error fetching player matchups: {e}') + return make_response(jsonify({"error": "Failed to fetch player matchups"}), 500) \ No newline at end of file diff --git a/api/backend/rest_entry.py b/api/backend/rest_entry.py index d8d78502d9..c262fde526 100644 --- a/api/backend/rest_entry.py +++ b/api/backend/rest_entry.py @@ -4,6 +4,9 @@ from backend.customers.customer_routes import customers from backend.products.products_routes import products from backend.simple.simple_routes import simple_routes +from backend.players.players_routes import players +from backend.games.games_routes import games_routes +from backend.teams.teams_routes import teams_routes import os from dotenv import load_dotenv @@ -42,6 +45,9 @@ def create_app(): app.register_blueprint(simple_routes) app.register_blueprint(customers, url_prefix='/c') app.register_blueprint(products, url_prefix='/p') + app.register_blueprint(players) + app.register_blueprint(games_routes) + app.register_blueprint(teams_routes) # Don't forget to return the app object return app diff --git a/api/backend/teams/teams_routes.py b/api/backend/teams/teams_routes.py new file mode 100644 index 0000000000..e1e2c83f1e --- /dev/null +++ b/api/backend/teams/teams_routes.py @@ -0,0 +1,87 @@ +from flask import Blueprint, request, jsonify, make_response, current_app, redirect, url_for +import json +from backend.db_connection import db + +teams_routes = Blueprint('teams_routes', __name__) + +@teams_routes.route('/teams//players', methods=['GET']) +def get_team_players(team_id): + try: + current_app.logger.info(f'GET /teams/{team_id}/players handler') + cursor = db.get_db().cursor() + + # get current players where left_date is NULL, meaning they haven't left) + query = ''' + SELECT DISTINCT p.player_id, p.first_name, p.last_name, p.position, + tp.jersey_num, tp.joined_date, p.age, p.college, p.height, p.weight + FROM Players p + JOIN TeamsPlayers tp ON p.player_id = tp.player_id + WHERE tp.team_id = %s + AND tp.left_date IS NULL + ORDER BY tp.jersey_num, p.last_name + ''' + + cursor.execute(query, (team_id,)) + theData = cursor.fetchall() + + the_response = make_response(jsonify(theData)) + the_response.status_code = 200 + return the_response + except Exception as e: + current_app.logger.error(f'Error fetching team players: {e}') + return make_response(jsonify({"error": "Failed to fetch team players"}), 500) + +@teams_routes.route('/teams//players', methods=['POST']) +def add_team_player(team_id): + try: + current_app.logger.info(f'POST /teams/{team_id}/players handler') + cursor = db.get_db().cursor() + + new_player = request.get_json() + player_id = new_player.get('player_id') + jersey_num = new_player.get('jersey_num') + joined_date = new_player.get('joined_date') + if not player_id or not jersey_num or not joined_date: + return make_response(jsonify({"error": "Missing required fields"}), 400) + + query = ''' + INSERT INTO TeamsPlayers (team_id, player_id, jersey_num, joined_date) + VALUES (%s, %s, %s, %s) + ''' + + cursor.execute(query, (team_id, player_id, jersey_num, joined_date)) + db.get_db().commit() + + the_response = make_response(jsonify(new_player), 201) + return the_response + except Exception as e: + current_app.logger.error(f'Error adding team player: {e}') + return make_response(jsonify({"error": "Failed to add team player"}), 500) + +@teams_routes.route('/teams//players/', methods=['PUT']) +def update_team_player(team_id, player_id): + try: + current_app.logger.info(f'PUT /teams/{team_id}/players/{player_id} handler') + cursor = db.get_db().cursor() + + # Update jersey_num and left_date + updated_player = request.get_json() + jersey_num = updated_player.get('jersey_num') + left_date = updated_player.get('left_date') + if not jersey_num: + return make_response(jsonify({"error": "Missing required fields"}), 400) + + query = ''' + UPDATE TeamsPlayers + SET jersey_num = %s, left_date = %s + WHERE team_id = %s AND player_id = %s + ''' + + cursor.execute(query, (jersey_num, left_date, team_id, player_id)) + db.get_db().commit() + the_response = make_response(jsonify(updated_player), 200) + return the_response + except Exception as e: + current_app.logger.error(f'Error updating team player: {e}') + return make_response(jsonify({"error": "Failed to update team player"}), 500) + \ No newline at end of file diff --git a/app/src/pages/04_Prediction.py b/app/src/pages/04_Regression_Prediction.py similarity index 100% rename from app/src/pages/04_Prediction.py rename to app/src/pages/04_Regression_Prediction.py diff --git a/database-files/ballwatchers-schema.sql b/database-files/ballwatchers-schema.sql new file mode 100644 index 0000000000..eebec185eb --- /dev/null +++ b/database-files/ballwatchers-schema.sql @@ -0,0 +1,301 @@ +CREATE SCHEMA IF NOT EXISTS BallWatch; +USE BallWatch; + + +DROP TABLE IF EXISTS DataErrors; +DROP TABLE IF EXISTS ErrorLogs; +DROP TABLE IF EXISTS DataLoads; +DROP TABLE IF EXISTS SystemHealth; +DROP TABLE IF EXISTS GamePlan; +DROP TABLE IF EXISTS KeyMatchups; +DROP TABLE IF EXISTS GamePlayers; +DROP TABLE IF EXISTS PlayerGameStats; +DROP TABLE IF EXISTS PlayerMatchup; +DROP TABLE IF EXISTS Game; +DROP TABLE IF EXISTS TeamsPlayers; +DROP TABLE IF EXISTS DraftEval; +DROP TABLE IF EXISTS PlayerLineups; +DROP TABLE IF EXISTS Teams; +DROP TABLE IF EXISTS Players; +DROP TABLE IF EXISTS LineupConfiguration; +DROP TABLE IF EXISTS Agent; +DROP TABLE IF EXISTS Users; + + +CREATE TABLE IF NOT EXISTS Users ( + user_id INT PRIMARY KEY AUTO_INCREMENT, + email VARCHAR(100) UNIQUE NOT NULL, + username VARCHAR(50) UNIQUE NOT NULL, + role ENUM('admin', 'coach', 'gm', 'analyst', 'fan') NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + is_active BOOLEAN DEFAULT TRUE +); + + +CREATE TABLE IF NOT EXISTS Agent ( + agent_id INT PRIMARY KEY AUTO_INCREMENT, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL, + agency_name VARCHAR(100), + phone VARCHAR(20), + email VARCHAR(100) UNIQUE +); + + +CREATE TABLE IF NOT EXISTS Players ( + player_id INT PRIMARY KEY AUTO_INCREMENT, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL, + age INT CHECK (age > 0), + college VARCHAR(100), + position ENUM('Guard', 'Forward', 'Center', 'PG', 'SG', 'SF', 'PF', 'C'), + weight INT CHECK (weight > 0), + player_status ENUM('Active', 'Injured', 'Retired', 'G-League') DEFAULT 'Active', + agent_id INT, + height VARCHAR(10), + picture TEXT, + DOB DATE, + years_exp INT DEFAULT 0, + dominant_hand ENUM('Left', 'Right') DEFAULT 'Right', + expected_salary DECIMAL(12,2), + player_type VARCHAR(50), + current_salary DECIMAL(12,2), + draft_year INT, + CONSTRAINT FK_Players_Agent FOREIGN KEY (agent_id) REFERENCES Agent(agent_id) + ON UPDATE CASCADE + ON DELETE SET NULL +); + + +CREATE TABLE IF NOT EXISTS Teams ( + team_id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL, + conference ENUM('Eastern', 'Western') NOT NULL, + abrv VARCHAR(5) UNIQUE NOT NULL, + division VARCHAR(50) NOT NULL, + head_coach VARCHAR(100), + offensive_system VARCHAR(100), + defensive_system VARCHAR(100) +); + + +CREATE TABLE IF NOT EXISTS LineupConfiguration ( + lineup_id INT PRIMARY KEY AUTO_INCREMENT, + team_id INT NOT NULL, + quarter INT CHECK (quarter BETWEEN 1 AND 4), + time_on TIME, + time_off TIME, + plus_minus INT, + offensive_rating DECIMAL(5,2), + defensive_rating DECIMAL(5,2), + CONSTRAINT FK_LineupConfiguration_Teams FOREIGN KEY (team_id) + REFERENCES Teams(team_id) + ON UPDATE CASCADE + ON DELETE CASCADE +); + + +CREATE TABLE IF NOT EXISTS PlayerLineups ( + player_id INT, + lineup_id INT, + position_in_lineup VARCHAR(50), + PRIMARY KEY (player_id, lineup_id), + CONSTRAINT FK_PlayerLineups_Players FOREIGN KEY (player_id) + REFERENCES Players(player_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_PlayerLineups_LineupConfiguration FOREIGN KEY (lineup_id) + REFERENCES LineupConfiguration(lineup_id) + ON UPDATE CASCADE + ON DELETE CASCADE +); + + +CREATE TABLE IF NOT EXISTS DraftEval ( + player_id INT, + team_id INT, + ranking INT, + notes TEXT, + last_updated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + nba_player_comparison VARCHAR(100), + PRIMARY KEY (player_id, team_id), + CONSTRAINT FK_DraftEval_Players FOREIGN KEY (player_id) + REFERENCES Players(player_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_DraftEval_Teams FOREIGN KEY (team_id) + REFERENCES Teams(team_id) + ON UPDATE CASCADE + ON DELETE CASCADE +); + + +CREATE TABLE IF NOT EXISTS TeamsPlayers ( + player_id INT, + team_id INT, + joined_date DATE, + jersey_num INT CHECK (jersey_num BETWEEN 0 AND 99), + left_date DATE, + PRIMARY KEY (player_id, team_id, joined_date), + CONSTRAINT FK_TeamsPlayers_Players FOREIGN KEY (player_id) + REFERENCES Players(player_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_TeamsPlayers_Teams FOREIGN KEY (team_id) + REFERENCES Teams(team_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT CHK_Dates CHECK (left_date IS NULL OR left_date >= joined_date) +); + + +CREATE TABLE IF NOT EXISTS Game ( + game_id INT PRIMARY KEY AUTO_INCREMENT, + date DATE NOT NULL, + season VARCHAR(20) NOT NULL, + is_playoff BOOLEAN DEFAULT FALSE, + home_team_id INT NOT NULL, + away_team_id INT NOT NULL, + home_score INT DEFAULT 0, + away_score INT DEFAULT 0, + league_id INT DEFAULT 1, + CONSTRAINT FK_Game_HomeTeam FOREIGN KEY (home_team_id) + REFERENCES Teams(team_id) + ON UPDATE CASCADE + ON DELETE RESTRICT, + CONSTRAINT FK_Game_AwayTeam FOREIGN KEY (away_team_id) + REFERENCES Teams(team_id) + ON UPDATE CASCADE + ON DELETE RESTRICT +); + + +CREATE TABLE IF NOT EXISTS PlayerMatchup ( + game_id INT, + offensive_player_id INT, + defensive_player_id INT, + offensive_rating DECIMAL(5,2), + defensive_rating DECIMAL(5,2), + possessions INT, + points_scored INT, + shooting_percentage DECIMAL(5,2) CHECK (shooting_percentage BETWEEN 0 AND 1), + PRIMARY KEY (game_id, offensive_player_id, defensive_player_id), + CONSTRAINT FK_PlayerMatchup_Game FOREIGN KEY (game_id) + REFERENCES Game(game_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_PlayerMatchup_OffensivePlayer FOREIGN KEY (offensive_player_id) + REFERENCES Players(player_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_PlayerMatchup_DefensivePlayer FOREIGN KEY (defensive_player_id) + REFERENCES Players(player_id) + ON UPDATE CASCADE + ON DELETE CASCADE +); + + +CREATE TABLE IF NOT EXISTS PlayerGameStats ( + player_id INT, + game_id INT, + team_id INT, + points INT DEFAULT 0, + rebounds INT DEFAULT 0, + assists INT DEFAULT 0, + shooting_percentage DECIMAL(5,2) CHECK (shooting_percentage BETWEEN 0 AND 1), + plus_minus INT DEFAULT 0, + minutes_played INT CHECK (minutes_played BETWEEN 0 AND 48), + turnovers INT DEFAULT 0, + steals INT DEFAULT 0, + blocks INT DEFAULT 0, + fouls_committed INT DEFAULT 0, + PRIMARY KEY (player_id, game_id), + CONSTRAINT FK_PlayerGameStats_Players FOREIGN KEY (player_id) + REFERENCES Players(player_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_PlayerGameStats_Game FOREIGN KEY (game_id) + REFERENCES Game(game_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_PlayerGameStats_Teams FOREIGN KEY (team_id) + REFERENCES Teams(team_id) + ON UPDATE CASCADE + ON DELETE RESTRICT +); + + +CREATE TABLE IF NOT EXISTS KeyMatchups ( + matchup_id INT PRIMARY KEY AUTO_INCREMENT, + matchup_text TEXT NOT NULL +); + + +CREATE TABLE IF NOT EXISTS GamePlan ( + gp_id INT PRIMARY KEY AUTO_INCREMENT, + game_id INT UNIQUE, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_date DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + offensive_strategy TEXT, + special_situations TEXT, + defensive_strategy TEXT, + key_matchups INT, + CONSTRAINT FK_GamePlan_Game FOREIGN KEY (game_id) + REFERENCES Game(game_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_GamePlan_KeyMatchups FOREIGN KEY (key_matchups) + REFERENCES KeyMatchups(matchup_id) + ON UPDATE CASCADE + ON DELETE SET NULL +); + + +CREATE TABLE IF NOT EXISTS SystemHealth ( + health_id INT PRIMARY KEY AUTO_INCREMENT, + check_time DATETIME DEFAULT CURRENT_TIMESTAMP, + service_name VARCHAR(100) NOT NULL, + error_rate_pct DECIMAL(5,2), + avg_response_time DECIMAL(10,2), + status ENUM('Healthy', 'Warning', 'Error', 'Critical') DEFAULT 'Healthy' +); + + +CREATE TABLE IF NOT EXISTS ErrorLogs ( + error_id INT PRIMARY KEY AUTO_INCREMENT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + error_type VARCHAR(100), + error_message TEXT, + service_component VARCHAR(100), + user_id INT, + CONSTRAINT FK_ErrorLogs_Users FOREIGN KEY (user_id) + REFERENCES Users(user_id) + ON UPDATE CASCADE + ON DELETE SET NULL +); + + +CREATE TABLE IF NOT EXISTS DataLoads ( + load_id INT PRIMARY KEY AUTO_INCREMENT, + load_date DATE NOT NULL, + data_source VARCHAR(100), + status ENUM('Started', 'Completed', 'Failed', 'In Progress') DEFAULT 'Started', + start_time DATETIME DEFAULT CURRENT_TIMESTAMP, + end_time DATETIME, + load_time TIME +); + + +CREATE TABLE IF NOT EXISTS DataErrors ( + load_id INT, + error_id INT, + PRIMARY KEY (load_id, error_id), + CONSTRAINT FK_DataErrors_DataLoads FOREIGN KEY (load_id) + REFERENCES DataLoads(load_id) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT FK_DataErrors_ErrorLogs FOREIGN KEY (error_id) + REFERENCES ErrorLogs(error_id) + ON UPDATE CASCADE + ON DELETE CASCADE +); diff --git a/database-files/inserts.sql b/database-files/inserts.sql new file mode 100644 index 0000000000..8348b30be5 --- /dev/null +++ b/database-files/inserts.sql @@ -0,0 +1,141 @@ +Use BallWatch; + +INSERT INTO Users (email, username, role) VALUES +('mike.lewis@ballwatch.com', 'mlewis', 'admin'), +('marcus.thompson@nets.com', 'mthompson', 'coach'), +('andre.wu@nets.com', 'awu', 'gm'), +('johnny.evans@gmail.com', 'jevans25', 'fan'); + + +INSERT INTO Agent (first_name, last_name, agency_name, phone, email) VALUES +('Rich', 'Paul', 'Klutch Sports Group', '555-0101', 'rich@klutchsports.com'), +('Jeff', 'Schwartz', 'Excel Sports Management', '555-0102', 'jeff@excelsports.com'), +('Mark', 'Bartelstein', 'Priority Sports', '555-0103', 'mark@prioritysports.com'); + + +INSERT INTO Teams (name, conference, abrv, division, head_coach, offensive_system, defensive_system) VALUES +('Brooklyn Nets', 'Eastern', 'BKN', 'Atlantic', 'Marcus Thompson', 'Motion Offense', 'Switch Everything'), +('Los Angeles Lakers', 'Western', 'LAL', 'Pacific', 'Darvin Ham', 'LeBron System', 'Drop Coverage'), +('Golden State Warriors', 'Western', 'GSW', 'Pacific', 'Steve Kerr', 'Motion Offense', 'Aggressive Switching'), +('Boston Celtics', 'Eastern', 'BOS', 'Atlantic', 'Joe Mazzulla', 'Five Out', 'Drop Coverage'), +('Miami Heat', 'Eastern', 'MIA', 'Southeast', 'Erik Spoelstra', 'Zone Attack', 'Zone Defense'); + + +INSERT INTO Players (first_name, last_name, age, college, position, weight, player_status, agent_id, + height, DOB, years_exp, dominant_hand, expected_salary, player_type, current_salary, draft_year) VALUES +('Kevin', 'Durant', 35, 'Texas', 'Forward', 240, 'Active', 1, '6-10', '1988-09-29', 16, 'Right', +51000000, 'Superstar', 47649433, 2007), +('Kyrie', 'Irving', 32, 'Duke', 'Guard', 195, 'Active', 2, '6-2', '1992-03-23', 13, 'Right', +42000000, 'All-Star', 37037037, 2011), +('Ben', 'Simmons', 28, 'LSU', 'Forward', 240, 'Active', 1, '6-10', '1996-07-20', 8, 'Left', +40000000, 'All-Star', 37893408, 2016), +('LeBron', 'James', 39, 'None', 'Forward', 250, 'Active', 1, '6-9', '1984-12-30', 21, 'Right', +51000000, 'Superstar', 47607350, 2003), +('Stephen', 'Curry', 36, 'Davidson', 'Guard', 185, 'Active', 2, '6-2', '1988-03-14', 15, 'Right', +55000000, 'Superstar', 51915615, 2009), +('Cooper', 'Flagg', 18, 'Duke', 'Forward', 200, 'Active', 3, '6-9', '2006-12-21', 0, 'Right', +10000000, 'Rookie', 0, 2025), +('Jayson', 'Tatum', 26, 'Duke', 'Forward', 210, 'Active', 2, '6-8', '1998-03-03', 7, 'Right', +35000000, 'All-Star', 32600060, 2017), +('Jimmy', 'Butler', 34, 'Marquette', 'Forward', 230, 'Active', 1, '6-7', '1989-09-14', 13, 'Right', +48000000, 'All-Star', 48798677, 2011); + + +INSERT INTO TeamsPlayers (player_id, team_id, joined_date, jersey_num) VALUES +(1, 1, '2023-02-09', 7), +(2, 1, '2023-02-06', 11), +(3, 1, '2022-02-10', 10), +(4, 2, '2018-07-01', 23), +(5, 3, '2009-06-25', 30), +(7, 4, '2017-06-22', 0), +(8, 5, '2019-07-06', 22); + + +INSERT INTO Game (date, season, is_playoff, home_team_id, away_team_id, home_score, away_score) VALUES +('2025-01-15', '2024-25', FALSE, 1, 2, 118, 112), +('2025-01-18', '2024-25', FALSE, 3, 1, 125, 120), +('2025-01-20', '2024-25', FALSE, 1, 3, 108, 115), +('2025-01-22', '2024-25', FALSE, 4, 5, 122, 118), +('2025-01-25', '2024-25', FALSE, 1, 4, 110, 105); + + +INSERT INTO LineupConfiguration (team_id, quarter, time_on, time_off, plus_minus, offensive_rating, defensive_rating) VALUES +(1, 1, '12:00:00', '06:00:00', 8, 118.5, 105.2), +(1, 2, '12:00:00', '05:30:00', -3, 102.3, 108.7), +(3, 1, '12:00:00', '07:00:00', 5, 115.2, 110.1), +(2, 1, '12:00:00', '06:30:00', 6, 112.5, 108.3); + + +INSERT INTO PlayerGameStats (player_id, game_id, team_id, points, rebounds, assists, shooting_percentage, + plus_minus, minutes_played, turnovers, steals, blocks, fouls_committed) VALUES +(1, 1, 1, 35, 8, 5, 0.58, 12, 38, 3, 1, 2, 2), +(2, 1, 1, 28, 4, 8, 0.52, 8, 36, 4, 2, 0, 3), +(3, 1, 1, 12, 6, 4, 0.33, 6, 24, 2, 0, 1, 4), +(4, 1, 2, 32, 10, 7, 0.55, -6, 37, 5, 1, 1, 2), +(1, 2, 1, 30, 6, 4, 0.48, -5, 35, 2, 0, 1, 3), +(5, 2, 3, 38, 5, 11, 0.62, 5, 36, 3, 3, 0, 2), +(1, 3, 1, 27, 9, 3, 0.45, -7, 34, 4, 1, 2, 2), +(5, 3, 3, 42, 4, 9, 0.68, 7, 38, 2, 2, 0, 1); + + +INSERT INTO PlayerMatchup (game_id, offensive_player_id, defensive_player_id, offensive_rating, defensive_rating, + possessions, points_scored, shooting_percentage) VALUES +(1, 1, 4, 125.5, 98.3, 15, 18, 0.60), +(1, 4, 1, 118.2, 102.5, 12, 14, 0.54), +(2, 5, 2, 132.1, 95.2, 18, 22, 0.65), +(3, 1, 5, 108.5, 112.3, 16, 12, 0.40); + + +INSERT INTO DraftEval (player_id, team_id, ranking, notes, nba_player_comparison) VALUES +(6, 1, 1, 'Elite two-way player with high basketball IQ. Can play multiple positions.', 'Jayson Tatum'), +(6, 2, 1, 'Perfect fit next to LeBron. Elite defender and versatile scorer.', 'Paul George'), +(6, 3, 2, 'Would complement Curry well but concerned about overlap with Wiggins.', 'Scottie Barnes'), +(6, 4, 1, 'Ideal modern wing for our system. High upside.', 'Jaylen Brown'), +(6, 5, 3, 'Great talent but concerned about fit with Butler and Bam.', 'Mikal Bridges'); + + +INSERT INTO GamePlan (game_id, offensive_strategy, defensive_strategy, special_situations) VALUES +(3, 'Attack Curry in pick and roll. Post up KD against smaller defenders.', + 'Switch 1-4, drop big on Curry PnR. Force others to beat us.', + 'Double Curry on all side PnRs in clutch time.'), +(5, 'Run through KD in the post. Push pace in transition.', + 'Pack the paint against Tatum drives. Stay home on shooters.', + 'Hack-a-Simmons if game is close in final 2 minutes.'); + + +INSERT INTO KeyMatchups (matchup_text) VALUES +('KD vs LeBron - Battle of the forwards'), +('Kyrie vs Curry - Elite guard matchup'), +('Simmons vs Draymond - Defensive anchors'), +('Durant vs Tatum - Scoring duel'), +('Kyrie vs Smart - Crafty guard battle'); + + +INSERT INTO SystemHealth (service_name, error_rate_pct, avg_response_time, status) VALUES +('API Gateway', 0.02, 145.5, 'Healthy'), +('Database Cluster', 0.00, 23.2, 'Healthy'), +('Cache Layer', 0.15, 8.5, 'Warning'), +('Load Balancer', 0.01, 12.3, 'Healthy'), +('File Storage', 0.05, 156.7, 'Healthy'); + + +INSERT INTO DataLoads (load_date, data_source, status, start_time, end_time) VALUES +('2025-01-20', 'NBA_API', 'Completed', '2025-01-20 02:00:00', '2025-01-20 02:15:30'), +('2025-01-21', 'ESPN_Feed', 'Completed', '2025-01-21 02:00:00', '2025-01-21 02:12:45'), +('2025-01-22', 'NBA_API', 'Failed', '2025-01-22 02:00:00', '2025-01-22 02:05:15'), +('2025-01-23', 'Stats_API', 'Completed', '2025-01-23 02:00:00', '2025-01-23 02:18:22'), +('2025-01-24', 'NBA_API', 'Completed', '2025-01-24 02:00:00', '2025-01-24 02:14:55'); + + +INSERT INTO ErrorLogs (error_type, error_message, service_component, user_id) VALUES +('DataQuality', 'Found 3 players with shooting percentage > 1.0', 'DataValidation', 1), +('APITimeout', 'NBA API request timeout after 30 seconds', 'DataIngestion', 1), +('DatabaseConnection', 'Lost connection to replica database', 'SystemHealth', NULL), +('DataIntegrity', 'Duplicate game entries detected', 'DataValidation', 1), +('MemoryLimit', 'Cache memory limit exceeded', 'CacheLayer', NULL); + + +INSERT INTO DataErrors (load_id, error_id) VALUES +(3, 2), +(1, 1), +(3, 3); \ No newline at end of file