Browse Source

Able to set fear and ready status with forms. Cannot actually advance phase yet.

feature/js
Daniel Perelman 2 years ago
parent
commit
454cc15835
4 changed files with 251 additions and 32 deletions
  1. +6
    -4
      fear_tracker/models.py
  2. +88
    -0
      fear_tracker/static/css/styles.css
  3. +78
    -23
      fear_tracker/templates/game.html
  4. +79
    -5
      fear_tracker/views.py

+ 6
- 4
fear_tracker/models.py View File

@@ -97,7 +97,7 @@ class Game(models.Model):

def get_fear_to_next_card(self):
total_fear = self.get_current_total_fear()
leftover_fear = total_fear // self.fear_per_card
leftover_fear = total_fear % self.fear_per_card
return self.fear_per_card - leftover_fear

def _fear_phase(self, previous):
@@ -247,6 +247,8 @@ class Fear(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE, db_index=True)
effect = models.IntegerField(default=0)
# "pure" = not from destroying a town or city
pure_fear = models.IntegerField()
towns_destroyed = models.IntegerField()
cities_destroyed = models.IntegerField()
pure_fear = models.IntegerField(default=0)
towns_destroyed = models.IntegerField(default=0)
cities_destroyed = models.IntegerField(default=0)

unique_together = (("phase", "player", "effect"))

+ 88
- 0
fear_tracker/static/css/styles.css View File

