diff --git a/bolao/admin.py b/bolao/admin.py index 9201ade..6550ce0 100644 --- a/bolao/admin.py +++ b/bolao/admin.py @@ -1,12 +1,16 @@ # -*- coding: utf-8 -*- +import flask + +from flask import request, redirect, url_for from flask.ext.admin import BaseView, AdminIndexView, expose from flask.ext.admin.contrib.sqla import ModelView as SQLAModelView from flask.ext import login - from wtforms import PasswordField + from bolao.utils import generate_password_hash -from bolao.tasks import update_scores_by_game, update_ranking, update_positions, update_scorer +from bolao.tasks import (update_scores_by_game, update_ranking, update_positions, + update_scorer, update_champions) from bolao.models import Scorer, Team @@ -64,3 +68,27 @@ def on_model_change(self, form, model, is_created): if not is_created: update_scorer(model) update_positions() + + +class ChampionsView(BaseView): + + @expose('/') + def index(self): + teams = Team.query.order_by(Team.name) + first = Team.query.filter_by(position=1).first() + second = Team.query.filter_by(position=2).first() + third = Team.query.filter_by(position=3).first() + fourth = Team.query.filter_by(position=4).first() + return self.render('admin/champions.html', teams=teams, first=first, second=second, third=third, fourth=fourth) + + @expose('/save', methods=['POST']) + def save(self): + + load = lambda x: Team.query.get(request.form.get(x, -1)) + try: + update_champions(load('first'), load('second'), load('third'), load('fourth')) + update_positions() + flask.flash("The champions was updated successfully", category='success') + except AssertionError: + flask.flash("You need to choose all four teams", category='error') + return redirect(url_for('.index')) diff --git a/bolao/main.py b/bolao/main.py index cf005af..b868117 100644 --- a/bolao/main.py +++ b/bolao/main.py @@ -126,7 +126,7 @@ def favicon(): def configure_admin(app): - from .admin import ModelView, IndexView, UserView, ScorerView, GameView + from .admin import ModelView, IndexView, UserView, ScorerView, GameView, ChampionsView admin = Admin(app, index_view=IndexView()) from .models import User, Scorer, Team, Game @@ -137,6 +137,7 @@ def configure_admin(app): admin.add_view(ScorerView(Scorer, db.session, 'Artilheiros')) # admin.add_view(ModelView(Team, db.session, u'Seleções')) admin.add_view(GameView(Game, db.session, 'Jogos')) + admin.add_view(ChampionsView(u"Campeões")) # admin.add_view(ModelView(BetGame, db.session)) # admin.add_view(ModelView(BetChampions, db.session)) # admin.add_view(ModelView(BetScorer, db.session)) diff --git a/bolao/models.py b/bolao/models.py index d84f28c..bea36dc 100644 --- a/bolao/models.py +++ b/bolao/models.py @@ -45,6 +45,7 @@ class Team(db.Model): id = db.Column(db.Integer, primary_key=True) alias = db.Column(db.String(3), unique=True) name = db.Column(db.String(80)) + position = db.Column(db.Integer) def __repr__(self): return self.name @@ -109,6 +110,10 @@ class BetChampions(db.Model): score = db.Column(db.Integer, default=0) + def __repr__(self): + return "1-{0} 2-{1} 3-{2} 4-{3}".format(self.first, self.second, self.third, self.fourth) + + class BetScorer(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) diff --git a/bolao/tasks.py b/bolao/tasks.py index 4372117..29da0a7 100644 --- a/bolao/tasks.py +++ b/bolao/tasks.py @@ -4,13 +4,15 @@ from sqlalchemy.orm.session import make_transient from bolao.database import db -from bolao.models import Scorer, BetGame, BetScorer, User +from bolao.models import User, Team, Scorer, BetGame, BetScorer, BetChampions EXACT_RESULT = 18 RESULT_AND_A_SCORE = 12 ONLY_RESULT = 9 ONLY_ONE_SCORE = 3 SCORER_POINTS = 20 +EXACT_CHAMPIONS = 10 +CHAMPIONS_POINTS = 5 def update_scorer(scorer): @@ -41,6 +43,40 @@ def update_scorer(scorer): db.session.commit() +def update_champions(first, second, third, fourth): + + assert None not in (first, second, third, fourth) + + # reset all + BetChampions.query.update({'score': 0}) + Team.query.update({'position': 0}) + + first.position = 1 + second.position = 2 + third.position = 3 + fourth.position = 4 + + rank = (first.id, second.id, third.id, fourth.id) + bets = BetChampions.query.filter(or_( + BetChampions.first_id.in_(rank), + BetChampions.second_id.in_(rank), + BetChampions.third_id.in_(rank), + BetChampions.fourth_id.in_(rank))).all() + + def update_pos(arg): + bet_team, team = arg[0], arg[1] + if bet_team.id in rank: + return EXACT_CHAMPIONS if bet_team == team else CHAMPIONS_POINTS + return 0 + + def update_all(bet): + bet.score = sum(map(update_pos, [(bet.first, first), (bet.second, second), (bet.third, third), (bet.fourth, fourth)])) + update_total_score(bet.user, bet_champions=bet) + + map(update_all, bets) + db.session.commit() + + def update_total_score(user, bet_scorer=None, bet_champions=None): user.score_total = user.score_games bet_scorer = bet_scorer or user.bet_scorer diff --git a/bolao/templates/admin/champions.html b/bolao/templates/admin/champions.html new file mode 100644 index 0000000..3cec432 --- /dev/null +++ b/bolao/templates/admin/champions.html @@ -0,0 +1,60 @@ +{% extends 'admin/master.html' %} + +{% block head %} +{{super()}} + +{% endblock %} + +{% block body %} +

