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.
 
 
 
 
padelclub_backend/tournaments/templates/tournaments/broadcast/broadcasted_auto.html

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>