first init of this template.

This commit is contained in:
2022-05-14 07:16:31 -05:00
parent d6ee55a050
commit 4632926a34
40 changed files with 1854 additions and 857 deletions

View File

@@ -1,6 +1,6 @@
from django import forms
from .models import Team, Location, Opponent, Event, Member
from django.forms import modelformset_factory
from django.forms import modelformset_factory, formset_factory, inlineformset_factory
select_kwargs = {
'attrs':{'class': 'form-control form-control-sm'}
@@ -74,4 +74,45 @@ class LocationForm(forms.ModelForm):
"benchcoach_object": forms.Select(**select_kwargs)
}
class LineupEntryForm(forms.Form):
member = None
availability = None
lineup_entry = None
event_lineup_entry_id = forms.Field(required=False)
event_lineup_id = forms.Field(required=False)
event_id = forms.Field()
member_id = forms.Field()
sequence = forms.IntegerField(required=False)
label = forms.ChoiceField(required=False, choices=[
("--", "--"),
("P","P"),
("C","C"),
("1B","1B"),
("2B", "2B"),
("3B", "3B"),
("SS", "SS"),
('LF','LF'),
('CF','CF'),
('RF','RF'),
('DH','DH'),
('DR','DR'),
('EH','EH')
],
widget=forms.Select(
attrs = {'onchange' : "colorPositions();"}
)
)
class EventChooseForm(forms.Form):
event_id = forms.ChoiceField()
# checked = forms.BooleanField(required=False)
# def __init__(self, events, *args, **kwargs):
# super(EventChooseForm, self).__init__(*args, **kwargs)
# self.fields['foo'].choices = [e.data['id'] for e in events]
LineupEntryFormset = formset_factory(LineupEntryForm, can_delete=True, can_order=True, extra=0)

View File

@@ -1,7 +1,7 @@
from django.db import models
import benchcoach.models
import teamsnap.teamsnap.api
import pyteamsnap.api
from django.utils.timezone import localtime
class TeamsnapBaseModel(models.Model):
@@ -9,7 +9,7 @@ class TeamsnapBaseModel(models.Model):
id = models.CharField(max_length=50, unique=True, primary_key=True)
created_at = models.DateTimeField(null=True)
updated_at = models.DateTimeField(null=True)
ApiObject = teamsnap.teamsnap.api.ApiObject
ApiObject = pyteamsnap.api.ApiObject
class Meta:
abstract = True
@@ -29,7 +29,7 @@ class Team(TeamsnapBaseModel):
on_delete=models.CASCADE,
related_name="teamsnap_team"
)
ApiObject = teamsnap.teamsnap.api.Team
ApiObject = pyteamsnap.api.Team
class User(TeamsnapBaseModel):
type = 'user'
@@ -37,7 +37,7 @@ class User(TeamsnapBaseModel):
last_name = models.CharField(max_length = 50, null=True)
email = models.EmailField(null=True)
managed_teams = models.ManyToManyField(Team)
ApiObject = teamsnap.teamsnap.api.User
ApiObject = pyteamsnap.api.User
@classmethod
def update_or_create_from_teamsnap_api(cls, teamsnap_data):
@@ -76,7 +76,7 @@ class Opponent(TeamsnapManagedObjectModel):
on_delete=models.CASCADE,
related_name="teamsnap_opponent"
)
ApiObject = teamsnap.teamsnap.api.Opponent
ApiObject = pyteamsnap.api.Opponent
class Location(TeamsnapManagedObjectModel):
type = 'location'
@@ -86,7 +86,7 @@ class Location(TeamsnapManagedObjectModel):
on_delete=models.CASCADE,
related_name="teamsnap_location"
)
ApiObject = teamsnap.teamsnap.api.Location
ApiObject = pyteamsnap.api.Location
class Member(TeamsnapManagedObjectModel):
# url format is
@@ -103,7 +103,7 @@ class Member(TeamsnapManagedObjectModel):
last_name = models.CharField(max_length = 50, null=True)
jersey_number = models.IntegerField(null=True)
is_non_player = models.BooleanField(null=True)
ApiObject = teamsnap.teamsnap.api.Member
ApiObject = pyteamsnap.api.Member
def __str__(self):
return f"{self.last_name}, {self.first_name} ({self.id})"
@@ -131,7 +131,7 @@ class Event(TeamsnapManagedObjectModel):
points_for_team = models.PositiveSmallIntegerField(null=True)
is_game = models.BooleanField(null=True)
game_type = models.CharField(max_length = 50, null=True)
ApiObject = teamsnap.teamsnap.api.Event
ApiObject = pyteamsnap.api.Event
@property
def csv_event_title(self)->str:
@@ -166,7 +166,7 @@ class Availability(TeamsnapManagedObjectModel):
related_name="teamsnap_availability"
)
status_code = models.SmallIntegerField(choices=status_codes, null=True, blank=True, default=None)
ApiObject = teamsnap.teamsnap.api.Availability
ApiObject = pyteamsnap.api.Availability
def __str__(self):
return f"{self.member} - {self.event} ({self.id})"
@@ -197,7 +197,7 @@ class LineupEntry(TeamsnapManagedObjectModel):
)
label = models.PositiveSmallIntegerField(choices=positions, default=None, null=True, blank=True)
sequence = models.PositiveSmallIntegerField(default=0, null=True, blank=True)
ApiObject = teamsnap.teamsnap.api.EventLineupEntry
ApiObject = pyteamsnap.api.EventLineupEntry
@classmethod
def update_or_create_from_teamsnap_api(cls, teamsnap_data):

View File

@@ -1,3 +0,0 @@
# from .utils import TeamSnap
#
# __all__ = ['TeamSnap']

View File