@@ -21,47 +21,135 @@ footer a, footer a:visited {
.player-1 {
background: #f0ba57;
}
.player-1 .player-effects .effect:nth-child(even) {
background: #f0e057;
}
.player-1 .player-effects .effect:nth-child(odd) {
background: #d9f057;
}

.player-2 {
background: #73fcf6;
}
.player-2 .player-effects .effect:nth-child(even) {
background: #73e0fc;
}
.player-2 .player-effects .effect:nth-child(odd) {
background: #73bdfc;
}

.player-3 {
background: #bc9c8b;
}
.player-3 .player-effects .effect:nth-child(even) {
background: #bca88b;
}
.player-3 .player-effects .effect:nth-child(odd) {
background: #bcb58b;
}

.player-4 {
background: #77a0a6;
}
.player-4 .player-effects .effect:nth-child(even) {
background: #7794a6;
}
.player-4 .player-effects .effect:nth-child(odd) {
background: #7788a6;
}

.player-5 {
background: #fff172;
}
.player-5 .player-effects .effect:nth-child(even) {
background: #eaff72;
}
.player-5 .player-effects .effect:nth-child(odd) {
background: #c7ff72;
}

.player-6 {
background: #3adb85;
}
.player-6 .player-effects .effect:nth-child(even) {
background: #3adbad;
}
.player-6 .player-effects .effect:nth-child(odd) {
background: #3adbd5;
}

.player-7 {
background: #99c8e1;
}
.player-7 .player-effects .effect:nth-child(even) {
background: #99b6e1;
}
.player-7 .player-effects .effect:nth-child(odd) {
background: #99a4e1;
}

.player-8 {
background: #f73347;
}
.player-8 .player-effects .effect:nth-child(even) {
background: #f75033;
}
.player-8 .player-effects .effect:nth-child(odd) {
background: #f78133;
}

.player-9 {
background: #cac186;
}
.player-9 .player-effects .effect:nth-child(even) {
background: #c2ca86;
}
.player-9 .player-effects .effect:nth-child(odd) {
background: #b1ca86;
}

.player-10 {
background: #8ca684;
}
.player-10 .player-effects .effect:nth-child(even) {
background: #84a685;
}
.player-10 .player-effects .effect:nth-child(odd) {
background: #84a68d;
}

.player-11 {
background: #f068a9;
}
.player-11 .player-effects .effect:nth-child(even) {
background: #f06887;
}
.player-11 .player-effects .effect:nth-child(odd) {
background: #f06b68;
}

.player-12 {
background: #ed822b;
}
.player-12 .player-effects .effect:nth-child(even) {
background: #edb32b;
}
.player-12 .player-effects .effect:nth-child(odd) {
background: #ede32b;
}

.players .player {
margin-top: 1em;
}

.player-visible {
display: none;
}

.player-body {
display: none;
}

.player-visible:checked ~ .player-body {
display: block;
}

+ 78
- 23
fear_tracker/templates/game.html View File

@@ -5,36 +5,91 @@
<div class="phase">{{ phase }} phase of turn #{{ turn }}</div>
<div class="fear_summary">
<span class="available_fear_cards">{{ available_fear_cards }}</span>
fear cards available;
😱🎴;
<span class="fear_to_next_card">{{ fear_to_next_card }}</span>
fear to next fear card;
players have generated
😱 to next 😱🎴;
<span class="fear_this_phase">{{ fear_this_phase }}</span>
fear this phase
😱 this phase
</div>
<div class="access-code">
<span class="header">Access Code:</span> <a href="{% url 'qr_code' access_code=access_code %}" target="_blank">{{ access_code }}</a>
<span class="header">🔐</span> <a href="{% url 'qr_code' access_code=access_code %}" target="_blank">{{ access_code }}</a>
</div>
</header>
<div class="players">
{% for order, player in players.items %}
<div class="player player-{{ player.order }}">
<div class="player-summary">
{% if player.ready %}(ready){% else %}(waiting...){% endif %}
(<span class="player-total-fear player-{{ player.order }}-total-fear">{{ player.total_fear }}</span> fear)
{{ player.name }} ({{ player.get_spirit_name }})
</div>
<div class="player-effects">
{% for effect_num, effect in player.fear.items %}
<div class="effect effect-{{ effect_num }}">
Effect #{{ effect_num|add:1 }}
{{ effect.pure_fear }} fear
{{ effect.towns }} towns
{{ effect.cities }} cities
<div class="errors">
{% for error in errors %}
<p class="error">
{{ error }}
</p>
{% endfor %}
</div>
<form action="#" method="POST">
{% csrf_token %}
<div class="players">
{% for order, player in players.items %}
<div class="player player-{{ player.order }}">
<label for="player-{{ player.order }}-visible">
<div class="player-summary">
{% if player.ready %}🏁{% else %}⏳{% endif %}
(<span class="player-total-fear player-{{ player.order }}-total-fear">{{ player.total_fear }}</span> 😱)
{{ player.name }} ({{ player.get_spirit_name }})
</div>
</label>
<input type="checkbox"
class="player-visible"
name="player-{{ player.order }}-visible"
id="player-{{ player.order }}-visible"
{% if player.visible %} checked{% endif %}/>
<div class="player-body">
<label>
<input type="hidden"
name="player-{{ player.order }}-ready-orig"
id="player-{{ player.order }}-ready-orig"
value="{{ player.ready|lower }}" />
<input type="hidden"
name="player-{{ player.order }}-ready"
value="false" />
<input type="checkbox"
name="player-{{ player.order }}-ready"
id="player-{{ player.order }}-ready"
value="true"
{% if player.ready %} checked{% endif %}/>Done with
<span class="phase">{{ phase }} phase of turn #{{ turn }}</span>
</label>
<div class="player-effects">
{% for effect_num, effect in player.fear.items %}
<div class="effect effect-{{ effect_num }}">
Effect #{{ effect_num|add:1 }}

<input type="hidden" name="player-{{ player.order }}-effect-{{ effect_num }}-fear-orig" value="{{ effect.pure_fear }}">
<select name="player-{{ player.order }}-effect-{{ effect_num }}-fear"{% if player.ready %} disabled{% endif %}>
{% for val in range %}
<option value="{{ val }}"{% if val == effect.pure_fear %} selected="selected"{% endif %}>{{ val }} 😱</option>
{% endfor %}
</select>

<input type="hidden" name="player-{{ player.order }}-effect-{{ effect_num }}-towns-orig" value="{{ effect.towns }}">
<select name="player-{{ player.order }}-effect-{{ effect_num }}-towns"{% if player.ready %} disabled{% endif %}>
{% for val in range %}
<option value="{{ val }}"{% if val == effect.towns %} selected="selected"{% endif %}>{{ val }} 🏠</option>
{% endfor %}
</select>

<input type="hidden" name="player-{{ player.order }}-effect-{{ effect_num }}-cities-orig" value="{{ effect.cities }}">
<select name="player-{{ player.order }}-effect-{{ effect_num }}-cities"{% if player.ready %} disabled{% endif %}>
{% for val in range %}
<option value="{{ val }}"{% if val == effect.cities %} selected="selected"{% endif %}>{{ val }} 🏙️</option>
{% endfor %}
</select>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endfor %}
</div>
<input type="submit" name="update" value="Update fear">
{% if all_ready %}
<input type="submit" name="advance" value="Advance to next phase">
{% endif %}
</form>
{% endblock %}

