Automatic broadcasting

clubs
Laurent 2 years ago
parent 7ac58ffd73
commit 3197938fa0
  1. 35
      tournaments/models/match.py
  2. 4
      tournaments/models/team_score.py
  3. 58
      tournaments/models/tournament.py
  4. 15
      tournaments/templates/tournaments/base_head.html
  5. 1
      tournaments/templates/tournaments/broadcast.html
  6. 14
      tournaments/templates/tournaments/broadcast_base.html
  7. 90
      tournaments/templates/tournaments/broadcasted.html
  8. 133
      tournaments/templates/tournaments/broadcasted_auto.html
  9. 2
      tournaments/templates/tournaments/broadcasted_group_stages.html
  10. 2
      tournaments/templates/tournaments/broadcasted_matches.html
  11. 2
      tournaments/templates/tournaments/broadcasted_summons.html
  12. 3
      tournaments/urls.py
  13. 26
      tournaments/views.py

@ -149,20 +149,21 @@ class Match(models.Model):
class Team:
def __init__(self, image, names, scores, weight, is_winner):
# print(f"image = {image}, names= {names}, scores ={scores}, weight={weight}, win={is_winner}")
self.image = image
self.names = names
self.scores = scores
self.weight = weight
self.is_winner = is_winner
# def to_dict(self):
# return {
# "image": self.image,
# "names": self.names,
# "scores": self.scores,
# "weight": self.weight,
# "is_winner": self.is_winner,
# }
def to_dict(self):
return {
"image": self.image,
"names": self.names,
"scores": self.scores,
"weight": self.weight,
"is_winner": self.is_winner,
}
class LiveMatch:
def __init__(self, title, date, duration, court, started):
@ -176,12 +177,12 @@ class LiveMatch:
def add_team(self, team):
self.teams.append(team)
# def to_dict(self):
# return {
# "title": self.title,
# "date": self.date,
# "teams": [team.to_dict() for team in self.teams],
# "duration": self.duration,
# "court": self.court,
# "started": self.started,
# }
def to_dict(self):
return {
"title": self.title,
"date": self.date,
"teams": [team.to_dict() for team in self.teams],
"duration": self.duration,
"court": self.court,
"started": self.started,
}

@ -18,7 +18,7 @@ class TeamScore(models.Model):
if self.team_registration.name:
return self.team_registration.name
else:
names = map(lambda player: player.name(), self.player_registrations.all())
names = [player.name() for player in self.player_registrations.all()]
return " - ".join(names)
def team_names(self):
@ -26,7 +26,7 @@ class TeamScore(models.Model):
if self.team_registration.name:
names.append(self.team_registration.name)
else:
names = list(map(lambda player: player.name(), self.player_registrations.all()))
names = [player.name() for player in self.player_registrations.all()]
return names
def scores(self):