@@ -1,618 +0,0 @@
__all__ = ['TeamSnap', 'Team', 'Event', 'Availability', 'Member', 'Location', 'Me']
from apiclient import APIClient, HeaderAuthentication, JsonResponseHandler
class ApiObject():
rel = None
version = None
template = None
def __init__(self, client, rel=rel, data={}):
self.client = client
self.data = data
self.rel = rel
@classmethod
def search(cls, client, **kwargs):
results = client.query(cls.rel, "search", **kwargs)
return [cls(client,rel=cls.rel, data=r) for r in results]
@classmethod
def get(cls, client, id):
r = client.get(f"{client.link(cls.rel)}/{id}")
return cls(client, cls.rel, client.parse_response(r)[0])
class Me (ApiObject):
rel = "me"
version = "3.866.0"
template = {
"data": [
{
"name": "first_name"
},
{
"name": "last_name"
},
{
"name": "password"
},
{
"name": "birthday"
},
{
"name": "email"
},
{
"name": "facebook_id",
"deprecated": True,
"prompt": "facebook_id is deprecated and has been removed. Continued use of facebook_id is not recommended it will no longer be stored."
},
{
"name": "facebook_access_token",
"deprecated": True,
"prompt": "facebook_access_token is deprecated and has been removed. Continued use of facebook_access_token is not recommended it will no longer be stored."
},
{
"name": "type",
"value": "user"
},
{
"name": "is_lab_rat"
},
{
"name": "receives_newsletter"
}
]
}
def __init__(self, client):
super().__init__(client=client, rel=self.rel, data=client.get(client.link(self.rel)))
class User (ApiObject):
rel = "users"
version = "3.866.0"
template = {
"data": [
{
"name": "first_name"
},
{
"name": "last_name"
},
{
"name": "password"
},
{
"name": "birthday"
},
{
"name": "email"
},
{
"name": "facebook_id",
"deprecated": True,
"prompt": "facebook_id is deprecated and has been removed. Continued use of facebook_id is not recommended it will no longer be stored."
},
{
"name": "facebook_access_token",
"deprecated": True,
"prompt": "facebook_access_token is deprecated and has been removed. Continued use of facebook_access_token is not recommended it will no longer be stored."
},
{
"name": "type",
"value": "user"
},
{
"name": "is_lab_rat"
},
{
"name": "receives_newsletter"
}
]
}
class Event (ApiObject):
rel = "events"
version = "3.866.0"
template = {
"data": [
{
"name": "type",
"value": "event"
},
{
"name": "additional_location_details"
},
{
"name": "browser_time_zone"
},
{
"name": "division_location_id"
},
{
"name": "doesnt_count_towards_record"
},
{
"name": "duration_in_minutes"
},
{
"name": "game_type_code"
},
{
"name": "icon_color"
},
{
"name": "is_canceled"
},
{
"name": "is_game"
},
{
"name": "is_overtime"
},
{
"name": "is_shootout"
},
{
"name": "is_tbd"
},
{
"name": "label"
},
{
"name": "location_id"
},
{
"name": "minutes_to_arrive_early"
},
{
"name": "name"
},
{
"name": "notes"
},
{
"name": "notify_opponent"
},
{
"name": "notify_opponent_contacts_email"
},
{
"name": "notify_opponent_contacts_name"
},
{
"name": "notify_opponent_notes"
},
{
"name": "notify_team"
},
{
"name": "notify_team_as_member_id"
},
{
"name": "opponent_id"
},
{
"name": "points_for_opponent"
},
{
"name": "points_for_team"
},
{
"name": "repeating_include",
"prompt": "When updating a repeating event, this is a required field. Values are: \"all\" - updates all events in this series, \"future\" - updates this event and all that occur after, \"none\" - only updates a single event."
},
{
"name": "repeating_type_code",
"prompt": "A code for the frequency of the repeated event, this is required with the \"repeating_include\" attribute when creating a repeating event. Valid values are: \"1\" - repeat an event daily, \"2\" - repeat an event weekly."
},
{
"name": "repeating_until",
"prompt": "A date when the repeating event should end, this is inclusive so an event will be created on this day if it falls before the next event specified by \"repeating_type_code\". This attribute is required with \"repeating_type_code\" when creating a repeating event."
},
{
"name": "results"
},
{
"name": "results_url"
},
{
"name": "shootout_points_for_opponent"
},
{
"name": "shootout_points_for_team"
},
{
"name": "start_date"
},
{
"name": "team_id"
},
{
"name": "time_zone"
},
{
"name": "tracks_availability"
},
{
"name": "uniform"
}
]}
class Team (ApiObject):
rel = "teams"
version = "3.866.0"
template = {
"data": [
{
"name": "name"
},
{
"name": "location_country"
},
{
"name": "location_postal_code"
},
{
"name": "time_zone",
"prompt": "The time_zone parameter is required when creating a team, but for changing a team's time_zone, use the update_time_zone command"
},
{
"name": "sport_id"
},
{
"name": "division_id"
},
{
"name": "division_name"
},
{
"name": "season_name"
},
{
"name": "league_name"
},
{
"name": "league_url"
},
{
"name": "owner_first_name"
},
{
"name": "owner_last_name"
},
{
"name": "owner_email"
},
{
"name": "is_ownership_pending"
},
{
"name": "ad_unit_hero_id"
},
{
"name": "ad_unit_hero_template_id"
},
{
"name": "ad_unit_inline_id"
},
{
"name": "type",
"value": "team"
}
]
}
class Availability (ApiObject):
rel = "availabilities"
version = "3.866.0"
template = {
"data": [
{
"name": "status_code"
},
{
"name": "notes"
},
{
"name": "event_id"
},
{
"name": "member_id"
},
{
"name": "notes_author_member_id"
},
{
"name": "source"
},
{
"name": "type",
"value": "availability"
}
]
}
class Member (ApiObject):
rel = "members"
version = "3.866.0"
template = {
"data": [
{
"name": "first_name"
},
{
"name": "last_name"
},
{
"name": "gender"
},
{
"name": "position"
},
{
"name": "is_manager"
},
{
"name": "birthday"
},
{
"name": "hide_age",
"deprecated": True,
"prompt": "hide_age is deprecated and will be removed in a future version, use is_age_hidden instead."
},
{
"name": "is_age_hidden"
},
{
"name": "hide_address",
"deprecated": True,
"prompt": "hide_address is deprecated and will be removed in a future version, use is_address_hidden instead."
},
{
"name": "is_address_hidden"
},
{
"name": "is_non_player"
},
{
"name": "address_street1"
},
{
"name": "address_street2"
},
{
"name": "address_city"
},
{
"name": "address_state"
},
{
"name": "address_zip"
},
{
"name": "jersey_number"
},
{
"name": "team_id"
},
{
"name": "is_ownership_pending"
},
{
"name": "source_action"
},
{
"name": "type",
"value": "member"
}
]
},
class Location (ApiObject):
rel = "locations"
version = "3.866.0"
template = {
"data": [
{
"name": "name"
},
{
"name": "url"
},
{
"name": "phone"
},
{
"name": "notes"
},
{
"name": "address"
},
{
"name": "latitude"
},
{
"name": "longitude"
},
{
"name": "team_id"
},
{
"name": "is_retired"
},
{
"name": "type",
"value": "location"
}
]
}
class Opponent (ApiObject):
rel = "opponents"
version = "3.866.0"
template = {
"data": [
{
"name": "name"
},
{
"name": "contacts_name"
},
{
"name": "contacts_phone"
},
{
"name": "contacts_email"
},
{
"name": "notes"
},
{
"name": "team_id"
},
{
"name": "type",
"value": "opponent"
}
]
}
class EventLineupEntry (ApiObject):
rel = "event_lineup_entries"
version = "3.866.0"
template = {
"data": [
{
"name": "event_lineup_id"
},
{
"name": "member_id"
},
{
"name": "sequence"
},
{
"name": "label"
},
{
"name": "type",
"value": "event_lineup_entry"
}
]
}
class Statistics (ApiObject):
rel = "statistics"
version = "3.866.0"
template = {
"data": [
{
"name": "acronym"
},
{
"name": "always_display_decimals"
},
{
"name": "formula"
},
{
"name": "is_in_descending_order"
},
{
"name": "display_zero_totals"
},
{
"name": "is_percentage"
},
{
"name": "is_private"
},
{
"name": "is_team_statistic"
},
{
"name": "is_top_statistic"
},
{
"name": "name"
},
{
"name": "precision"
},
{
"name": "statistic_group_id"
},
{
"name": "team_id"
},
{
"name": "type",
"value": "statistic"
}
]
}
class MemberStatistics (ApiObject):
rel = "member_statistics"
class TeamSnap(APIClient):
base_url = 'https://api.teamsnap.com/v3'
def __init__(self, token, *args, **kwargs):
super().__init__(*args,
authentication_method=HeaderAuthentication(token=token),
response_handler=JsonResponseHandler,
**kwargs)
self._root_collection = self.get(self.base_url)['collection']
self._links = self._by_rel(self.base_url, 'links')
self._queries = self._by_rel(self.base_url, 'queries')
self._commands = self._by_rel(self.base_url, 'commands')
pass
def link(self, link_name):
d = {l['rel']:l['href'] for l in self._root_collection["links"]}
return d.get(link_name)
def _by_rel (self, url, k):
try:
{l['rel']: l for l in self._root_collection[k]}
except Exception as e:
return {}
self.get(url)['collection'][k]
return {l['rel']:l for l in self.get(url)['collection'][k]}
def query (self, rel, query, **kwargs):
queries = self._by_rel(self._get_href(rel), 'queries')
response = self.get(self._get_href(query, queries), params=kwargs)
return self.parse_response(response)
def command (self, rel, command, **kwargs):
commands = self._by_rel(self._get_href(rel), 'commands')
response = self.get(self._get_href(command, commands), params=kwargs)
return self.parse_response(response)
def _get_href (self, rel: str, links:dict = None, url = base_url) -> str:
"""returns a hyperlink from a the links dictionary. Each item in the links dictionary is a
dictionary with a rel and href key"""
if links is None: links = self._by_rel(url, 'links')
link = links[rel]['href']
return link
def get_item (self, rel, id):
r = self.get(f"{self.link(rel)}/{id}")
return self.parse_response(r)[0]
@classmethod
def parse_response(self, response):
result = []
items = [item['data'] for item in response['collection'].get('items',[])]
for item in response['collection'].get('items',[]):
details = {}
for detail in item['data']:
# TODO type casting and validation based on item['type']
details[detail['name']] = detail['value']
result.append(details)
return result
# return [{detail['name']: detail['value'] for detail in item} for item in items]

View File

