diff --git a/app/main/forms.py b/app/main/forms.py index 4bb5392..f692e31 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -3,17 +3,19 @@ from flask_wtf.file import FileField, FileAllowed, FileRequired from wtforms import StringField, SubmitField, DateTimeField, BooleanField, HiddenField, FloatField, SelectField from wtforms.validators import InputRequired, DataRequired, ValidationError, Length, NumberRange from pytz import timezone -from app.models import Objective +from app.models import Objective, Game from app import Config class CreateGameForm(FlaskForm): game_name = StringField('Game Name', validators=[InputRequired(), Length(min=0, max=64)]) + state = SelectField('Game State', coerce=int, validators=[InputRequired()]) start_time_disabled = BooleanField('No start time') start_time = DateTimeField(id='datetimepicker_start', format="%d-%m-%Y %H:%M") end_time_disabled = BooleanField('No end time') end_time = DateTimeField(id='datetimepicker_end', format="%d-%m-%Y %H:%M") timezone = HiddenField(validators=[DataRequired()]) submit = SubmitField('Create') + old_name = '' def validate_start_time(self, start_time): self.date_time_validator(self.start_time_disabled, start_time) @@ -29,6 +31,15 @@ class CreateGameForm(FlaskForm): date_time_utc = clientzone.localize(date_time.data).astimezone(timezone('UTC')) date_time.data = date_time_utc + def validate_game_name(self, game_name): + if game_name.data == '': + return + if game_name.data == self.old_name: + return + game = Game.query.filter_by(name=game_name.data).first() + if game is not None: + raise ValidationError('Please use a different name.') + class ObjectiveForm(FlaskForm): objective_name = StringField('Objective Name', validators=[Length(min=0, max=64)]) latitude = FloatField('Latitude', validators=[DataRequired(), NumberRange(min=-90, max=90)]) diff --git a/app/main/routes.py b/app/main/routes.py index e8eb602..8c95ff4 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -13,7 +13,7 @@ from sqlalchemy import and_ from app import db from app.main import bp from app.utils import generate_qr_code, serve_pil_image -from app.models import User, Game, Role, GamePlayer, Objective, ObjectiveMinimalEncoder, \ +from app.models import User, Game, Role, GamePlayer, GameState, Objective, ObjectiveMinimalEncoder,\ LocationEncoder, PlayerCaughtPlayer, Review, Location from app.main.forms import CreateGameForm, ObjectiveForm, PlayerAddForm, UserCreateForm, \ PlayerUpdateForm, CatchBunnyForm @@ -36,9 +36,14 @@ def index(): @login_required def create_game(): form = CreateGameForm() + form.state.choices = [(state.value, state.name) for state in GameState] + if form.validate_on_submit(): - game = Game(name=form.game_name.data, start_time=form.start_time.data, - end_time=form.end_time.data) + if Game.query.filter_by(name=form.game_name.data): + flash('Please choose a different game name') + return render_template('create_game.html', title='Create Game', form=form) + game = Game(name=form.game_name.data, start_time=form.start_time.data, + end_time=form.end_time.data, state=GameState(form.state.data)) game.players.append(GamePlayer(user=current_user, role=Role['owner'])) db.session.add(game) db.session.commit() @@ -46,6 +51,43 @@ def create_game(): return redirect(url_for('main.game_dashboard', game_name=game.name)) return render_template('create_game.html', title='Create Game', form=form) +@bp.route('/game//change_settings', methods=['GET', 'POST']) +@login_required +def change_game_settings(game_name): + game = Game.query.filter_by(name=game_name).first_or_404() + if not game.owned_by(current_user): + abort(403) + + form = CreateGameForm() + form.state.choices = [(state.value, state.name) for state in GameState] + form.old_name = game.name + + if request.method == 'GET': + form.state.default = game.state.value + # pylint: disable=no-member + form.process() + form.game_name.data = game.name + if game.start_time: + form.start_time.data = game.start_time + else: + form.start_time_disabled.data = True + form.start_time.data = None + if game.end_time: + form.end_time.data = game.end_time + else: + form.end_time_disabled.data = True + form.end_time.data = None + + if form.validate_on_submit(): + game.name = form.game_name.data + game.start_time = form.start_time.data + game.end_time = form.end_time.data + game.state = GameState(form.state.data) + db.session.commit() + flash(f"'{game.name}' had been updated!") + return redirect(url_for('main.game_dashboard', game_name=game.name)) + return render_template('create_game.html', title='Chage Game Settings', form=form) + @bp.route('/game//delete') @login_required def delete_game(game_name): @@ -89,6 +131,9 @@ def catch_bunny(game_name): if current_user.role_in_game(game) is not Role.hunter: flash('Only hunters can catch bunnies!') abort(403) + if not game.is_active(): + flash("Its not possible to catch a bunny before or after a game, or if the game is not in 'started' mode.") + return redirect(url_for('main.game_dashboard', game_name=game.name)) game_bunnies = game.bunnies() form = CatchBunnyForm() @@ -180,7 +225,6 @@ def add_player(game_name): if not game.owned_by(current_user): abort(403) - form_add = PlayerAddForm() form_add.role.choices = [(role.value, role.name) for role in Role] form_create = UserCreateForm() @@ -283,6 +327,9 @@ def objective_qrcode(objective_hash): def objective(objective_hash): objective = Objective.query.filter_by(hash=objective_hash).first_or_404() if current_user.role_in_game(objective.game) == Role.bunny: + if not objective.game.is_active(): + flash("Its not find an objective before or after a game, or if the game is not in 'started' mode.") + return redirect(url_for('main.game_dashboard', game_name=objective.game.name)) player = current_user.player_in(objective.game) if not objective in player.found_objectives: player.found_objectives.append(objective) @@ -345,4 +392,4 @@ def user_profile(username): user = User.query.filter_by(name=username).first_or_404() if current_user != user: abort(403) - return render_template('user_profile.html', user=user) \ No newline at end of file + return render_template('user_profile.html', user=user) diff --git a/app/models/game.py b/app/models/game.py index 67d5444..d8a95c6 100644 --- a/app/models/game.py +++ b/app/models/game.py @@ -1,3 +1,4 @@ +from datetime import datetime from sqlalchemy.ext.associationproxy import association_proxy from app import db from .game_state import GameState @@ -64,3 +65,9 @@ class Game(db.Model): return [pcp for pcps in [player.player_caught_players for player in self.players] for pcp in pcps if pcp.review == Review.none] + + def is_active(self): + now = datetime.utcnow() + return now > (self.start_time or datetime.min) and \ + now < (self.end_time or datetime.max) and \ + self.state == GameState.started \ No newline at end of file diff --git a/app/templates/_game_player_info.html b/app/templates/_game_player_info.html index 43d868d..9c9be1b 100644 --- a/app/templates/_game_player_info.html +++ b/app/templates/_game_player_info.html @@ -25,5 +25,18 @@ End Time {% if game.end_time %}{{ moment(game.end_time).format('DD-MM-YYYY, hh:mm')}}{% else %}-{% endif %} + {% if current_user.role_in_game(game).name == 'bunny' %} + + Been Found + + {{ current_user.player_caught_by_players | selectattr('catching_player', '==', player) | selectattr('review.name', '==', 'accepted') |list|length}} / + {{ current_user.player_caught_by_players | selectattr('catching_player', '==', player) | selectattr('review.name', '==', 'denied') |list|length}} / + {{ current_user.player_caught_by_players | selectattr('catching_player', '==', player) | selectattr('review.name', '==', 'none') |list|length}} + + (Accepted/Denied/Not reviewed) + + + + {% endif %} diff --git a/app/templates/create_game.html b/app/templates/create_game.html index adc3160..d7d0d61 100644 --- a/app/templates/create_game.html +++ b/app/templates/create_game.html @@ -7,7 +7,7 @@ {% endblock %} {% block app_content %} -

Create a new game

+

{{ title }}


@@ -15,6 +15,7 @@ {{ form.hidden_tag() }} {{ form.timezone }} {{ wtf.form_field(form.game_name, class='form-control') }} + {{ wtf.form_field(form.state, class='form-control') }} {{ form.start_time.label }}
@@ -35,7 +36,11 @@ {{ wtf.form_field(form.end_time_disabled, class='form-control') }}
+ {% if form.old_name %} + {{ wtf.form_field(form.submit, class='btn btn-primary', value="Update") }} + {% else %} {{ wtf.form_field(form.submit, class='btn btn-primary') }} + {% endif %}
@@ -50,26 +55,38 @@