@ -131,36 +131,70 @@ class Tournament(models.Model):
def live_group_stages(self):
return [gs.live_group_stages() for gs in self.groupstage_set.all()]
def live_matches(self):
def broadcast_content(self):
now = timezone.now()
today_matches = [match for match in self.all_matches() if match.start_date.date() == now]
today_matches.sort(key=lambda m: m.start_date)
matches, group_stages = self.broadcasted_matches_and_group_stages()
group_stages_dicts = [gs.to_dict() for gs in group_stages]
# if now is before the first match, we want to show the summons + group stage or first matches
if today_matches and now < today_matches[0].start_date:
team_summons_dicts = [summon.to_dict() for summon in self.team_summons()]
if group_stages:
return {
'matches': [],
'group_stages': group_stages_dicts,
'summons': team_summons_dicts,
}
else:
live_matches_dicts = [match.live_match().to_dict() for match in matches]
return {
'matches': live_matches_dicts,
'group_stages': [],
'summons': team_summons_dicts,
}
else: # we want to display the broadcasted content
live_matches_dicts = [match.live_match().to_dict() for match in matches]
return {
'matches': live_matches_dicts,
'group_stages': group_stages_dicts,
'summons': [],
}
def broadcasted_matches_and_group_stages(self):
matches = []
last_started_match = self.last_match()
group_stages = []
last_started_match = self.last_started_match()
current_round = last_started_match.round
if current_round:
previous_round = self.round_for_index(current_round.index - 1)
previous_round = self.round_for_index(current_round.index + 1)
if previous_round:
matches.extend(current_round.all_matches())
matches.extend(previous_round.all_matches())
else:
matches.extend(current_round.all_matches())
# todo on veut les matchs du round et les poules, comment ça marche ?
# dans le monde idéal on veut afficher plusieurs pages de plusieurs types différents
# est-ce que je construis un json avec des types différents dans un même array ?
# je veux pas que des types différents apparaissent sur une même page
group_stages = self.live_group_stages()
else:
matches = self.group_stages_matches()
return [match.live_match() for match in matches]
return matches, group_stages
def last_match(self):
def all_matches(self):
matches = []
for round in self.round_set.all():
matches.extend(round.match_set.all())
matches.extend(round.all_matches())
for group_stage in self.groupstage_set.all():
matches.extend(group_stage.match_set.all())
return matches
matches = [m for m in matches if m.start_date]
def last_started_match(self):
matches = [m for m in self.all_matches() if m.start_date]
matches.sort(key=lambda m: m.start_date, reverse=True)
return matches[0]
@ -172,7 +206,7 @@ class Tournament(models.Model):
for group_stage in self.groupstage_set.all():
matches.extend(group_stage.match_set.all())
matches = [m for m in matches if m.should_appear()]
matches.sort(key=lambda m: -m.start_date)
matches.sort(key=lambda m: m.start_date, reverse=True)
return matches
class MatchGroup:

@ -0,0 +1,15 @@
{% load static %}
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link
rel="stylesheet"
href="{% static 'tournaments/css/foundation.min.css' %}"
/>
<link rel="stylesheet" href="{% static 'tournaments/css/style.css' %}" />
<link rel="stylesheet" href="{% static 'tournaments/css/broadcast.css' %}" />
<link
rel="icon"
type="image/png"
href="{% static 'tournaments/images/favicon.png' %}"
/>

@ -11,6 +11,7 @@
<div class="grid-x">
<div class="cell medium-6 large-6 topblock my-block">
<div class="bubble">
<div><a href="{% url 'automatic-broadcast' tournament.id %}">Automatic</a></div>
<div><a href="{% url 'broadcasted-matches' tournament.id %}">Matchs</a></div>
<div><a href="{% url 'broadcasted-group-stages' tournament.id %}">Poules</a></div>
<div><a href="{% url 'broadcasted-summons' tournament.id %}">Convocations</a></div>

@ -3,19 +3,7 @@
{% load static %}
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link
rel="stylesheet"
href="{% static 'tournaments/css/foundation.min.css' %}"
/>
<link rel="stylesheet" href="{% static 'tournaments/css/style.css' %}" />
<link rel="stylesheet" href="{% static 'tournaments/css/broadcast.css' %}" />
<link
rel="icon"
type="image/png"
href="{% static 'tournaments/images/favicon.png' %}"
/>
{% include 'tournaments/base_head.html' %}
<script src="{% static 'tournaments/js/alpine.min.js' %}"></script>

