mtg-playerinfo 1.4.2 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/update-test-data.yml +2 -0
- package/package.json +5 -5
- package/scripts/update-test-data.js +3 -2
- package/src/fetchers/topdeck.js +14 -10
- package/src/fetchers/untapped.js +2 -1
- package/test/data/melee.html +52 -48
- package/test/data/mtgElo.html +3 -3
- package/test/data/topdeck.html +7 -639
- package/test/data/topdeck.json +1 -1
- package/test/data/unityLeague.html +664 -24
- package/test/data/untapped.json +1 -1
- package/test/melee.test.js +1 -1
- package/test/mtgElo.test.js +1 -1
- package/test/topdeck.test.js +5 -3
- package/test/unityLeague.test.js +1 -1
- package/test/untapped.test.js +33 -1
- /package/{test → test_utils}/helpers.js +0 -0
package/test/data/topdeck.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<meta name="player-id" content="m4VSTJShiXR1PCSCWaM9TBY0rcg1"/><!DOCTYPE html><html lang="en" data-bs-theme="dark"><head><meta charset="utf-8"><title>Björn Kimminich - Profile</title><!-- SEO Meta Tags--><meta name="description" content="Björn Kimminich's tournament profile and stats"><meta name="keywords" content="magic, magic the gathering, cedh, edh, competitive, commander, events, tournament, software, pairing software"><meta name="author" content="Zain Nayer"><!-- Viewport--><meta name="viewport" content="width=device-width, initial-scale=1"><!-- PWA meta tags--><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="apple-mobile-web-app-title" content="TopDeck.gg"><!-- Font Awesome - Async load to prevent render blocking--><link rel="preconnect" href="https://kit.fontawesome.com" crossorigin><link rel="preconnect" href="https://ka-f.fontawesome.com" crossorigin><script src="https://kit.fontawesome.com/3df2a3da01.js" crossorigin="anonymous" async></script><!-- Manifest--><link rel="manifest" href="/manifest.json"><!-- Apple App Store Banner--><meta name="apple-itunes-app" content="app-id=6581480935"><!-- Favicon and Touch Icons--><link rel="apple-touch-icon" sizes="192x192" href="/icons/192x192.png"><link rel="icon" type="image/png" sizes="32x32" href="/topdeck-favicon/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/topdeck-favicon/favicon-16x16.png"><!-- Meta Tags Media--><meta name="theme-color" content="#6ca6ea"><meta name="og:title" content="Björn Kimminich - Profile"><meta name="og:description" content="Björn Kimminich's tournament profile and stats"><meta property="og:image" content="https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/aa6d70ad-de73-4c09-a4d7-1e64d5ed6d00/cover"><meta name="twitter:title" content="Björn Kimminich - Profile"><meta property="twitter:image" content="https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/aa6d70ad-de73-4c09-a4d7-1e64d5ed6d00/cover"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@TopDeckGG_"><!-- Global site tag (gtag.js) - Google Analytics--><script async="" src="https://www.googletagmanager.com/gtag/js?id=G-56527VG23P"></script><script>window.dataLayer = window.dataLayer || [];
|
|
1
|
+
<meta name="player-id" content="m4VSTJShiXR1PCSCWaM9TBY0rcg1"/><!DOCTYPE html><html lang="en" data-bs-theme="dark"><head><meta charset="utf-8"><title>Björn Kimminich - Profile</title><!-- SEO Meta Tags--><meta name="description" content="Björn Kimminich's tournament profile and stats"><meta name="keywords" content="magic, magic the gathering, cedh, edh, competitive, commander, events, tournament, software, pairing software"><meta name="author" content="Zain Nayer"><!-- Viewport--><meta name="viewport" content="width=device-width, initial-scale=1"><!-- PWA meta tags--><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="apple-mobile-web-app-title" content="TopDeck.gg"><!-- Font Awesome - Async load to prevent render blocking--><link rel="preconnect" href="https://kit.fontawesome.com" crossorigin><link rel="preconnect" href="https://ka-f.fontawesome.com" crossorigin><!-- Image CDN and search API preconnects--><link rel="preconnect" href="https://imagedelivery.net"><link rel="preconnect" href="https://images.topdeck.gg"><link rel="preconnect" href="https://3utwcn9824msk5jlp-1.a2.typesense.net" crossorigin><script src="https://kit.fontawesome.com/3df2a3da01.js" crossorigin="anonymous" async></script><!-- Manifest--><link rel="manifest" href="/manifest.json"><!-- Apple App Store Banner--><meta name="apple-itunes-app" content="app-id=6581480935"><!-- Favicon and Touch Icons--><link rel="apple-touch-icon" sizes="192x192" href="/icons/192x192.png"><link rel="icon" type="image/png" sizes="32x32" href="/topdeck-favicon/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/topdeck-favicon/favicon-16x16.png"><!-- Meta Tags Media--><meta name="theme-color" content="#6ca6ea"><meta name="og:title" content="Björn Kimminich - Profile"><meta name="og:description" content="Björn Kimminich's tournament profile and stats"><meta property="og:image" content="https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/aa6d70ad-de73-4c09-a4d7-1e64d5ed6d00/cover"><meta name="twitter:title" content="Björn Kimminich - Profile"><meta property="twitter:image" content="https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/aa6d70ad-de73-4c09-a4d7-1e64d5ed6d00/cover"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@TopDeckGG_"><!-- Global site tag (gtag.js) - Google Analytics--><script async="" src="https://www.googletagmanager.com/gtag/js?id=G-56527VG23P"></script><script>window.dataLayer = window.dataLayer || [];
|
|
2
2
|
function gtag(){dataLayer.push(arguments);}
|
|
3
3
|
gtag('js', new Date());
|
|
4
4
|
gtag('config', 'G-56527VG23P');
|
|
@@ -86,7 +86,7 @@ gtag('config', 'G-56527VG23P');
|
|
|
86
86
|
preloader.classList.remove('active');
|
|
87
87
|
};
|
|
88
88
|
})();
|
|
89
|
-
</script><!-- Vendor Styles--><link rel="stylesheet" media="screen" href="/vendor/simplebar/dist/simplebar.min.css"/><!-- Custom Styles--><!-- Main Theme Styles + Bootstrap--><link rel="stylesheet" media="screen" href="/css/theme.min.css?v2.2"><link rel="stylesheet" href="/css/etemplate.css?v1.1"><!-- Enhancement layer (loads after theme to override)--><!-- Firebase--><script src="https://www.gstatic.com/firebasejs/8.6.7/firebase-app.js" defer data-cfasync="false"></script><script src="https://www.gstatic.com/firebasejs/8.6.7/firebase-auth.js" defer data-cfasync="false"></script><script src="https://www.gstatic.com/firebasejs/8.6.7/firebase-firestore.js" defer data-cfasync="false"></script><script src="/js/cookie.js" defer data-cfasync="false"></script><!-- Moment - Deferred to prevent blocking--><script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script><!-- Jquery - Conditionally deferred on Event Hub only--><script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script><!-- Notyf--><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css"><script src="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js" defer></script></head><!-- Body--><body style="background-color:#0a0e17;"><!-- Page loading spinner--><div class="page-loading active"><div class="page-loading-inner"><div class="page-spinner"></div><span>Loading...</span></div></div><div class="offcanvas offcanvas-end" id="notificationOffcanvas" tabindex="-1"><div class="offcanvas-header"><h5 class="offcanvas-title">Notifications</h5><button class="btn-close btn-close-white" type="button" data-bs-dismiss="offcanvas" aria-label="Close"></button></div><div class="offcanvas-body"></div></div><main class="page-wrapper"><!-- Sign In Modal--><div class="modal fade" id="modal-signin" tabindex="-1"><div class="modal-dialog modal-dialog-centered" role="document"><div class="modal-content border-0"><div class="view show" id="modal-signin-view"><div class="modal-header border-0 bg-primary px-4"><h4 class="modal-title text-light">Sign in</h4><button class="btn-close btn-close-white" type="button" data-bs-dismiss="modal" aria-label="btn-close "></button></div><div class="modal-body px-4 bg-dark"><form class="needs-validation" id="LoginForm" novalidate><div class="mb-3"><div class="input-group"><i class="ai-mail position-absolute top-50 start-0 translate-middle-y ms-3"></i><input class="form-control rounded" id="loginEmail" type="email" placeholder="Email" required></div></div><div class="mb-3"><div class="input-group"><i class="ai-lock position-absolute top-50 start-0 translate-middle-y ms-3"></i><div class="password-toggle w-100"><input class="form-control" id="loginPassword" type="password" placeholder="Password" required><label class="password-toggle-btn" aria-label="Show/hide password"><input class="password-toggle-check" type="checkbox"><span class="password-toggle-indicator"></span></label></div></div></div><div class="d-flex justify-content-between align-items-center mb-3 mb-3"><div class="form-check"><input class="form-check-input" type="checkbox" id="keep-signed"><label class="form-check-label fs-sm" for="keep-signed">Keep me signed in</label></div><a class="nav-link-style fs-ms" href="/forgot-password">Forgot password?</a></div><button class="btn btn-primary d-block w-100" id="loginSubmit" type="submit">Sign in</button><p class="fs-sm pt-3 mb-0">Don't have an account? <a href='#' class='fw-medium' data-view='#modal-signup-view'>Sign up</a></p></form></div></div><div class="view" id="modal-signup-view"><div class="modal-header border-0 bg-primary px-4"><h4 class="modal-title text-light">Sign up</h4><button class="btn-close btn-close-white" type="button" data-bs-dismiss="modal" aria-label="btn-close"></button></div><div class="modal-body px-4 bg-dark"><p class="fs-ms text-muted">Registration takes less than a minute!</p><form class="needs-validation" id="RegisterForm" novalidate><div class="mb-3"><input class="form-control" id="regName" type="text" placeholder="Full name" required></div><div class="mb-3"><input class="form-control" id="regEmail" type="email" placeholder="Email" required></div><div class="mb-3 password-toggle"><input class="form-control" id="regPass1" type="password" placeholder="Password" required><label class="password-toggle-btn" aria-label="Show/hide password"><input class="password-toggle-check" type="checkbox"><span class="password-toggle-indicator"></span></label></div><div class="mb-3 password-toggle"><input class="form-control" id="regPass2" type="password" placeholder="Confirm password" required><label class="password-toggle-btn" aria-label="Show/hide password"><input class="password-toggle-check" type="checkbox"><span class="password-toggle-indicator"></span></label></div><div class="mb-3 form-check"><input class="form-check-input" id="regAgree" type="checkbox" required><label class="form-check-label">I agree to the <a href="/privacy-policy" target="_blank">Privacy Policy </a>and <a href="/terms-and-conditions" target="_blank">Terms and Conditions</a></label></div><div class="mb-3 form-check"><input class="form-check-input" id="regNewsletter" type="checkbox" checked><label class="form-check-label">Subscribe to our <a href="https://newsletter.topdeck.gg/">monthly newsletter</a></label></div><button class="btn btn-primary d-block w-100" id="regSubmit" type="submit">Sign up</button><p class="text-danger fs-sm pt-1 mb-0" id="signup-error" style="display: none"></p><p class="fs-sm pt-3 mb-0">Already have an account? <a href='#' class='fw-medium' data-view='#modal-signin-view'>Sign in</a></p></form></div></div></div></div></div><script src="/js/account/login.js?v1.4"></script><!-- Navbar (Solid background)--><!-- Remove "navbar-sticky" class to make navigation bar scrollable with the page.--><header class="header navbar navbar-expand-lg navbar-light bg-dark navbar-sticky" data-scroll-header data-fixed-element><div class="container px-0 px-xl-3"><button class="navbar-toggler ms-n2 me-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#primaryMenu"><span class="navbar-toggler-icon"></span></button><a class="navbar-brand flex-shrink-0 order-lg-1 mx-auto ms-lg-0 pe-lg-2 me-lg-4" href="/"><img class="d-none d-lg-block" src="/img/logo/TopDeckNoBorder.png" alt="TopDeck.gg" width="58"><img class="d-lg-none" src="/img/logo/TopDeckFullWhiteNS.png" alt="TopDeck.gg" width="150"></a><div class="d-flex align-items-center order-lg-3 ms-lg-auto"><a class="nav-link-style text-nowrap" href="#modal-signin" data-bs-toggle="modal" data-view="#modal-signin-view"><i class="ai-user fs-xl me-2 align-middle"></i>Sign in</a><a class="btn btn-primary ms-grid-gutter d-none d-lg-inline-block" href="#modal-signin" data-bs-toggle="modal" data-view="#modal-signup-view">Sign up</a></div><div class="offcanvas offcanvas-collapse order-lg-2" id="primaryMenu"><div class="offcanvas-header navbar-shadow"><h5 class="mt-1 mb-0">Menu</h5><button class="btn-close btn-close-white lead" type="button" data-bs-dismiss="offcanvas" aria-label="Close"></button></div><div class="offcanvas-body"><!-- Menu--><ul class="navbar-nav"><li class="nav-item dropdown dropdown-mega"><a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">Events</a><div class="dropdown-menu"><div class="dropdown-column mb-0"><h5 class="dropdown-header">Browse Events</h5><a class="dropdown-item" href="/">All Events</a><a class="dropdown-item" href="/magic-the-gathering">Magic: The Gathering</a><a class="dropdown-item" href="/pokemon">Pokémon</a><a class="dropdown-item" href="/yu-gi-oh">Yu-Gi-Oh!</a><a class="dropdown-item" href="/one-piece">One Piece</a><a class="dropdown-item" href="/gundam">Gundam TCG</a><a class="dropdown-item" href="/star-wars-unlimited">Star Wars Unlimited</a><a class="dropdown-item" href="/disney-lorcana">Disney Lorcana</a></div><div class="dropdown-column mb-0"><h5 class="dropdown-header d-none d-lg-block"> </h5><a class="dropdown-item" href="/riftbound">Riftbound</a><a class="dropdown-item" href="/marvel-snap">Marvel Snap</a><a class="dropdown-item" href="/naruto">Naruto Mythos TCG</a><a class="dropdown-item" href="/world-of-kylia">Hadrai'da Ascendant</a><a class="dropdown-item" href="/beyblade">Beyblade</a><a class="dropdown-item" href="/cardfight-vanguard">Cardfight Vanguard</a><a class="dropdown-item" href="/digimon">Digimon</a><a class="dropdown-item" href="/flesh-and-blood">Flesh and Blood</a></div><div class="dropdown-column mb-0"><h5 class="dropdown-header d-none d-lg-block"> </h5><a class="dropdown-item" href="/shadowverse-evolve">Shadowverse: Evolve</a><a class="dropdown-item" href="/sorcery-contested-realm">Sorcery: Contested Realm</a><a class="dropdown-item" href="/altered">Altered</a><a class="dropdown-item" href="/rush-of-ikorr">Rush of Ikorr</a><a class="dropdown-item" href="/cookierun-braverse">CookieRun: Braverse</a><a class="dropdown-item" href="/lairen-la-historia">Lairen: La Historia</a><a class="dropdown-item" href="/settlers-of-catan">Settlers of Catan</a><a class="dropdown-item" href="/gudnak">Gudnak</a></div></div></li><li class="nav-item"><a class="nav-link" href="/subscribe">Subscribe</a></li><li class="nav-item"><a class="nav-link" href="/hubs">Find Stores</a></li><li class="nav-item dropdown dropdown-mega"><a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">Leaderboards</a><div class="dropdown-menu"><div class="dropdown-column mb-2 mb-lg-0"><h5 class="dropdown-header">Magic: The Gathering</h5><a class="dropdown-item" href="/elo/magic-the-gathering/edh">EDH</a><a class="dropdown-item" href="/elo/magic-the-gathering/pauper-edh">Pauper EDH</a><a class="dropdown-item" href="/elo/magic-the-gathering/standard">Standard</a><a class="dropdown-item" href="/elo/magic-the-gathering/pioneer">Pioneer</a><a class="dropdown-item" href="/elo/magic-the-gathering/modern">Modern</a><a class="dropdown-item" href="/elo/magic-the-gathering/legacy">Legacy</a><a class="dropdown-item" href="/elo/magic-the-gathering/pauper">Pauper</a><a class="dropdown-item" href="/elo/magic-the-gathering/vintage">Vintage</a><a class="dropdown-item" href="/elo/magic-the-gathering/premodern">Premodern</a><a class="dropdown-item" href="/elo/magic-the-gathering/limited">Limited</a><a class="dropdown-item" href="/elo/magic-the-gathering/canadian-highlander">Canadian Highlander</a><a class="dropdown-item" href="/elo/magic-the-gathering/duel-commander">Duel Commander</a><a class="dropdown-item" href="/elo/magic-the-gathering/tiny-leaders">Tiny Leaders</a><a class="dropdown-item" href="/elo/magic-the-gathering/7pt-highlander">7pt Highlander</a><a class="dropdown-item" href="/championship-series-2026/leaderboard">Championship Series 2026</a></div><div class="dropdown-column mb-2 mb-lg-0"><h5 class="dropdown-header">Star Wars Unlimited</h5><a class="dropdown-item" href="/elo/star-wars-unlimited/premier">Premier</a><a class="dropdown-item" href="/elo/star-wars-unlimited/draft">Draft</a><a class="dropdown-item" href="/elo/star-wars-unlimited/twin-suns">Twin Suns</a><div class="dropdown-divider"></div><h5 class="dropdown-header my-2">Yu-Gi-Oh!</h5><a class="dropdown-item" href="/elo/yu-gi-oh/advanced">Advanced</a><a class="dropdown-item" href="/elo/yu-gi-oh/edison">Edison</a><a class="dropdown-item" href="/elo/yu-gi-oh/goat">Goat</a><a class="dropdown-item" href="/elo/yu-gi-oh/domain">Domain</a><div class="dropdown-divider"></div><h5 class="dropdown-header my-2">Pokémon</h5><a class="dropdown-item" href="/elo/pokemon/standard">Standard</a><a class="dropdown-item" href="/elo/pokemon/expanded">Expanded</a><a class="dropdown-item" href="/elo/pokemon/legacy">Legacy</a></div><div class="dropdown-column mb-2 mb-lg-0"><h5 class="dropdown-header">More Games</h5><a class="dropdown-item" href="/elo/marvel-snap">Marvel Snap</a><a class="dropdown-item" href="/elo/lorcana">Disney Lorcana</a><a class="dropdown-item" href="/elo/one-piece">One Piece</a><a class="dropdown-item" href="/elo/digimon">Digimon</a><a class="dropdown-item" href="/elo/shadowverse-evolve">Shadowverse Evolve</a><a class="dropdown-item" href="/elo/flesh-and-blood">Flesh and Blood</a><a class="dropdown-item" href="/elo/sorcery-contested-realm">Sorcery: Contested Realm</a><a class="dropdown-item" href="/elo/altered/standard">Altered: Standard</a><a class="dropdown-item" href="/elo/altered/draft">Altered: Draft</a><a class="dropdown-item" href="/elo/beyblade/x">Beyblade X</a></div></div></li><li class="nav-item"><a class="nav-link" href="/championship-series-2026">Championship Series</a></li><li class="nav-item"><a class="nav-link" href="https://shop.topdeck.gg/" target="_blank">Merch</a></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">More</a><ul class="dropdown-menu"><li><h6 class="dropdown-header">Community</h6></li><li><a class="dropdown-item" href="https://newsletter.topdeck.gg/" target="_blank"><i class="fa-solid fa-envelope opacity-60 me-2"></i>Newsletter</a></li><li><a class="dropdown-item" href="/blog"><i class="fa-solid fa-newspaper opacity-60 me-2"></i>What's New</a></li><li><a class="dropdown-item" href="https://discord.topdeck.gg/" target="_blank"><i class="fa-brands fa-discord opacity-60 me-2"></i>Discord Bot</a></li><div class="dropdown-divider"></div><li><h6 class="dropdown-header">Resources</h6></li><li><a class="dropdown-item" href="/docs/tournaments-v2"><i class="fa-solid fa-code opacity-60 me-2"></i>API Documentation</a></li><li><a class="dropdown-item" href="/help"><i class="fa-solid fa-circle-question opacity-60 me-2"></i>Help Center</a></li><div class="dropdown-divider"></div><li><h6 class="dropdown-header">Mobile App</h6></li><li><a class="dropdown-item" href="https://apple.co/3A4Z0FK" target="_blank"><i class="fa-brands fa-apple opacity-60 me-2"></i>Download on iOS</a></li><li><a class="dropdown-item" href="https://play.google.com/store/apps/details?id=com.topdeck.app" target="_blank"><i class="fa-brands fa-google-play opacity-60 me-2"></i>Download on Android</a></li></ul></li></ul></div></div></div></header><script>function EndSession(){
|
|
89
|
+
</script><!-- Vendor Styles--><link rel="stylesheet" media="screen" href="/vendor/simplebar/dist/simplebar.min.css"/><!-- Custom Styles--><link rel="stylesheet" media="screen" href="/css/eventhub-v2.css?v1.1.2"/><link rel="stylesheet" media="screen" href="/css/player-profile-v2.css?v=1.3"/><!-- Main Theme Styles + Bootstrap--><link rel="stylesheet" media="screen" href="/css/theme.min.css?v2.3"><link rel="stylesheet" href="/css/etemplate.css?v1.1"><!-- Enhancement layer (loads after theme to override)--><link rel="stylesheet" href="/css/enhancements.css?v1.1"><!-- Firebase--><script src="https://www.gstatic.com/firebasejs/8.6.7/firebase-app.js" defer data-cfasync="false"></script><script src="https://www.gstatic.com/firebasejs/8.6.7/firebase-auth.js" defer data-cfasync="false"></script><script src="https://www.gstatic.com/firebasejs/8.6.7/firebase-firestore.js" defer data-cfasync="false"></script><script src="/js/cookie.js" defer data-cfasync="false"></script><!-- Moment - Deferred to prevent blocking--><script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script><!-- Jquery - Conditionally deferred on Event Hub only--><script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script><!-- Notyf--><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css"><link rel="stylesheet" href="/css/notyf-theme.css?v1.0"><script src="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js" defer></script></head><!-- Body--><body><!-- Page loading spinner--><div class="page-loading active"><div class="page-loading-inner"><div class="page-spinner"></div><span>Loading...</span></div></div><div class="offcanvas offcanvas-end" id="notificationOffcanvas" tabindex="-1"><div class="offcanvas-header"><h5 class="offcanvas-title">Notifications</h5><button class="btn-close btn-close-white" type="button" data-bs-dismiss="offcanvas" aria-label="Close"></button></div><div class="offcanvas-body"></div></div><main class="page-wrapper"><!-- Sign In Modal--><div class="modal fade" id="modal-signin" tabindex="-1"><div class="modal-dialog modal-dialog-centered" role="document"><div class="modal-content border-0"><div class="view show" id="modal-signin-view"><div class="modal-header border-0 bg-primary px-4"><h4 class="modal-title text-light">Sign in</h4><button class="btn-close btn-close-white" type="button" data-bs-dismiss="modal" aria-label="btn-close "></button></div><div class="modal-body px-4 bg-dark"><form class="needs-validation" id="LoginForm" novalidate><div class="mb-3"><div class="input-group"><i class="ai-mail position-absolute top-50 start-0 translate-middle-y ms-3"></i><input class="form-control rounded" id="loginEmail" type="email" placeholder="Email" required></div></div><div class="mb-3"><div class="input-group"><i class="ai-lock position-absolute top-50 start-0 translate-middle-y ms-3"></i><div class="password-toggle w-100"><input class="form-control" id="loginPassword" type="password" placeholder="Password" required><label class="password-toggle-btn" aria-label="Show/hide password"><input class="password-toggle-check" type="checkbox"><span class="password-toggle-indicator"></span></label></div></div></div><div class="d-flex justify-content-between align-items-center mb-3 mb-3"><div class="form-check"><input class="form-check-input" type="checkbox" id="keep-signed"><label class="form-check-label fs-sm" for="keep-signed">Keep me signed in</label></div><a class="nav-link-style fs-ms" href="/forgot-password">Forgot password?</a></div><button class="btn btn-primary d-block w-100" id="loginSubmit" type="submit">Sign in</button><p class="fs-sm pt-3 mb-0">Don't have an account? <a href='#' class='fw-medium' data-view='#modal-signup-view'>Sign up</a></p></form></div></div><div class="view" id="modal-signup-view"><div class="modal-header border-0 bg-primary px-4"><h4 class="modal-title text-light">Sign up</h4><button class="btn-close btn-close-white" type="button" data-bs-dismiss="modal" aria-label="btn-close"></button></div><div class="modal-body px-4 bg-dark"><p class="fs-ms text-muted">Registration takes less than a minute!</p><form class="needs-validation" id="RegisterForm" novalidate><div class="mb-3"><input class="form-control" id="regName" type="text" placeholder="Full name" required></div><div class="mb-3"><input class="form-control" id="regEmail" type="email" placeholder="Email" required></div><div class="mb-3 password-toggle"><input class="form-control" id="regPass1" type="password" placeholder="Password" required><label class="password-toggle-btn" aria-label="Show/hide password"><input class="password-toggle-check" type="checkbox"><span class="password-toggle-indicator"></span></label></div><div class="mb-3 password-toggle"><input class="form-control" id="regPass2" type="password" placeholder="Confirm password" required><label class="password-toggle-btn" aria-label="Show/hide password"><input class="password-toggle-check" type="checkbox"><span class="password-toggle-indicator"></span></label></div><div class="mb-3 form-check"><input class="form-check-input" id="regAgree" type="checkbox" required><label class="form-check-label">I agree to the <a href="/privacy-policy" target="_blank">Privacy Policy </a>and <a href="/terms-and-conditions" target="_blank">Terms and Conditions</a></label></div><div class="mb-3 form-check"><input class="form-check-input" id="regNewsletter" type="checkbox" checked><label class="form-check-label">Subscribe to our <a href="https://newsletter.topdeck.gg/">monthly newsletter</a></label></div><button class="btn btn-primary d-block w-100" id="regSubmit" type="submit">Sign up</button><p class="text-danger fs-sm pt-1 mb-0" id="signup-error" style="display: none"></p><p class="fs-sm pt-3 mb-0">Already have an account? <a href='#' class='fw-medium' data-view='#modal-signin-view'>Sign in</a></p></form></div></div></div></div></div><script src="/js/account/login.js?v1.7"></script><!-- Navbar (Solid background)--><!-- Remove "navbar-sticky" class to make navigation bar scrollable with the page.--><header class="header navbar navbar-expand-lg navbar-light bg-dark navbar-sticky" data-scroll-header data-fixed-element><div class="container px-0 px-xl-3"><button class="navbar-toggler ms-n2 me-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#primaryMenu"><span class="navbar-toggler-icon"></span></button><a class="navbar-brand flex-shrink-0 order-lg-1 mx-auto ms-lg-0 pe-lg-2 me-lg-4" href="/"><img class="d-none d-lg-block" src="/img/logo/TopDeckNoBorder.png" alt="TopDeck.gg" width="58"><img class="d-lg-none" src="/img/logo/TopDeckFullWhiteNS.png" alt="TopDeck.gg" width="150"></a><div class="d-flex align-items-center order-lg-3 ms-lg-auto"><a class="nav-link-style text-nowrap" href="#modal-signin" data-bs-toggle="modal" data-view="#modal-signin-view"><i class="ai-user fs-xl me-2 align-middle"></i>Sign in</a><a class="btn btn-primary ms-grid-gutter d-none d-lg-inline-block" href="#modal-signin" data-bs-toggle="modal" data-view="#modal-signup-view">Sign up</a></div><div class="offcanvas offcanvas-collapse order-lg-2" id="primaryMenu"><div class="offcanvas-header navbar-shadow"><h5 class="mt-1 mb-0">Menu</h5><button class="btn-close btn-close-white lead" type="button" data-bs-dismiss="offcanvas" aria-label="Close"></button></div><div class="offcanvas-body"><!-- Menu--><ul class="navbar-nav"><li class="nav-item dropdown dropdown-mega"><a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">Events</a><div class="dropdown-menu"><div class="dropdown-column mb-0"><h5 class="dropdown-header">Browse Events</h5><a class="dropdown-item" href="/">All Events</a><a class="dropdown-item" href="/magic-the-gathering">Magic: The Gathering</a><a class="dropdown-item" href="/pokemon">Pokémon</a><a class="dropdown-item" href="/yu-gi-oh">Yu-Gi-Oh!</a><a class="dropdown-item" href="/riftbound">Riftbound</a><a class="dropdown-item" href="/one-piece">One Piece</a><a class="dropdown-item" href="/gundam">Gundam TCG</a><a class="dropdown-item" href="/star-wars-unlimited">Star Wars Unlimited</a><a class="dropdown-item" href="/disney-lorcana">Disney Lorcana</a></div><div class="dropdown-column mb-0"><h5 class="dropdown-header d-none d-lg-block"> </h5><a class="dropdown-item" href="https://cookierun.topdeck.gg">CookieRun: Braverse</a><a class="dropdown-item" href="https://naruto.topdeck.gg">Naruto Mythos TCG</a><a class="dropdown-item" href="https://battle.overpower.game">OverPower Card Game</a><a class="dropdown-item" href="https://chronocore.topdeck.gg">Chrono Core TCG</a><a class="dropdown-item" href="/digimon">Digimon</a><a class="dropdown-item" href="/flesh-and-blood">Flesh and Blood</a><a class="dropdown-item" href="/shadowverse-evolve">Shadowverse: Evolve</a><a class="dropdown-item" href="/marvel-snap">Marvel Snap</a><a class="dropdown-item" href="/sorcery-contested-realm">Sorcery: Contested Realm</a></div><div class="dropdown-column mb-0"><h5 class="dropdown-header d-none d-lg-block"> </h5><a class="dropdown-item" href="/beyblade">Beyblade</a><a class="dropdown-item" href="/cardfight-vanguard">Cardfight Vanguard</a><a class="dropdown-item" href="/rush-of-ikorr">Rush of Ikorr</a><a class="dropdown-item" href="/lairen-la-historia">Lairen: La Historia</a><a class="dropdown-item" href="/settlers-of-catan">Settlers of Catan</a><a class="dropdown-item" href="/gudnak">Gudnak</a><a class="dropdown-item" href="/world-of-kylia">Hadrai'da Ascendant</a></div></div></li><li class="nav-item"><a class="nav-link" href="/subscribe">Host an Event</a></li><li class="nav-item"><a class="nav-link" href="/hubs">Find Stores</a></li><li class="nav-item dropdown dropdown-mega"><a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">Leaderboards</a><div class="dropdown-menu"><div class="dropdown-column mb-2 mb-lg-0"><h5 class="dropdown-header">Magic: The Gathering</h5><a class="dropdown-item" href="/elo/magic-the-gathering/edh">EDH</a><a class="dropdown-item" href="/elo/magic-the-gathering/pauper-edh">Pauper EDH</a><a class="dropdown-item" href="/elo/magic-the-gathering/standard">Standard</a><a class="dropdown-item" href="/elo/magic-the-gathering/pioneer">Pioneer</a><a class="dropdown-item" href="/elo/magic-the-gathering/modern">Modern</a><a class="dropdown-item" href="/elo/magic-the-gathering/legacy">Legacy</a><a class="dropdown-item" href="/elo/magic-the-gathering/pauper">Pauper</a><a class="dropdown-item" href="/elo/magic-the-gathering/vintage">Vintage</a><a class="dropdown-item" href="/elo/magic-the-gathering/premodern">Premodern</a><a class="dropdown-item" href="/elo/magic-the-gathering/limited">Limited</a><a class="dropdown-item" href="/elo/magic-the-gathering/canadian-highlander">Canadian Highlander</a><a class="dropdown-item" href="/elo/magic-the-gathering/duel-commander">Duel Commander</a><a class="dropdown-item" href="/elo/magic-the-gathering/tiny-leaders">Tiny Leaders</a><a class="dropdown-item" href="/elo/magic-the-gathering/7pt-highlander">7pt Highlander</a><a class="dropdown-item" href="/championship-series-2026/leaderboard">Championship Series 2026</a></div><div class="dropdown-column mb-2 mb-lg-0"><h5 class="dropdown-header">Star Wars Unlimited</h5><a class="dropdown-item" href="/elo/star-wars-unlimited/premier">Premier</a><a class="dropdown-item" href="/elo/star-wars-unlimited/draft">Draft</a><a class="dropdown-item" href="/elo/star-wars-unlimited/twin-suns">Twin Suns</a><div class="dropdown-divider"></div><h5 class="dropdown-header my-2">Yu-Gi-Oh!</h5><a class="dropdown-item" href="/elo/yu-gi-oh/advanced">Advanced</a><a class="dropdown-item" href="/elo/yu-gi-oh/edison">Edison</a><a class="dropdown-item" href="/elo/yu-gi-oh/goat">Goat</a><a class="dropdown-item" href="/elo/yu-gi-oh/domain">Domain</a><div class="dropdown-divider"></div><h5 class="dropdown-header my-2">Pokémon</h5><a class="dropdown-item" href="/elo/pokemon/standard">Standard</a><a class="dropdown-item" href="/elo/pokemon/expanded">Expanded</a><a class="dropdown-item" href="/elo/pokemon/legacy">Legacy</a></div><div class="dropdown-column mb-2 mb-lg-0"><h5 class="dropdown-header">More Games</h5><a class="dropdown-item" href="/elo/marvel-snap">Marvel Snap</a><a class="dropdown-item" href="/elo/lorcana">Disney Lorcana</a><a class="dropdown-item" href="/elo/one-piece">One Piece</a><a class="dropdown-item" href="/elo/digimon">Digimon</a><a class="dropdown-item" href="/elo/shadowverse-evolve">Shadowverse Evolve</a><a class="dropdown-item" href="/elo/flesh-and-blood">Flesh and Blood</a><a class="dropdown-item" href="/elo/sorcery-contested-realm">Sorcery: Contested Realm</a><a class="dropdown-item" href="/elo/altered/standard">Altered: Standard</a><a class="dropdown-item" href="/elo/altered/draft">Altered: Draft</a><a class="dropdown-item" href="/elo/beyblade/x">Beyblade X</a></div></div></li><li class="nav-item"><a class="nav-link" href="/championship-series-2026">Championship Series</a></li><li class="nav-item"><a class="nav-link" href="https://shop.topdeck.gg/" target="_blank">Merch</a></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">More</a><ul class="dropdown-menu"><li><h6 class="dropdown-header">Community</h6></li><li><a class="dropdown-item" href="/blog"><i class="fa-solid fa-newspaper opacity-60 me-2"></i>What's New</a></li><li><a class="dropdown-item" href="https://newsletter.topdeck.gg/" target="_blank"><i class="fa-solid fa-envelope opacity-60 me-2"></i>Newsletter</a></li><li><a class="dropdown-item" href="https://discord.topdeck.gg/" target="_blank"><i class="fa-brands fa-discord opacity-60 me-2"></i>Discord Bot</a></li><div class="dropdown-divider"></div><li><h6 class="dropdown-header">Resources</h6></li><li><a class="dropdown-item" href="/docs/tournaments-v2"><i class="fa-solid fa-code opacity-60 me-2"></i>API Documentation</a></li><li><a class="dropdown-item" href="/help"><i class="fa-solid fa-circle-question opacity-60 me-2"></i>Help Center</a></li><div class="dropdown-divider"></div><li><h6 class="dropdown-header">Mobile App</h6></li><li><a class="dropdown-item" href="https://apple.co/3A4Z0FK" target="_blank"><i class="fa-brands fa-apple opacity-60 me-2"></i>Download on iOS</a></li><li><a class="dropdown-item" href="https://play.google.com/store/apps/details?id=com.topdeck.app" target="_blank"><i class="fa-brands fa-google-play opacity-60 me-2"></i>Download on Android</a></li></ul></li></ul></div></div></div></header><script>function EndSession(){
|
|
90
90
|
fetch("/endSession", {
|
|
91
91
|
method: "POST",
|
|
92
92
|
headers: {
|
|
@@ -96,7 +96,7 @@ gtag('config', 'G-56527VG23P');
|
|
|
96
96
|
}).then((ret) => {
|
|
97
97
|
location.reload();
|
|
98
98
|
});
|
|
99
|
-
}</script><!-- Page content--><div class="offcanvas offcanvas-end w-100" id="viewDecklistOffcanvas" tabindex="-1" aria-labelledby="viewDecklistOffcanvasLabel" aria-hidden="true"><div class="offcanvas-header bg-primary"><h5 class="offcanvas-title" id="viewDecklistOffcanvasLabel">Decklist</h5><button class="btn-close btn-close-white" type="button" data-bs-dismiss="offcanvas" aria-label="Close"></button></div><div class="offcanvas-body bg-dark"><pre class="mb-3"><code class="language-json" id="decklistContent"></code></pre></div></div><script src="/js/supportedGames?t=
|
|
99
|
+
}</script><!-- Page content--><div class="offcanvas offcanvas-end w-100" id="viewDecklistOffcanvas" tabindex="-1" aria-labelledby="viewDecklistOffcanvasLabel" aria-hidden="true"><div class="offcanvas-header bg-primary"><h5 class="offcanvas-title" id="viewDecklistOffcanvasLabel">Decklist</h5><button class="btn-close btn-close-white" type="button" data-bs-dismiss="offcanvas" aria-label="Close"></button></div><div class="offcanvas-body bg-dark"><pre class="mb-3"><code class="language-json" id="decklistContent"></code></pre></div></div><script src="/js/supportedGames?t=1777362567454"></script><script>function viewTextDecklist(decklist, title, tournamentId = null, playerId = null, game = null) {
|
|
100
100
|
// Use dynamically served games list
|
|
101
101
|
const supportedGames = window.SUPPORTED_GAMES;
|
|
102
102
|
|
|
@@ -139,640 +139,8 @@ gtag('config', 'G-56527VG23P');
|
|
|
139
139
|
#viewDecklistOffcanvas {
|
|
140
140
|
width: 660px !important;
|
|
141
141
|
}
|
|
142
|
-
}</style
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
// Initialize UI with loading states
|
|
148
|
-
let statsTitle = document.getElementById('statsTitle');
|
|
149
|
-
const badgeContainer = document.getElementById('badgeContainer');
|
|
150
|
-
const tournamentList = document.getElementById('tournamentList');
|
|
151
|
-
|
|
152
|
-
// Add loading indicators using Bootstrap 5
|
|
153
|
-
document.getElementById('statsTitle').parentElement.classList.add('position-relative');
|
|
154
|
-
document.getElementById('statsTitle').parentElement.innerHTML += `
|
|
155
|
-
<div class="position-absolute top-0 start-0 w-100 h-100 d-flex justify-content-center align-items-center bg-dark bg-opacity-75" style="z-index: 10; border-radius: 0.5rem;">
|
|
156
|
-
<div class="spinner-border text-primary" role="status">
|
|
157
|
-
<span class="visually-hidden">Loading...</span>
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
`;
|
|
161
|
-
|
|
162
|
-
tournamentList.innerHTML = `
|
|
163
|
-
<div class="text-center py-5">
|
|
164
|
-
<div class="spinner-border text-primary mb-3" role="status">
|
|
165
|
-
<span class="visually-hidden">Loading...</span>
|
|
166
|
-
</div>
|
|
167
|
-
<p class="text-muted mb-0">Loading tournament data...</p>
|
|
168
|
-
</div>
|
|
169
|
-
`;
|
|
170
|
-
|
|
171
|
-
// Store these as global variables to be used after data load
|
|
172
|
-
let gameFormats = {};
|
|
173
|
-
let topFinishes = {};
|
|
174
|
-
let yearlyStats = {};
|
|
175
|
-
let tdcsData = null;
|
|
176
|
-
let leaguesData = null;
|
|
177
|
-
|
|
178
|
-
let selectedFormat = 'all';
|
|
179
|
-
let selectedYear = 'all';
|
|
180
|
-
|
|
181
|
-
// Fetch player data from API
|
|
182
|
-
fetchPlayerData(playerId);
|
|
183
|
-
|
|
184
|
-
// API function to get player data
|
|
185
|
-
async function fetchPlayerData(playerId) {
|
|
186
|
-
try {
|
|
187
|
-
const response = await fetch(`/profile/${playerId}/stats`);
|
|
188
|
-
if (!response.ok) {
|
|
189
|
-
throw new Error('Failed to fetch player data');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const data = await response.json();
|
|
193
|
-
|
|
194
|
-
// Store the data globally
|
|
195
|
-
gameFormats = data.gameFormats || {};
|
|
196
|
-
topFinishes = data.topFinishes || {};
|
|
197
|
-
yearlyStats = data.yearlyStats || {};
|
|
198
|
-
tdcsData = data.tdcsData || null;
|
|
199
|
-
leaguesData = data.leaguesData || null;
|
|
200
|
-
|
|
201
|
-
// Remove loading indicators
|
|
202
|
-
const loadingOverlay = document.getElementById('statsTitle').parentElement.querySelector('.position-absolute');
|
|
203
|
-
if (loadingOverlay) {
|
|
204
|
-
loadingOverlay.remove();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
statsTitle = document.getElementById('statsTitle');
|
|
208
|
-
|
|
209
|
-
// Initialize the UI with the data
|
|
210
|
-
initializeUI();
|
|
211
|
-
|
|
212
|
-
// Populate the UI with data
|
|
213
|
-
updateStatistics();
|
|
214
|
-
|
|
215
|
-
} catch (error) {
|
|
216
|
-
console.error('Error fetching player data:', error);
|
|
217
|
-
tournamentList.innerHTML = `
|
|
218
|
-
<div class="alert alert-danger">
|
|
219
|
-
<i class="fa-solid fa-exclamation-circle me-2"></i>
|
|
220
|
-
Failed to load tournament data. Please try refreshing the page.
|
|
221
|
-
</div>
|
|
222
|
-
`;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function initializeUI() {
|
|
227
|
-
// Initialize dropdowns with available formats and years
|
|
228
|
-
populateDropdowns();
|
|
229
|
-
|
|
230
|
-
// Set up event handlers
|
|
231
|
-
setupEventHandlers();
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function populateDropdowns() {
|
|
235
|
-
// Format dropdown
|
|
236
|
-
const formatDropdown = document.querySelector('#formatDropdown + .dropdown-menu');
|
|
237
|
-
formatDropdown.innerHTML = '<li><a class="dropdown-item" href="#" data-value="all">All Formats</a></li>';
|
|
238
|
-
|
|
239
|
-
Object.keys(gameFormats).forEach(format => {
|
|
240
|
-
const li = document.createElement('li');
|
|
241
|
-
li.innerHTML = `<a class="dropdown-item" href="#" data-value="${format}">${format}</a>`;
|
|
242
|
-
formatDropdown.appendChild(li);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
// Year dropdown
|
|
246
|
-
const yearDropdown = document.querySelector('#yearDropdown + .dropdown-menu');
|
|
247
|
-
yearDropdown.innerHTML = '<li><a class="dropdown-item" href="#" data-value="all">All Years</a></li>';
|
|
248
|
-
|
|
249
|
-
if (yearlyStats) {
|
|
250
|
-
Object.keys(yearlyStats).sort((a, b) => b - a).forEach(year => {
|
|
251
|
-
const li = document.createElement('li');
|
|
252
|
-
li.innerHTML = `<a class="dropdown-item" href="#" data-value="${year}">${year}</a>`;
|
|
253
|
-
yearDropdown.appendChild(li);
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function setupEventHandlers() {
|
|
259
|
-
// Dropdown click handlers
|
|
260
|
-
document.querySelectorAll('#formatDropdown + .dropdown-menu a').forEach(item => {
|
|
261
|
-
item.addEventListener('click', e => {
|
|
262
|
-
e.preventDefault();
|
|
263
|
-
selectedFormat = item.getAttribute('data-value');
|
|
264
|
-
document.getElementById('formatDropdownLabel').textContent = item.textContent;
|
|
265
|
-
updateStatistics();
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
document.querySelectorAll('#yearDropdown + .dropdown-menu a').forEach(item => {
|
|
270
|
-
item.addEventListener('click', e => {
|
|
271
|
-
e.preventDefault();
|
|
272
|
-
selectedYear = item.getAttribute('data-value');
|
|
273
|
-
document.getElementById('yearDropdownLabel').textContent = item.textContent;
|
|
274
|
-
updateStatistics();
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function updateStatistics() {
|
|
280
|
-
updateTitles(selectedFormat, selectedYear);
|
|
281
|
-
updateFormatStats(selectedFormat, selectedYear);
|
|
282
|
-
updateTournamentList(selectedFormat, selectedYear);
|
|
283
|
-
updateLeaguesTab();
|
|
284
|
-
updateTdcsTab();
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function updateTitles(format, year) {
|
|
288
|
-
const formatText = format === 'all' ? 'Player' : format;
|
|
289
|
-
const yearText = year === 'all' ? '' : ` ${year}`;
|
|
290
|
-
statsTitle.textContent = `${formatText} Stats${yearText}`;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function updateFormatStats(format, year) {
|
|
294
|
-
// Clear badges first - this ensures badges are completely reset when changing formats/years
|
|
295
|
-
badgeContainer.innerHTML = '';
|
|
296
|
-
|
|
297
|
-
let stats;
|
|
298
|
-
if (year === 'all') {
|
|
299
|
-
stats = format === 'all' ? calculateOverallStats() : calculateFormatStats(format);
|
|
300
|
-
} else {
|
|
301
|
-
// When a specific year is selected
|
|
302
|
-
if (format === 'all') {
|
|
303
|
-
// All formats for a specific year
|
|
304
|
-
stats = yearlyStats[year]?.overall;
|
|
305
|
-
} else {
|
|
306
|
-
// Specific format for a specific year
|
|
307
|
-
stats = yearlyStats[year]?.[format];
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (!stats) {
|
|
312
|
-
// If no stats for the selected format/year combination, show zeros
|
|
313
|
-
document.getElementById('totalTournaments').textContent = '0';
|
|
314
|
-
document.getElementById('overallRecord').textContent = '0-0-0';
|
|
315
|
-
document.getElementById('overallWinRate').textContent = '0.00%';
|
|
316
|
-
document.getElementById('conversionRate').textContent = '0.00%';
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
document.getElementById('totalTournaments').textContent = stats.totalTournaments;
|
|
321
|
-
document.getElementById('overallRecord').textContent = `${stats.wins}-${stats.losses}-${stats.draws}`;
|
|
322
|
-
const totalGames = stats.wins + stats.losses + stats.draws;
|
|
323
|
-
const winRate = totalGames > 0 ? ((stats.wins / totalGames) * 100).toFixed(2) + '%' : '0.00%';
|
|
324
|
-
document.getElementById('overallWinRate').textContent = winRate;
|
|
325
|
-
|
|
326
|
-
const topFinishesCount = stats.firstPlaceFinishes + stats.top2 + stats.top4 + stats.top8 + stats.top10 + stats.top16;
|
|
327
|
-
const conversionRate = stats.topCutEligible > 0 ? ((topFinishesCount / stats.topCutEligible) * 100).toFixed(2) + '%' : '0.00%';
|
|
328
|
-
document.getElementById('conversionRate').textContent = conversionRate;
|
|
329
|
-
|
|
330
|
-
const createBadge = (label, value, color) => {
|
|
331
|
-
if (value > 0) {
|
|
332
|
-
const badge = document.createElement('span');
|
|
333
|
-
badge.className = 'badge me-1 mb-2';
|
|
334
|
-
badge.style.cssText = `background-color: ${color}; color: #1e1e1e !important;`;
|
|
335
|
-
badge.innerHTML = `<i class="fa-solid fa-medal me-1"></i>${label}: ${value}`;
|
|
336
|
-
badgeContainer.appendChild(badge);
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
// Only create badges if there are stats
|
|
341
|
-
createBadge('Wins', stats.firstPlaceFinishes, '#ffc321');
|
|
342
|
-
createBadge('Finals', stats.top2 + stats.top4, '#C0C0C0');
|
|
343
|
-
createBadge('Top 8', stats.top8, '#f08035');
|
|
344
|
-
createBadge('Top 10', stats.top10, '#3d85c6');
|
|
345
|
-
createBadge('Top 16', stats.top16, '#f08035');
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
function updateTournamentList(format, year) {
|
|
349
|
-
tournamentList.innerHTML = '';
|
|
350
|
-
|
|
351
|
-
// If no gameFormats, show empty state
|
|
352
|
-
if (Object.keys(gameFormats).length === 0) {
|
|
353
|
-
tournamentList.innerHTML = `
|
|
354
|
-
<div class="text-center py-5">
|
|
355
|
-
<p class="text-muted">No tournament data available</p>
|
|
356
|
-
</div>
|
|
357
|
-
`;
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// Filter formats based on selection
|
|
362
|
-
const formatsToShow = format === 'all'
|
|
363
|
-
? Object.entries(gameFormats)
|
|
364
|
-
: [[format, gameFormats[format]]].filter(([_, tournaments]) => tournaments);
|
|
365
|
-
|
|
366
|
-
if (formatsToShow.length === 0) {
|
|
367
|
-
tournamentList.innerHTML = `
|
|
368
|
-
<div class="text-center py-5">
|
|
369
|
-
<p class="text-muted">No tournaments found for the selected criteria</p>
|
|
370
|
-
</div>
|
|
371
|
-
`;
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
formatsToShow.forEach(([formatName, tournaments]) => {
|
|
376
|
-
// Filter tournaments by year if a specific year is selected
|
|
377
|
-
const filteredTournaments = year === 'all'
|
|
378
|
-
? tournaments
|
|
379
|
-
: tournaments.filter(t => new Date(t.date).getFullYear().toString() === year);
|
|
380
|
-
|
|
381
|
-
if (filteredTournaments.length > 0) {
|
|
382
|
-
// Format header with a more modern design
|
|
383
|
-
const formatHeader = document.createElement('div');
|
|
384
|
-
formatHeader.className = 'd-flex align-items-center mt-4 mb-3';
|
|
385
|
-
formatHeader.innerHTML = `
|
|
386
|
-
<div class="p-2 rounded-3 me-2" style="background-color: rgba(90, 79, 158, 0.3);">
|
|
387
|
-
<i class="fa-solid fa-dice-d20 text-light"></i>
|
|
388
|
-
</div>
|
|
389
|
-
<h5 class="mb-0 text-white">${formatName}</h5>
|
|
390
|
-
`;
|
|
391
|
-
tournamentList.appendChild(formatHeader);
|
|
392
|
-
|
|
393
|
-
// Create a container for the tournament cards in this format
|
|
394
|
-
const cardContainer = document.createElement('div');
|
|
395
|
-
cardContainer.className = 'row g-3';
|
|
396
|
-
tournamentList.appendChild(cardContainer);
|
|
397
|
-
|
|
398
|
-
filteredTournaments.forEach(tournament => {
|
|
399
|
-
// Get placement for styling
|
|
400
|
-
const placement = parseInt(tournament.placement);
|
|
401
|
-
let placementClass = '';
|
|
402
|
-
let placementIcon = '';
|
|
403
|
-
|
|
404
|
-
if (placement === 1) {
|
|
405
|
-
placementClass = 'border-warning';
|
|
406
|
-
placementIcon = '<i class="fa-solid fa-trophy text-warning me-1"></i>';
|
|
407
|
-
} else if (placement <= 4) {
|
|
408
|
-
placementClass = 'border-info';
|
|
409
|
-
placementIcon = '<i class="fa-solid fa-medal text-info me-1"></i>';
|
|
410
|
-
} else if (placement <= 8) {
|
|
411
|
-
placementClass = 'border-primary';
|
|
412
|
-
placementIcon = '<i class="fa-solid fa-award text-primary me-1"></i>';
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// Tournament card with enhanced styling
|
|
416
|
-
const tournamentCol = document.createElement('div');
|
|
417
|
-
tournamentCol.className = 'col-12 col-md-6 col-lg-4';
|
|
418
|
-
|
|
419
|
-
const tournamentCard = document.createElement('div');
|
|
420
|
-
tournamentCard.className = `card h-100 bg-secondary text-white shadow-sm ${placementClass ? 'border-start' : ''} ${placementClass}`;
|
|
421
|
-
|
|
422
|
-
// Calculate match percentages for the progress bar
|
|
423
|
-
const [wins, losses, draws] = tournament.record.split('-').map(Number);
|
|
424
|
-
const matches = wins + losses + draws;
|
|
425
|
-
const winPercentage = matches > 0 ? Math.round((wins / matches) * 100) : 0;
|
|
426
|
-
const lossPercentage = matches > 0 ? Math.round((losses / matches) * 100) : 0;
|
|
427
|
-
const drawPercentage = matches > 0 ? Math.round((draws / matches) * 100) : 0;
|
|
428
|
-
|
|
429
|
-
// Format date nicely
|
|
430
|
-
const tournamentDate = new Date(tournament.date);
|
|
431
|
-
const dateOptions = { year: 'numeric', month: 'short', day: 'numeric' };
|
|
432
|
-
const formattedDate = tournamentDate.toLocaleDateString(undefined, dateOptions);
|
|
433
|
-
|
|
434
|
-
tournamentCard.innerHTML = `
|
|
435
|
-
<div class="card-body d-flex flex-column">
|
|
436
|
-
<h6 class="card-title mb-1 text-truncate">${tournament.name}</h6>
|
|
437
|
-
<div class="mb-2">
|
|
438
|
-
<span class="badge bg-dark text-light border border-light">${formattedDate}</span>
|
|
439
|
-
</div>
|
|
440
|
-
|
|
441
|
-
<div class="mt-2 mb-3">
|
|
442
|
-
<div class="d-flex justify-content-between mb-2">
|
|
443
|
-
<div>
|
|
444
|
-
${placementIcon}
|
|
445
|
-
<span class="text-light">${tournament.placement} of ${tournament.size}</span>
|
|
446
|
-
</div>
|
|
447
|
-
<div class="text-light">
|
|
448
|
-
${tournament.record}
|
|
449
|
-
</div>
|
|
450
|
-
</div>
|
|
451
|
-
|
|
452
|
-
<div class="progress rounded-pill" style="height: 8px;" title="${wins} wins, ${losses} losses, ${draws} draws">
|
|
453
|
-
${wins > 0 ? `<div class="progress-bar bg-success" role="progressbar" style="width: ${winPercentage}%" aria-valuenow="${winPercentage}" aria-valuemin="0" aria-valuemax="100"></div>` : ''}
|
|
454
|
-
${losses > 0 ? `<div class="progress-bar bg-danger" role="progressbar" style="width: ${lossPercentage}%" aria-valuenow="${lossPercentage}" aria-valuemin="0" aria-valuemax="100"></div>` : ''}
|
|
455
|
-
${draws > 0 ? `<div class="progress-bar bg-warning" role="progressbar" style="width: ${drawPercentage}%" aria-valuenow="${drawPercentage}" aria-valuemin="0" aria-valuemax="100"></div>` : ''}
|
|
456
|
-
</div>
|
|
457
|
-
</div>
|
|
458
|
-
|
|
459
|
-
<div class="d-flex flex-wrap gap-2 mt-auto">
|
|
460
|
-
<a href="${tournament.bracketLink}" target="_blank" class="btn btn-sm btn-outline-secondary">
|
|
461
|
-
<i class="fa-solid fa-link me-1"></i>Bracket
|
|
462
|
-
</a>
|
|
463
|
-
${(tournament.game && window.SUPPORTED_GAMES.has(tournament.game)) ? `
|
|
464
|
-
<button type="button" class="btn btn-sm btn-outline-secondary decklist-btn"
|
|
465
|
-
data-tournament-name="${tournament.name}"
|
|
466
|
-
data-tournament-id="${tournament.id}"
|
|
467
|
-
data-format="${formatName}">
|
|
468
|
-
<i class="fa-solid fa-cards-blank me-1"></i>Decklist
|
|
469
|
-
</button>
|
|
470
|
-
` : ''}
|
|
471
|
-
</div>
|
|
472
|
-
</div>
|
|
473
|
-
`;
|
|
474
|
-
|
|
475
|
-
tournamentCol.appendChild(tournamentCard);
|
|
476
|
-
cardContainer.appendChild(tournamentCol);
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
// If no tournaments were found after filtering
|
|
482
|
-
if (tournamentList.innerHTML === '') {
|
|
483
|
-
tournamentList.innerHTML = `
|
|
484
|
-
<div class="text-center py-5">
|
|
485
|
-
<p class="text-muted">No tournaments found for the selected criteria</p>
|
|
486
|
-
</div>
|
|
487
|
-
`;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// Add event listeners for decklist buttons
|
|
491
|
-
document.querySelectorAll('.decklist-btn').forEach(button => {
|
|
492
|
-
button.addEventListener('click', function() {
|
|
493
|
-
const tournamentName = this.dataset.tournamentName;
|
|
494
|
-
const tournamentId = this.dataset.tournamentId;
|
|
495
|
-
const playerIdentifier = playerUsername || playerId;
|
|
496
|
-
|
|
497
|
-
const format = this.dataset.format;
|
|
498
|
-
const baseGame = format.includes(':') ? format.split(':').slice(0, 2).join(':').trim() : format;
|
|
499
|
-
|
|
500
|
-
viewTextDecklist(null, tournamentName, tournamentId, playerIdentifier, baseGame);
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function updateTdcsTab() {
|
|
506
|
-
// First, update the tab visibility
|
|
507
|
-
const tabList = document.querySelector('.nav-pills');
|
|
508
|
-
const existingTab = document.querySelector('a[href="#championship"]');
|
|
509
|
-
|
|
510
|
-
if (tdcsData) {
|
|
511
|
-
// Show the tab if TDCS data exists
|
|
512
|
-
if (!existingTab) {
|
|
513
|
-
const tabItem = document.createElement('li');
|
|
514
|
-
tabItem.className = 'nav-item';
|
|
515
|
-
tabItem.innerHTML = `
|
|
516
|
-
<a class="nav-link py-3 rounded-3" href="#championship" data-bs-toggle="tab">
|
|
517
|
-
<i class="fa-solid fa-award me-2"></i>
|
|
518
|
-
Series
|
|
519
|
-
</a>
|
|
520
|
-
`;
|
|
521
|
-
tabList.appendChild(tabItem);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
// Create or update the tab content
|
|
525
|
-
const tabContent = document.querySelector('.tab-content');
|
|
526
|
-
let championshipPane = document.getElementById('championship');
|
|
527
|
-
|
|
528
|
-
if (!championshipPane) {
|
|
529
|
-
championshipPane = document.createElement('div');
|
|
530
|
-
championshipPane.id = 'championship';
|
|
531
|
-
championshipPane.className = 'tab-pane fade';
|
|
532
|
-
tabContent.appendChild(championshipPane);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
championshipPane.innerHTML = `
|
|
536
|
-
<div class="card bg-secondary text-white shadow-sm">
|
|
537
|
-
<div class="card-body">
|
|
538
|
-
<h4 class="card-title text-center mb-4">TopDeck Championship Series 2026</h4>
|
|
539
|
-
|
|
540
|
-
<div class="text-center mb-5">
|
|
541
|
-
<p class="fs-6 mb-1">Total Points</p>
|
|
542
|
-
<h2 class="fw-bold text-highlight">${tdcsData.points}</h2>
|
|
543
|
-
</div>
|
|
544
|
-
|
|
545
|
-
${generateTierContent()}
|
|
546
|
-
</div>
|
|
547
|
-
</div>
|
|
548
|
-
`;
|
|
549
|
-
} else {
|
|
550
|
-
// Remove the tab if no TDCS data
|
|
551
|
-
if (existingTab) {
|
|
552
|
-
existingTab.parentElement.remove();
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
const championshipPane = document.getElementById('championship');
|
|
556
|
-
if (championshipPane) {
|
|
557
|
-
championshipPane.remove();
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
function updateLeaguesTab() {
|
|
563
|
-
const tabList = document.querySelector('.nav-pills');
|
|
564
|
-
const existingTab = document.querySelector('a[href="#leagues"]');
|
|
565
|
-
|
|
566
|
-
if (leaguesData && leaguesData.length > 0) {
|
|
567
|
-
if (!existingTab) {
|
|
568
|
-
const tabItem = document.createElement('li');
|
|
569
|
-
tabItem.className = 'nav-item';
|
|
570
|
-
tabItem.innerHTML = `
|
|
571
|
-
<a class="nav-link py-3 rounded-3" href="#leagues" data-bs-toggle="tab">
|
|
572
|
-
<i class="fa-solid fa-people-group me-2"></i>
|
|
573
|
-
Leagues
|
|
574
|
-
</a>
|
|
575
|
-
`;
|
|
576
|
-
tabList.appendChild(tabItem);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
const tabContent = document.querySelector('.tab-content');
|
|
580
|
-
let leaguesPane = document.getElementById('leagues');
|
|
581
|
-
|
|
582
|
-
if (!leaguesPane) {
|
|
583
|
-
leaguesPane = document.createElement('div');
|
|
584
|
-
leaguesPane.id = 'leagues';
|
|
585
|
-
leaguesPane.className = 'tab-pane fade';
|
|
586
|
-
tabContent.appendChild(leaguesPane);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
let cardsHtml = '';
|
|
590
|
-
leaguesData.forEach(league => {
|
|
591
|
-
const placement = league.placementNumber;
|
|
592
|
-
let placementClass = '';
|
|
593
|
-
let placementIcon = '';
|
|
594
|
-
|
|
595
|
-
if (placement === 1) {
|
|
596
|
-
placementClass = 'border-warning';
|
|
597
|
-
placementIcon = '<i class="fa-solid fa-trophy text-warning me-1"></i>';
|
|
598
|
-
} else if (placement <= 4) {
|
|
599
|
-
placementClass = 'border-info';
|
|
600
|
-
placementIcon = '<i class="fa-solid fa-medal text-info me-1"></i>';
|
|
601
|
-
} else if (placement <= 8) {
|
|
602
|
-
placementClass = 'border-primary';
|
|
603
|
-
placementIcon = '<i class="fa-solid fa-award text-primary me-1"></i>';
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
const [wins, losses, draws] = league.record.split('-').map(Number);
|
|
607
|
-
const matches = wins + losses + draws;
|
|
608
|
-
const winPct = matches > 0 ? Math.round((wins / matches) * 100) : 0;
|
|
609
|
-
const lossPct = matches > 0 ? Math.round((losses / matches) * 100) : 0;
|
|
610
|
-
const drawPct = matches > 0 ? Math.round((draws / matches) * 100) : 0;
|
|
611
|
-
|
|
612
|
-
const leagueDate = new Date(league.date);
|
|
613
|
-
const formattedDate = leagueDate.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
|
|
614
|
-
const gameFormat = league.format ? `${league.game}: ${league.format}` : league.game;
|
|
615
|
-
|
|
616
|
-
cardsHtml += `
|
|
617
|
-
<div class="col-12 col-md-6 col-lg-4">
|
|
618
|
-
<div class="card h-100 bg-secondary text-white shadow-sm ${placementClass ? 'border-start' : ''} ${placementClass}">
|
|
619
|
-
<div class="card-body d-flex flex-column">
|
|
620
|
-
<h6 class="card-title mb-1 text-truncate">${league.name}</h6>
|
|
621
|
-
<div class="mb-2">
|
|
622
|
-
<span class="badge bg-dark text-light border border-light">${formattedDate}</span>
|
|
623
|
-
<span class="badge bg-dark text-light border border-light ms-1">${gameFormat}</span>
|
|
624
|
-
</div>
|
|
625
|
-
|
|
626
|
-
<div class="mt-2 mb-3">
|
|
627
|
-
<div class="d-flex justify-content-between mb-2">
|
|
628
|
-
<div>
|
|
629
|
-
${placementIcon}
|
|
630
|
-
<span class="text-light">${league.placement} of ${league.size}</span>
|
|
631
|
-
</div>
|
|
632
|
-
<div class="text-light">
|
|
633
|
-
${league.record}
|
|
634
|
-
</div>
|
|
635
|
-
</div>
|
|
636
|
-
|
|
637
|
-
<div class="progress rounded-pill" style="height: 8px;" title="${wins} wins, ${losses} losses, ${draws} draws">
|
|
638
|
-
${wins > 0 ? `<div class="progress-bar bg-success" role="progressbar" style="width: ${winPct}%"></div>` : ''}
|
|
639
|
-
${losses > 0 ? `<div class="progress-bar bg-danger" role="progressbar" style="width: ${lossPct}%"></div>` : ''}
|
|
640
|
-
${draws > 0 ? `<div class="progress-bar bg-warning" role="progressbar" style="width: ${drawPct}%"></div>` : ''}
|
|
641
|
-
</div>
|
|
642
|
-
</div>
|
|
643
|
-
|
|
644
|
-
<div class="d-flex flex-wrap gap-2 mt-auto">
|
|
645
|
-
<a href="${league.bracketLink}" target="_blank" class="btn btn-sm btn-outline-secondary">
|
|
646
|
-
<i class="fa-solid fa-link me-1"></i>Bracket
|
|
647
|
-
</a>
|
|
648
|
-
</div>
|
|
649
|
-
</div>
|
|
650
|
-
</div>
|
|
651
|
-
</div>
|
|
652
|
-
`;
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
leaguesPane.innerHTML = `
|
|
656
|
-
<div class="card bg-dark border-0 rounded-4 shadow-lg py-4 px-3 px-sm-4">
|
|
657
|
-
<h3 class="card-title text-white fw-bold">
|
|
658
|
-
<i class="fa-solid fa-people-group me-2 text-info"></i>
|
|
659
|
-
League History
|
|
660
|
-
</h3>
|
|
661
|
-
<div class="row g-3 mt-2">
|
|
662
|
-
${cardsHtml}
|
|
663
|
-
</div>
|
|
664
|
-
</div>
|
|
665
|
-
`;
|
|
666
|
-
} else {
|
|
667
|
-
if (existingTab) {
|
|
668
|
-
existingTab.parentElement.remove();
|
|
669
|
-
}
|
|
670
|
-
const leaguesPane = document.getElementById('leagues');
|
|
671
|
-
if (leaguesPane) {
|
|
672
|
-
leaguesPane.remove();
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
function generateTierContent() {
|
|
678
|
-
const tiers = ['Diamond', 'Platinum', 'Gold', 'Silver', 'Bronze'];
|
|
679
|
-
let content = '';
|
|
680
|
-
|
|
681
|
-
tiers.forEach(tier => {
|
|
682
|
-
if (tdcsData.tierBreakdown && tdcsData.tierBreakdown[tier] && tdcsData.tierBreakdown[tier].length > 0) {
|
|
683
|
-
content += `
|
|
684
|
-
<div class="d-flex align-items-center mb-3 mt-5">
|
|
685
|
-
<img src="/img/tdcs/new/TD${tier}.png" alt="${tier} Tier" style="height: 40px; width: auto; margin-right: 12px;">
|
|
686
|
-
<h5 class="mb-0">${tier} Tier</h5>
|
|
687
|
-
</div>
|
|
688
|
-
|
|
689
|
-
<div class="row g-3">
|
|
690
|
-
`;
|
|
691
|
-
|
|
692
|
-
tdcsData.tierBreakdown[tier].forEach(item => {
|
|
693
|
-
if (item.tournamentName && item.points > 0) {
|
|
694
|
-
content += `
|
|
695
|
-
<div class="col-12 col-md-6 col-lg-4">
|
|
696
|
-
<div class="card bg-dark text-white h-100 shadow-sm">
|
|
697
|
-
<div class="card-body d-flex flex-column justify-content-between">
|
|
698
|
-
<div class="mb-3">
|
|
699
|
-
<h6 class="card-title mb-1">${item.tournamentName}</h6>
|
|
700
|
-
<p class="text-muted mb-0 small">(${item.standing} of ${item.totalPlayers})</p>
|
|
701
|
-
</div>
|
|
702
|
-
<div class="d-flex justify-content-between align-items-end mt-auto">
|
|
703
|
-
<span class="fw-bold">${item.points} pts</span>
|
|
704
|
-
</div>
|
|
705
|
-
</div>
|
|
706
|
-
</div>
|
|
707
|
-
</div>
|
|
708
|
-
`;
|
|
709
|
-
}
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
content += '</div>';
|
|
713
|
-
}
|
|
714
|
-
});
|
|
715
|
-
|
|
716
|
-
return content;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
function calculateOverallStats() {
|
|
720
|
-
let overallStats = {
|
|
721
|
-
totalTournaments: 0, topCutEligible: 0, wins: 0, losses: 0, draws: 0,
|
|
722
|
-
firstPlaceFinishes: 0, top2: 0, top4: 0, top8: 0, top10: 0, top16: 0
|
|
723
|
-
};
|
|
724
|
-
|
|
725
|
-
Object.values(topFinishes).forEach(formatFinishes => {
|
|
726
|
-
Object.keys(overallStats).forEach(key => {
|
|
727
|
-
if (key in formatFinishes) {
|
|
728
|
-
overallStats[key] += formatFinishes[key];
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
|
-
});
|
|
732
|
-
|
|
733
|
-
Object.values(gameFormats).forEach(tournaments => {
|
|
734
|
-
overallStats.totalTournaments += tournaments.length;
|
|
735
|
-
tournaments.forEach(t => {
|
|
736
|
-
const [wins, losses, draws] = t.record.split('-').map(Number);
|
|
737
|
-
overallStats.wins += wins;
|
|
738
|
-
overallStats.losses += losses;
|
|
739
|
-
overallStats.draws += draws;
|
|
740
|
-
if (t.topCut > 0) {
|
|
741
|
-
overallStats.topCutEligible++;
|
|
742
|
-
}
|
|
743
|
-
});
|
|
744
|
-
});
|
|
745
|
-
|
|
746
|
-
return overallStats;
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
function calculateFormatStats(format) {
|
|
750
|
-
// If the format doesn't exist, return empty stats
|
|
751
|
-
if (!gameFormats[format] || !topFinishes[format]) {
|
|
752
|
-
return {
|
|
753
|
-
totalTournaments: 0, topCutEligible: 0, wins: 0, losses: 0, draws: 0,
|
|
754
|
-
firstPlaceFinishes: 0, top2: 0, top4: 0, top8: 0, top10: 0, top16: 0
|
|
755
|
-
};
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
const formatStats = {
|
|
759
|
-
...topFinishes[format],
|
|
760
|
-
totalTournaments: gameFormats[format].length,
|
|
761
|
-
topCutEligible: 0,
|
|
762
|
-
wins: 0, losses: 0, draws: 0
|
|
763
|
-
};
|
|
764
|
-
|
|
765
|
-
gameFormats[format].forEach(t => {
|
|
766
|
-
const [wins, losses, draws] = t.record.split('-').map(Number);
|
|
767
|
-
formatStats.wins += wins;
|
|
768
|
-
formatStats.losses += losses;
|
|
769
|
-
formatStats.draws += draws;
|
|
770
|
-
if (t.topCut > 0) {
|
|
771
|
-
formatStats.topCutEligible++;
|
|
772
|
-
}
|
|
773
|
-
});
|
|
774
|
-
|
|
775
|
-
return formatStats;
|
|
776
|
-
}
|
|
777
|
-
});</script><!-- Back to top button--><a class="btn-scroll-top" href="#top" data-scroll data-fixed-element><span class="btn-scroll-top-tooltip text-muted fs-sm me-2">Top</span><i class="btn-scroll-top-icon ai-arrow-up"> </i></a><!-- Vendor scrits: js libraries and plugins--><script src="/vendor/bootstrap/dist/js/bootstrap.bundle.min.js"></script><script src="/vendor/simplebar/dist/simplebar.min.js"></script><script src="/vendor/smooth-scroll/dist/smooth-scroll.polyfills.min.js"></script><!-- Main theme script--><script src="/js/theme.min.js"></script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"version":"2024.11.0","token":"0e3ccdaf832b48f5a3585d27a3a6e921","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
|
|
142
|
+
}</style><div class="pp-hero" style="background-image: url(https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/aa6d70ad-de73-4c09-a4d7-1e64d5ed6d00/cover)"></div><div class="container"><div class="pp-profile-card"><div class="pp-profile-row"><div class="pp-avatar-col"><img class="pp-avatar" src="https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/2a7b8d12-5924-4a58-5f9c-c0bf55766800/square" alt="Björn Kimminich" onerror="this.src='/img/logo/TopDeckLogoBorder.png'"></div><div class="pp-info"><h1 class="pp-name">Björn Kimminich<span class="pp-pronouns">He/Him</span></h1><div class="pp-socials"><a class="pp-social-link" href="https://twitter.com/bkimminich" target="_blank" rel="noopener" title="Twitter"><i class="fa-brands fa-twitter"></i></a><a class="pp-social-link" href="https://www.youtube.com/@Bj%C3%B6rnKimminich" target="_blank" rel="noopener" title="YouTube"><i class="fa-brands fa-youtube"></i></a></div></div></div><div class="pp-stats" id="ppStats"><div class="pp-stat"><span class="pp-stat-value" id="totalTournaments">–</span><span class="pp-stat-label">Events</span></div><div class="pp-stat-divider"></div><div class="pp-stat"><span class="pp-stat-value" id="overallRecord">–</span><span class="pp-stat-label">Record</span></div><div class="pp-stat-divider"></div><div class="pp-stat"><span class="pp-stat-value" id="overallWinRate">–</span><span class="pp-stat-label">Win Rate</span></div><div class="pp-stat-divider"></div><div class="pp-stat"><span class="pp-stat-value" id="conversionRate">–</span><span class="pp-stat-label">Conversion</span></div></div></div></div><div class="container pp-content"><div class="pp-filter-bar eh-filter-bar mt-2"><div class="eh-filter-row"><span class="eh-filter-label">Game</span><div class="eh-chips" id="ppGameChips"><button class="eh-chip active" data-filter="game" data-value="all" type="button">All</button></div></div><div class="eh-filter-row"><span class="eh-filter-label">Year</span><div class="eh-chips" id="ppYearChips"><button class="eh-chip active" data-filter="year" data-value="all" type="button">All</button></div></div></div><section class="pp-heatmap-section" id="ppHeatmapSection" style="display:none"><div class="pp-heatmap-inner"><div class="pp-panel-header"><h3 class="pp-panel-title"><i class="fa-solid fa-fire"></i><span>Activity</span></h3><div class="pp-heatmap-legend"><span class="pp-legend-label">Less</span><span class="pp-legend-cell" data-intensity="1"></span><span class="pp-legend-cell" data-intensity="2"></span><span class="pp-legend-cell" data-intensity="3"></span><span class="pp-legend-cell" data-intensity="4"></span><span class="pp-legend-label">More</span></div></div><div class="pp-heatmap" id="ppHeatmap"></div><div class="pp-streak" id="ppStreak" style="display:none"></div></div></section><div class="pp-h2h" id="ppH2H" style="display:none"></div><div class="pp-tabs-wrap"><ul class="nav pp-tabs" role="tablist"><li class="nav-item"><a class="nav-link active" href="#history" data-bs-toggle="tab"><i class="fa-solid fa-trophy me-2"></i>Tournaments</a></li></ul></div><div class="tab-content pp-tab-content"><div class="tab-pane fade show active" id="history"><div class="pp-elo-group" id="ppEloGroup" style="display:none"><span class="pp-elo-heading">Elo</span><div class="pp-elo-list" id="ppEloList"></div></div><div class="pp-badges" id="badgeContainer"></div><div class="pp-tournament-list" id="tournamentList"></div></div></div></div></main><footer class="footer bg-black py-5"><div class="container pt-md-2 pt-lg-3"><div class="row pt-sm-2"><!-- Logo, description, and social column--><div class="col-md-4 col-lg-3 pb-2 pb-md-0 mb-4 mb-md-0"><a class="d-block mb-3 mb-md-4" href="/"><img class="img-fluid" src="/img/logo/TopDeckFullWhiteNS.png" alt="TopDeck.gg" style="max-width: 200px;"></a><p class="text-muted pb-2 pb-md-3 mb-3 fs-sm">Discover, organize, and compete in trading card game events. Connect with players worldwide and elevate your game.</p><div class="d-flex gap-1"><a class="btn-social bs-outline bs-light bs-facebook bs-lg me-2" href="https://discord.gg/RjS3mDf3wt" target="_blank"><i class="fa-brands fa-discord"></i></a><a class="btn-social bs-outline bs-light bs-youtube bs-lg me-2" href="https://www.youtube.com/@TopDeckGG_" target="_blank"><i class="fa-brands fa-youtube"></i></a></div></div><!-- Nested columns for links--><div class="col-md-8 col-lg-7 offset-lg-2"><div class="row row-cols-1 row-cols-sm-3"><!-- Company column--><div class="col mb-4 mb-md-0"><div class="widget widget-light"><h4 class="widget-title mb-3">Company</h4><ul><li><a class="widget-link" href="/subscribe">Run a Tournament</a></li><li><a class="widget-link" href="https://newsletter.topdeck.gg/">Newsletter</a></li><li><a class="widget-link" href="/docs/tournaments-v2">API Documentation</a></li><li><a class="widget-link" href="/championship-series-2026">Championship Series</a></li></ul></div></div><!-- Support column--><div class="col mb-4 mb-md-0"><div class="widget widget-light"><h4 class="widget-title mb-3">Support</h4><ul><li><a class="widget-link" href="/cdn-cgi/l/email-protection#d8bbb7b6acb9bbac98acb7a8bcbdbbb3f6bfbf">Contact Us</a></li><li><a class="widget-link" href="/cdn-cgi/l/email-protection#bed3dbdad7dffecad1cedadbddd590d9d9">Media Inquiries</a></li><li><a class="widget-link" href="/privacy-policy" target="_blank">Privacy Policy</a></li><li><a class="widget-link" href="/terms-and-conditions" target="_blank">Terms & Conditions</a></li></ul></div></div><!-- Install App column--><div class="col"><h4 class="h6 fw-bold pb-2 mb-0 mb-lg-1">Install App</h4><a class="btn btn-outline-secondary d-inline-flex align-items-center px-3 py-2 mt-3 me-3 me-md-0" href="https://apple.co/3A4Z0FK" role="button" style="min-width: 160px;"><i class="fa-brands fa-apple fs-xl me-2"></i><span class="d-flex flex-column align-items-start"><small class="fs-xs text-white-50">Download on the</small><span class="fs-sm">App Store</span></span></a><a class="btn btn-outline-secondary d-inline-flex align-items-center px-3 py-2 mt-3 me-3 me-md-0" href="https://play.google.com/store/apps/details?id=com.topdeck.app" role="button" style="min-width: 160px;"><i class="fa-brands fa-google-play fs-xl me-2"></i><span class="d-flex flex-column align-items-start"><small class="fs-xs text-white-50">Get it on</small><span class="fs-sm">Google Play</span></span></a></div></div></div></div></div></footer><script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script>window.PROFILE_PLAYER_ID = "m4VSTJShiXR1PCSCWaM9TBY0rcg1";
|
|
143
|
+
window.PROFILE_PLAYER_USERNAME = "@k0shiii";
|
|
144
|
+
window.PROFILE_VIEWER_UID = null;
|
|
145
|
+
</script><script src="/js/player-profile-v2.js?v=1.3" defer></script><!-- Back to top button--><a class="btn-scroll-top" href="#top" data-scroll data-fixed-element><span class="btn-scroll-top-tooltip text-muted fs-sm me-2">Top</span><i class="btn-scroll-top-icon ai-arrow-up"> </i></a><!-- Vendor scrits: js libraries and plugins--><script src="/vendor/bootstrap/dist/js/bootstrap.bundle.min.js"></script><script src="/vendor/simplebar/dist/simplebar.min.js"></script><script src="/vendor/smooth-scroll/dist/smooth-scroll.polyfills.min.js"></script><!-- Main theme script--><script src="/js/theme.min.js"></script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"0e3ccdaf832b48f5a3585d27a3a6e921","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
|
|
778
146
|
</body></html>
|