Browse Source

enforce game start,end, and state, add been found to gameplayerinfo

testing
Burathar 4 years ago
parent
commit
b4e508e020
  1. 13
      app/main/forms.py
  2. 57
      app/main/routes.py
  3. 7
      app/models/game.py
  4. 13
      app/templates/_game_player_info.html
  5. 27
      app/templates/create_game.html
  6. 7
      app/templates/game_owner_dashboard.html

13
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 import StringField, SubmitField, DateTimeField, BooleanField, HiddenField, FloatField, SelectField
from wtforms.validators import InputRequired, DataRequired, ValidationError, Length, NumberRange from wtforms.validators import InputRequired, DataRequired, ValidationError, Length, NumberRange
from pytz import timezone from pytz import timezone
from app.models import Objective from app.models import Objective, Game
from app import Config from app import Config
class CreateGameForm(FlaskForm): class CreateGameForm(FlaskForm):
game_name = StringField('Game Name', validators=[InputRequired(), Length(min=0, max=64)]) 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_disabled = BooleanField('No start time')
start_time = DateTimeField(id='datetimepicker_start', format="%d-%m-%Y %H:%M") start_time = DateTimeField(id='datetimepicker_start', format="%d-%m-%Y %H:%M")
end_time_disabled = BooleanField('No end time') end_time_disabled = BooleanField('No end time')
end_time = DateTimeField(id='datetimepicker_end', format="%d-%m-%Y %H:%M") end_time = DateTimeField(id='datetimepicker_end', format="%d-%m-%Y %H:%M")
timezone = HiddenField(validators=[DataRequired()]) timezone = HiddenField(validators=[DataRequired()])
submit = SubmitField('Create') submit = SubmitField('Create')
old_name = ''
def validate_start_time(self, start_time): def validate_start_time(self, start_time):
self.date_time_validator(self.start_time_disabled, 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_utc = clientzone.localize(date_time.data).astimezone(timezone('UTC'))
date_time.data = date_time_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): class ObjectiveForm(FlaskForm):
objective_name = StringField('Objective Name', validators=[Length(min=0, max=64)]) objective_name = StringField('Objective Name', validators=[Length(min=0, max=64)])
latitude = FloatField('Latitude', validators=[DataRequired(), NumberRange(min=-90, max=90)]) latitude = FloatField('Latitude', validators=[DataRequired(), NumberRange(min=-90, max=90)])

57
app/main/routes.py