@ -1,90 +0,0 @@
{% extends 'tournaments/broadcast_base.html' %}
{% block head_title %}Convocations{% endblock %}
{% block first_title %}{{ tournament.name }}{% endblock %}
{% block second_title %}Convocations{% endblock %}
{% block content %}
{% load static %}
<div x-data="{
paginatedMatches: null,
paginatedGroupStages: null,
paginatedSummons: null,
active: 1,
retrieveData() {
fetch('/tournament/{{ tournament.id }}/broadcast/json/')
.then(res => res.json())
.then((data) => {
this.paginatedMatches = this.paginate(data.matches, 8)
this.paginatedGroupStages = this.paginate(data.group_stages, 4)
this.paginatedSummons = this.paginateSummons(data.summons)
})
},
paginateSummons(array) {
let pageSize = 20
pages = this.paginate(array, pageSize)
const splitGroups = []
pages.forEach(group => {
const firstHalf = group.slice(0, pageSize / 2)
const secondHalf = group.slice(pageSize / 2)
if (secondHalf.length > 0) {
splitGroups.push([firstHalf, secondHalf])
} else {
splitGroups.push([firstHalf])
}
});
return splitGroups
},
paginate(array, pageSize) {
let paginatedArray = [];
for (let i = 0; i < array.length; i += pageSize) {
paginatedArray.push(array.slice(i, i + pageSize))
}
return paginatedArray;
},
loop() {
this.retrieveData()
setInterval(() => {
this.retrieveData()
this.active = this.active === this.pageCount() ? 1 : this.active+1
}, 15000)
},
pageCount() {
return this.paginatedMatches.length + this.paginatedGroupStages.length + this.paginatedSummons.length
}
}" x-init="loop()">
<div class="grid-x">
<template x-for="i in paginatedSummons.length">
<template x-for="column in paginatedSummons[i-1]">
<div class="cell medium-6 large-6 topblock my-block" x-show="active === i">
{% include 'tournaments/broadcasted_summon.html' %}
</div>
</template>
</template>
<template x-for="i in paginatedMatches.length" >
<template x-for="match in paginatedMatches[i-1]" >
<div class="cell medium-6 large-3 my-block" x-show="active === i + paginatedSummons.length">
{% include 'tournaments/broadcasted_match.html' %}
</div>
</template>
</template>
<template x-for="i in paginatedGroupStages.length">
<template x-for="group_stage in paginatedGroupStages[i-1]">
<div class="cell medium-6 large-3 my-block" x-show="active === i + paginatedSummons.length + paginatedMatches.length">
{% include 'tournaments/broadcasted_group_stage.html' %}
</div>
</template>
</template>
</div>
</div>
{% endblock %}

@ -0,0 +1,133 @@
<!DOCTYPE html>
<html>
{% load static %}
<head>
{% include 'tournaments/base_head.html' %}
<script src="{% static 'tournaments/js/alpine.min.js' %}"></script>
<title>Broadcast</title>
</head>
<body>
<div x-data="{
paginatedMatches: null,
paginatedGroupStages: null,
paginatedSummons: null,
active: 1,
title: '',
retrieveData() {
fetch('/tournament/{{ tournament.id }}/broadcast/json/')
.then(res => res.json())
.then((data) => {
this.paginatedMatches = this.paginate(data.matches, 8)
this.paginatedGroupStages = this.paginate(data.group_stages, 4)
this.paginatedSummons = this.paginateSummons(data.summons)
this.setTitle()
})
},
paginateSummons(array) {
let pageSize = 20
pages = this.paginate(array, pageSize)
const splitGroups = []
pages.forEach(group => {
const firstHalf = group.slice(0, pageSize / 2)
const secondHalf = group.slice(pageSize / 2)
if (secondHalf.length > 0) {
splitGroups.push([firstHalf, secondHalf])
} else {
splitGroups.push([firstHalf])
}
});
return splitGroups
},
paginate(array, pageSize) {
let paginatedArray = [];
for (let i = 0; i < array.length; i += pageSize) {
paginatedArray.push(array.slice(i, i + pageSize))
}
return paginatedArray;
},
loop() {
this.retrieveData()
setInterval(() => {
this.retrieveData()
this.active = this.active === this.pageCount() ? 1 : this.active+1
this.setTitle()
}, 15000)
},
pageCount() {
return this.paginatedMatches.length + this.paginatedGroupStages.length + this.paginatedSummons.length
},
setTitle() {
if (this.active < 1 + this.paginatedSummons.length) {
this.title = 'Convocations'
} else if (this.active < 1 + this.paginatedSummons.length + this.paginatedMatches.length) {
this.title = 'Matchs'
} else {
this.title = 'Poules'
}
}
}" x-init="loop()">
<div class="wrapper">
<header>
<div class="grid-x">
<div class="cell medium-6 large-6 topblock my-block">
<div class="bubble">
<img
src="{% static 'tournaments/images/PadelClub_logo_512.png' %}"
class="logo inline"
/>
<div class="inline">
<h1 class="club">{{ tournament.name }}</h1>
<h1 class="event"><span x-text="title"></span></h1>
<!-- <span>Propulsé par Padel Club</span> -->
</div>
</div>
</div>
</div>
</header>
<main>
<div class="grid-x">
<template x-for="i in paginatedSummons.length">
<template x-for="column in paginatedSummons[i-1]">
<div class="cell medium-6 large-6 topblock my-block" x-show="active === i">
{% include 'tournaments/broadcasted_summon.html' %}
</div>
</template>
</template>
<template x-for="i in paginatedMatches.length" >
<template x-for="match in paginatedMatches[i-1]" >
<div class="cell medium-6 large-3 my-block" x-show="active === i + paginatedSummons.length">
{% include 'tournaments/broadcasted_match.html' %}
</div>
</template>
</template>
<template x-for="i in paginatedGroupStages.length">
<template x-for="group_stage in paginatedGroupStages[i-1]">
<div class="cell medium-6 large-3 my-block" x-show="active === i + paginatedSummons.length + paginatedMatches.length">
{% include 'tournaments/broadcasted_group_stage.html' %}
</div>
</template>
</template>
</div>
</main>
</div>
</div>
</body>
</html>