Quais seleções foram as quatro primeiras colocadas da Copa do Mundo 2014?

+
+
+ + + + + + + + + {% for team in teams %} + + + + {% endfor %} +
 
{{team.name}}{{team.name}} ({{team.alias}}) + + + +
+ +
+
+{% endblock %} + +{% block tail_js %} +{{super()}} + +{% endblock %} diff --git a/bolao/templates/profile_champions.html b/bolao/templates/profile_champions.html index 51d0b92..3a17f78 100644 --- a/bolao/templates/profile_champions.html +++ b/bolao/templates/profile_champions.html @@ -1,5 +1,5 @@ -{% macro row_champion(team, position, pts=0) %} +{% macro row_champion(team, position) %} {{position}}º @@ -9,7 +9,11 @@   Não escolhido {% endif %} - {{pts}} + {% if team.position %} + {{10 if team.position == position else 5}} + {% else %} + 0 + {% endif %} {% endmacro %} @@ -25,6 +29,10 @@ {{row_champion(bet.second, 2)}} {{row_champion(bet.third, 3)}} {{row_champion(bet.fourth, 4)}} + + Total ({{((100*bet.score)/(40))|round(2)}}%) + {{bet.score}} + {% if profile.id == current_user.id and now() < config.BOLAO_BET_CHAMPIONS_LIMIT %} Editar diff --git a/tests/tasks.py b/tests/tasks.py index 78a407a..18ab5e1 100644 --- a/tests/tasks.py +++ b/tests/tasks.py @@ -2,10 +2,10 @@ from flask.ext.testing import TestCase -from bolao.models import Team, User, Game, Scorer, BetScorer, BetGame +from bolao.models import Team, User, Game, Scorer, BetScorer, BetGame, BetChampions from bolao.main import app_factory from bolao.tasks import (update_scores_by_game, update_ranking, update_ranking_criterias, - update_scorer) + update_scorer, update_champions) from bolao.database import db @@ -456,3 +456,102 @@ def test_no_changes(self): update_scorer(self.fred) self.assertEqual(20, bet.score) self.assertEqual(20, self.user.score_total) + + +class UpdateChampionsTest(TestCase): + + def create_app(self): + app = app_factory('Testing') + return app + + def setUp(self): + db.create_all() + + user = User(name="Test", email="email@test.co", active=True) + db.session.add(user) + + bra = Team(name='Brasil', alias='BRA') + arg = Team(name='Argentina', alias='ARG') + uru = Team(name='Uruguai', alias='URU') + ale = Team(name='Alemanha', alias='ALE') + usa = Team(name='Estados Unidos', alias='USA') + db.session.add(bra) + db.session.add(arg) + db.session.add(uru) + db.session.add(ale) + db.session.add(usa) + + db.session.commit() + + self.user = user + self.bra = bra + self.arg = arg + self.uru = uru + self.ale = ale + self.usa = usa + + def tearDown(self): + db.session.remove() + db.drop_all() + + def test_exact_positions(self): + + bet = BetChampions(first=self.bra, second=self.arg, third=self.ale, fourth=self.uru, user=self.user) + db.session.add(bet) + db.session.commit() + + update_champions(self.bra, self.arg, self.ale, self.uru) + + self.assertEqual(40, bet.score) + self.assertEqual(40, self.user.score_total) + + def test_only_positions(self): + + bet = BetChampions(first=self.bra, second=self.arg, third=self.ale, fourth=self.uru, user=self.user) + db.session.add(bet) + db.session.commit() + + update_champions(self.uru, self.ale, self.arg, self.bra) + + self.assertEqual(20, bet.score) + self.assertEqual(20, self.user.score_total) + + def test_mixed_positions(self): + + bet = BetChampions(first=self.ale, second=self.arg, third=self.bra, fourth=self.uru, user=self.user) + db.session.add(bet) + db.session.commit() + + update_champions(self.bra, self.usa, self.arg, self.uru) + + self.assertEqual(20, bet.score) + self.assertEqual(20, self.user.score_total) + + def test_any_position(self): + + t1 = Team(name="T1", alias="T1") + t2 = Team(name="T2", alias="T2") + t3 = Team(name="T3", alias="T3") + t4 = Team(name="T4", alias="T4") + + db.session.add(t1) + db.session.add(t2) + db.session.add(t3) + db.session.add(t4) + + bet = BetChampions(first=self.bra, second=self.arg, third=self.ale, fourth=self.uru, user=self.user) + db.session.add(bet) + db.session.commit() + + update_champions(t1, t2, t3, t4) + + self.assertEqual(0, bet.score) + + + def test_raises_with_none(self): + bet = BetChampions(first=self.bra, second=self.arg, third=self.ale, fourth=self.uru, user=self.user) + db.session.add(bet) + db.session.commit() + + self.assertRaises(AssertionError, update_champions, None, None, None, None) +