Advanced event types

This commit is contained in:
2019-10-17 20:35:18 +02:00
parent d6d0d0fcbb
commit ad3b216a0d
9 changed files with 151 additions and 38 deletions

View File

@@ -43,10 +43,11 @@ def enemy_choice_for_season(season_id: int):
""" """
db = new_session() db = new_session()
season: Season = db.query(Season).get(season_id) season: Season = db.query(Season).get(season_id)
season_enemies = [enemy for enemy in season.enemies if not enemy.is_defeated]
global_enemies = db.query(Enemy).filter(Enemy.season_id == -1).all() global_enemies = db.query(Enemy).filter(Enemy.season_id == -1).all()
if not season and not global_enemies: if not season and not global_enemies:
return [] return []
combined = global_enemies + season.enemies combined = global_enemies + season_enemies
return [(e.id, e.name) for e in combined] return [(e.id, e.name) for e in combined]

View File

@@ -79,9 +79,7 @@ class EventForm(FlaskForm):
event_id = HiddenField("Event ID") event_id = HiddenField("Event ID")
episode_id = HiddenField("Episode ID") episode_id = HiddenField("Episode ID")
event_type = SelectField( event_type = SelectField(
"Type", choices=choices.EventChoiceIterable(), coerce=int, "Type", choices=choices.EventChoiceIterable(), coerce=int)
validators=[DataRequired()]
)
time = TimeField("Time", format="%H:%M", validators=[DataRequired()]) time = TimeField("Time", format="%H:%M", validators=[DataRequired()])
player = SelectField("Player", choices=choices.PlayerChoiceIterable(), coerce=int) player = SelectField("Player", choices=choices.PlayerChoiceIterable(), coerce=int)
enemy = SelectField("Enemy", coerce=int) enemy = SelectField("Enemy", coerce=int)

View File

@@ -94,6 +94,10 @@ class Enemy(Base):
events: Iterable["Event"] = relationship('Event', back_populates="enemy") events: Iterable["Event"] = relationship('Event', back_populates="enemy")
@property
def is_defeated(self):
return any([e for e in self.events if e.type == EventType.Victory])
def populate_from_form(self, form: "forms.EnemyForm"): def populate_from_form(self, form: "forms.EnemyForm"):
self.name = str(form.name.data) self.name = str(form.name.data)
self.boss = bool(form.is_boss.data) self.boss = bool(form.is_boss.data)

View File

