<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OKEYSİN Tournament</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
</head>
<body>
<div id="particles-js"></div>
<div class="cyber-container">
<h1 class="cyber-title">🏆 OKEYSİN TOURNAMENT 🏆</h1>
<div class="tournament-mode-selector">
<label class="mode-label">
<input type="radio" name="tournamentMode" value="single" checked>
<span><i class="fas fa-user"></i> Tek Katılımcı Modu</span>
</label>
<label class="mode-label">
<input type="radio" name="tournamentMode" value="double">
<span><i class="fas fa-users"></i> Çift Katılımcı Modu</span>
</label>
</div>
<div class="top-menu">
<a href="#" class="cyber-button new-tournament-btn" onclick="resetTournament()">
<i class="fas fa-plus"></i> Yeni Turnuva
</a>
<a href="#" class="cyber-button copy-btn" onclick="copyTournamentData()">
<i class="fas fa-copy"></i> Eşleşmeleri Kopyala
</a>
<a href="#" class="cyber-button next-round-btn" onclick="advanceRound()">
<i class="fas fa-forward"></i> Sonraki Tur
</a>
<a href="#" class="cyber-button history-btn" onclick="toggleHistory()">
<i class="fas fa-history"></i> Geçmiş
</a>
<a href="#" class="cyber-button export-btn" onclick="exportTournamentData()">
<i class="fas fa-download"></i> Dışa Aktar
</a>
</div>
<div class="tournament-panels">
<div class="panel single-tournament-panel" id="singleTournamentPanel">
<div class="input-area-wrapper">
<div class="input-participant-area cyber-card">
<h3><i class="fas fa-user"></i> Tek Katılımcı Turnuvası</h3>
<input type="text" id="adminName" class="nes-input" placeholder="Admin Adı (isteğe bağlı)">
<div class="search-wrapper">
<input type="text" id="singlePlayerInput" class="nes-input" placeholder="Katılımcı Adı">
<input type="text" id="participantSearch" class="nes-input" placeholder="Ara...">
</div>
<a href="#" class="cyber-button" onclick="addSingleParticipant()">
<i class="fas fa-user-plus"></i> Ekle
</a>
</div>
</div>
</div>
<div class="panel double-tournament-panel" id="doubleTournamentPanel" style="display: none;">
<div class="input-area-wrapper">
<div class="input-participant-area cyber-card">
<h3><i class="fas fa-users"></i> Çift Katılımcı Turnuvası</h3>
<input type="text" id="doubleAdminName" class="nes-input" placeholder="Admin Adı (isteğe bağlı)">
<div class="search-wrapper">
<input type="text" id="playerInput" class="nes-input" placeholder="Katılımcı Ekle (2 isim)">
<input type="text" id="doubleParticipantSearch" class="nes-input" placeholder="Ara...">
</div>
<a href="#" class="cyber-button" onclick="addDoubleParticipant()">
<i class="fas fa-users"></i> Ekle
</a>
</div>
</div>
</div>
<div class="participant-list-area cyber-card bordered-area">
<h4 onclick="toggleParticipantList()" style="cursor: pointer;">
<i class="fas fa-users"></i> Katılımcı Listesi (<span id="participantCount">0</span>)
</h4>
<div id="participantList" class="participant-list" style="display: none;"></div>
</div>
<div class="tournament-stats cyber-card">
<h3><i class="fas fa-chart-bar"></i> Turnuva İstatistikleri</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Toplam Turnuva</span>
<span id="totalTournaments">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Aktif Tur</span>
<span id="currentRoundStat">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Katılımcı Sayısı</span>
<span id="totalParticipants">0</span>
</div>
</div>
<canvas id="statsChart"></canvas>
</div>
<div class="tournament-controls">
<button id="startTournamentBtn" class="cyber-button next-round-btn" onclick="startTournament()">
<i class="fas fa-play"></i> Turnuvayı Başlat
</button>
</div>
</div>
<div id="matchesContainer" class="matches-container">
<div id="tournamentContainer" class="tournament-matches"></div>
</div>
<div class="right-side-wrapper">
<div class="special-message-area cyber-card">
<h3><i class="fas fa-comment"></i> Özel Mesaj</h3>
<textarea id="specialMessage" class="nes-textarea" placeholder="Özel mesajınızı buraya girin (isteğe bağlı)"></textarea>
</div>
<div class="notification-area cyber-card">
<h3><i class="fas fa-bell"></i> Bildirimler</h3>
<div class="notification-filters">
<button class="filter-btn active" data-filter="all">Tümü</button>
<button class="filter-btn" data-filter="system">Sistem</button>
<button class="filter-btn" data-filter="match">Maç</button>
</div>
<div id="notificationList" class="notification-list"></div>
</div>
</div>
<div id="tournamentResultsArea" class="cyber-card bordered-area" style="display: none;">
<h3>🏆 Turnuva Sonuçları 🏆</h3>
<p><b><i class="fas fa-trophy"></i> Şampiyon:</b> <span id="tournamentChampion"></span></p>
<p><b><i class="fas fa-info-circle"></i> Turnuva Durumu:</b> <span id="tournamentStatus"></span></p>
<p><b><i class="fas fa-clock"></i> Başlangıç Zamanı:</b> <span id="tournamentDateTime"></span></p>
<p><b><i class="fas fa-flag-checkered"></i> Bitiş Zamanı:</b> <span id="tournamentEndTime"></span></p>
<p><b><i class="fas fa-user"></i> Admin Adı:</b> <span id="tournamentAdmin"></span></p>
</div>
<div id="tournamentHistory" class="cyber-card bordered-area" style="display: none;">
<h3><i class="fas fa-history"></i> Turnuva Geçmişi</h3>
<div id="historyList" class="history-list"></div>
</div>
</div>
<script src="{{ url_for('static', filename='script.js') }}"></script>
</body>
</html>
/* Ana Tema Renkleri */
:root {
--primary-color: #00bfff;
--secondary-color: #004d99;
--text-color: #ffffff;
--border-color: #0066cc;
--neon-glow: 0 0 10px rgba(0, 191, 255, 0.5),
0 0 20px rgba(0, 191, 255, 0.3),
0 0 30px rgba(0, 191, 255, 0.1);
}
/* Genel Ayarlar */
body {
background: linear-gradient(45deg, #000000, #001a33);
color: var(--text-color);
font-family: 'Courier New', monospace;
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
/* Partiküller için Arka Plan */
#particles-js {
position: fixed;
width: 100%;
height: 100%;
z-index: -1;
}
/* Ana Konteyner */
.cyber-container {
width: 95%;
max-width: 1200px;
margin: 20px auto;
padding: 20px;
border-radius: 15px;
box-shadow: var(--neon-glow);
background: rgba(0, 10, 20, 0.95);
backdrop-filter: blur(10px);
border: 2px solid var(--border-color);
display: flex;
flex-direction: column;
gap: 20px;
}
/* Başlık */
.cyber-title {
color: var(--primary-color);
text-shadow: var(--neon-glow);
animation: neon-pulse 2s ease-in-out infinite alternate;
font-size: 2.5em;
text-align: center;
margin: 0;
padding: 20px;
border: 2px solid var(--border-color);
border-radius: 10px;
background: rgba(0, 20, 40, 0.8);
}
/* Turnuva Panel Stilleri */
.tournament-panels {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
.panel {
background: rgba(0, 20, 40, 0.8);
border: 1px solid var(--border-color);
border-radius: 10px;
padding: 15px;
transition: all 0.3s ease;
}
.panel:hover {
box-shadow: var(--neon-glow);
}
/* Eşleşme Alanı */
.matches-container {
margin: 20px 0;
padding: 15px;
border: 2px solid var(--border-color);
border-radius: 10px;
background: rgba(0, 20, 40, 0.8);
}
.match-card {
background: rgba(0, 15, 30, 0.9);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 15px;
margin: 10px auto;
max-width: 500px;
display: grid;
grid-template-columns: 2fr 1fr 2fr;
gap: 10px;
align-items: center;
transition: all 0.3s ease;
box-shadow: 0 0 20px rgba(0, 77, 153, 0.2);
}
.match-card:hover {
transform: translateY(-2px);
box-shadow: var(--neon-glow);
border-color: var(--primary-color);
}
.player-vs {
background: rgba(0, 25, 50, 0.8);
padding: 8px;
border-radius: 5px;
text-align: center;
border: 1px solid var(--border-color);
transition: all 0.3s ease;
}
.vs-text-area {
text-align: center;
font-size: 0.9em;
color: var(--text-color);
}
.match-controls {
grid-column: 1 / -1;
text-align: center;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.winner-select {
background: rgba(0, 25, 50, 0.8);
border: 1px solid var(--border-color);
color: var(--text-color);
padding: 8px;
border-radius: 5px;
width: 100%;
max-width: 300px;
cursor: pointer;
transition: all 0.3s ease;
flex: 1;
}
.winner-select:hover {
border-color: var(--primary-color);
box-shadow: 0 0 10px rgba(0, 191, 255, 0.2);
}
/* Tur Konteyneri */
.round-container {
margin-bottom: 30px;
padding: 15px;
border: 1px solid var(--border-color);
border-radius: 10px;
background: rgba(0, 20, 40, 0.8);
}
.round-container h2 {
text-align: center;
color: var(--primary-color);
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid var(--border-color);
}
/* Butonlar */
.cyber-button {
background: rgba(0, 25, 50, 0.8);
color: var(--primary-color);
border: 2px solid var(--primary-color);
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: bold;
text-shadow: 0 0 10px rgba(0, 191, 255, 0.5);
position: relative;
overflow: hidden;
display: inline-flex;
align-items: center;
gap: 8px;
}
.cyber-button:hover {
background: rgba(0, 35, 70, 0.9);
box-shadow: var(--neon-glow);
transform: translateY(-2px);
}
.cyber-button::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border-radius: 8px;
background: linear-gradient(45deg, var(--primary-color), transparent);
z-index: -1;
animation: border-flow 3s linear infinite;
}
.cyber-button i {
margin-right: 5px;
}
/* Katılımcı Listesi */
.participant-list {
max-height: 300px;
overflow-y: auto;
padding: 10px;
}
.participant-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px;
margin: 5px 0;
background: rgba(0, 25, 50, 0.8);
border: 1px solid var(--border-color);
border-radius: 5px;
transition: all 0.3s ease;
}
.participant-item:hover {
background: rgba(0, 35, 70, 0.9);
border-color: var(--primary-color);
}
/* Form Elementleri */
.nes-input,
.nes-textarea {
border: 2px solid var(--border-color);
color: var(--text-color);
background: rgba(0, 10, 20, 0.95);
padding: 10px;
border-radius: 8px;
font-family: 'Courier New', monospace;
margin-bottom: 10px;
transition: all 0.3s ease;
}
.nes-input:focus,
.nes-textarea:focus {
border-color: var(--primary-color);
box-shadow: 0 0 15px rgba(0, 77, 153, 0.5);
outline: none;
}
/* Responsive */
@media (max-width: 768px) {
.cyber-container {
padding: 10px;
margin: 10px;
}
.match-card {
grid-template-columns: 1fr;
text-align: center;
}
.vs-text-area {
margin: 10px 0;
}
}
/* Animasyonlar */
@keyframes neon-pulse {
from {
text-shadow: 0 0 10px var(--primary-color),
0 0 20px var(--primary-color),
0 0 30px var(--primary-color);
}
to {
text-shadow: 0 0 15px var(--primary-color),
0 0 25px var(--primary-color),
0 0 35px var(--primary-color);
}
}
@keyframes border-flow {
0% {
background-position: 0% 0%;
}
100% {
background-position: 200% 0%;
}
}
/* Mod Seçici */
.tournament-mode-selector {
display: flex;
justify-content: center;
gap: 20px;
margin-bottom: 20px;
padding: 15px;
border: 1px solid var(--border-color);
border-radius: 10px;
background: rgba(0, 30, 60, 0.5);
}
.mode-label {
color: var(--primary-color);
cursor: pointer;
padding: 10px 20px;
border: 2px solid var(--primary-color);
border-radius: 8px;
transition: all 0.3s ease;
display: flex;
align-items: center;
background: rgba(0, 0, 0, 0.8);
}
.mode-label:hover {
background: rgba(0, 191, 255, 0.1);
box-shadow: var(--neon-glow);
transform: translateY(-2px);
}
.mode-label input[type="radio"] {
margin-right: 8px;
}
.mode-label input[type="radio"]:checked + span {
color: #000;
background: var(--primary-color);
padding: 2px 8px;
border-radius: 4px;
}
/* Tournament Stats Styles */
.tournament-stats {
margin-top: 20px;
border: 2px solid var(--border-color);
border-radius: 10px;
padding: 15px;
background: rgba(0, 20, 40, 0.8);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
padding: 10px;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 10px;
border: 1px solid var(--border-color);
border-radius: 8px;
background: rgba(0, 30, 60, 0.5);
transition: all 0.3s ease;
}
.stat-item:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 77, 153, 0.3);
}
.stat-label {
font-size: 0.9em;
color: var(--primary-color);
margin-bottom: 5px;
}
/* Notification Filters */
.notification-filters {
display: flex;
gap: 10px;
margin-bottom: 10px;
padding: 10px;
border: 1px solid var(--border-color);
border-radius: 8px;
background: rgba(0, 20, 40, 0.8);
}
.filter-btn {
background: transparent;
border: 1px solid var(--border-color);
color: var(--primary-color);
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-btn:hover {
background: rgba(0, 77, 153, 0.3);
border-color: var(--primary-color);
}
.filter-btn.active {
background: var(--border-color);
color: var(--primary-color);
border-color: var(--primary-color);
}
/* Tournament History */
.history-list {
max-height: 300px;
overflow-y: auto;
padding: 10px;
border: 1px solid var(--border-color);
border-radius: 8px;
background: rgba(0, 20, 40, 0.8);
}
.history-item {
border-bottom: 1px solid var(--border-color);
padding: 10px;
margin-bottom: 10px;
transition: all 0.3s ease;
}
.history-item:hover {
background: rgba(0, 30, 60, 0.5);
}
.history-item:last-child {
border-bottom: none;
}
.history-item h4 {
color: var(--primary-color);
margin: 0 0 5px 0;
text-shadow: 0 0 10px rgba(0, 191, 255, 0.5);
}
.history-item p {
margin: 5px 0;
font-size: 0.9em;
color: rgba(0, 191, 255, 0.8);
}
/* Responsive enhancements */
@media (max-width: 768px) {
.tournament-mode-selector {
flex-direction: column;
align-items: center;
}
.stats-grid {
grid-template-columns: 1fr;
}
.notification-filters {
flex-wrap: wrap;
justify-content: center;
}
.search-wrapper {
flex-direction: column;
}
.match-card {
margin: 10px;
}
}
/* Popup Mesajları */
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
}
.toast {
background: rgba(0, 10, 20, 0.95);
color: var(--primary-color);
border: 1px solid var(--primary-color);
border-radius: 8px;
padding: 15px 25px;
margin-bottom: 10px;
box-shadow: var(--neon-glow);
animation: slide-in 0.3s ease-out;
display: flex;
align-items: center;
gap: 10px;
}
@keyframes slide-in {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
/* Arama alanı stilleri */
.search-wrapper {
display: flex;
gap: 10px;
margin-bottom: 10px;
}
.search-wrapper .nes-input {
flex: 1;
}
/* İstatistik grafiği stilleri */
#statsChart {
margin-top: 20px;
background: rgba(0, 10, 20, 0.8);
border-radius: 8px;
padding: 10px;
border: 1px solid var(--border-color);
}
/* Bildirim alanı güncellemeleri */
.notification-item {
padding: 8px;
margin: 5px 0;
border-radius: 5px;
background: rgba(0, 20, 40, 0.8);
border: 1px solid var(--border-color);
transition: all 0.3s ease;
}
.notification-item:hover {
background: rgba(0, 30, 60, 0.9);
border-color: var(--primary-color);
}
/* Buton güncellemeleri */
.participant-delete-btn {
background: rgba(255, 0, 0, 0.2);
border: 1px solid #ff0000;
color: #ff0000;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.participant-delete-btn:hover {
background: rgba(255, 0, 0, 0.4);
box-shadow: 0 0 10px rgba(255, 0, 0, 0.4);
}
/* Kopyalama butonu stili */
.copy-match-btn {
margin-left: 10px;
padding: 8px 15px;
font-size: 0.9em;
background: rgba(0, 25, 50, 0.8);
}
// Tek katılımcı modu değişkenleri
let singleParticipants = [];
let singleTournamentData = [];
let singleCurrentRound = 0;
let singleTotalRounds = 0;
let singleTournamentStartTime;
let singleTournamentEndTime;
let singleAdminName = "";
// Çift katılımcı modu değişkenleri
let doubleParticipants = [];
let doubleTournamentData = [];
let doubleCurrentRound = 0;
let doubleTotalRounds = 0;
let doubleTournamentStartTime;
let doubleTournamentEndTime;
let doubleAdminName = "";
// Ortak değişkenler
let tournamentMode = "single";
let notifications = [];
let singleTournamentHistory = [];
let doubleTournamentHistory = [];
// Sayfa yüklendiğinde
$(document).ready(function() {
// Mod seçimi değiştiğinde
$('input[name="tournamentMode"]').change(function() {
tournamentMode = $(this).val();
toggleTournamentPanels();
resetTournament(); // Mod değiştiğinde sıfırla
});
// Enter tuşu ile katılımcı ekleme
$('#singlePlayerInput').on('keypress', function(e) {
if (e.which === 13) addSingleParticipant();
});
$('#playerInput').on('keypress', function(e) {
if (e.which === 13) addDoubleParticipant();
});
// Arama inputları
$('#participantSearch').on('input', function() {
searchParticipants($(this).val(), 'single');
});
$('#doubleParticipantSearch').on('input', function() {
searchParticipants($(this).val(), 'double');
});
// Bildirim filtresi
$('.filter-btn').click(function() {
$('.filter-btn').removeClass('active');
$(this).addClass('active');
filterNotifications($(this).data('filter'));
});
// Başlangıç yüklemeleri
loadTournamentHistory();
updateStats();
initializeParticles();
// Katılımcı listesini göster
toggleParticipantList();
});
// Panel değiştirme
function toggleTournamentPanels() {
if (tournamentMode === "single") {
$('#singleTournamentPanel').show();
$('#doubleTournamentPanel').hide();
renderParticipantList('single');
} else {
$('#singleTournamentPanel').hide();
$('#doubleTournamentPanel').show();
renderParticipantList('double');
}
updateStats();
}
// Katılımcı listesini göster/gizle
function toggleParticipantList() {
$('#participantList').slideToggle();
}
// Tek katılımcı ekleme
function addSingleParticipant() {
const inputVal = $('#singlePlayerInput').val().trim();
if (!inputVal) return;
if (singleParticipants.includes(inputVal)) {
showToast('⚠️ Bu katılımcı zaten eklendi!', 'warning');
return;
}
singleParticipants.push(inputVal);
$('#singlePlayerInput').val('');
renderParticipantList('single');
updateStats();
showToast('✅ Katılımcı eklendi', 'success');
}
// Çift katılımcı ekleme
function addDoubleParticipant() {
const inputVal = $('#playerInput').val().trim();
if (!inputVal) return;
const teamNames = inputVal.split(' ').filter(name => name.trim() !== '');
if (teamNames.length !== 2) {
showToast('⚠️ Lütfen 2 katılımcı ismi (boşlukla ayrılmış) girin!', 'warning');
return;
}
const teamName = `${teamNames[0]} & ${teamNames[1]}`;
if (doubleParticipants.includes(teamName)) {
showToast('⚠️ Bu takım zaten eklendi!', 'warning');
return;
}
doubleParticipants.push(teamName);
$('#playerInput').val('');
renderParticipantList('double');
updateStats();
showToast('✅ Takım eklendi', 'success');
}
// Katılımcı listesini güncelle
function renderParticipantList(mode, filteredList = null) {
const participants = mode === 'single' ? singleParticipants : doubleParticipants;
const listToRender = filteredList || participants;
$('#participantCount').text(listToRender.length);
$('#participantList').html(listToRender.map((name, index) => `
<div class="participant-item">
<span>
<i class="fas fa-${mode === 'single' ? 'user' : 'users'}"></i>
${name}
</span>
<button class="participant-delete-btn" onclick="deleteParticipant(${index}, '${mode}')">
<i class="fas fa-trash"></i> Sil
</button>
</div>
`).join(''));
}
// Katılımcı silme
function deleteParticipant(index, mode) {
const participants = mode === 'single' ? singleParticipants : doubleParticipants;
const deletedParticipant = participants.splice(index, 1)[0];
renderParticipantList(mode);
updateStats();
showToast(`🗑️ ${deletedParticipant} silindi`, 'info');
}
// Turnuvayı başlat
function startTournament() {
const mode = tournamentMode;
const participants = mode === 'single' ? singleParticipants : doubleParticipants;
const minParticipants = mode === 'single' ? 2 : 4;
if (participants.length < minParticipants) {
showToast(`❌ En az ${minParticipants} katılımcı gereklidir!`, 'error');
return;
}
if (mode === 'single') {
singleCurrentRound = 1;
singleTournamentData = [];
singleTotalRounds = Math.ceil(Math.log2(participants.length));
singleTournamentStartTime = new Date();
singleAdminName = $('#adminName').val().trim();
generateRound(shuffleArray([participants]), 'single');
} else {
doubleCurrentRound = 1;
doubleTournamentData = [];
doubleTotalRounds = Math.ceil(Math.log2(participants.length));
doubleTournamentStartTime = new Date();
doubleAdminName = $('#doubleAdminName').val().trim();
generateRound(shuffleArray([participants]), 'double');
}
renderTournament();
updateStats();
showToast('🎮 Turnuva başladı!', 'success');
$('#startTournamentBtn').hide();
}
// Turnuvayı sıfırla
function resetTournament() {
if (tournamentMode === 'single') {
singleParticipants = [];
singleTournamentData = [];
singleCurrentRound = 0;
singleTotalRounds = 0;
singleTournamentStartTime = null;
singleTournamentEndTime = null;
singleAdminName = "";
} else {
doubleParticipants = [];
doubleTournamentData = [];
doubleCurrentRound = 0;
doubleTotalRounds = 0;
doubleTournamentStartTime = null;
doubleTournamentEndTime = null;
doubleAdminName = "";
}
// UI sıfırlama
$('#participantList').empty();
$('#tournamentContainer').empty();
$('#tournamentResultsArea').hide();
$('#startTournamentBtn').show();
// Input alanlarını temizle
if (tournamentMode === 'single') {
$('#singlePlayerInput').val('');
$('#adminName').val('');
} else {
$('#playerInput').val('');
$('#doubleAdminName').val('');
}
$('#specialMessage').val('');
// Listeleri ve istatistikleri güncelle
renderParticipantList(tournamentMode);
updateStats();
showToast('🔄 Turnuva sıfırlandı', 'info');
}
// Maç turunu oluştur
function generateRound(players, mode) {
const needed = Math.pow(2, Math.ceil(Math.log2(players.length)));
while (players.length < needed) players.push('Bay');
players = shuffleArray(players);
const round = {
number: mode === 'single' ? singleCurrentRound : doubleCurrentRound,
matches: []
};
for (let i = 0; i < players.length; i += 2) {
round.matches.push({
id: `${mode}-round-${round.number}-match-${i / 2}`,
player1: players[i],
player2: players[i + 1],
winner: null,
});
}
if (mode === 'single') {
singleTournamentData.push(round);
} else {
doubleTournamentData.push(round);
}
}
// Toast mesajı göster
function showToast(message, type = 'info') {
const icons = {
success: '✅',
error: '❌',
warning: '⚠️',
info: 'ℹ️'
};
const toast = $(`
<div class="toast ${type}">
<span class="toast-icon">${icons[type]}</span>
<span class="toast-message">${message}</span>
</div>
`);
$('.toast-container').length || $('body').append('<div class="toast-container"></div>');
$('.toast-container').append(toast);
setTimeout(() => {
toast.animate({ opacity: 0, marginRight: '-100%' }, 300, () => {
toast.remove();
});
}, 3000);
}
// Eşleşme kopyalama fonksiyonu
function copyMatchWithMessage(matchId) {
const match = findMatch(matchId);
if (!match) return;
const specialMessage = $('#specialMessage').val().trim();
const matchText = `${match.player1} VS ${match.player2}\n${specialMessage}`;
navigator.clipboard.writeText(matchText).then(() => {
showToast('✅ Eşleşme kopyalandı!', 'success');
}).catch(() => {
showToast('❌ Kopyalama başarısız!', 'error');
});
}
function findMatch(matchId) {
const tournamentData = tournamentMode === 'single' ? singleTournamentData : doubleTournamentData;
for (const round of tournamentData) {
const match = round.matches.find(m => m.id === matchId);
if (match) return match;
}
return null;
}
function renderTournament() {
const container = $('#tournamentContainer');
container.empty();
const tournamentData = tournamentMode === 'single' ? singleTournamentData : doubleTournamentData;
const currentRound = tournamentMode === 'single' ? singleCurrentRound : doubleCurrentRound;
for (let i = 0; i < tournamentData.length; i++) {
const round = tournamentData[i];
const roundDiv = $(`
<div class="round-container">
<h2><i class="fas fa-trophy"></i> ${round.number}. Tur</h2>
<div class="match-list" id="round-${round.number}-matches"></div>
</div>`);
round.matches.forEach(match => {
const matchCard = $(`
<div class="match-card" id="match-${match.id}">
<div class="player-vs">
<i class="fas fa-${tournamentMode === 'single' ? 'user' : 'users'}"></i> ${match.player1}
</div>
<div class="vs-text-area">
<i class="fas fa-gamepad"></i>
>>>>>VS<<<<<
${$('#specialMessage').val().trim()}
</div>
<div class="player-vs">
<i class="fas fa-${tournamentMode === 'single' ? 'user' : 'users'}"></i> ${match.player2}
</div>
<div class="match-controls">
<select class="winner-select" data-match-id="${match.id}" onchange="setWinner(this)">
<option value="">Kazananı Seç</option>
<option value="${match.player1}">${match.player1}</option>
<option value="${match.player2}">${match.player2}</option>
</select>
<button class="cyber-button copy-match-btn" onclick="copyMatchWithMessage('${match.id}')">
<i class="fas fa-copy"></i> Kopyala
</button>
</div>
</div>
`);
roundDiv.find('.match-list').append(matchCard);
});
container.append(roundDiv);
}
}
// Tournament history
function saveTournamentHistory() {
const mode = tournamentMode;
const tournament = {
id: Date.now(),
mode: mode,
startTime: mode === 'single' ? singleTournamentStartTime : doubleTournamentStartTime,
endTime: mode === 'single' ? singleTournamentEndTime : doubleTournamentEndTime,
champion: $('#tournamentChampion').text(),
participants: mode === 'single' ? [singleParticipants] : [doubleParticipants],
adminName: mode === 'single' ? singleAdminName : doubleAdminName
};
if (mode === 'single') {
singleTournamentHistory.push(tournament);
localStorage.setItem('singleTournamentHistory', JSON.stringify(singleTournamentHistory));
} else {
doubleTournamentHistory.push(tournament);
localStorage.setItem('doubleTournamentHistory', JSON.stringify(doubleTournamentHistory));
}
updateStats();
}
function loadTournamentHistory() {
const singleHistory = localStorage.getItem('singleTournamentHistory');
const doubleHistory = localStorage.getItem('doubleTournamentHistory');
if (singleHistory) {
singleTournamentHistory = JSON.parse(singleHistory);
}
if (doubleHistory) {
doubleTournamentHistory = JSON.parse(doubleHistory);
}
renderTournamentHistory();
updateStats();
}
function renderTournamentHistory() {
const historyList = $('#historyList');
historyList.empty();
const currentHistory = tournamentMode === 'single' ? singleTournamentHistory : doubleTournamentHistory;
currentHistory.reverse().forEach(tournament => {
const historyItem = $(`
<div class="history-item">
<h4>${tournament.mode === 'single' ? 'Tek' : 'Çift'} Katılımcı Turnuvası</h4>
<p><i class="fas fa-trophy"></i> Şampiyon: ${tournament.champion}</p>
<p><i class="fas fa-calendar"></i> Tarih: ${new Date(tournament.startTime).toLocaleDateString()}</p>
<p><i class="fas fa-user"></i> Admin: ${tournament.adminName || 'Belirtilmedi'}</p>
<p><i class="fas fa-users"></i> Katılımcı Sayısı: ${tournament.participants.length}</p>
</div>
`);
historyList.append(historyItem);
});
}
function toggleHistory() {
$('#tournamentHistory').slideToggle();
}
// İstatistikleri güncelle
function updateStats() {
const currentHistory = tournamentMode === 'single' ? singleTournamentHistory : doubleTournamentHistory;
const currentParticipants = tournamentMode === 'single' ? singleParticipants : doubleParticipants;
const currentRound = tournamentMode === 'single' ? singleCurrentRound : doubleCurrentRound;
$('#totalTournaments').text(currentHistory.length);
$('#currentRoundStat').text(currentRound);
$('#totalParticipants').text(currentParticipants.length);
$('#participantCount').text(currentParticipants.length);
updateStatsChart();
}
// When tournament ends
function endTournament(winner) {
const mode = tournamentMode;
if (mode === 'single') {
singleTournamentEndTime = new Date();
} else {
doubleTournamentEndTime = new Date();
}
$('#tournamentChampion').text(winner);
$('#tournamentStatus').text("Tamamlandı");
$('#tournamentEndTime').text((mode === 'single' ? singleTournamentEndTime : doubleTournamentEndTime).toLocaleTimeString());
$('#tournamentDateTime').text((mode === 'single' ? singleTournamentStartTime : doubleTournamentStartTime).toLocaleString());
$('#tournamentAdmin').text(mode === 'single' ? singleAdminName : doubleAdminName);
$('#tournamentResultsArea').show();
addNotification(`Turnuva tamamlandı! Şampiyon: ${winner}`, 'system');
saveTournamentHistory();
updateStats();
}
// Bildirimleri filtrele ve göster
function filterNotifications(filter) {
const notificationList = $('#notificationList');
notificationList.empty();
const filteredNotifications = filter === 'all'
? notifications
: notifications.filter(n => n.type === filter);
filteredNotifications.slice(-5).reverse().forEach(notif => {
const notifDiv = $(`
<div class="notification-item ${notif.type}">
${notif.message}
<span class="notification-time">(${formatTime(notif.timestamp)})</span>
</div>
`);
notificationList.prepend(notifDiv);
});
}
// Yardımcı fonksiyonlar
function formatTime(date) {
return date.toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' });
}
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
// particles.js başlatma kodunu güncelleyelim
function initializeParticles() {
particlesJS('particles-js', {
particles: {
number: {
value: 80,
density: {
enable: true,
value_area: 800
}
},
color: {
value: '#00ff00'
},
shape: {
type: 'circle',
stroke: {
width: 0,
color: '#000000'
},
polygon: {
nb_sides: 5
}
},
opacity: {
value: 0.7,
random: true,
anim: {
enable: true,
speed: 1,
opacity_min: 0.1,
sync: false
}
},
size: {
value: 3,
random: true,
anim: {
enable: false,
speed: 4,
size_min: 0.3,
sync: false
}
},
line_linked: {
enable: false
},
move: {
enable: true,
speed: 1,
direction: 'none',
random: true,
straight: false,
out_mode: 'out',
bounce: false,
attract: {
enable: false,
rotateX: 600,
rotateY: 1200
}
}
},
interactivity: {
detect_on: 'canvas',
events: {
onhover: {
enable: true,
mode: 'bubble'
},
onclick: {
enable: true,
mode: 'push'
},
resize: true
},
modes: {
bubble: {
distance: 83.91608391608392,
size: 6,
duration: 1,
opacity: 0.8,
speed: 3
},
push: {
particles_nb: 4
}
}
},
retina_detect: true
});
}
// Add notification function
function addNotification(message, type = 'user') {
const timestamp = new Date();
notifications.push({ message, type, timestamp });
filterNotifications('all'); // Update notifications display
}
function setWinner(selectElement) {
const winner = selectElement.value;
const matchId = selectElement.getAttribute('data-match-id');
const mode = tournamentMode;
const tournamentData = mode === 'single' ? singleTournamentData : doubleTournamentData;
const roundIndex = mode === 'single' ? singleCurrentRound -1 : doubleCurrentRound -1;
const match = tournamentData[roundIndex].matches.find(m => m.id === matchId);
if (roundIndex >= 0 && roundIndex < tournamentData.length) {
const matchIndex = tournamentData[roundIndex].matches.findIndex(m => m.id === matchId);
if (matchIndex !== -1) {
tournamentData[roundIndex].matches[matchIndex].winner = winner;
addNotification(`${match.player1} vs ${match.player2} maçının kazananı: ${winner}`, 'match');
if (checkRoundCompletion(mode)) {
advanceRound(mode);
}
}
}
}
function checkRoundCompletion(mode) {
const tournamentData = mode === 'single' ? singleTournamentData : doubleTournamentData;
const roundIndex = mode === 'single' ? singleCurrentRound - 1 : doubleCurrentRound - 1;
if (roundIndex >= 0 && roundIndex < tournamentData.length) {
return tournamentData[roundIndex].matches.every(m => m.winner);
}
return false;
}
function advanceRound(mode) {
const tournamentData = mode === 'single' ? singleTournamentData : doubleTournamentData;
const winners = tournamentData[mode === 'single' ? singleCurrentRound - 1 : doubleCurrentRound - 1].matches
.map(m => m.winner)
.filter(Boolean)
.filter(w => w !== 'Bay');
if (winners.length <= 1) {
endTournament(winners[0]);
return;
}
if (mode === 'single') {
singleCurrentRound++;
} else {
doubleCurrentRound++;
}
generateRound(winners, mode);
renderTournament();
addNotification(`${tournamentMode === 'single' ? singleCurrentRound : doubleCurrentRound}. Tur başladı!`, 'system');
updateStats();
}
// Katılımcı arama fonksiyonu
function searchParticipants(searchTerm, mode) {
const participants = mode === 'single' ? singleParticipants : doubleParticipants;
const filteredParticipants = participants.filter(p =>
p.toLowerCase().includes(searchTerm.toLowerCase())
);
renderParticipantList(mode, filteredParticipants);
}
// İstatistik grafiği oluşturma
function updateStatsChart() {
const ctx = document.getElementById('statsChart').getContext('2d');
// Mevcut grafik varsa yok et
if (window.statsChart) {
window.statsChart.destroy();
}
const currentParticipants = tournamentMode === 'single' ? singleParticipants : doubleParticipants;
const data = {
labels: ['Toplam Turnuva', 'Aktif Tur', 'Katılımcı Sayısı'],
datasets: [{
label: 'Turnuva İstatistikleri',
data: [
(tournamentMode === 'single' ? singleTournamentHistory : doubleTournamentHistory).length,
tournamentMode === 'single' ? singleCurrentRound : doubleCurrentRound,
currentParticipants.length
],
backgroundColor: [
'rgba(0, 255, 0, 0.2)',
'rgba(0, 191, 255, 0.2)',
'rgba(255, 0, 255, 0.2)'
],
borderColor: [
'rgba(0, 255, 0, 1)',
'rgba(0, 191, 255, 1)',
'rgba(255, 0, 255, 1)'
],
borderWidth: 1
}]
};
window.statsChart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 255, 0, 0.1)'
},
ticks: {
color: '#00FF00'
}
},
x: {
grid: {
color: 'rgba(0, 255, 0, 0.1)'
},
ticks: {
color: '#00FF00'
}
}
},
plugins: {
legend: {
labels: {
color: '#00FF00'
}
}
}
}
});
}
// Turnuva verilerini dışa aktarma
function exportTournamentData() {
const exportData = {
tournamentMode,
participants: tournamentMode === 'single' ? singleParticipants : doubleParticipants,
currentRound: tournamentMode === 'single' ? singleCurrentRound : doubleCurrentRound,
tournamentData: tournamentMode === 'single' ? singleTournamentData : doubleTournamentData,
startTime: tournamentMode === 'single' ? singleTournamentStartTime : doubleTournamentStartTime,
endTime: tournamentMode === 'single' ? singleTournamentEndTime : doubleTournamentEndTime,
adminName: tournamentMode === 'single' ? singleAdminName : doubleAdminName,
champion: $('#tournamentChampion').text()
};
const dataStr = JSON.stringify(exportData, null, 2);
const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
const exportFileDefaultName = `tournament_${new Date().toISOString().slice(0,10)}.json`;
const linkElement = document.createElement('a');
linkElement.setAttribute('href', dataUri);
linkElement.setAttribute('download', exportFileDefaultName);
linkElement.click();
showToast('✅ Turnuva verileri dışa aktarıldı!');
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.