""" Project: PARTS Website Author: Edward Middleton-Smith Precision And Research Technology Systems Limited Technology: App Routing Feature: TCG - MTG Game Routes Description: MTG Game Page Controller. """ # IMPORTS # internal from business_objects.api import API from business_objects.tcg.mtg_deck import MTG_Deck from business_objects.tcg.mtg_game import MTG_Game from business_objects.tcg.mtg_game_player import MTG_Game_Player, Parameters_MTG_Game_Player from business_objects.tcg.mtg_game_round import MTG_Game_Round, Parameters_MTG_Game_Round from business_objects.tcg.mtg_game_round_player_damage import MTG_Game_Round_Player_Damage, Parameters_MTG_Game_Round_Player_Damage from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck from business_objects.tcg.user import User, Parameters_User from datastores.datastore_mtg import DataStore_MTG from datastores.datastore_user import DataStore_User from forms.tcg.game import Filters_MTG_Game, Filters_MTG_Deck from helpers.helper_app import Helper_App from models.model_view_mtg_base import Model_View_MTG_Base from models.model_view_mtg_decks import Model_View_MTG_Decks from models.model_view_mtg_game import Model_View_MTG_Game from models.model_view_mtg_games import Model_View_MTG_Games from models.model_view_mtg_home import Model_View_MTG_Home import lib.argument_validation as av # external from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app, flash, Response from flask_mail import Mail, Message from extensions import db, oauth, mail from urllib.parse import quote_plus, urlencode from authlib.integrations.flask_client import OAuth from authlib.integrations.base_client import OAuthError from urllib.parse import quote, urlparse, parse_qs import json import base64 import hmac import hashlib import datetime routes_mtg_game = Blueprint('routes_mtg_game', __name__) @routes_mtg_game.route(Model_View_MTG_Base.HASH_PAGE_MTG_GAMES, methods=['GET']) def games(): Helper_App.console_log('mtg games') Helper_App.console_log(f'request_args: {request.args}') try: form_filters = Filters_MTG_Game.from_json(request.args) except Exception as e: Helper_App.console_log(f'Error: {e}') form_filters = Filters_MTG_Game() Helper_App.console_log(f'form_filters={form_filters}') datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): return redirect(url_for('routes_mtg_game.home')) parameters_game = form_filters.to_parameters(user_id_session = user_session.user_id) model = Model_View_MTG_Games(parameters_game = parameters_game) model.form_filters = form_filters Helper_App.console_log(f'form_filters={form_filters}') return render_template('pages/tcg/mtg/_games.html', model=model) @routes_mtg_game.route(f'{Model_View_MTG_Base.HASH_PAGE_MTG_GAME}/', methods=['GET']) def game_detail(game_id): Helper_App.console_log(f'mtg game detail: {game_id}') model = Model_View_MTG_Game(game_id=game_id) if not model.is_user_logged_in: return redirect(url_for('routes_mtg_game.home')) if model.game is None: flash('Game not found', 'error') return redirect(url_for('routes_mtg_game.games')) return render_template('pages/tcg/mtg/_game.html', model=model) @routes_mtg_game.route(Model_View_MTG_Base.HASH_SAVE_MTG_GAME, methods=['POST']) def save_game(): _m = 'routes_mtg_game.save_game' data = Helper_App.get_request_data(request) Helper_App.console_log(f'{_m}\n{data}') try: """ form_filters = Filters_MTG_Game.from_json(data.get(Model_View_MTG_Base.FLAG_FORM_FILTERS, {})) if not form_filters.validate_on_submit(): return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}' }) form_filters = Filters_MTG_Game.get_default() """ datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): raise Exception('User not logged in') games = data.get(Model_View_MTG_Base.FLAG_GAME, []) if len(games) == 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'No games to save.' }) Helper_App.console_log(f"Games to save: {games}") obj_game = MTG_Game.from_json(games[0]) Helper_App.console_log(f'obj_game={obj_game}') game_id, errors = DataStore_MTG.save_mtg_game(obj_game) if len(errors) > 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error saving games.\n{Model_View_MTG_Game.convert_list_objects_to_json(errors)}' }) return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_SUCCESS , Model_View_MTG_Base.ATTR_GAME_ID: game_id }) # return redirect(url_for('routes_mtg_game.game_detail', game_id = game_id)) except Exception as e: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' }) @routes_mtg_game.route(Model_View_MTG_Base.HASH_PAGE_MTG_HOME, methods=['GET']) def home(): model = Model_View_MTG_Home() if model.user.get_is_logged_in(): return redirect(url_for('routes_mtg_game.games')) return render_template('pages/tcg/mtg/_home.html', model=model) @routes_mtg_game.route(Model_View_MTG_Base.HASH_PAGE_MTG_TRIAL_GAME, methods=['GET']) def trial_game(): return send_from_directory('templates/pages/tcg/mtg', 'trial_game.html') @routes_mtg_game.route('/mtg/api/game//players', methods=['GET']) def get_game_players(game_id): """Get players for a game with enriched user and deck information.""" _m = 'routes_mtg_game.get_game_players' Helper_App.console_log(f'{_m}: game_id={game_id}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'User not logged in' }), 401 # Get players for this game parameters_player = Parameters_MTG_Game_Player.get_default(user_session.user_id) parameters_player.game_ids = str(game_id) parameters_player.get_all_game = False players, errors = datastore.get_many_mtg_game_player(parameters_player) if len(errors) > 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error fetching players: {errors}' }), 500 players_json = [p.to_json() for p in players] return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_SUCCESS , Model_View_MTG_Base.FLAG_DATA: players_json }) except Exception as e: Helper_App.console_log(f'{_m} Error: {str(e)}') return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error: {str(e)}' }), 500 @routes_mtg_game.route('/mtg/api/game//rounds', methods=['GET']) def get_many_game_round(game_id): """Get rounds for a game.""" _m = 'routes_mtg_game.get_many_game_round' Helper_App.console_log(f'{_m}: game_id={game_id}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'User not logged in' }), 401 # Get rounds for this game parameters_round = Parameters_MTG_Game_Round.get_default(user_session.user_id) parameters_round.game_ids = str(game_id) parameters_round.get_all_game = False rounds, errors = datastore.get_many_mtg_game_round(parameters_round) if len(errors) > 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error fetching rounds: {errors}' }), 500 rounds_json = [r.to_json() for r in rounds] return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_SUCCESS , Model_View_MTG_Base.FLAG_DATA: rounds_json }) except Exception as e: Helper_App.console_log(f'{_m} Error: {str(e)}') return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error: {str(e)}' }), 500 @routes_mtg_game.route('/mtg/api/game//damage-records', methods=['GET']) def get_many_game_player_damage(game_id): """Get damage records for a game.""" _m = 'routes_mtg_game.get_many_game_player_damage' Helper_App.console_log(f'{_m}: game_id={game_id}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'User not logged in' }), 401 parameters_damage = Parameters_MTG_Game_Round_Player_Damage.get_default(user_session.user_id) parameters_damage.game_ids = str(game_id) parameters_damage.get_all_game = False damages, errors = datastore.get_many_mtg_game_round_player_damage(parameters_damage) if len(errors) > 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error fetching damage records: {errors}' }), 500 damage_records = [d.to_json() for d in damages] return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_SUCCESS , Model_View_MTG_Base.FLAG_DATA: damage_records }) except Exception as e: Helper_App.console_log(f'{_m} Error: {str(e)}') return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error: {str(e)}' }), 500 @routes_mtg_game.route(Model_View_MTG_Base.HASH_SAVE_MTG_GAME_PLAYER, methods=['POST']) def save_game_player(): _m = 'routes_mtg_game.save_game_player' data = Helper_App.get_request_data(request) Helper_App.console_log(f'{_m}\n{data}') try: """ form_filters = Filters_MTG_Game.from_json(data.get(Model_View_MTG_Base.FLAG_FORM_FILTERS, {})) if not form_filters.validate_on_submit(): return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE, Model_View_MTG_Base.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}' }) form_filters = Filters_MTG_Game.get_default() """ datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): raise Exception('User not logged in') players = data.get(Model_View_MTG_Base.FLAG_PLAYER, []) if len(players) == 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'No players to save.' }) objs_player = [] for player in players: obj_player = MTG_Game_Player.from_json(player) Helper_App.console_log(f'obj_player = {obj_player}') objs_player.append(obj_player) success, errors = DataStore_MTG.save_mtg_game_player(objs_player) if len(errors) > 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error saving players.\n{Model_View_MTG_Game.convert_list_objects_to_json(errors)}' }) return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_SUCCESS if success else Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_DATA: None }) # return redirect(url_for('routes_mtg_game.game_detail', game_id = game_id)) except Exception as e: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' }) @routes_mtg_game.route(Model_View_MTG_Base.HASH_SAVE_MTG_GAME_ROUND_PLAYER_DAMAGE, methods=['POST']) def save_game_round_player_damage(): _m = 'routes_mtg_game.save_game_round_player_damage' data = Helper_App.get_request_data(request) Helper_App.console_log(f'{_m}\n{data}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): raise Exception('User not logged in') rounds = data.get(Model_View_MTG_Base.FLAG_ROUND, []) if len(rounds) == 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'No rounds to save.' }) objs_round = [] for round in rounds: obj_round = MTG_Game_Round.from_json(round) Helper_App.console_log(f'obj_round = {obj_round}') objs_round.append(obj_round) damages = data.get(Model_View_MTG_Base.FLAG_DAMAGE, []) if len(damages) == 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'No damages to save.' }) objs_damage = [] for damage in damages: obj_damage = MTG_Game_Round_Player_Damage.from_json(damage) Helper_App.console_log(f'obj_damage = {obj_damage}') objs_damage.append(obj_damage) success, errors = DataStore_MTG.save_mtg_game_round_player_damage(objs_round, objs_damage) if len(errors) > 0: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error saving round player damages.\n{Model_View_MTG_Game.convert_list_objects_to_json(errors)}' }) return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_SUCCESS if success else Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_DATA: None if success else ", ".join([str(e) for e in errors]) }) # return redirect(url_for('routes_mtg_game.game_detail', game_id = game_id)) except Exception as e: return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' }) @routes_mtg_game.route(Model_View_MTG_Base.HASH_PAGE_MTG_DECKS, methods=['GET']) def decks(): Helper_App.console_log('mtg decks') Helper_App.console_log(f'request_args: {request.args}') try: form_filters = Filters_MTG_Deck.from_json(request.args) except Exception as e: Helper_App.console_log(f'Error: {e}') form_filters = Filters_MTG_Deck() Helper_App.console_log(f'form_filters={form_filters}') datastore = DataStore_MTG() user_session = datastore.get_user_session() if not user_session.get_is_logged_in(): return redirect(url_for('routes_mtg_game.home')) parameters_deck = form_filters.to_parameters() model = Model_View_MTG_Decks(parameters_deck = parameters_deck) model.form_filters = form_filters Helper_App.console_log(f'form_filters={form_filters}') return render_template('pages/tcg/mtg/_decks.html', model=model)