@ -13,7 +13,7 @@ from sqlalchemy import and_
from app import db from app import db
from app.main import bp from app.main import bp
from app.utils import generate_qr_code, serve_pil_image 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 LocationEncoder, PlayerCaughtPlayer, Review, Location
from app.main.forms import CreateGameForm, ObjectiveForm, PlayerAddForm, UserCreateForm, \ from app.main.forms import CreateGameForm, ObjectiveForm, PlayerAddForm, UserCreateForm, \
PlayerUpdateForm, CatchBunnyForm PlayerUpdateForm, CatchBunnyForm
@ -36,9 +36,14 @@ def index():
@login_required @login_required
def create_game(): def create_game():
form = CreateGameForm() form = CreateGameForm()
form.state.choices = [(state.value, state.name) for state in GameState]
if form.validate_on_submit(): if form.validate_on_submit():
game = Game(name=form.game_name.data, start_time=form.start_time.data, if Game.query.filter_by(name=form.game_name.data):
end_time=form.end_time.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'])) game.players.append(GamePlayer(user=current_user, role=Role['owner']))
db.session.add(game) db.session.add(game)
db.session.commit() db.session.commit()
@ -46,6 +51,43 @@ def create_game():
return redirect(url_for('main.game_dashboard', game_name=game.name)) return redirect(url_for('main.game_dashboard', game_name=game.name))
return render_template('create_game.html', title='Create Game', form=form) return render_template('create_game.html', title='Create Game', form=form)
@bp.route('/game/<game_name>/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/<game_name>/delete') @bp.route('/game/<game_name>/delete')
@login_required @login_required
def delete_game(game_name): 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: if current_user.role_in_game(game) is not Role.hunter:
flash('Only hunters can catch bunnies!') flash('Only hunters can catch bunnies!')
abort(403) 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() game_bunnies = game.bunnies()
form = CatchBunnyForm() form = CatchBunnyForm()
@ -180,7 +225,6 @@ def add_player(game_name):
if not game.owned_by(current_user): if not game.owned_by(current_user):
abort(403) abort(403)
form_add = PlayerAddForm() form_add = PlayerAddForm()
form_add.role.choices = [(role.value, role.name) for role in Role] form_add.role.choices = [(role.value, role.name) for role in Role]
form_create = UserCreateForm() form_create = UserCreateForm()
@ -283,6 +327,9 @@ def objective_qrcode(objective_hash):
def objective(objective_hash): def objective(objective_hash):
objective = Objective.query.filter_by(hash=objective_hash).first_or_404() objective = Objective.query.filter_by(hash=objective_hash).first_or_404()
if current_user.role_in_game(objective.game) == Role.bunny: 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) player = current_user.player_in(objective.game)
if not objective in player.found_objectives: if not objective in player.found_objectives:
player.found_objectives.append(objective) player.found_objectives.append(objective)
@ -345,4 +392,4 @@ def user_profile(username):
user = User.query.filter_by(name=username).first_or_404() user = User.query.filter_by(name=username).first_or_404()
if current_user != user: if current_user != user:
abort(403) abort(403)
return render_template('user_profile.html', user=user) return render_template('user_profile.html', user=user)

7
app/models/game.py

