403 lines
16 KiB
Python
403 lines
16 KiB
Python
"""
|
|
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}/<int:game_id>', 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/<int:game_id>/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/<int:game_id>/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/<int:game_id>/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)
|
|
|