@ -9,7 +9,7 @@
<link rel="icon" type="image/png" href="{% static 'tournaments/images/favicon.png' %}" />
<title>Padel</title>
<title>Poules</title>
<script src="{% static 'tournaments/js/alpine.min.js' %}"></script>

@ -9,7 +9,7 @@
<link rel="icon" type="image/png" href="{% static 'tournaments/images/favicon.png' %}" />
<title>Padel</title>
<title>Matchs</title>
<script src="{% static 'tournaments/js/alpine.min.js' %}"></script>

@ -8,7 +8,6 @@
{% load static %}
<div x-data="{
paginatedMatches: null,
active: 1,
@ -55,6 +54,7 @@
<template x-for="i in paginatedMatches.length" >
<template x-for="column in paginatedMatches[i-1]" >
<div class="cell medium-6 large-6 topblock my-block" x-show="active === i">
<div class="bubble">
<template x-for="summon in column" >
<div class="table-row-4-colums bottom-border">

@ -13,7 +13,8 @@ urlpatterns = [
path('broadcast/summons/', views.tournament_broadcasted_summons, name='broadcasted-summons'),
path('summons/json/', views.tournament_summons_json, name='tournament-summons-json'),
path('broadcast/matches/', views.tournament_matches, name='broadcasted-matches'),
path('broadcast/', views.tournament_broadcast, name='broadcast'),
path('broadcast/', views.tournament_broadcast_home, name='broadcast'),
path('broadcast/auto/', views.automatic_broadcast, name='automatic-broadcast'),
path('matches/json/', views.tournament_matches_json, name='tournament-matches-json'),
path('broadcast/json/', views.broadcast_json, name='broadcast-json'),
path('broadcast/group-stages/', views.tournament_broadcasted_group_stages, name='broadcasted-group-stages'),

@ -107,9 +107,15 @@ def tournament_summons_json(request, tournament_id):
data = json.dumps(team_summons)
return HttpResponse(data, content_type='application/json')
def tournament_broadcast(request, tournament_id):
def tournament_broadcast_home(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcasted.html', {
return render(request, 'tournaments/broadcast.html', {
'tournament': tournament,
})
def automatic_broadcast(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcasted_auto.html', {
'tournament': tournament,
})
@ -121,23 +127,15 @@ def tournament_matches(request, tournament_id):
def broadcast_json(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
matches = [m.__dict__ for m in tournament.live_matches()]
group_stages = [gs.to_dict() for gs in tournament.live_group_stages()]
team_summons = [summon.to_dict() for summon in tournament.team_summons()]
broadcast = {
'matches': matches,
'group_stages': group_stages,
'summons': team_summons,
}
broadcast = tournament.broadcast_content()
data = json.dumps(broadcast)
return HttpResponse(data, content_type='application/json')
def tournament_matches_json(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
live_matches = tournament.live_matches()
matches, group_stages = tournament.broadcasted_content()
live_matches = [match.live_match() for match in matches]
data = json.dumps(live_matches, default=vars)
return HttpResponse(data, content_type='application/json')

Loading…
Cancel
Save