From ad5e690e215c0f07aaf2d910a881beaf53096560 Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Tue, 17 Jan 2023 10:55:10 +0100 Subject: [PATCH] Allow GM to increase/decrese battle effects rounds --- src/party/models.py | 27 ++++++- src/party/templates/party/party_details.html | 10 ++- .../templates/party/snippets/effects.html | 21 ++++++ src/party/tests/test_interactions.py | 75 ++++++++++++++++--- src/party/urls.py | 6 ++ src/party/views.py | 27 +++++++ 6 files changed, 146 insertions(+), 20 deletions(-) diff --git a/src/party/models.py b/src/party/models.py index e30380a..83ffbeb 100644 --- a/src/party/models.py +++ b/src/party/models.py @@ -1,5 +1,5 @@ from django.db import models -from django.db.models import Q +from django.db.models import F, Q from django.urls import reverse from django_extensions.db.models import TimeStampedModel @@ -69,9 +69,28 @@ class Party(UniquelyNamedModel, TimeStampedModel, models.Model): character.reset_stats() +class BattleEffectQuerySet(models.QuerySet): + def increase_rounds(self): + self.temporary().update(remaining_rounds=F("remaining_rounds") + 1) + + def decrease_rounds(self): + self.active().update(remaining_rounds=F("remaining_rounds") - 1) + + def active(self): + return self.filter(remaining_rounds__gt=0) + + def terminated(self): + return self.filter(remaining_rounds=0) + + def permanent(self): + return self.filter(remaining_rounds=-1) + + def temporary(self): + return self.exclude(remaining_rounds=-1) + + class BattleEffectManager(models.Manager): - def decrease_all_remaining_rounds(self): - pass + pass class BattleEffect(TimeStampedModel, models.Model): @@ -99,7 +118,7 @@ class BattleEffect(TimeStampedModel, models.Model): verbose_name="créé par", ) - objects = BattleEffectManager() + objects = BattleEffectManager.from_queryset(BattleEffectQuerySet)() @property def remaining_percent(self) -> float: diff --git a/src/party/templates/party/party_details.html b/src/party/templates/party/party_details.html index 94481c9..6d14bb5 100644 --- a/src/party/templates/party/party_details.html +++ b/src/party/templates/party/party_details.html @@ -7,10 +7,12 @@ {% block content %}

{{ party.name }}

MJ : {{ party.game_master.get_full_name|default:party.game_master.username }}

-

- Réinitialiser - les stats -

+ {% if party.game_master == request.user %} +

+ Réinitialiser + les stats +

+ {% endif %}

Personnages