+ 79
- 5
fear_tracker/views.py View File

@@ -8,7 +8,7 @@ from django.views.decorators.http import require_safe, require_http_methods
from django.urls import reverse

from .forms import NewGameForm, JoinGameForm, PlayerFormSet
from .models import Game, Player
from .models import Game, Player, Fear


def lookup_access_code(func):
@@ -89,15 +89,85 @@ def qr_code(request, access_code):


@lookup_access_code
@require_safe
@require_http_methods(["HEAD", "GET", "POST"])
def game(request, game):
players = OrderedDict()
for player in game.player_set.order_by('order').all():
player.total_fear = 0
player.changed_to_ready = False
player.fear = OrderedDict()
players[player.order] = player
for fear in game.get_current_phase().fear_set.order_by('effect').all():
player[fear.player.order].fear[fear.effect] = {

errors = []
fear_kind_dict = {
'fear': 'pure_fear',
'towns': 'towns_destroyed',
'cities': 'cities_destroyed',
}
current_phase = game.get_current_phase()
if request.method == 'POST':
for key, value in request.POST.items():
sections = key.split('-')
if key == 'csrfmiddlewaretoken' or sections[-1] == 'orig':
pass
elif sections[0] == 'player':
orig_value = request.POST.get(key + '-orig', None)
player_ord = int(sections[1])
player = players[player_ord]
if sections[2] == 'visible':
player.visible = True
elif sections[2] == 'ready':
if value != orig_value:
if value == 'true':
player.ready = True
player.changed_to_ready = True
else:
player.ready = False
player.save()
elif sections[2] == 'effect':
effect_num = int(sections[3])
effect_kind = sections[4]
if orig_value != value:
amount = int(value)
orig = int(orig_value)
if amount != orig:
if player.ready and not player.changed_to_ready:
errors.append(
f"{player.name} " +
f"({player.get_spirit_name()}) was " +
"marked as ready by another user, so " +
"your attempt to change their effect " +
f"#{effect_num} {effect_kind} " +
f"from {orig} to {amount} " +
"was not processed.")
else:
fear_row, created = Fear.objects.get_or_create(
phase=current_phase,
player=player,
effect=effect_num)
prop_name = fear_kind_dict[effect_kind]
current_value = getattr(fear_row, prop_name)
if current_value == orig:
setattr(fear_row, prop_name, amount)
fear_row.save()
else:
errors.append(
f"{player.name} " +
f"({player.get_spirit_name()})'s " +
"effect " +
f"#{effect_num} {effect_kind} " +
"was changed by another user to " +
f"{current_value}, so " +
f"your attempt to change it from " +
f"{orig} to {amount} " +
"was not processed.")
else:
raise Exception(key + ": " + value)
else:
raise Exception(key + ": " + value)

for fear in current_phase.fear_set.order_by('effect').all():
players[fear.player.order].fear[fear.effect] = {
'pure_fear': fear.pure_fear,
'towns': fear.towns_destroyed,
'cities': fear.cities_destroyed,
@@ -121,8 +191,12 @@ def game(request, game):
'phase': game.get_current_phase_name(),
'available_fear_cards': game.num_available_fear_cards(),
'fear_to_next_card': game.get_fear_to_next_card(),
'fear_this_phase': game.get_current_phase().fear_this_phase(),
'fear_this_phase': current_phase.fear_this_phase(),
'total_fear': game.get_current_total_fear(),
'players': players,
'all_ready': all(player.ready for player in players.values()),
'range': range(21),
'errors': errors,
})




Loading…
Cancel
Save