start card and csv views

This commit is contained in:
2021-12-31 14:47:50 -06:00
parent b0316e2188
commit f880d7fb13
8 changed files with 423 additions and 2 deletions

View File

@@ -0,0 +1,280 @@
{% load static %}
<head>
<meta charset="utf-8">
<title>Gamecard</title>
<link rel="stylesheet" href="{% static "css/base.css"%}">
<link rel="stylesheet" href="{% static "css/paper.css"%}">
<style> @page { size: letter }
</style>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inconsolata">
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Open+Sans">
<style>
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
@font-face {
font-family: 'Open Sans';
src: url("{% static 'fonts/OpenSans.ttf' %}") format("truetype-variations");
font-weight: 1 999;
font-stretch: 0% 100%
}
@font-face {
font-family: 'Inconsolata';
src: url("{% static 'fonts/Inconsolata.ttf' %}") format("truetype-variations");
font-weight: 1 999;
font-stretch: 0% 100%
}
.whole-card {
margin:0;
padding:0;
height: 12.5cm;
width: 17.5cm;
outline: .8px dashed lightgray;
margin: auto;
display: flex;
}
.half-card {
margin: auto;
padding: .1in;
height: 100%;
width: 50%;
}
card-left {
float: left;
margin: auto;
}
card-right {
float: right;
}
.content {
height: 100%;
width: 100%;
{#outline: solid grey;#}
}
table {
font-family: "Open Sans";
border-collapse: collapse;
empty-cells: show;
font-size:11px;
table-layout: fixed;
white-space: nowrap;
text-overflow: ellipsis;
overflow-x: hidden;
width: 100%;
border: 1px solid #000;
}
th, td {
/* box-sizing: content-box; */
border: 0.5px solid black;
height: 17px;
text-overflow: ellipsis;
overflow-x: hidden;
padding: 0px;
padding-left: 2px;
padding-right: 2px;
}
.gametitle {
text-transform: uppercase;
font-stretch: condensed;
text-align: center;
font-weight: bold;
}
.homeaway {
text-transform: uppercase;
font-stretch: extra-expanded;
text-align: center;
font-weight: 900;
font-size: 12px;
}
.numbercell {
font-family: "Inconsolata";
text-align: center;
font-size: 10px;
}
.statscell {
font-family: "Inconsolata";
text-align: center;
font-stretch: extra-condensed;
font-size: 9px;
width: 60px;
}
tr:nth-child(even) {background-color: #f2f2f2;}
th{
background: black;
color: white;
border: none;
}
.customcol{
width: 120px;
text-transform: uppercase;
font-stretch: condensed;
}
.condensedNameCell{
width: 70px;
text-transform: uppercase;
font-stretch: condensed;
}
.square {
height: 14px;
width: 14px;
}
.available{
background-color: #B7E1CD;
}
.notavailable{
background-color: #F4C7C3;
}
.maybeavailable{
background-color: #B7E1CD;
}
.starting{
font-weight: bold;
}
</style>
</head>
<body class="letter">
<section class="sheet padding-10mm">
<div class="whole-card">
<div id="NW" class="half-card red">
<div class="content card-left">
<table>
<thead>
<tr>
<th colspan="9" class="gametitle">{{ event.teamsnap_event.csv_event_title }}</th>
<th colspan="3" class="homeaway">
{% if event.home_team.name == user.profile.teamsnapsettings.managed_team.name %}
HOME
{% elif event.away_team.name == user.profile.teamsnapsettings.managed_team.name %}
AWAY
{% else %}
{% endif %}
</th>
</tr>
</thead>
</table>
<table>
<thead>
<tr>
<th class="numbercell"></td>
<th class="customcol"></td>
<th class="numbercell"></td>
<th class="numbercell"></td>
<th class="numbercell">1</td>
<th class="numbercell">2</td>
<th class="numbercell">3</td>
<th class="numbercell">4</td>
<th class="numbercell">5</td>
<th class="numbercell">6</td>
<th class="numbercell">7</td>
<th class="numbercell">X</td>
</tr>
</thead>
<tbody>
{% for positioning in positionings_starting %}
{% if positioning.order == 0 %}<tr style="border: 1px solid;">
{% else %}<tr>{% endif %}
<td class="numbercell">{{ positioning.order }}</td>
<td class="customcol">{{ positioning.player.last_name }}</td>
<td class="numbercell">{{ positioning.player.jersey_number }}</td>
<td class="numbercell">{{ positioning.position|default_if_none:'' }}</td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
</tr>
{% endfor %}
</tbody>
</table>
<table>
<tbody>
{% for line in empty_lines %}
<tr>
<td class="numbercell"></td>
<td class="customcol"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="half-card">
<div class="content card-right">
<table>
<thead>
<tr>
<th class="numbercell"></td>
<th class="numbercell"></td>
<th class="customcol"></td>
<th class="numbercell"></td>
<th class="numbercell">1</td>
<th class="numbercell">2</td>
<th class="numbercell">3</td>
<th class="numbercell">4</td>
<th class="numbercell">5</td>
<th class="numbercell">6</td>
<th class="numbercell">7</td>
<th class="numbercell">X</td>
</tr>
</thead>
<tbody>
{% for positioning in positionings %}
<tr>
<td class="numbercell"></td>
<td class="numbercell">{{ positioning.player.jersey_number }}</td>
<td class="customcol{% if positioning.event_availability == 2 %} available{% endif %}{% if positioning.event_availability == 0 %} notavailable{% endif %}{% if positioning.order or positioning.position %} starting{% endif %}">{{ positioning.player.last_name }}</td>
<td class="numbercell"><i class="bi bi-check-lg"></i></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
<td class="numbercell"></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</section>
</body>

View File

@@ -11,5 +11,7 @@ urlpatterns = [
path('events/<int:pk>/lineup', login_required(views.EventDetailView.as_view()), name="event lineup"),
path('players/list/', login_required(views.PlayerListView.as_view()), name="player list"),
path('teams/list/', login_required(views.TeamListView.as_view()), name="team list"),
path('venues/list/', login_required(views.VenueListView.as_view()), name="venue list")
path('venues/list/', login_required(views.VenueListView.as_view()), name="venue list"),
path('events/<int:event_id>/card', login_required(views.lineupcard), name="lineup card"),
path('events/<int:event_id>/csv', login_required(views.csv_export), name="lineup csv")
]

View File

@@ -1,9 +1,10 @@
from django.shortcuts import render
from django.shortcuts import render, HttpResponse
from .models import Event, Team, Player, Positioning, Venue
from .forms import PositioningFormSet, TeamsnapEventForm
from django.contrib import messages
from django.db.models import F
from django.views.generic import ListView, DetailView
import csv
class BenchCoachListView(ListView):
@@ -136,3 +137,102 @@ def lineup_edit(request, event_id, active_tab='details'):
"formset_dhd": formset_dhd,
},
)
def lineupcard(request, event_id):
previous_event = Event.objects.filter(id=event_id - 1).first()
event = Event.objects.get(id=event_id)
next_event = Event.objects.get(id=event_id + 1)
players = Player.objects.prefetch_related("availability_set", "positioning_set")
for player in players:
Positioning.objects.get_or_create(player_id=player.id, event_id=event_id)
qs = (
event.positioning_set.all()
.filter(player__availability__event=event_id, player__teamsnap_member__is_non_player=False)
.order_by("-player__availability__available", "player__last_name", "order")
.annotate(event_availability=F("player__availability__available"))
)
qs_starting = qs.filter(order__isnull=False).order_by("order")
details = {
"Away Team": event.away_team,
"Home Team": event.home_team,
"Date": event.start.date(),
"Time": event.start.time(),
"Venue": event.venue,
}
return render(
request,
"benchcoach/card.html",
{
"title": "Lineup",
"event": event,
"details": details,
"previous_event": previous_event,
"next_event": next_event,
"positionings": qs,
"positionings_starting": qs_starting,
"empty_lines": range(14)
},
)
def csv_export(request, event_id):
response = HttpResponse(
content_type='text/csv',
headers={'Content-Disposition': f'attachment; filename=lineup-event-{event_id}.csv'},
)
previous_event = Event.objects.filter(id=event_id - 1).first()
event = Event.objects.get(id=event_id)
players = Player.objects.prefetch_related("availability_set", "positioning_set")
for player in players:
Positioning.objects.get_or_create(player_id=player.id, event_id=event_id)
qs = (
event.positioning_set.all()
.filter(player__availability__event=event_id, player__teamsnap_member__is_non_player=False)
.order_by("-player__availability__available", "player__last_name", "order")
.annotate(event_availability=F("player__availability__available"))
)
rows = []
rows.append(event.teamsnap_event.csv_event_title) # 2
rows.append(event.venue.name) # 3
[rows.append('') for i in range(3)] #4-6
p = qs.filter(position='P').first()
rows.append(f"{p.player.last_name}, {p.player.first_name}") #7
[rows.append('') for i in range(3)] #8-10
for pos in ['C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF', 'DH']: #11-19
p = qs.filter(position=pos).first()
if p:
rows.append(f"{p.player.last_name}, {p.player.first_name}")
else:
rows.append('')
ehs = qs.filter(position='EH')
if len(ehs) > 0:
p=qs.filter(position='EH')[0]
rows.append(f"{p.player.last_name}, {p.player.first_name}") # 20
else:
rows.append('')
if len(ehs) > 1:
p=qs.filter(position='EH')[1]
rows.append(f"{p.player.last_name}, {p.player.first_name}") # 21
else:
rows.append('')
rows.append('') #22
p=qs.filter(position__isnull=False, order=0).first()
rows.append(f"{p.player.last_name}, {p.player.first_name}") # 23
rows.append('')
for p in qs.filter(order__gt=0).order_by('order'):
rows.append(f"{p.player.last_name}, {p.player.first_name}")
writer = csv.writer(response)
for row in rows:
writer.writerow([row])
return response