@@ -0,0 +1,27 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ title }}{% endblock %}
{% block page_heading %}Schedule{% endblock %}
{% block content %}
{% load tz %}
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# </thead>#}
<tbody>
{% for event in events %}
<tr>
<td>
<a href="{% url 'teamsnap_event' id=event.data.id team_id=schedule.html %}">{{ event.data.formatted_title }}</a>
</td>
<td>
{{ event.data.start_date | localtime}}
</td>
<td>
{{ event.data.location_name }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -1,116 +0,0 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ event.data.formatted_title }}{% endblock %}
{% block page_heading %}{{ event.data.formatted_title }}{% endblock %}
{% block page_subheading %}{{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
{% block content %}
<h6>Lineup</h6>
<form method="post" action="{% url 'teamsnap_submit_lineup' team_id=team_id event_id=event_id %}">
{{ formset.management_form }}
{% csrf_token %}
<div class="table-responsive">
<table class="table table-striped table-sm" id="table-event-lineup">
<tbody id="tablebody-event-lineup">
{% for form in formset %}
{% if form.event_lineup_entry_id.value %}
<tr>
{{ form.event_lineup_entry_id.as_hidden }}
{{ form.event_lineup_id.as_hidden }}
{{ form.event_id.as_hidden }}
{{ form.member_id.as_hidden }}
{{ form.sequence.as_hidden }}
{{ form.label.as_hidden }}
{{ form.member_name.as_hidden }}
<td class="col-1 px-1">
{{ forloop.counter }}
</td>
<td class="col-auto">
{{ form.member_name.value }}
</td>
<td class="col-3">
<div class="form-select-sm">{{ form.label }}</div>
</td>
<td class="col-1">
<div class="d-flex">
<div class="px-1">
<i class="bi bi-dash-circle text-danger"></i>
{{ form.DELETE.as_hidden }}
</div>
</div>
</td>
<td class="col-1 drag-handle">
<i class="bi bi-grip-vertical text-secondary"></i>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
<input class="btn btn-success" type="submit" value="Submit">
</form>
<h6>Bench</h6>
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# <th scope="row">#}
{# <td>Status</td>#}
{# <td>Last</td>#}
{# <td>First</td>#}
{# </th>#}
{# </thead>#}
{% for availability in availablities %}
{% if availability.data.member_is_non_player is False %}
<tr>
<td class="col-1">
{% if availability.data.status_code == 1 %}
<i class="bi bi-check-circle-fill text-success"></i>
{% endif %}
{% if availability.data.status_code == 0 %}
<i class="bi bi-x-circle-fill text-danger"></i>
{% endif %}
{% if availability.data.status_code == None %}
<i class="bi bi-circle"></i>
{% endif %}
{% if availability.data.status_code == 2 %}
<i class="bi bi-circle-half text-info"></i>
{% endif %}
</td>
<td class="col-auto">
{{ availability.data.member_first_name }} {{ availability.data.member_last_name }}
</td>
<td class="col-3">
</td>
<td class="col-1">
<div class="d-flex">
<div class="px-1">
<i class="bi bi-plus-circle"></i>
</div>
</div>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
<script src="{% static 'js/Sortable.js' %}"></script>
<script id="sortable">
var lineup = new Sortable.create(
document.getElementById('tablebody-event-lineup'), {
animation: 150,
ghostClass:"ghost",
handle: ".drag-handle",
group:{
put:true,
pull:true
},
});
</script>
{% endblock %}

View File

@@ -0,0 +1,76 @@
<html lang="en">
{% extends "base.html" %}{% load static %}
{% block title %} {{ event.data.formatted_title }} - Instagenerator{% endblock %}
{% block page_heading %}
<div class="row d-inline-flex">
<div class="col">
<img src="{% static 'teamsnap/ig/graphics/hounds-insta.jpg' %}" class="mx-auto d-block img-fluid shadow-sm" style="height:30px;border-radius: 8px;">
</div>
<div class="col text-nowrap px-0">Hounds Instagenerator</div>
</div>
{% endblock %}
{% block page_subheading %}{{ event.data.formatted_title }}, {{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
{% block content %}
<form method="get" action="generate">
<div class="mb-3">
<select hidden class="form-select" name="game_id" id="game_id">
<optgroup label="Events">
<option value="" disabled="disabled">Select an event...</option>
<option selected value="{{event.data.id}}">{{event.data.formatted_title}}</option>
</optgroup>
</select>
</div>
<div class="mb-3">
<legend class="">Background</legend>
<div class="form-check">
<input class="form-check-input" type="radio" name="background" id="backgroundLocation" checked value="location">
<label class="form-check-label" for="backgroundLocation">
Location
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="background" id="backgroundTransparent" value="transparent">
<label class="form-check-label" for="backgroundTransparent">
Transparent
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="background" id="badge_only" value="badge">
<label class="form-check-label" for="badge_only">
Badge only
</label>
</div>
</div>
<div class="mb-3">
<legend class="">Layout</legend>
<div class="form-check">
<input class="form-check-input" type="radio" name="dimensions" id="square" checked value="1080x1080">
<label class="form-check-label" for="square">
Square
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="dimensions" id="portrait" value="1080x1920">
<label class="form-check-label" for="portrait">
Portrait
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="dimensions" id="portrait" value="1920x1080">
<label class="form-check-label" for="portrait">
Landscape
</label>
</div>
</div>
<div class="d-lg-flex justify-content-lg-end align-items-lg-center mb-3">
<button type="submit" class="btn btn-primary btn-block">Get Image</button>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ event.data.formatted_title }}{% endblock %}
{% block page_heading %}{{ event.data.formatted_title }}{% endblock %}
{% block page_subheading %}{{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
{% block content %}
{% include 'teamsnap/lineup/widgets/lineup.html' with formset_lineup=formset_lineup formset_bench=formset_bench%}
<script src="{% static 'js/Sortable.js' %}"></script>
<script src="{% static 'teamsnap/js/lineup-table.js' %}"></script>
{% endblock %}

View File

@@ -0,0 +1,95 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ title }}{% endblock %}
{% csrf_token %}
{% block page_heading %}
<div class="row d-inline-flex">
<div class="col">
Schedule
</div>
</div>
{% endblock %}
{% block content %}
<form method="get" action="{% url 'teamsnap_edit_multiple_lineups' team_id=team_id%}">
{{ formset.management_form }}
<input class="btn btn-sm btn-outline-primary text-nowrap" type="submit" value="Submit">
{% load tz %}
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# </thead>#}
<tbody>
{% for form in formset %}
<tr>
{{ form.event_id }}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
<!-- create_normal.html :: part 4 -->
<script type='text/javascript'>
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+)');
var replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function cloneMore(selector, prefix) {
var newElement = $(selector).clone(true);
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
newElement.find(':input:not([type=button]):not([type=submit]):not([type=reset])').each(function() {
var name = $(this).attr('name').replace('-' + (total-1) + '-', '-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
});
newElement.find('label').each(function() {
var forValue = $(this).attr('for');
if (forValue) {
forValue = forValue.replace('-' + (total-1) + '-', '-' + total + '-');
$(this).attr({'for': forValue});
}
});
total++;
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
var conditionRow = $('.form-row:not(:last)');
conditionRow.find('.btn.add-form-row')
.removeClass('btn-success').addClass('btn-danger')
.removeClass('add-form-row').addClass('remove-form-row')
.html('<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>');
return false;
}
function deleteForm(prefix, btn) {
var total = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
if (total > 1){
btn.closest('.form-row').remove();
var forms = $('.form-row');
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
for (var i=0, formCount=forms.length; i<formCount; i++) {
$(forms.get(i)).find(':input').each(function() {
updateElementIndex(this, prefix, i);
});
}
}
return false;
}
$(document).on('click', '.add-form-row', function(e){
e.preventDefault();
cloneMore('.form-row:last', 'form');
return false;
});
$(document).on('click', '.remove-form-row', function(e){
e.preventDefault();
deleteForm('form', $(this));
return false;
});
</script>
{% endblock %}

View File

@@ -0,0 +1,45 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ title }}{% endblock %}
{% csrf_token %}
{% block page_heading %}
<div class="row d-inline-flex">
<div class="col">
Schedule
</div>
</div>
{% endblock %}
{% block content %}
<form method="get" action="{% url 'teamsnap_edit_multiple_lineups' team_id=team_id%}">
{{ formset.management_form }}
<input class="btn btn-sm btn-outline-primary text-nowrap" type="submit" value="Submit">
{% load tz %}
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# </thead>#}
<tbody>
{% for form in formset %}
{{ form.event_id.as_hidden }}
<tr>
<td>
{{ form.checked }}
</td>
<td>
<a href="{% url 'teamsnap_view_event' event_id=form.event.data.id team_id=request.user.profile.teamsnapsettings.managed_team.id%}">{{ form.event.data.formatted_title }}</a>
</td>
<td>
{{ form.event.data.start_date | localtime}}
</td>
<td>
{{ form.event.data.location_name }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,100 @@
{% extends "base.html" %}{% load static %}
{% block title %} Edit Lineups {% endblock %}
{% block page_heading %}Edit Lineups{% endblock %}
{% block page_subheading %}{% endblock %}
{% block content %}
{# <div class="container overflow-scroll mx-0 px-0">#}
{# <div class="row flex-row flex-nowrap">#}
{# {% for event_data in contexts %}#}
{# <div class="col border-start border-end">#}
{# <div class = "border-bottom">#}
{# <h4>{{ event_data.event.data.formatted_title }}</h4>#}
{# <h6 class="text-muted" >{{ event_data.data.start_date }}</h6>#}
{# </div>#}
{# {% include 'teamsnap/lineup/widgets/lineup.html' with formset_lineup=event_data.formset_lineup formset_bench=event_data.formset_bench event_id=event_data.event.data.id %}#}
{# </div>#}
{# {% endfor %}#}
{# </div>#}
{# </div>#}
<div class="container overflow-scroll">
<div class="row flex-row flex-nowrap">
<table>
<tbody>
<tr>
{% for event_data in contexts %}
<td>
<h4>{{ event_data.event.data.formatted_title }}</h4>
<h6 class="text-muted" >{{ event_data.data.start_date }}</h6>
{% with 'P C 1B 2B 3B SS LF CF RF EH DH' as position_list %}
{% for position in position_list.split %}
<span class="position-status fw-bold small px-1" id="position-status-{{ position }}">{{ position }}</span>
{% endfor %}
{% endwith %}
</td>
{% endfor %}
</tr>
<tr>
<td class="bg-light" colspan="{{ contexts|length }}"><h4>Lineup</h4></td>
</tr>
<tr>
{% for event_data in contexts %}
<td class="align-top">
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=event_data.formset_lineup table_id="players-lineup" %}
</td>
{% endfor %}
</tr>
<tr>
<td class="bg-light" colspan="{{ contexts|length }}"><h4>Bench</h4></td>
</tr>
<tr>
{% for event_data in contexts %}
<td class="align-top">
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=event_data.formset_bench table_id="players-bench" %}
</td>
{% endfor %}
</tr>
<tr>
<td class="bg-light" colspan="{{ contexts|length }}"><h4>Out</h4></td>
</tr>
<tr>
{% for event_data in contexts %}
<td class="align-top">
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=event_data.formset_out table_id="players-bench" %}
</td>
{% endfor %}
</tr>
</tbody>
</table>
{# <div class="align-content-start">#}
{# <div class = "bg-light rounded-3 p-2">#}
{# <div class="row">#}
{# {% with 'P C 1B 2B 3B SS LF CF RF EH DH' as position_list %}#}
{# {% for position in position_list.split %}#}
{# <span class="position-status fw-bold small px-1" id="position-status-{{ position }}">{{ position }}</span>#}
{# {% endfor %}#}
{# {% endwith %}#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <form method="post" action="{% url 'teamsnap_submit_lineup' team_id=team_id event_id=event_id%}">#}
{# {{ formset.management_form }}#}
{# {% csrf_token %}#}
{# <h4 class="border-bottom">Lineup</h4>#}
{# {% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_lineup table_id="players-lineup" %}#}
{# <input class="btn btn-success" type="submit" value="Submit">#}
{##}
{# <h4 class="border-bottom">Bench</h4>#}
{# {% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_bench table_id="players-bench" %}#}
{##}
{# <h4 class="border-bottom">Out</h4>#}
{# {% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_out table_id="players-out" %}#}
{# </form>#}
<script src="{% static 'js/Sortable.js' %}"></script>
<script src="{% static 'teamsnap/js/lineup-table.js' %}"></script>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,28 @@
<div>
<div class="align-content-start">
<div class = "bg-light rounded-3 p-2">
{# <div class="row">#}
{% with 'P C 1B 2B 3B SS LF CF RF EH DH' as position_list %}
{% for position in position_list.split %}
<span class="position-status fw-bold small px-1" id="position-status-{{ position }}">{{ position }}</span>
{% endfor %}
{% endwith %}
{# </div>#}
</div>
</div>
<form method="post" action="{% url 'teamsnap_submit_lineup' team_id=team_id event_id=event_id%}">
{{ formset.management_form }}
{% csrf_token %}
<h4 class="border-bottom">Lineup</h4>
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_lineup table_id="players-lineup" %}
<input class="btn btn-success" type="submit" value="Submit">
<h4 class="border-bottom">Bench</h4>
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_bench table_id="players-bench" %}
<h4 class="border-bottom">Out</h4>
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_out table_id="players-out" %}
</form>
</div>

View File

@@ -0,0 +1,59 @@
<table class="table table-sm my-0" style="min-height: 1rem" id="table-{{ table_id }}">
<tbody id="tbody-{{ table_id }}">
{% for form in formset %}
<tr data-player-id="{{ form.member.data.id }}"
data-position="{{ form.label.value }}"
data-order="{{ form.sequence.value }}">
{{ form.event_lineup_entry_id.as_hidden }}
{{ form.event_lineup_id.as_hidden }}
{{ form.event_id.as_hidden }}
{{ form.member_id.as_hidden }}
{{ form.sequence.as_hidden }}
{{ form.label.as_hidden }}
{{ form.member_name.as_hidden }}
<th class="col-1" id="sequence-member-{{ form.member.data.id }}">
{{ form.sequence.value | add:"1" }}
</th>
<td class="col-1">
<div class="mx-1">
<span id="player-order-{{ form.member.id }}" class="lineup-sequence-value">
{% if form.order.value > 0 %} {{ form.order.value | add:"1" }} {% endif %}
</span>
<span id="player-availability-{{ form.member.id }}" class="member-availability-status small">
{% if form.availability.data.status_code == 2 %}
<i class="bi bi-question-circle-fill text-info"></i>
{% elif form.availability.data.status_code == 1 %}
<i class="bi bi-check-circle-fill text-success"></i>
{% elif form.availability.data.status_code == 0 %}
<i class="bi bi-x-circle-fill text-danger"></i>
{% else %}
<i class="bi bi-question-circle"></i>
{% endif %}
</span>
</div>
</td>
<th class="">
<div class="text-nowrap">
<span class="d-none d-md-inline-block">
{{ form.member.data.first_name }}
</span>
{{ form.member.data.last_name }}
<span class="small text-muted fw-light d-none d-lg-inline-block">
#{{ form.member.data.jersey_number }}
</span>
</div>
{# <br><code><small>{{ form.statline }}</small></code>#}
</th>
<td class="col-2">
{{ form.label }}
</td>
<td class="col-1 drag-handle">
<i class="bi bi-grip-vertical text-secondary"></i>
</td>
{# <td>{{ form.instance.position }}</td>#}
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -0,0 +1,22 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ location.data.name }}{% endblock %}
{% block page_heading %}{{ location.data.name }}{% endblock %}
{% block content %}
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# </thead>#}
<tbody>
{% for key, value in location.data.items %}
<tr>
<th scope="col">
{{ key }}
</th>
<td>
{{ value }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@@ -0,0 +1,22 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ opponent.data.name }}{% endblock %}
{% block page_heading %}{{ opponent.data.name }}{% endblock %}
{% block content %}
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# </thead>#}
<tbody>
{% for key, value in opponent.data.items %}
<tr>
<th scope="col">
{{ key }}
</th>
<td>
{{ value }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@@ -0,0 +1,47 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ title }}{% endblock %}
{% block page_heading %}
<div class="row d-inline-flex">
<div class="col">
Schedule
</div>
<div hidden class="col">
<div class="container m-2">
<div class="container m-2">
<div class="btn-group">
<form action="">
<a class="btn btn-sm btn-outline-primary text-nowrap" href="{% url 'teamsnap_schedule' team_id=team_id%}?filters=no_past">No Past Events</a>
<button class="btn btn-sm btn-outline-primary text-nowrap">Games Only</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block content %}
{% load tz %}
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# </thead>#}
<tbody>
{% for event in events %}
<tr>
<td>
<a href="{% url 'teamsnap_view_event' event_id=event.data.id team_id=request.user.profile.teamsnapsettings.managed_team.id%}">{{ event.data.formatted_title }}</a>
</td>
<td>
{{ event.data.start_date | localtime}}
</td>
<td>
{{ event.data.location_name }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@@ -0,0 +1,137 @@
{% extends "base.html" %}{% load static %}
{% block title %} {{ event.data.formatted_title }}{% endblock %}
{% block page_heading %}{{ event.data.formatted_title }}{% endblock %}
{% block page_subheading %}{{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
{% block content %}
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# </thead>#}
<tbody>
<tr>
<th scope="col">
Date
</th>
<td>
{{ event.data.start_date }}
</td>
</tr>
<tr>
<th scope="col">
Opponent
</th>
<td>
<a href="{% url 'teamsnap_opponent' team_id=request.user.profile.teamsnapsettings.managed_team.id id=event.data.opponent_id %}">{{ event.data.opponent_name }}</a>
</td>
</tr>
<tr>
<th scope="col">
Location
</th>
<td>
<a href="{% url 'teamsnap_location' team_id=request.user.profile.teamsnapsettings.managed_team.id id=event.data.location_id %}">{{ event.data.location_name }}</a>
</td>
</tr>
</tbody>
</table>
</div>
<h3>Availabilities</h3>
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# <th scope="row">#}
{# <td>Status</td>#}
{# <td>Last</td>#}
{# <td>First</td>#}
{# </th>#}
{# </thead>#}
<tbody>
<tr>
<th scope="col" class="col-1">
<i class="bi bi-check-circle-fill text-success"></i>
</th>
<td>
{{ availability_summary.data.player_going_count }}
</td>
</tr>
<tr>
<th scope="col" class="col-1">
<i class="bi bi-question-circle-fill text-info"></i>
</th>
<td>
{{ availability_summary.data.player_maybe_count }}
</td>
</tr>
<tr>
<th scope="col" class="col-1">
<i class="bi bi-x-circle-fill text-danger"></i>
</th>
<td>
{{ availability_summary.data.player_not_going_count }}
</td>
</tr>
<tr>
<th scope="col" class="col-1">
<i class="bi bi-question-circle"></i>
</th>
<td>
{{ availability_summary.data.player_unknown_count }}
</td>
</tr>
</tbody>
</table>
</div>
<div class="">
<h3>Lineup Entries</h3>
<a class="btn btn-primary btn-sm" href="{% url 'teamsnap_edit_lineup' event_id=event.data.id team_id=request.user.profile.teamsnapsettings.managed_team.id%}" role="button">Edit</a>
</div>
<div class="table-responsive">
<table class="table table-striped table-sm">
{# <thead>#}
{# <th scope="row">#}
{# <td>Status</td>#}
{# <td>Last</td>#}
{# <td>First</td>#}
{# </th>#}
{# </thead>#}
<tbody>
{% for lineup_entry in lineup_entries %}
<tr>
<td class="col-1">
{{ lineup_entry.data.sequence }}
</td>
<td>
{{ lineup_entry.data.member_name }}
</td>
<td>
{{ lineup_entry.data.label }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<h3>Functions</h3>
<div class="">
<form method="get" action="{% url "teamsnap_image_generator_generate" team_id=request.user.profile.teamsnapsettings.managed_team.id event_id=event.data.id %}">
<select hidden class="form-select" name="game_id" id="game_id">
<optgroup label="Events">
<option value="" disabled="disabled">Select an event...</option>
<option selected value="{{event.data.id}}">{{event.data.formatted_title}}</option>
</optgroup>
</select>
<input hidden class="form-check-input" type="radio" name="background" id="backgroundLocation" checked value="location">
<input hidden class="form-check-input" type="radio" name="dimensions" id="square" checked value="1080x1080">
<button type="submit" class="btn btn-primary btn-block"><i class="bi bi-instagram"></i></button>
</form>
<a class="btn btn-primary" href="{% url "teamsnap_image_generator" team_id=request.user.profile.teamsnapsettings.managed_team.id event_id=event.data.id %}" role="button"><div class="d-inline-block"><i class="bi bi-instagram"></i> <i class="bi bi-three-dots"></i></div></a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -6,8 +6,19 @@ from functools import partial
from . import views
urlpatterns = [
path('', views.home, name='teamsnap home'),
path('', views.home, name='teamsnap_home'),
path('edit/event/<int:id>', views.edit_event, name='teamsnap edit event'),
path('sync/download', views.sync_from_teamsnap, name="sync from teamsnap"),
path('import/', views.import_teamsnap, name="import")
path('import/', views.import_teamsnap, name="import"),
path('<int:team_id>/schedule/', views.schedule, name='teamsnap_schedule'),
path('<int:team_id>/schedule/view_event/<int:event_id>', views.event, name='teamsnap_view_event'),
path('<int:team_id>/opponent/view/<int:id>', views.opponent, name='teamsnap_opponent'),
path('<int:team_id>/location/view/<int:id>', views.location, name='teamsnap_location'),
path('<int:team_id>/event/<int:event_id>/edit_lineup/', views.edit_lineup, name='teamsnap_edit_lineup'),
path('<int:team_id>/event/<int:event_id>/submit_lineup/', views.submit_lineup, name='teamsnap_submit_lineup'),
path('<int:team_id>/event/<int:event_id>/image_generator/', views.image_generator, name='teamsnap_image_generator'),
path('<int:team_id>/event/<int:event_id>/image_generator/generate', views.get_matchup_image, name='teamsnap_image_generator_generate'),
path('<int:team_id>/multievent/edit_lineups', views.edit_multiple_lineups, name='teamsnap_edit_multiple_lineups'),
path('<int:team_id>/multievent/choose', views.multi_lineup_choose, name='teamsnap_choose_multiple_lineups')
]

331
teamsnap/utils/gen_image.py Normal file
View File

@@ -0,0 +1,331 @@
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFilter, ImageFont
from pathlib import Path
import os
from datetime import datetime
from zoneinfo import ZoneInfo
from typing import List
from dataclasses import dataclass
# image_directory = 'input/images/logos-bw/{filename}.{ext}'
# font_regular_path = "input/fonts/DINAlternate-Bold.ttf"
# font_condensed_path = "input/fonts/DINCondensed-Bold.ttf"
font_regular_path = "benchcoachproject/static/teamsnap/ig/fonts/ScalaSans-BoldLF.otf"
font_condensed_path = "benchcoachproject/static/teamsnap/ig/fonts/ScalaSans-BoldLF.otf"
@dataclass
class Team:
name: str
winlosstie: List[int] = None
image_directory: str = '../input/images/logos-bw/{filename}.{ext}'
@property
def id(self):
return self.name.lower().replace(' ', '-')
@property
def image(self):
path = self.image_directory.format(filename=self.id, ext="png")
if os.path.isfile(path):
return path
else:
return None
@dataclass
class Location:
name: str
address1: str = ""
address2: str = ""
image_directory: str = 'benchcoachproject/static/teamsnap/ig/locations/{filename}.{ext}'
@property
def id(self):
return self.name.lower().replace(' ', '-')
@property
def image(self):
path = self.image_directory.format(filename=self.id, ext="png")
if os.path.isfile(path):
return path
else:
return None
@property
def address(self):
return ",".join([self.address1,self.address2])
args = {
"team_fave" : Team("Hounds"),
"team_opponent" : Team("Trojans"),
"home": False,
"date" : "2021-05-08 12:30 pm",
"location" : Location("Maywood", image_directory="benchcoachproject/static/teamsnap/ig/locations/maywood.{ext}"),
"runs_for": 8,
"runs_against": 9
}
def gen_image (team_fave, team_opponent, date, location=None,
location_name = None,
home=False,
background='location',
address = None,
width = 1080,
height = 1080,
*kwargs,
**args
):
if not isinstance(date, datetime):
# date = parser.parse(date)
# date = date.astimezone(ZoneInfo("America/Chicago"))
pass
if location.image and background == 'location':
background_image = Image.open(location.image).copy()
background_image = background_image.resize((width, height))
# background_image = background_image.filter(ImageFilter.GaussianBlur(radius=5))
background_image = background_image.convert("RGBA")
elif background == 'transparent':
background_image = Image.new('RGBA', (width, height), (0, 0, 0, 0))
else:
background_image = Image.new('RGBA', (width, height), (50, 55, 102))
title_images = []
for team in [team_fave, team_opponent]:
if team.image:
title_images.append(Image.open(team.image).copy())
else:
title_images.append(Image.new('RGBA', (1080, 1080)))
title_image_left = title_images[0]
title_image_right = title_images[1]
# Make a blank image for the rectangle, initialized to a completely
# transparent color.
tmp = Image.new('RGBA', background_image.size, (0, 0, 0, 0))
# Create a drawing context for it.
draw = ImageDraw.Draw(tmp)
# section margin describes the margin of the section rectangles from the sides of the image
section_margin_pct = .05
llx = int(section_margin_pct * background_image.size[0])
urx = int((1 - section_margin_pct) * background_image.size[0])
lly = int((1 - section_margin_pct) * background_image.size[1])
ury = int(.50 * background_image.size[1])
lly2 = int(.49 * background_image.size[1])
ury2 = int(.05 * background_image.size[1])
section_info = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-tan", ext=".png")))
section_info_draw = ImageDraw.Draw(section_info)
section_title = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-green", ext=".png")))
section_title_draw = ImageDraw.Draw(section_title)
# First line: Date
font = ImageFont.truetype(font_regular_path, 62)
text = "{:%a, %B %-d %-I:%M %p}".format(date).upper()
# text = date
text_size = draw.textsize(text, font)
loc = (
1050,
280
)
section_info_draw.text(loc, text, (14,42,28), font=font, anchor="ra")
# Second line: Venue
font = ImageFont.truetype(font_condensed_path, 34)
if not location_name:
text = location.name.upper()
else:
text = location_name.upper()
text_size = section_info_draw.textsize(text, font)
loc = (
1050,
355
)
section_info_draw.text(loc, text, (14,42,28), font=font, anchor="ra")
font = ImageFont.truetype(font_regular_path, 80)
if home:
text = "VS"
else:
text = "AT"
text_size = section_title_draw.textsize(text, font)
loc = (
540,
120
)
color = (255, 255, 255)
section_title_draw.text(loc, text, color, font=font, anchor="mm")
# Alpha composite the two images together.
background_image = Image.alpha_composite(background_image, tmp)
# Title Image Left
title_image_left.thumbnail([350, 350])
loc = (
50, -50
)
section_title.paste(title_image_left, loc, title_image_left)
# Title Image Right
title_image_right.thumbnail([350, 350])
loc = (
650, -50
)
section_title.paste(title_image_right, loc, title_image_right)
# background_image.paste(section_info, (llx, ury), section_info)
# background_image.paste(section_title, (llx, ury2), section_title)
section_title.paste(section_info,(0,0),section_info)
section_title.thumbnail([800, 800])
if background=="badge":
return section_title
background_image.paste(section_title,(
int((background_image.size[0]-section_title.size[0])/2),
height - 360
),section_title)
return background_image
def gen_results_image (team_fave, team_opponent, date,
location=None,
location_name = None,
home=False,
background='location',
address = None,
width = 1080,
height = 1080,
runs_for=0,
runs_against=0,
*kwargs,
**args
):
if not isinstance(date, datetime):
# date = parser.parse(date)
# date = date.astimezone(ZoneInfo("America/Chicago"))
pass
if location.image and background == 'location':
background_image = Image.open(location.image).copy()
background_image = background_image.resize((width, height))
# background_image = background_image.filter(ImageFilter.GaussianBlur(radius=5))
background_image = background_image.convert("RGBA")
elif background == 'transparent':
background_image = Image.new('RGBA', (width, height), (0, 0, 0, 0))
else:
background_image = Image.new('RGBA', (width, height), (50, 55, 102))
title_images = []
for team in [team_fave, team_opponent]:
if team.image:
title_images.append(Image.open(team.image).copy())
else:
title_images.append(Image.new('RGBA', (1080, 1080)))
title_image_left = title_images[0]
title_image_right = title_images[1]
# Make a blank image for the rectangle, initialized to a completely
# transparent color.
tmp = Image.new('RGBA', background_image.size, (0, 0, 0, 0))
# Create a drawing context for it.
draw = ImageDraw.Draw(tmp)
# section margin describes the margin of the section rectangles from the sides of the image
section_margin_pct = .05
llx = int(section_margin_pct * background_image.size[0])
urx = int((1 - section_margin_pct) * background_image.size[0])
lly = int((1 - section_margin_pct) * background_image.size[1])
ury = int(.50 * background_image.size[1])
lly2 = int(.49 * background_image.size[1])
ury2 = int(.05 * background_image.size[1])
#todo fix path
section_info = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-tan", ext=".png")))
section_info_draw = ImageDraw.Draw(section_info)
section_title = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-green", ext=".png")))
section_title_draw = ImageDraw.Draw(section_title)
# First line: Results
loc = (
1050,
265
)
if runs_for > runs_against:
result_letter = "W"
elif runs_for < runs_against:
result_letter = "L"
elif runs_for == runs_against:
result_letter = "T"
font = ImageFont.truetype(font_regular_path, 100)
section_info_draw.text(loc, f"FINAL: {result_letter} {runs_for}-{runs_against}", (14,42,28), font=font, anchor="ra")
# Second line: Date
text = "{:%a, %B %-d %-I:%M %p}".format(date).upper()
# text = date
font = ImageFont.truetype(font_condensed_path, 34)
text_size = section_info_draw.textsize(text, font)
loc = (
1050,
355
)
section_info_draw.text(loc, text, (14,42,28), font=font, anchor="ra")
font = ImageFont.truetype(font_regular_path, 80)
if home:
text = "VS"
else:
text = "AT"
text_size = section_title_draw.textsize(text, font)
loc = (
540,
120
)
color = (255, 255, 255)
section_title_draw.text(loc, text, color, font=font, anchor="mm")
# Alpha composite the two images together.
background_image = Image.alpha_composite(background_image, tmp)
# Title Image Left
title_image_left.thumbnail([350, 350])
loc = (
50, -50
)
section_title.paste(title_image_left, loc, title_image_left)
# Title Image Right
title_image_right.thumbnail([350, 350])
loc = (
650, -50
)
section_title.paste(title_image_right, loc, title_image_right)
# background_image.paste(section_info, (llx, ury), section_info)
# background_image.paste(section_title, (llx, ury2), section_title)
section_title.paste(section_info,(0,0),section_info)
section_title.thumbnail([800, 800])
if background=="badge":
return section_title
background_image.paste(section_title,(
int((background_image.size[0]-section_title.size[0])/2),
height - 360
),section_title)
# background_image.show()
return background_image
# gen_results_image(**args)

View File

@@ -3,7 +3,8 @@ from typing import List, Tuple
import benchcoach.models
from benchcoach.models import BenchcoachModel, Availability, Player, Team, Positioning, Event, Venue
from teamsnap.teamsnap.api import TeamSnap
from pyteamsnap.api import TeamSnap
import pyteamsnap
import teamsnap.models
from django.db.models import QuerySet
@@ -50,14 +51,14 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
}
teamsnapmodel_to_apiobject = {
teamsnap.models.Availability: teamsnap.teamsnap.api.Availability,
teamsnap.models.Event: teamsnap.teamsnap.api.Event,
# teamsnap.models.LineupEntry:teamsnap.teamsnap.api.LineupEntry, # Not implemented Yet
teamsnap.models.Location: teamsnap.teamsnap.api.Location,
teamsnap.models.Member: teamsnap.teamsnap.api.Member,
teamsnap.models.Opponent: teamsnap.teamsnap.api.Opponent,
teamsnap.models.Team: teamsnap.teamsnap.api.Team,
# teamsnap.models.User:teamsnap.teamsnap.api.User # Not implemented yet
teamsnap.models.Availability: pyteamsnap.api.Availability,
teamsnap.models.Event: pyteamsnap.api.Event,
# teamsnap.models.LineupEntry:pyteamsnap.api.LineupEntry, # Not implemented Yet
teamsnap.models.Location: pyteamsnap.api.Location,
teamsnap.models.Member: pyteamsnap.api.Member,
teamsnap.models.Opponent: pyteamsnap.api.Opponent,
teamsnap.models.Team: pyteamsnap.api.Team,
# teamsnap.models.User:pyteamsnap.api.User # Not implemented yet
}
apiobject_to_teamsnapmodel = {v:k for k,v in teamsnapmodel_to_apiobject.items()}
@@ -104,14 +105,14 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
}
teamsnapmodel_to_apiobject = {
teamsnap.models.Availability: teamsnap.teamsnap.api.Availability,
teamsnap.models.Event: teamsnap.teamsnap.api.Event,
# teamsnap.models.LineupEntry:teamsnap.teamsnap.api.LineupEntry, # Not implemented Yet
teamsnap.models.Location: teamsnap.teamsnap.api.Location,
teamsnap.models.Member: teamsnap.teamsnap.api.Member,
teamsnap.models.Opponent: teamsnap.teamsnap.api.Opponent,
teamsnap.models.Team: teamsnap.teamsnap.api.Team,
# teamsnap.models.User:teamsnap.teamsnap.api.User # Not implemented yet
teamsnap.models.Availability: pyteamsnap.api.Availability,
teamsnap.models.Event: pyteamsnap.api.Event,
# teamsnap.models.LineupEntry:pyteamsnap.api.LineupEntry, # Not implemented Yet
teamsnap.models.Location: pyteamsnap.api.Location,
teamsnap.models.Member: pyteamsnap.api.Member,
teamsnap.models.Opponent: pyteamsnap.api.Opponent,
teamsnap.models.Team: pyteamsnap.api.Team,
# teamsnap.models.User:pyteamsnap.api.User # Not implemented yet
}
if isinstance(benchcoach_instance, benchcoach.models.Team):
@@ -128,9 +129,9 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
r = self._update_teamsnapdb_to_benchcoachdb(teamsnap_instance, benchcoach_instance)
return r
def _update_from_teamsnapdata(self, teamsnap_instance:teamsnap.models.TeamsnapBaseModel, teamsnap_data: teamsnap.teamsnap.api.ApiObject) -> teamsnap.models.TeamsnapBaseModel:
def _update_from_teamsnapdata(self, teamsnap_instance:teamsnap.models.TeamsnapBaseModel, teamsnap_data: pyteamsnap.api.ApiObject) -> teamsnap.models.TeamsnapBaseModel:
''''''
if isinstance(teamsnap_data, teamsnap.teamsnap.api.ApiObject):
if isinstance(teamsnap_data, pyteamsnap.api.ApiObject):
teamsnap_data = teamsnap_data.data
else:
raise TypeError
@@ -390,7 +391,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
r['team'] = []
# Search API for objects belonging to currently managed team, and iterate
for teamsnap_data in teamsnap.teamsnap.api.Team.search(client=self.client, id=self.managed_teamsnap_team_id):
for teamsnap_data in pyteamsnap.api.Team.search(client=self.client, id=self.managed_teamsnap_team_id):
# check if TeamSnap ID already exists in the Teamsnap DB.
if teamsnap.models.Team.objects.filter(id=teamsnap_data.data['id']):
teamsnap_instance = teamsnap.models.Team.objects.filter(id=teamsnap_data.data['id']).first()
@@ -417,7 +418,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
# Opponents from teamsnap go to the BenchCoach "Team" database.
# Dependent on Team. These objects need to be available to attach as related objects or the functions
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
for teamsnap_data in teamsnap.teamsnap.api.Opponent.search(**kwargs):
for teamsnap_data in pyteamsnap.api.Opponent.search(**kwargs):
if teamsnap.models.Opponent.objects.filter(id=teamsnap_data.data['id']):
teamsnap_instance = teamsnap.models.Opponent.objects.filter(id=teamsnap_data.data['id']).first()
benchcoach_instance = teamsnap_instance.benchcoach_object
@@ -435,7 +436,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
# Dependent on Team. These objects need to be available to attach as related objects or the functions
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
r['location'] = []
for teamsnap_data in teamsnap.teamsnap.api.Location.search(**kwargs):
for teamsnap_data in pyteamsnap.api.Location.search(**kwargs):
if teamsnap.models.Location.objects.filter(id=teamsnap_data.data['id']):
teamsnap_instance = teamsnap.models.Location.objects.filter(id=teamsnap_data.data['id']).first()
benchcoach_instance = teamsnap_instance.benchcoach_object
@@ -455,7 +456,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
r['member'] = []
# Search API for members to import. Note: Non players are not included in sync.
for teamsnap_data in teamsnap.teamsnap.api.Member.search(**kwargs,
for teamsnap_data in pyteamsnap.api.Member.search(**kwargs,
is_non_player = False
):
if teamsnap_data.data['is_non_player'] == True:
@@ -478,7 +479,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
# Dependent on Team, Opponent, Location. These objects need to be available to attach as related objects or the functions
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
r['event'] = []
for teamsnap_data in teamsnap.teamsnap.api.Event.search(**kwargs):
for teamsnap_data in pyteamsnap.api.Event.search(**kwargs):
if teamsnap.models.Event.objects.filter(id=teamsnap_data.data['id']):
teamsnap_instance = teamsnap.models.Event.objects.filter(id=teamsnap_data.data['id']).first()
benchcoach_instance = teamsnap_instance.benchcoach_object
@@ -504,7 +505,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
# Search API for members to import. Note: Non players are not included in sync.
player_ids = [member.id for member in teamsnap.models.Member.objects.filter(is_non_player=False)]
for teamsnap_data in teamsnap.teamsnap.api.Availability.search(**kwargs,
for teamsnap_data in pyteamsnap.api.Availability.search(**kwargs,
member_id=",".join(player_ids)
):
if teamsnap.models.Availability.objects.filter(id=teamsnap_data.data['id']):

View File

@@ -1,11 +1,16 @@
import operator
import time
from django.shortcuts import render, redirect
from .models import User, Member, Team, Event, Location, LineupEntry, Opponent, Availability
from django.http import HttpResponse
from django.http import HttpResponse, HttpResponseNotAllowed
import benchcoach.models
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .utils.teamsnap_sync_engine import TeamsnapSyncEngine
from django.templatetags.static import static
import datetime
def edit_event(request, id):
'''
@@ -112,6 +117,7 @@ def sync_from_teamsnap(request, object_name=None, object_id=None):
return HttpResponse(404)
def import_teamsnap(request):
TEAM_ID = request.user.profile.teamsnapsettings.managed_team.id
TOKEN = request.user.profile.teamsnap_access_token
@@ -127,5 +133,437 @@ def import_teamsnap(request):
return redirect('teamsnap home')
def schedule(request, team_id):
TEAM_ID = team_id
TOKEN = request.user.profile.teamsnap_access_token
no_past = bool(request.GET.get('no_past', 0))
games_only = bool(request.GET.get('games_only',0))
from pyteamsnap.api import TeamSnap, Event, Location, Opponent
client = TeamSnap(token=TOKEN)
time.sleep(.5)
ts_events = Event.search(client, team_id=TEAM_ID)
if no_past:
ts_events = [e for e in ts_events if e.data['start_date'] > datetime.datetime.now(datetime.timezone.utc)]
if games_only:
ts_events = [e for e in ts_events if e.data['is_game']]
ts_events = {e.data['id']:e for e in ts_events}
# ts_opponents = {o.data['id']:o for o in Opponent.search(client, team_id=TEAM_ID)}
# ts_locations = {l.data['id']:l for l in Location.search(client, team_id=TEAM_ID)}
# for event in ts_events:
pass
return render(request, "teamsnap/schedule.html", context={"events":ts_events.values(), "team_id":team_id})
def event(request, event_id, team_id):
TOKEN = request.user.profile.teamsnap_access_token
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary
client = TeamSnap(token=TOKEN)
time.sleep(0.5)
ts_bulkload = client.bulk_load(team_id=team_id,
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
event__id=event_id)
ts_event = [i for i in ts_bulkload if isinstance(i, Event)][0]
# ts_availabilities = Availability.search(client, event_id=ts_event.data['id'])
ts_availability_summary = \
[i for i in ts_bulkload if isinstance(i, AvailabilitySummary) and i.data['event_id'] == event_id][0]
ts_lineup_entries = [i for i in ts_bulkload if isinstance(i, EventLineupEntry) and i.data['event_id'] == event_id]
ts_members = [i for i in ts_bulkload if isinstance(i, Member)]
ts_member_lookup = {m.data['id']: m for m in ts_members}
# ts_availability_lookup = {m.data['member_id']: m for m in ts_availabilities}
ts_lineup_entries_lookup = {m.data['member_id']: m for m in ts_lineup_entries}
members = []
return render(request, "teamsnap/view_event.html", context={
"availability_summary":ts_availability_summary,
"event":ts_event,
"availablities":[],
"lineup_entries": ts_lineup_entries,
})
def location(request, id, team_id):
TOKEN = request.user.profile.teamsnap_access_token
from pyteamsnap.api import TeamSnap, Location
client = TeamSnap(token=TOKEN)
return render(request, "teamsnap/location/view.html", context={"location": Location.get(client, id=id)})
pass
def opponent(request, id):
TOKEN = request.user.profile.teamsnap_access_token
from pyteamsnap.api import TeamSnap, Opponent
time.sleep(0.5)
client = TeamSnap(token=TOKEN)
return render(request, "teamsnap/opponent.html", context={"opponent": Opponent.get(client, id=id)})
pass
def edit_lineup(request, event_id, team_id):
TOKEN = request.user.profile.teamsnap_access_token
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary, Opponent
client = TeamSnap(token=TOKEN)
time.sleep(0.5)
ts_bulkload = client.bulk_load(team_id=team_id,
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
event__id=event_id)
ts_event = [i for i in ts_bulkload if isinstance(i, Event)][0]
ts_availabilities = Availability.search(client, event_id=ts_event.data['id'])
ts_availability_summary = \
[i for i in ts_bulkload if isinstance(i, AvailabilitySummary) and i.data['event_id'] == event_id][0]
ts_lineup_entries = [i for i in ts_bulkload if isinstance(i, EventLineupEntry) and i.data['event_id'] == event_id]
if ts_lineup_entries:
ts_lineup = EventLineup.get(client, id=ts_lineup_entries[0].data['event_lineup_id'])
else:
ts_lineup = EventLineup.search(client, event_id=event_id)
ts_members = [i for i in ts_bulkload if isinstance(i, Member)]
ts_member_lookup = {m.data['id']: m for m in ts_members}
ts_availability_lookup = {m.data['member_id']: m for m in ts_availabilities}
ts_lineup_entries_lookup = {m.data['member_id']: m for m in ts_lineup_entries}
members=[]
for member in ts_members:
members.append ({
"member":getattr(member, 'data'),
"availability": getattr(ts_availability_lookup.get(member.data['id'], {}), 'data', {}),
"lineup_entry": getattr(ts_lineup_entries_lookup.get(member.data['id'], {}), 'data', {})
}
)
members = sorted(members, key=lambda d: (
{
None:3, # No Response
0:2, # No
2:1, # Maybe
1:0 # Yes
}.get(d['availability'].get('status_code')),
d['member'].get('last_name'))
)
from teamsnap.forms import LineupEntryFormset, LineupEntryForm
formset = LineupEntryFormset(
initial=[
{
"event_lineup_entry_id" : member['lineup_entry'].get('id'),
"event_lineup_id" : member['lineup_entry'].get('event_lineup_id'),
"event_id": event_id,
"member_id" : member['member']['id'],
"sequence" : member['lineup_entry'].get('sequence'),
"label" : member['lineup_entry'].get('label'),
}
for member in members
]
)
for form in formset:
form.member = ts_member_lookup.get(form['member_id'].initial)
form.availability = ts_availability_lookup.get(form['member_id'].initial)
formset_lineup = [form for form in formset if form.initial.get('event_lineup_entry_id')]
formset_lineup = sorted(
formset_lineup,
key=lambda d: d.initial.get('sequence',100)
)
formset_bench = [form for form in formset if
form not in formset_lineup and
form.availability.data['status_code'] in [2, 1]
]
formset_out = [form for form in formset if
form not in formset_lineup and
form not in formset_bench and
not form.member.data['is_non_player']
]
return render(request, "teamsnap/lineup/edit.html", context={
"team_id": team_id,
"event_id": event_id,
"event": ts_event,
"formset": formset,
"formset_lineup":formset_lineup,
"formset_bench": formset_bench,
"formset_out": formset_out,
"lineup": ts_lineup
})
def edit_multiple_lineups(request, team_id):
TOKEN = request.user.profile.teamsnap_access_token
from django.forms import formset_factory
from teamsnap.forms import EventChooseForm
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary, Opponent
client = TeamSnap(token=TOKEN)
time.sleep(0.5)
ts_events = Event.search(client, team_id=team_id)
EventChooseFormset = formset_factory(EventChooseForm)
formset = EventChooseFormset(request.GET)
choices = [(e.data['id'], e.data['formatted_title']) for e in ts_events]
for form in formset:
form.fields['event_id'].choices = choices
if formset.is_valid():
event_ids = [f.cleaned_data['event_id'] for f in formset]
else:
event_ids = request.GET.get("event_ids").split(",")
ts_bulkload = client.bulk_load(team_id=team_id,
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
event__id=",".join(event_ids))
event_ids = [int(i) for i in event_ids]
formsets_lineup = []
formsets_bench = []
formsets = []
events = []
contexts = []
for event_id in event_ids:
ts_event = [i for i in ts_bulkload if isinstance(i, Event) and i.data['id']==event_id][0]
ts_availabilities = Availability.search(client, event_id=ts_event.data['id'])
ts_availability_summary = \
[i for i in ts_bulkload if isinstance(i, AvailabilitySummary) and i.data['event_id'] == event_id][0]
ts_lineup_entries = [i for i in ts_bulkload if isinstance(i, EventLineupEntry) and i.data['event_id'] == event_id]
if ts_lineup_entries:
ts_lineup = EventLineup.get(client, id=ts_lineup_entries[0].data['event_lineup_id'])
else:
ts_lineup = EventLineup.search(client, event_id=event_id)
ts_members = [i for i in ts_bulkload if isinstance(i, Member)]
ts_member_lookup = {m.data['id']: m for m in ts_members}
ts_availability_lookup = {m.data['member_id']: m for m in ts_availabilities}
ts_lineup_entries_lookup = {m.data['member_id']: m for m in ts_lineup_entries}
members=[]
for member in ts_members:
members.append ({
"member":getattr(member, 'data'),
"availability": getattr(ts_availability_lookup.get(member.data['id'], {}), 'data', {}),
"lineup_entry": getattr(ts_lineup_entries_lookup.get(member.data['id'], {}), 'data', {})
}
)
members = sorted(members, key=lambda d: (
{
None:3, # No Response
0:2, # No
2:1, # Maybe
1:0 # Yes
}.get(d['availability'].get('status_code')),
d['member'].get('last_name'))
)
from teamsnap.forms import LineupEntryFormset, LineupEntryForm
formset = LineupEntryFormset(
initial=[
{
"event_lineup_entry_id" : member['lineup_entry'].get('id'),
"event_lineup_id" : member['lineup_entry'].get('event_lineup_id'),
"event_id": event_id,
"member_id" : member['member']['id'],
"sequence" : member['lineup_entry'].get('sequence'),
"label" : member['lineup_entry'].get('label'),
}
for member in members
]
)
for form in formset:
form.member = ts_member_lookup.get(form['member_id'].initial)
form.availability = ts_availability_lookup.get(form['member_id'].initial)
formset_lineup = [form for form in formset if form.initial.get('event_lineup_entry_id')]
formset_lineup = sorted(
formset_lineup,
key=lambda d: d.initial.get('sequence',100)
)
formset_bench = [form for form in formset if
form not in formset_lineup and
form.availability.data['status_code'] in [2, 1]
]
formset_out = [form for form in formset if
form not in formset_lineup and
form not in formset_bench and
not form.member.data['is_non_player']
]
contexts.append({
"event":ts_event,
"formset": formset,
"formset_bench":formset_bench,
"formset_lineup":formset_lineup,
"formset_out":formset_out
})
return render(request, "teamsnap/lineup/multiple_edit.html", context={
"team_id": team_id,
"contexts":contexts
})
def submit_lineup(request, team_id, event_id):
from pyteamsnap.api import TeamSnap, EventLineupEntry, EventLineup
from teamsnap.forms import LineupEntryFormset
TOKEN = request.user.profile.teamsnap_access_token
client = TeamSnap(token=TOKEN)
time.sleep(0.5)
ts_lineup = EventLineup.search(client, event_id=event_id)
event_lineup_id = ts_lineup[0].data['id']
if request.GET:
return HttpResponseNotAllowed()
if request.POST:
formset = LineupEntryFormset(request.POST)
if formset.is_valid():
r = []
for form in formset:
data = form.cleaned_data
if data.get('event_lineup_entry_id'):
event_lineup_entry = EventLineupEntry.get(client, id=data.get('event_lineup_entry_id'))
event_lineup_entry.data.update(data)
# breakpoint()
r.append(event_lineup_entry.put())
# breakpoint()
pass
elif data.get('sequence') is not None and data.get('label'):
event_lineup_entry = EventLineupEntry.new(client)
event_lineup_entry.data.update(data)
event_lineup_entry.data.update({"event_lineup_id":event_lineup_id})
r.append(event_lineup_entry.post())
else:
pass
else:
# breakpoint()
pass
# breakpoint()
pass
return HttpResponse(f'{team_id} {event_id}')
pass
return HttpResponse(f'{team_id} {event_id}')
def image_generator(request, team_id, event_id):
TOKEN = request.user.profile.teamsnap_access_token
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary
client = TeamSnap(token=TOKEN)
time.sleep(0.5)
ts_event = Event.get(client, id=event_id)
return render(request, "teamsnap/event/instagen.html", context = {"event":ts_event})
# @app.route('/get_matchup_image')
def get_matchup_image(request, team_id, event_id, dimensions=None, background=None):
from pyteamsnap.api import TeamSnap, EventLineupEntry, EventLineup, Event, Team, Opponent, Location
from .utils.gen_image import Team as ImagegenTeam, Location as ImagegenLocation
from .utils.gen_image import gen_image, gen_results_image
import io
TOKEN = request.user.profile.teamsnap_access_token
if request.GET:
POSTPONED = request.GET.get('postponed', 'false') == 'true'
INCLUDE_WINLOSS = request.GET.get('winloss', 'false') == 'true'
BACKGROUND = request.GET.get('background', 'location')
game_id = event_id
dimensions = request.GET.get('dimensions')
width = int(dimensions.split("x")[0])
height = int(dimensions.split("x")[1])
teamsnap = TeamSnap(TOKEN)
time.sleep(0.5)
ts_event = Event.get(teamsnap, game_id).data
fave_team = Team.get(teamsnap, ts_event['team_id']).data
opponent_team = Opponent.get(teamsnap, ts_event['opponent_id']).data
location = Location.get(teamsnap, ts_event['location_id']).data
formatted_results = ts_event['formatted_results']
if formatted_results:
# L 4-3
runs_for = formatted_results.split(" ")[1].split("-")[0]
runs_against = formatted_results.split(" ")[1].split("-")[1]
else:
runs_for, runs_against = None, None
logo_image_directory = 'benchcoachproject/static/teamsnap/ig/logos-bw/{filename}.{ext}'
venue_image_directory = 'benchcoachproject/static/teamsnap/ig/locations/{filename}.{ext}'
def shortname_from_name(name):
return name.replace(" ", "").lower()
# date = parser.parse(ts_event['start_date'])
# date = date.astimezone(ZoneInfo("America/Chicago"))
game_info = {
"date": ts_event['start_date'],
"team_fave": ImagegenTeam(
name=fave_team["name"],
image_directory=logo_image_directory.format(filename=shortname_from_name(fave_team["name"]), ext="png")
),
"team_opponent": ImagegenTeam(
name=opponent_team["name"],
image_directory=logo_image_directory.format(filename=shortname_from_name(opponent_team["name"]),
ext="png")
),
"location": ImagegenLocation(
name=location['name'],
image_directory=venue_image_directory.format(filename=shortname_from_name(location["name"]), ext="png"),
# address=location['address']
),
"runs_for": runs_for,
"runs_against": runs_against
}
if not game_info['runs_for'] and not game_info['runs_against']:
image = gen_image(**game_info, background=BACKGROUND, width=width, height=height)
elif game_info['runs_for'] and game_info['runs_against']:
image = gen_results_image(**game_info, background=BACKGROUND, width=width, height=height)
else:
raise Exception
imgByteArr = io.BytesIO()
image.save(imgByteArr, format='PNG')
imgByteArr = imgByteArr.getvalue()
return HttpResponse(imgByteArr, content_type="image/png")
def multi_lineup_choose(request, team_id):
from teamsnap.forms import EventChooseForm
from django.forms import formset_factory
if not request.GET.get('num'):
return HttpResponse(500)
else:
num = int(request.GET.get('num'))
TEAM_ID = team_id
TOKEN = request.user.profile.teamsnap_access_token
no_past = bool(request.GET.get('no_past', 0))
games_only = bool(request.GET.get('games_only', 0))
from pyteamsnap.api import TeamSnap, Event, Location, Opponent
client = TeamSnap(token=TOKEN)
time.sleep(.5)
ts_events = Event.search(client, team_id=TEAM_ID)
if no_past:
ts_events = [e for e in ts_events if e.data['start_date'] > datetime.datetime.now(datetime.timezone.utc)]
if games_only:
ts_events = [e for e in ts_events if e.data['is_game']]
ts_events = {e.data['id']: e for e in ts_events}
# ts_opponents = {o.data['id']:o for o in Opponent.search(client, team_id=TEAM_ID)}
# ts_locations = {l.data['id']:l for l in Location.search(client, team_id=TEAM_ID)}
# for event in ts_events:
EventChooseFormset = formset_factory(EventChooseForm, extra=num)
formset = EventChooseFormset()
choices= [(id, e.data['formatted_title']) for id, e in ts_events.items()]
for form in formset:
form.fields['event_id'].choices = choices
pass
return render(request, "teamsnap/lineup/multiple_choose.html", context={"formset": formset, "team_id": team_id})