@ -1,3 +1,4 @@
from datetime import datetime
from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.associationproxy import association_proxy
from app import db from app import db
from .game_state import GameState from .game_state import GameState
@ -64,3 +65,9 @@ class Game(db.Model):
return [pcp for pcps in return [pcp for pcps in
[player.player_caught_players for player in self.players] [player.player_caught_players for player in self.players]
for pcp in pcps if pcp.review == Review.none] 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

13
app/templates/_game_player_info.html

@ -25,5 +25,18 @@
<th>End Time</th> <th>End Time</th>
<td>{% if game.end_time %}{{ moment(game.end_time).format('DD-MM-YYYY, hh:mm')}}{% else %}-{% endif %}</td> <td>{% if game.end_time %}{{ moment(game.end_time).format('DD-MM-YYYY, hh:mm')}}{% else %}-{% endif %}</td>
</tr> </tr>
{% if current_user.role_in_game(game).name == 'bunny' %}
<tr>
<th>Been Found</th>
<td>
<span style="color:green;">{{ current_user.player_caught_by_players | selectattr('catching_player', '==', player) | selectattr('review.name', '==', 'accepted') |list|length}}</span> /
<span style="color:red;">{{ current_user.player_caught_by_players | selectattr('catching_player', '==', player) | selectattr('review.name', '==', 'denied') |list|length}}</span> /
<span style="color:gray;">{{ current_user.player_caught_by_players | selectattr('catching_player', '==', player) | selectattr('review.name', '==', 'none') |list|length}}</span>
<span style="font-size: smaller;">
(<span style="color:green;">Accepted</span>/<span style="color:red;">Denied</span>/<span style="color:gray;">Not reviewed</span>)
</span>
</td>
</tr>
{% endif %}
</table> </table>
</div> </div>

27
app/templates/create_game.html

@ -7,7 +7,7 @@
{% endblock %} {% endblock %}
{% block app_content %} {% block app_content %}
<h1>Create a new game</h1> <h1>{{ title }}</h1>
<div class="col-md-4 col-sm-6 col-xs-8"> <div class="col-md-4 col-sm-6 col-xs-8">
<hr> <hr>
@ -15,6 +15,7 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
{{ form.timezone }} {{ form.timezone }}
{{ wtf.form_field(form.game_name, class='form-control') }} {{ wtf.form_field(form.game_name, class='form-control') }}
{{ wtf.form_field(form.state, class='form-control') }}
{{ form.start_time.label }} {{ form.start_time.label }}
<div class="form-group row"> <div class="form-group row">
@ -35,7 +36,11 @@
{{ wtf.form_field(form.end_time_disabled, class='form-control') }} {{ wtf.form_field(form.end_time_disabled, class='form-control') }}
</div> </div>
</div> </div>
{% 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') }} {{ wtf.form_field(form.submit, class='btn btn-primary') }}
{% endif %}
</form> </form>
<hr> <hr>
</div> </div>
@ -50,26 +55,38 @@
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var date = new Date() '{% if form.start_time_enabled %}'
var startDate = new Date()
'{% else %}'
var startDate = null
'{% endif %}'
'{% if form.end_time_enabled %}'
var endDate = new Date()
'{% else %}'
var endDate = null
'{% endif %}'
$('#datetimepicker_start').datetimepicker({ $('#datetimepicker_start').datetimepicker({
//useCurrent: false, //Important! See issue #1075 //useCurrent: false, //Important! See issue #1075
locale: 'en-gb', locale: 'en-gb',
format: 'DD-MM-YYYY HH:mm', format: 'DD-MM-YYYY HH:mm',
keepInvalid: true, keepInvalid: true,
sideBySide: true, sideBySide: true,
defaultDate: date, defaultDate: startDate,
timeZone: moment.tz.guess() timeZone: moment.tz.guess()
}); });
date.setDate(date.getDate() + 1) //date.setDate(date.getDate() + 1)
$('#datetimepicker_end').datetimepicker({ $('#datetimepicker_end').datetimepicker({
//useCurrent: false, //Important! See issue #1075 //useCurrent: false, //Important! See issue #1075
locale: 'en-gb', locale: 'en-gb',
format: 'DD-MM-YYYY HH:mm', format: 'DD-MM-YYYY HH:mm',
keepInvalid: true, keepInvalid: true,
sideBySide: true, sideBySide: true,
defaultDate: date, defaultDate: endDate,
timeZone: moment.tz.guess() timeZone: moment.tz.guess()
}); });
var date = new Date()
$("#datetimepicker_start").on("dp.change", function (e) { $("#datetimepicker_start").on("dp.change", function (e) {
$('#datetimepicker_end').data("DateTimePicker").minDate(e.date); $('#datetimepicker_end').data("DateTimePicker").minDate(e.date);
}); });

7
app/templates/game_owner_dashboard.html

@ -10,11 +10,18 @@
{% block app_content %} {% block app_content %}
<h1>{{ game.name }} Dashboard</h1> <h1>{{ game.name }} Dashboard</h1>
<button class="btn btn-danger" onclick="deleteGame()">Delete Game</button> <button class="btn btn-danger" onclick="deleteGame()">Delete Game</button>
<a href="{{ url_for('main.change_game_settings', game_name=game.name) }}">
<button class="btn btn-primary">Change Game Settings</button>
</a>
{% if game.unreviewed_bunny_photos() %} {% if game.unreviewed_bunny_photos() %}
<a href="{{ url_for('main.review_caught_bunny_photos', game_name=game.name) }}"> <a href="{{ url_for('main.review_caught_bunny_photos', game_name=game.name) }}">
<button class="btn btn-primary">Review Bunny Photos</button> <button class="btn btn-primary">Review Bunny Photos</button>
</a> </a>
{% endif %} {% endif %}
<br><br>
<p><b>Start Time: </b>{{ game.start_time }}</p>
<p><b>End Time: </b>{{ game.end_time }}</p>
<p><b>State: </b>{{ game.state.name.title() }}</p>
<h2>Players:</h2> <h2>Players:</h2>
<p><a href="{{ url_for('main.add_player', game_name = game.name) }}">Add player</a></p> <p><a href="{{ url_for('main.add_player', game_name = game.name) }}">Add player</a></p>
<div class="table-responsive"> <div class="table-responsive">

Loading…
Cancel
Save