{% for character in party.characters.all %} diff --git a/src/party/templates/party/snippets/effects.html b/src/party/templates/party/snippets/effects.html index 345f697..0b9de97 100644 --- a/src/party/templates/party/snippets/effects.html +++ b/src/party/templates/party/snippets/effects.html @@ -1,3 +1,4 @@ +{% load character_extras %}
+ {% if party.game_master == request.user %} +
+ + +
+ {% endif %}
{% for effect in party.effects.all %} diff --git a/src/party/tests/test_interactions.py b/src/party/tests/test_interactions.py index d7eaf33..3cbe128 100644 --- a/src/party/tests/test_interactions.py +++ b/src/party/tests/test_interactions.py @@ -1,3 +1,5 @@ +import random + import pytest from django.urls import reverse from model_bakery import baker @@ -137,13 +139,8 @@ def test_player_can_add_effect_to_group( ) remaining_rounds = "8" - login(selenium, live_server, user, password) - - url = reverse("party:details", kwargs={"pk": party.pk}) - selenium.get(live_server.url + url) - + go_to_party(selenium, live_server, party, user, password) fill_effect(selenium, name, description, target, remaining_rounds) - assert_effect_is_created(name, description, target, remaining_rounds) # Todo: assert effect is displayed @@ -170,13 +167,8 @@ def test_gm_can_add_effect_to_group( ) remaining_rounds = "-1" - login(selenium, live_server, user, password) - - url = reverse("party:details", kwargs={"pk": party.pk}) - selenium.get(live_server.url + url) - + go_to_party(selenium, live_server, party, user, password) fill_effect(selenium, name, description, target, remaining_rounds) - assert_effect_is_created(name, description, target, remaining_rounds) # Todo: assert effect is displayed @@ -186,6 +178,59 @@ def test_gm_can_change_remaining_rounds( selenium: WebDriver, live_server: LiveServer, initial_data: None ): """The GM of a group can increase or decrease the remaining rounds of effects.""" + user, password = "gm", "password" + gm = User.objects.create_user(user, password=password) + party = baker.make(Party, game_master=gm) + + active_not_nearly_terminated = baker.make( # noqa: F841 + BattleEffect, + _quantity=7, + remaining_rounds=lambda: random.randint(2, 12), + party=party, + ) + active_nearly_terminated = baker.make( # noqa: F841 + BattleEffect, _quantity=3, remaining_rounds=1, party=party + ) + terminated = baker.make( # noqa: F841 + BattleEffect, _quantity=5, remaining_rounds=0, party=party + ) + permanent = baker.make( # noqa: F841 + BattleEffect, _quantity=2, remaining_rounds=-1, party=party + ) + not_party = baker.make(BattleEffect, _quantity=4, remaining_rounds=55) # noqa: F841 + + go_to_party(selenium, live_server, party, user, password) + selenium.find_element(By.ID, "increase-rounds").click() + assert BattleEffect.objects.filter(party=party).permanent().count() == 2 + assert ( + BattleEffect.objects.filter(party=party, remaining_rounds__gt=1).count() == 10 + ) + assert BattleEffect.objects.filter(party=party, remaining_rounds=1).count() == 5 + assert BattleEffect.objects.filter(party=party).terminated().count() == 0 + assert ( + BattleEffect.objects.exclude(party=party).filter(remaining_rounds=55).count() + == 4 + ) + + selenium.find_element(By.ID, "decrease-rounds").click() + assert BattleEffect.objects.filter(party=party).permanent().count() == 2 + assert BattleEffect.objects.filter(party=party, remaining_rounds__gt=1).count() == 7 + assert BattleEffect.objects.filter(party=party, remaining_rounds=1).count() == 3 + assert BattleEffect.objects.filter(party=party).terminated().count() == 5 + assert ( + BattleEffect.objects.exclude(party=party).filter(remaining_rounds=55).count() + == 4 + ) + + selenium.find_element(By.ID, "decrease-rounds").click() + assert BattleEffect.objects.filter(party=party).permanent().count() == 2 + assert BattleEffect.objects.filter(party=party).active().count() == 7 + assert BattleEffect.objects.filter(party=party, remaining_rounds=1).count() == 0 + assert BattleEffect.objects.filter(party=party).terminated().count() == 8 + assert ( + BattleEffect.objects.exclude(party=party).filter(remaining_rounds=55).count() + == 4 + ) @pytest.mark.django_db @@ -234,3 +279,9 @@ def assert_effect_is_created(name, description, target, remaining_rounds): assert effect.target == target assert effect.description == description assert str(effect.remaining_rounds) == remaining_rounds + + +def go_to_party(selenium, live_server, party, user, password): + login(selenium, live_server, user, password) + url = reverse("party:details", kwargs={"pk": party.pk}) + selenium.get(live_server.url + url) diff --git a/src/party/urls.py b/src/party/urls.py index b5708e7..568698d 100644 --- a/src/party/urls.py +++ b/src/party/urls.py @@ -11,6 +11,12 @@ urlpatterns = [ path("/delete/", views.party_delete, name="delete"), path("/reset_stats/", views.party_reset_stats, name="reset_stats"), path("/add_effect/", views.party_add_effect, name="add_effect"), + path( + "/increase_rounds/", views.party_increase_rounds, name="increase_rounds" + ), + path( + "/decrease_rounds/", views.party_decrease_rounds, name="decrease_rounds" + ), path("/leave//", views.party_leave, name="leave"), path("/join//", views.party_join, name="join"), path("/refuse//", views.party_refuse, name="refuse"), diff --git a/src/party/views.py b/src/party/views.py index a7bc196..1d298d2 100644 --- a/src/party/views.py +++ b/src/party/views.py @@ -1,12 +1,14 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.shortcuts import get_object_or_404, redirect, render +from django.views.decorators.http import require_GET, require_http_methods from character.models import Character, HarmfulState from party.forms import BattleEffectForm, PartyForm from party.models import Party +@require_GET @login_required def parties_list(request): context = { @@ -17,6 +19,7 @@ def parties_list(request): return render(request, "party/parties_list.html", context) +@require_http_methods(["GET", "POST"]) @login_required def party_create(request): if request.method == "GET": @@ -33,6 +36,7 @@ def party_create(request): return render(request, "party/party_form.html", context) +@require_GET @login_required def party_details(request, pk): party = get_object_or_404(Party.objects.related_to(request.user), pk=pk) @@ -43,6 +47,7 @@ def party_details(request, pk): return render(request, "party/party_details.html", context) +@require_http_methods(["GET", "POST"]) @login_required def party_delete(request, pk): party = get_object_or_404(Party.objects.managed_by(request.user), pk=pk) @@ -55,6 +60,7 @@ def party_delete(request, pk): return render(request, "party/party_delete.html", context) +@require_http_methods(["GET", "POST"]) @login_required def party_reset_stats(request, pk): party = get_object_or_404(Party.objects.managed_by(request.user), pk=pk) @@ -68,6 +74,7 @@ def party_reset_stats(request, pk): return render(request, "party/party_reset_stats.html", context) +@require_http_methods(["GET", "POST"]) @login_required def party_add_effect(request, pk): party = get_object_or_404(Party.objects.played_or_mastered_by(request.user), pk=pk) @@ -86,6 +93,23 @@ def party_add_effect(request, pk): return render(request, "party/snippets/add_effect_form.html", context) +@require_GET +@login_required +def party_increase_rounds(request, pk): + party = get_object_or_404(Party.objects.managed_by(request.user), pk=pk) + party.effects.increase_rounds() + return render(request, "party/snippets/effects.html", {"party": party}) + + +@require_GET +@login_required +def party_decrease_rounds(request, pk): + party = get_object_or_404(Party.objects.managed_by(request.user), pk=pk) + party.effects.decrease_rounds() + return render(request, "party/snippets/effects.html", {"party": party}) + + +@require_http_methods(["GET", "POST"]) @login_required def party_change(request, pk): party = get_object_or_404(Party.objects.managed_by(request.user), pk=pk) @@ -102,6 +126,7 @@ def party_change(request, pk): return render(request, "party/party_form.html", context) +@require_http_methods(["GET", "POST"]) @login_required def party_leave(request, pk, character_pk): party = get_object_or_404(Party.objects.played_by(request.user).distinct(), pk=pk) @@ -116,6 +141,7 @@ def party_leave(request, pk, character_pk): return render(request, "party/party_leave.html", context) +@require_GET @login_required def party_join(request, pk, character_pk): party = get_object_or_404(Party.objects.invited_to(request.user).distinct(), pk=pk) @@ -128,6 +154,7 @@ def party_join(request, pk, character_pk): return redirect("party:list") +@require_GET @login_required def party_refuse(request, pk, character_pk): party = get_object_or_404(Party.objects.invited_to(request.user).distinct(), pk=pk)