@@ -51,8 +51,19 @@ a:hover {
font-family: 'DarkSouls', serif; font-family: 'DarkSouls', serif;
} }
.nav-container{
margin-bottom: 10px;
}
.btn-toolbar{ .btn-toolbar{
padding: 5px 0; margin: 10px 0;
}
.btn-toolbar .btn {
margin-right: 10px;
}
.card{
margin-bottom: 25px;
} }
.vertical-center { .vertical-center {
@@ -64,6 +75,11 @@ a:hover {
} }
/* Theme customizations */ /* Theme customizations */
.list-group-item {
display: flex;
justify-content: space-between;
}
.list-group-item:hover { .list-group-item:hover {
color: inherit; color: inherit;
background-color: rgb(34, 34, 34); background-color: rgb(34, 34, 34);
@@ -72,3 +88,19 @@ a:hover {
h1 { h1 {
font-size: 2.5rem; font-size: 2.5rem;
} }
html {
height: 100%;
}
body {
display: flex;
flex-direction: column;
height: 100%;
}
.content{
flex: 1 0 auto;
}
.footer {
flex-shrink: 0;
}

View File

@@ -14,7 +14,8 @@
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
{% endblock %} {% endblock %}
{% block body %}
<div class="content">
{% block navbar %} {% block navbar %}
{% set nav_bar = [ {% set nav_bar = [
('/season', 'seasons', 'Seasons', 'fas fa-calendar'), ('/season', 'seasons', 'Seasons', 'fas fa-calendar'),
@@ -22,7 +23,7 @@
('/enemy', 'enemies', 'Enemies', 'fas fa-skull-crossbones'), ('/enemy', 'enemies', 'Enemies', 'fas fa-skull-crossbones'),
('/drink', 'drinks', 'Drinks', 'fas fa-beer') ('/drink', 'drinks', 'Drinks', 'fas fa-beer')
]-%} ]-%}
<div class="container"> <div class="container nav-container">
<nav class="navbar navbar-expand-lg bg-dark navbar-dark"> <nav class="navbar navbar-expand-lg bg-dark navbar-dark">
<a class="navbar-brand"> <a class="navbar-brand">
@@ -56,13 +57,14 @@
{% block content %} {% block content %}
<div class="container"> <div class="container">
{% block page %} {% block page %}
{% endblock %}
<div>
{% block footer %}
&copy; Sauf Software by D⁵: <a href="#">Durstiger Donnerstag Digital Drinking Divison</a>.
{% endblock %}
</div>
</div>
{% endblock %}
</div>
{% endblock %} {% endblock %}
</div>
<div class="container footer">&copy; Sauf Software by D⁵: <a href="#">Durstiger Donnerstag Digital Drinking Divison</a>.</div>
{% endblock %}

View File

@@ -19,6 +19,7 @@
<th scope="col" class="col-sm-auto text-center">Name</th> <th scope="col" class="col-sm-auto text-center">Name</th>
<th scope="col" class="col-sm-auto text-center">Season</th> <th scope="col" class="col-sm-auto text-center">Season</th>
<th scope="col" class="col-sm-auto text-center">Boss Enemy</th> <th scope="col" class="col-sm-auto text-center">Boss Enemy</th>
<th scope="col" class="col-sm-auto text-center">Defeated</th>
{% if g.is_editor %} {% if g.is_editor %}
<th scope="col" class="col-sm-auto text-center">Editor</th> <th scope="col" class="col-sm-auto text-center">Editor</th>
@@ -32,7 +33,12 @@
<td class="col-sm-auto text-center">{{ enemy.season.game }}</td> <td class="col-sm-auto text-center">{{ enemy.season.game }}</td>
<td class="col-sm-auto text-center"> <td class="col-sm-auto text-center">
{% if enemy.boss %} {% if enemy.boss %}
<span class="fas fa-check"></span> <i class="fas fa-check"></i>
{% endif %}
</td>
<td class="col-sm-auto text-center">
{% if enemy.is_defeated %}
<i class="fas fa-check"></i>
{% endif %} {% endif %}
</td> </td>

View File

@@ -17,7 +17,7 @@
{% endif %} {% endif %}
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-4">
<!--region Info Card--> <!--region Info Card-->
@@ -46,7 +46,7 @@
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<span class="font-weight-bold">Enemies Defeated:</span> <span class="font-weight-bold">Enemies Defeated:</span>
{{ 0 }} {{ model.victories|length or 0 }}
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<span class="font-weight-bold">Deaths:</span> <span class="font-weight-bold">Deaths:</span>
@@ -59,8 +59,6 @@
<!--endregion--> <!--endregion-->
<hr>
<!--region Player Card--> <!--region Player Card-->
<div class="card"> <div class="card">
@@ -72,12 +70,14 @@
<thead> <thead>
<tr> <tr>
<th scope="col" class="col-sm-auto text-center">Name</th> <th scope="col" class="col-sm-auto text-center">Name</th>
<th scope="col" class="col-sm-auto text-center">Playtime</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for player in model.players %} {% for player in model.players %}
<tr> <tr>
<td class="col-sm-auto text-center">{{ player.name }}</td> <td class="col-sm-auto text-center">{{ player.name }}</td>
<td class="col-sm-auto text-center">{{ "0m" }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@@ -89,7 +89,7 @@
</div> </div>
<div class="col-sm-6"> <div class="col-sm-8">
<!--region Deaths Card--> <!--region Deaths Card-->
@@ -130,6 +130,45 @@
<!--endregion--> <!--endregion-->
<!--region Victories Card-->
<div class="card">
<div class="card-header text-center">
Victories
</div>
<div class="card-body">
{% if model.victories %}
<table class="table table-striped table-bordered">
<thead>
<tr>
<th scope="col" class="col-xs-auto text-center">Time</th>
<th scope="col" class="col-xs text-center">Enemy</th>
<th scope="col" class="col-xs text-center">Player</th>
</tr>
</thead>
<tbody>
{% for entry in model.victories %}
<tr>
<td class="col-xs-auto text-center">{{ entry.time|format_time }}</td>
<td class="col-xs text-center">{{ entry.enemy.name }}</td>
<td class="col-xs text-center">{{ entry.player.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="alert alert-info">No Enemies were defeated</div>
{% endif %}
</div>
</div>
<!--endregion-->
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@@ -3,7 +3,7 @@ from flask import render_template, request, redirect, url_for
from estusshots import app from estusshots import app
from estusshots import forms, models, orm from estusshots import forms, models, orm
from estusshots.util import authorize from estusshots.util import authorize
from estusshots.orm import Season, Episode, Player, Event from estusshots.orm import Season, Episode, Player
@app.route("/season/<season_id>/episode/<episode_id>") @app.route("/season/<season_id>/episode/<episode_id>")
@@ -12,13 +12,14 @@ def episode_detail(season_id: int, episode_id: int):
db = orm.new_session() db = orm.new_session()
episode: Episode = db.query(Episode).get(episode_id) episode: Episode = db.query(Episode).get(episode_id)
deaths = [event for event in episode.events if event.type == orm.EventType.Death] deaths = [event for event in episode.events if event.type == orm.EventType.Death]
victories = [event for event in episode.events if event.type == orm.EventType.Victory]
model = { model = {
"title": f"{episode.season.code}{episode.code}", "title": f"{episode.season.code}{episode.code}",
"episode": episode, "episode": episode,
"season": episode.season, "season": episode.season,
"players": episode.players, "players": episode.players,
"deaths": sorted(deaths, key=lambda x: x.time), "deaths": sorted(deaths, key=lambda x: x.time),
"victories": sorted(victories, key=lambda x: x.time)
} }
return render_template("episode_details.html", model=model) return render_template("episode_details.html", model=model)

View File

@@ -3,11 +3,49 @@ from collections import namedtuple
from flask import render_template, request, redirect from flask import render_template, request, redirect
from estusshots import app, orm from estusshots import app, orm
from estusshots import forms, models, choices from estusshots import forms, choices
from estusshots.util import authorize from estusshots.util import authorize
from estusshots.orm import new_session, EventType, Event, Episode, Enemy, Penalty from estusshots.orm import new_session, EventType, Event, Episode, Enemy, Penalty
def death_event(event, db, form):
"""Add penalties to the event if it is a death event"""
if not event.id:
for entry in form.penalties:
penalty = orm.Penalty()
penalty.player_id = entry.player_id.data
penalty.drink_id = entry.drink.data
db.add(penalty)
event.penalties.append(penalty)
else:
for event in event.penalties:
penalty = next((p for p in form.penalties.data if p["penalty_id"] == event.id), None)
if not penalty:
continue
penalty.player_id = form.player_id.data
penalty.drink_id = form.drink.data
def victory_event(event, db, form):
"""No need for additional actions yet"""
pass
def pause_event(event, db, form):
"""Pause events have neither penalties or enemies"""
event.enemy_id = None
event.enemy = None
event.player_id = None
event.player = None
event_type_map = {
EventType.Death: death_event,
EventType.Victory: victory_event,
EventType.Pause: pause_event
}
@app.route("/season/<s_id>/episode/<ep_id>/event/new", methods=["GET"]) @app.route("/season/<s_id>/episode/<ep_id>/event/new", methods=["GET"])
@authorize @authorize
def event_new(s_id: int, ep_id: int): def event_new(s_id: int, ep_id: int):
@@ -61,21 +99,13 @@ def event_edit(s_id: int, ep_id: int, ev_id: int):
return render_template("event_editor.html", model=model, form=form) return render_template("event_editor.html", model=model, form=form)
if not event: if not event:
event = Event() event = Event()
for entry in form.penalties:
penalty = orm.Penalty()
penalty.player_id = entry.player_id.data
penalty.drink_id = entry.drink.data
db.add(penalty)
event.penalties.append(penalty)
db.add(event) db.add(event)
else:
for event in event.penalties:
penalty = next((p for p in form.penalties.data if p["penalty_id"] == event.id), None)
if not penalty:
continue
penalty.player_id = form.player_id.data
penalty.drink_id = form.drink.data
event.populate_from_form(form) event.populate_from_form(form)
# Different event types fill different fields
func = event_type_map[event.type]
func(event, db, form)
db.commit() db.commit()
return redirect(f"/season/{s_id}/episode/{ep_id}") return redirect(f"/season/{s_id}/episode/{ep_id}")