You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
335 lines
14 KiB
335 lines
14 KiB
<!DOCTYPE html>
|
|
<html>
|
|
{% load static %}
|
|
{% load qr_code %}
|
|
|
|
<head>
|
|
{% include 'tournaments/broadcast/base_head.html' %}
|
|
|
|
<script src="{% static 'tournaments/js/alpine.min.js' %}" defer></script>
|
|
|
|
<title>Broadcast</title>
|
|
|
|
<!-- Matomo -->
|
|
<script>
|
|
var _paq = window._paq = window._paq || [];
|
|
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
|
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
|
|
_paq.push(["setDoNotTrack", true]);
|
|
_paq.push(['trackPageView']);
|
|
_paq.push(['enableLinkTracking']);
|
|
(function() {
|
|
var u="//matomo.padelclub.app/";
|
|
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
|
_paq.push(['setSiteId', '1']);
|
|
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
|
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
|
})();
|
|
</script>
|
|
<!-- End Matomo Code -->
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div x-data="{
|
|
paginatedMatches: null,
|
|
paginatedGroupStages: null,
|
|
paginatedSummons: null,
|
|
paginatedRankings: null,
|
|
active: 1,
|
|
hide_weight: {{ tournament.hide_weight|lower }},
|
|
has_sponsors: {{ tournament.has_sponsors|lower }},
|
|
prefixTitle: '',
|
|
retrieveData() {
|
|
fetch('/tournament/{{ tournament.id }}/broadcast/json/')
|
|
.then(res => {
|
|
if (!res.ok) {
|
|
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
}
|
|
return 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.paginatedRankings = this.paginateRankings(data.rankings)
|
|
this.setPrefixTitle()
|
|
|
|
// Adjust active if it exceeds the new page count
|
|
if (this.active > this.pageCount()) {
|
|
this.active = 1; // Reset to the first page
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.error('Error fetching tournament data:', error);
|
|
|
|
// If this tournament is in an iframe (part of event/club auto), notify parent
|
|
if (window.parent !== window) {
|
|
console.log('Notifying parent of tournament error');
|
|
window.parent.postMessage({
|
|
type: 'tournamentError',
|
|
tournamentId: '{{ tournament.id }}',
|
|
error: error.message
|
|
}, '*');
|
|
}
|
|
|
|
// Set empty data to prevent further errors
|
|
this.paginatedMatches = [];
|
|
this.paginatedGroupStages = [];
|
|
this.paginatedSummons = [];
|
|
this.paginatedRankings = [];
|
|
})
|
|
},
|
|
paginateSummons(array) {
|
|
let pageSize = 16
|
|
if (window.innerHeight <= 720) {
|
|
pageSize = 12;
|
|
if (this.has_sponsors) {
|
|
pageSize = 10
|
|
}
|
|
} else if (window.innerHeight <= 1080) {
|
|
if (this.has_sponsors) {
|
|
pageSize = 12
|
|
}
|
|
}
|
|
|
|
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
|
|
},
|
|
paginateRankings(array) {
|
|
let pageSize = 16
|
|
if (window.innerHeight <= 720) {
|
|
pageSize = 12;
|
|
if (this.has_sponsors) {
|
|
pageSize = 10
|
|
}
|
|
} else if (window.innerHeight <= 1080) {
|
|
if (this.has_sponsors) {
|
|
pageSize = 12
|
|
}
|
|
}
|
|
|
|
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.setPrefixTitle()
|
|
}, 15000)
|
|
},
|
|
pageCount() {
|
|
return (this.paginatedMatches?.length || 0) + (this.paginatedGroupStages?.length || 0) + (this.paginatedSummons?.length || 0) + (this.paginatedRankings?.length || 0)
|
|
},
|
|
setPrefixTitle() {
|
|
const summonsLength = this.paginatedSummons?.length || 0;
|
|
const matchesLength = this.paginatedMatches?.length || 0;
|
|
const groupStagesLength = this.paginatedGroupStages?.length || 0;
|
|
|
|
if (this.active < 1 + summonsLength) {
|
|
this.prefixTitle = 'Convocations'
|
|
} else if (this.active < 1 + summonsLength + matchesLength) {
|
|
this.prefixTitle = 'Matchs'
|
|
} else if (this.active < 1 + summonsLength + matchesLength + groupStagesLength) {
|
|
this.prefixTitle = 'Poules'
|
|
} else {
|
|
this.prefixTitle = 'Classement'
|
|
}
|
|
}
|
|
|
|
}" x-init="loop()">
|
|
<header>
|
|
<div id="header">
|
|
<div class="left-content bubble-header">
|
|
<img src="{% static 'tournaments/images/PadelClub_logo_512.png' %}" alt="logo" class="logo">
|
|
<div class="left-margin">
|
|
<h1 class="club">{{ tournament.broadcast_event_display_name }}</h1>
|
|
<h1 class="event"><span x-text="prefixTitle"></span> {{ tournament.broadcast_display_name }}</h1>
|
|
</div >
|
|
</div>
|
|
{% if qr_code_options %}
|
|
<div class="right-content">{% qr_from_text qr_code_url options=qr_code_options %}</div>
|
|
{% endif %}
|
|
</div>
|
|
</header>
|
|
|
|
|
|
<div class="wrapper">
|
|
<main>
|
|
<div class="grid-x">
|
|
|
|
<template x-for="i in (paginatedSummons?.length || 0)">
|
|
<template x-for="column in paginatedSummons[i-1]">
|
|
<div class="cell medium-6 large-6 topblock padding10" x-show="active === i">
|
|
{% include 'tournaments/broadcast/broadcasted_summon.html' %}
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
<template x-for="i in (paginatedMatches?.length || 0)" >
|
|
<template x-for="match in paginatedMatches[i-1]" >
|
|
<div class="cell medium-6 large-3 padding10" x-show="active === i + (paginatedSummons?.length || 0)">
|
|
{% include 'tournaments/broadcast/broadcasted_match.html' %}
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
<template x-for="i in (paginatedGroupStages?.length || 0)">
|
|
<template x-for="group_stage in paginatedGroupStages[i-1]">
|
|
<div class="cell medium-6 large-3 padding10" x-show="active === i + (paginatedSummons?.length || 0) + (paginatedMatches?.length || 0)">
|
|
{% include 'tournaments/broadcast/broadcasted_group_stage.html' %}
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
<template x-for="i in (paginatedRankings?.length || 0)">
|
|
<template x-for="column in paginatedRankings[i-1]">
|
|
<div class="cell medium-6 large-6 topblock padding10" x-show="active === i + (paginatedSummons?.length || 0) + (paginatedMatches?.length || 0) + (paginatedGroupStages?.length || 0)">
|
|
{% include 'tournaments/broadcast/broadcasted_ranking.html' %}
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
|
|
</main>
|
|
</div>
|
|
|
|
</div>
|
|
</body>
|
|
</body>
|
|
|
|
<footer class="footer-broadcast">
|
|
{% if tournament.event.images.exists %}
|
|
<div class="bubble-footer">
|
|
<div class="bubble-sponsor">
|
|
{% for image in tournament.event.images.all %}
|
|
<img src="{{ image.image.url }}" alt="{{ image.title|default:'Sponsor' }}"
|
|
class="sponsor-logo-broadcast">
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</footer>
|
|
|
|
<script>
|
|
console.log('Tournament auto page loaded, tournament ID: {{ tournament.id }}');
|
|
|
|
let startTime = Date.now();
|
|
let lastActive = null;
|
|
let cycleCount = 0;
|
|
let maxPagesSeen = 0;
|
|
let hasNotifiedParent = false;
|
|
|
|
function checkForCompletion() {
|
|
try {
|
|
// Find the Alpine.js element
|
|
const alpineEl = document.querySelector('[x-data]');
|
|
if (!alpineEl || !alpineEl._x_dataStack) {
|
|
console.log('Alpine not ready yet');
|
|
return;
|
|
}
|
|
|
|
const data = alpineEl._x_dataStack[0];
|
|
const currentActive = data.active;
|
|
const pageCount = data.pageCount();
|
|
const elapsed = Date.now() - startTime;
|
|
|
|
if (pageCount === 0) {
|
|
console.log('No pages to display yet');
|
|
return;
|
|
}
|
|
|
|
// Track the maximum page number we've seen
|
|
maxPagesSeen = Math.max(maxPagesSeen, currentActive);
|
|
|
|
console.log(`Current page: ${currentActive}/${pageCount}, Max seen: ${maxPagesSeen}, Elapsed: ${Math.round(elapsed/1000)}s`);
|
|
|
|
let shouldComplete = false;
|
|
let reason = '';
|
|
|
|
// Calculate completion time: 15 seconds per page
|
|
const completionTime = pageCount * 15000; // 15 seconds per page
|
|
|
|
if (pageCount === 1) {
|
|
// Single page tournament: complete after 15 seconds
|
|
if (elapsed >= 15000) {
|
|
shouldComplete = true;
|
|
reason = 'Single page - 15 seconds elapsed';
|
|
}
|
|
} else if (pageCount > 1) {
|
|
// Multi-page tournament: complete when we cycle back to page 1 after seeing all pages
|
|
if (currentActive === 1 && lastActive > 1 && maxPagesSeen >= pageCount) {
|
|
shouldComplete = true;
|
|
reason = 'Multi-page - full cycle completed';
|
|
} else if (elapsed >= completionTime) {
|
|
// Fallback: complete after (pageCount * 15 seconds)
|
|
shouldComplete = true;
|
|
reason = `Multi-page - ${pageCount * 15} seconds elapsed`;
|
|
}
|
|
}
|
|
|
|
if (shouldComplete && !hasNotifiedParent) {
|
|
hasNotifiedParent = true;
|
|
cycleCount++;
|
|
console.log(`🎯 TOURNAMENT COMPLETED! Reason: ${reason}`);
|
|
|
|
// Send message to parent
|
|
if (window.parent !== window) {
|
|
window.parent.postMessage({
|
|
type: 'tournamentCycleComplete',
|
|
cycleCount: cycleCount,
|
|
tournamentId: '{{ tournament.id }}',
|
|
pageCount: pageCount,
|
|
reason: reason,
|
|
elapsedSeconds: Math.round(elapsed/1000)
|
|
}, '*');
|
|
console.log('Message sent to parent window');
|
|
} else {
|
|
console.log('No parent window found');
|
|
}
|
|
}
|
|
|
|
lastActive = currentActive;
|
|
} catch (error) {
|
|
console.error('Error checking completion:', error);
|
|
}
|
|
}
|
|
|
|
// Check every 2 seconds
|
|
setInterval(checkForCompletion, 2000);
|
|
|
|
console.log('Tournament completion detection initialized');
|
|
</script>
|
|
</html>
|
|
|