mtg-playerinfo 1.2.2 → 1.3.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.
@@ -7,7 +7,25 @@ on:
7
7
  branches: [ main ]
8
8
 
9
9
  jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Use Node.js
16
+ uses: actions/setup-node@v4
17
+ with:
18
+ node-version: 24
19
+ cache: 'npm'
20
+
21
+ - name: Install dependencies
22
+ run: npm install
23
+
24
+ - name: Run linter
25
+ run: npm run lint
26
+
10
27
  test:
28
+ needs: [lint]
11
29
  runs-on: ${{ matrix.os }}
12
30
 
13
31
  strategy:
@@ -29,5 +29,5 @@ jobs:
29
29
  - name: Commit and push changes
30
30
  uses: stefanzweifel/git-auto-commit-action@v5
31
31
  with:
32
- commit_message: "🤖 Update test data HTML files"
33
- file_pattern: 'test/data/*.html'
32
+ commit_message: "🤖 Update test data files"
33
+ file_pattern: 'test/data/*.*'
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Coverage Status](https://coveralls.io/repos/github/bkimminich/mtg-playerinfo/badge.svg?branch=main)](https://coveralls.io/github/bkimminich/mtg-playerinfo?branch=main)
8
8
  [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
9
9
 
10
- A simple NPM module and CLI tool to pull Magic: The Gathering player data from various sources (Unity League, MTG Elo Project, Melee, and Topdeck).
10
+ A simple NPM module and CLI tool to pull Magic: The Gathering player data from various sources (Unity League, MTG Elo Project, Melee, Topdeck, and Untapped.gg).
11
11
 
12
12
  ## Installation
13
13
 
@@ -18,13 +18,13 @@ npm i -g mtg-playerinfo
18
18
  ## CLI Usage
19
19
 
20
20
  ```bash
21
- mtg-playerinfo --unity-id 16215 --mtgelo-id 3irvwtmk --melee-user k0shiii --topdeck-handle k0shiii
21
+ mtg-playerinfo --unity-id 16215 --mtgelo-id 3irvwtmk --melee-user k0shiii --topdeck-handle k0shiii --untapped-id 7de50700-c3f6-48e4-a38d-2add5b0d9b71/76DCDWCZS5FX5PIEEMUVY6GV74
22
22
  ```
23
23
 
24
24
  or without previous installation
25
25
 
26
26
  ```bash
27
- npx mtg-playerinfo --unity-id 16215 --mtgelo-id 3irvwtmk --melee-user k0shiii --topdeck-handle k0shiii
27
+ npx mtg-playerinfo --unity-id 16215 --mtgelo-id 3irvwtmk --melee-user k0shiii --topdeck-handle k0shiii --untapped-id 7de50700-c3f6-48e4-a38d-2add5b0d9b71/76DCDWCZS5FX5PIEEMUVY6GV74
28
28
  ```
29
29
 
30
30
  ## Output Format
@@ -33,7 +33,7 @@ The tool returns a JSON object representing the player and their combined metada
33
33
 
34
34
  ### General meta-data and merging priority
35
35
 
36
- General meta-data fields like `name`, `photo`, `age`, `country`, and `hometown` are extracted from the first source that provides them and placed in the `general` section. Merging follows a "first-come, first-served" approach based on the order of sources provided in the command line or processed by the manager. In the [CLI usage example](#cli-usage) above, the source priority is `Unity League` > `MTG Elo Project` > `Melee` > `Topdeck`.
36
+ General meta-data fields like `name`, `photo`, `age`, `country`, and `hometown` are extracted from the first source that provides them and placed in the `general` section. Merging follows a "first-come, first-served" approach based on the order of sources provided in the command line or processed by the manager. In the [CLI usage example](#cli-usage) above, the source priority is `Unity League` > `MTG Elo Project` > `Melee` > `Topdeck` > `Untapped.gg`.
37
37
 
38
38
  > If you notice any inconsistencies or unexpected fields values, you can run the tool with the `-v` or `--verbose` flag to see the full list of extracted fields and if they were promoted to the `general` section or deviated from a previous source.
39
39
 
@@ -53,7 +53,8 @@ General meta-data fields like `name`, `photo`, `age`, `country`, and `hometown`
53
53
  "facebook": "bjoern.kimminich",
54
54
  "twitch": "koshiii",
55
55
  "youtube": "@BjörnKimminich",
56
- "win rate": "42.49%"
56
+ "mtga_rank": "Platinum 4",
57
+ "win rate": "47.37%"
57
58
  },
58
59
  "sources": {
59
60
  "Unity League": {
@@ -67,11 +68,11 @@ General meta-data fields like `name`, `photo`, `age`, `country`, and `hometown`
67
68
  "local organizer": "Mulligan TCG Shop",
68
69
  "team": "Mull to Five",
69
70
  "bio": "Smugly held back on an Untimely Malfunction against a Storm player going off, being totally sure that you can redirect the summed-up damage of their Grapeshots back to their face with its \"Change the target of target spell or ability with a single target\" mode.",
70
- "rank germany": "63",
71
- "rank europe": "547",
72
- "rank points": "304",
73
- "record": "45-43-5",
74
- "win rate": "50.2%"
71
+ "rank germany": "62",
72
+ "rank europe": "503",
73
+ "rank points": "325",
74
+ "record": "50-45-5",
75
+ "win rate": "51.7%"
75
76
  }
76
77
  },
77
78
  "MTG Elo Project": {
@@ -105,6 +106,12 @@ General meta-data fields like `name`, `photo`, `age`, `country`, and `hometown`
105
106
  "win rate": "36.36%",
106
107
  "conversion": "0%"
107
108
  }
109
+ },
110
+ "Untapped.gg": {
111
+ "url": "https://mtga.untapped.gg/profile/7de50700-c3f6-48e4-a38d-2add5b0d9b71/76DCDWCZS5FX5PIEEMUVY6GV74",
112
+ "data": {
113
+ "mtga_rank": "Platinum 4"
114
+ }
108
115
  }
109
116
  }
110
117
  }
@@ -120,6 +127,7 @@ The following sites are currently supported based on HTML scraping and/or API ca
120
127
  | MTG Elo Project | ✅Scraping |
121
128
  | Topdeck | ✅Scraping / ✅API |
122
129
  | Melee | ✅Scraping / 🚧API ([#1](https://github.com/bkimminich/mtg-playerinfo/issues/1)) |
130
+ | Untapped.gg | ✅API |
123
131
 
124
132
  _Note: Some sites may have anti-bot protections that can lead to "Maximum number of redirects exceeded" or "403 Forbidden" errors depending on the execution environment._
125
133
 
package/cli.js CHANGED
@@ -12,10 +12,11 @@ program
12
12
  .option('--mtgelo-id <id>', 'MTG Elo Project Player ID')
13
13
  .option('--melee-user <username>', 'Melee Username')
14
14
  .option('--topdeck-handle <handle>', 'Topdeck Handle')
15
+ .option('--untapped-id <id>', 'Untapped.gg Player ID (format: userId/playerCode)')
15
16
  .option('-v, --verbose', 'Print consistency check information to console')
16
17
  .action(async (options) => {
17
- if (!options.unityId && !options.mtgeloId && !options.meleeUser && !options.topdeckHandle) {
18
- console.error('Error: Please provide at least one search option (unity-id, mtgelo-id, melee-user, or topdeck-handle).')
18
+ if (!options.unityId && !options.mtgeloId && !options.meleeUser && !options.topdeckHandle && !options.untappedId) {
19
+ console.error('Error: Please provide at least one search option (unity-id, mtgelo-id, melee-user, topdeck-handle, or untapped-id).')
19
20
  process.exit(1)
20
21
  }
21
22
 
@@ -25,7 +26,8 @@ program
25
26
  '--unity-id': 'unity',
26
27
  '--mtgelo-id': 'mtgelo',
27
28
  '--melee-user': 'melee',
28
- '--topdeck-handle': 'topdeck'
29
+ '--topdeck-handle': 'topdeck',
30
+ '--untapped-id': 'untapped'
29
31
  }
30
32
 
31
33
  process.argv.forEach(arg => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mtg-playerinfo",
3
- "version": "1.2.2",
3
+ "version": "1.3.1",
4
4
  "description": "A simple NPM module and CLI tool to pull Magic: The Gathering player data from various sources",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -7,7 +7,8 @@ const targets = [
7
7
  { id: '3irvwtmk', url: 'https://mtgeloproject.net/profile/3irvwtmk', file: 'mtgElo.html' },
8
8
  { id: 'k0shiii', url: 'https://melee.gg/Profile/Index/k0shiii', file: 'melee.html' },
9
9
  { id: 'k0shiii', url: 'https://topdeck.gg/profile/@k0shiii', file: 'topdeck.html' },
10
- { id: 'm4VSTJShiXR1PCSCWaM9TBY0rcg1', url: 'https://topdeck.gg/profile/m4VSTJShiXR1PCSCWaM9TBY0rcg1/stats', file: 'topdeck.json' }
10
+ { id: 'm4VSTJShiXR1PCSCWaM9TBY0rcg1', url: 'https://topdeck.gg/profile/m4VSTJShiXR1PCSCWaM9TBY0rcg1/stats', file: 'topdeck.json' },
11
+ { id: 'e9d6fb9b-1f91-4063-8b28-0d46458d01a9/ZTATRXEQEJHUDOO52NWQCJGMQY', url: 'https://api.mtga.untapped.gg/api/v1/games/users/e9d6fb9b-1f91-4063-8b28-0d46458d01a9/players/ZTATRXEQEJHUDOO52NWQCJGMQY/?card_set=ECL', file: 'untapped.json' }
11
12
  ]
12
13
 
13
14
  async function updateTestData () {
@@ -0,0 +1,84 @@
1
+ const { request } = require('../utils/httpClient')
2
+
3
+ class UntappedFetcher {
4
+ async fetchById (id) {
5
+ const parts = id.split('/')
6
+ if (parts.length !== 2) {
7
+ console.error('Untapped ID must be in format "userId/playerCode"')
8
+ return null
9
+ }
10
+
11
+ const userId = parts[0]
12
+ const playerCode = parts[1]
13
+ const url = `https://mtga.untapped.gg/profile/${userId}/${playerCode}`
14
+ const apiUrl = `https://api.mtga.untapped.gg/api/v1/games/users/${userId}/players/${playerCode}/?card_set=ECL`
15
+
16
+ try {
17
+ const { data } = await request(apiUrl)
18
+ const matches = typeof data === 'string' ? JSON.parse(data) : data
19
+
20
+ if (!Array.isArray(matches) || matches.length === 0) {
21
+ console.warn(`No matches found for Untapped player ${id}`)
22
+ return null
23
+ }
24
+
25
+ return this.parseMatches(matches, url)
26
+ } catch (error) {
27
+ console.error(`Error fetching Untapped profile ${id}:`, error.message)
28
+ return null
29
+ }
30
+ }
31
+
32
+ parseMatches (matches, url) {
33
+ const data = {
34
+ source: 'Untapped.gg',
35
+ url,
36
+ mtga_rank: {}
37
+ }
38
+
39
+ const constructedMatch = this.findMostRecentByFormat(matches, 2)
40
+ const constructedRank = this.formatRank(constructedMatch)
41
+ if (constructedRank) {
42
+ data.mtga_rank.constructed = constructedRank
43
+ }
44
+
45
+ const limitedMatch = this.findMostRecentByFormat(matches, 1)
46
+ const limitedRank = this.formatRank(limitedMatch)
47
+ if (limitedRank) {
48
+ data.mtga_rank.limited = limitedRank
49
+ }
50
+
51
+ return data
52
+ }
53
+
54
+ formatRank (match) {
55
+ if (!match || !match.friendly_ranking_class_after) {
56
+ return null
57
+ }
58
+
59
+ if (match.friendly_ranking_class_after === 'Mythic') {
60
+ if (match.friendly_mythic_leaderboard_place_after !== null && match.friendly_mythic_leaderboard_place_after !== undefined) {
61
+ return `Mythic #${match.friendly_mythic_leaderboard_place_after}`
62
+ }
63
+ return null
64
+ }
65
+
66
+ if (match.friendly_ranking_tier_after !== null && match.friendly_ranking_tier_after !== undefined) {
67
+ return `${match.friendly_ranking_class_after} ${match.friendly_ranking_tier_after}`
68
+ }
69
+
70
+ return null
71
+ }
72
+
73
+ findMostRecentByFormat (matches, superFormat) {
74
+ const filteredMatches = matches.filter(match => match.super_format === superFormat)
75
+ if (filteredMatches.length === 0) {
76
+ return null
77
+ }
78
+ return filteredMatches.reduce((latest, current) => {
79
+ return (current.match_start > latest.match_start) ? current : latest
80
+ })
81
+ }
82
+ }
83
+
84
+ module.exports = UntappedFetcher
package/src/index.js CHANGED
@@ -2,6 +2,7 @@ const UnityLeagueFetcher = require('./fetchers/unityLeague')
2
2
  const MtgEloFetcher = require('./fetchers/mtgElo')
3
3
  const MeleeFetcher = require('./fetchers/melee')
4
4
  const TopdeckFetcher = require('./fetchers/topdeck')
5
+ const UntappedFetcher = require('./fetchers/untapped')
5
6
 
6
7
  class PlayerInfoManager {
7
8
  constructor () {
@@ -9,7 +10,8 @@ class PlayerInfoManager {
9
10
  unity: new UnityLeagueFetcher(),
10
11
  mtgelo: new MtgEloFetcher(),
11
12
  melee: new MeleeFetcher(),
12
- topdeck: new TopdeckFetcher()
13
+ topdeck: new TopdeckFetcher(),
14
+ untapped: new UntappedFetcher()
13
15
  }
14
16
  }
15
17
 
@@ -18,11 +20,12 @@ class PlayerInfoManager {
18
20
  unity: { option: 'unityId', fetcher: this.fetchers.unity },
19
21
  mtgelo: { option: 'mtgeloId', fetcher: this.fetchers.mtgelo },
20
22
  melee: { option: 'meleeUser', fetcher: this.fetchers.melee },
21
- topdeck: { option: 'topdeckHandle', fetcher: this.fetchers.topdeck }
23
+ topdeck: { option: 'topdeckHandle', fetcher: this.fetchers.topdeck },
24
+ untapped: { option: 'untappedId', fetcher: this.fetchers.untapped }
22
25
  }
23
26
 
24
27
  // Default order if no priority specified
25
- const defaultOrder = ['unity', 'mtgelo', 'melee', 'topdeck']
28
+ const defaultOrder = ['unity', 'mtgelo', 'melee', 'topdeck', 'untapped']
26
29
  const order = priorityOrder.length > 0 ? priorityOrder : defaultOrder
27
30
 
28
31
  const results = []
@@ -57,7 +60,7 @@ class PlayerInfoManager {
57
60
  if (seenUrls.has(res.url)) return
58
61
  seenUrls.add(res.url)
59
62
 
60
- const generalProps = ['name', 'photo', 'age', 'bio', 'team', 'country', 'hometown', 'pronouns', 'facebook', 'twitch', 'youtube']
63
+ const generalProps = ['name', 'photo', 'age', 'bio', 'team', 'country', 'hometown', 'pronouns', 'facebook', 'twitch', 'youtube', 'mtga_rank']
61
64
  generalProps.forEach(prop => {
62
65
  if (res[prop]) {
63
66
  if (!player.general[prop]) {
@@ -7,7 +7,7 @@
7
7
  <title>Profile k0shiii | Melee</title>
8
8
  <impact-site-verification value="4c243f18-8267-493f-a951-c8659ec151bc"></impact-site-verification>
9
9
  <meta content="@MeleePlatform" property="twitter:site"></meta>
10
- <meta content="0.3.62.22" name="version"></meta>
10
+ <meta content="0.3.63.85" name="version"></meta>
11
11
  <meta content="https://cdn.melee.gg/images/blankbrandimage.png" property="og:image"></meta>
12
12
  <meta content="Melee.gg Logo" property="twitter:image:alt"></meta>
13
13
  <meta content="https://melee.gg/" property="og:url"></meta>
@@ -36,9 +36,9 @@
36
36
  <meta name="author" content="Keyrune Incorporated"/>
37
37
  <meta property="og:site_name" content="Melee.gg"/>
38
38
  <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
39
- <link href="https://cdn.melee.gg/content/site.dependencies.min.css?v=0.3.62.22" rel="stylesheet"/>
39
+ <link href="https://cdn.melee.gg/content/site.dependencies.min.css?v=0.3.63.85" rel="stylesheet"/>
40
40
 
41
- <link href="/Content/site.min.css?v=0.3.62.22&lg=en" rel="stylesheet"/>
41
+ <link href="/Content/site.min.css?v=0.3.63.85&lg=en" rel="stylesheet"/>
42
42
 
43
43
 
44
44
 
@@ -47,7 +47,14 @@
47
47
  }}
48
48
  </script>
49
49
 
50
- <script id="data-tables-control-template" type="x-tmpl-mustache"> <div class="data-tables-filter-input-wrapper">
50
+ <script id="data-tables-control-template" type="x-tmpl-mustache">
51
+ {{#quickLookup}}
52
+ <div class="data-tables-quick-filter-input-wrapper">
53
+ <input id="{{tableId}}-quick-filter-input" class="form-control data-tables-quick-filter-input" placeholder="Quick search..." aria-quicksearch="{{tableId}}"/>
54
+ </div>
55
+ {{/quickLookup}}
56
+
57
+ <div class="data-tables-filter-input-wrapper">
51
58
  <input id="{{tableId}}-filter-input" class="form-control data-tables-filter-input" placeholder="Search results..." aria-controls="{{tableId}}"/>
52
59
  </div>
53
60
  {{#useFilters}}
@@ -572,36 +579,36 @@
572
579
  </div>
573
580
  </script>
574
581
 
575
- <script src="https://cdn.melee.gg/scripts/site.min.js?v=0.3.62.22"></script>
576
- <script src="https://cdn.melee.gg/scripts/font-awesome.min.js?v=0.3.62.22"></script>
577
- <script src="/Scripts/flattsware.core.min.js?v=0.3.62.22&lg=en"></script>
578
- <script src="/Scripts/flattsware.filters.min.js?v=0.3.62.22&lg=en"></script>
579
- <script src="/Scripts/flattsware.enums.min.js?v=0.3.62.22&lg=en"></script>
580
- <script src="/Scripts/flattsware.standings.min.js?v=0.3.62.22&lg=en"></script>
581
- <script src="/Scripts/flattsware.datatables.min.js?v=0.3.62.22&lg=en"></script>
582
- <script src="/Scripts/flattsware.datetime.min.js?v=0.3.62.22&lg=en"></script>
583
- <script src="/Scripts/flattsware.encode.min.js?v=0.3.62.22&lg=en"></script>
584
- <script src="/Scripts/flattsware.regex.min.js?v=0.3.62.22&lg=en"></script>
585
- <script src="/Scripts/flattsware.notify.min.js?v=0.3.62.22&lg=en"></script>
586
- <script src="/Scripts/flattsware.spinner.min.js?v=0.3.62.22&lg=en"></script>
587
- <script src="/Scripts/flattsware.forms.min.js?v=0.3.62.22&lg=en"></script>
588
- <script src="/Scripts/flattsware.decklist.min.js?v=0.3.62.22&lg=en"></script>
589
- <script src="/Scripts/flattsware.idle.min.js?v=0.3.62.22&lg=en"></script>
590
- <script src="/Scripts/flattsware.hovercard.min.js?v=0.3.62.22&lg=en"></script>
591
- <script src="/Scripts/flattsware.chart.min.js?v=0.3.62.22&lg=en"></script>
592
- <script src="/Scripts/flattsware.formats.min.js?v=0.3.62.22&lg=en"></script>
593
- <script src="/Scripts/flattsware.star-rating.min.js?v=0.3.62.22&lg=en"></script>
594
- <script src="/Scripts/flattsware.progress.min.js?v=0.3.62.22&lg=en"></script>
595
- <script src="/Scripts/flattsware.location.min.js?v=0.3.62.22&lg=en"></script>
596
- <script src="/Scripts/flattsware.players.min.js?v=0.3.62.22&lg=en"></script>
597
- <script src="/signalr/hubs?v=0.3.62.22"></script>
598
-
599
-
600
-
601
-
602
- <script src="/Scripts/wp-banners.min.js?v=0.3.62.22&lg=en"></script>
582
+ <script src="https://cdn.melee.gg/scripts/site.min.js?v=0.3.63.85"></script>
583
+ <script src="https://cdn.melee.gg/scripts/font-awesome.min.js?v=0.3.63.85"></script>
584
+ <script src="/Scripts/flattsware.core.min.js?v=0.3.63.85&lg=en"></script>
585
+ <script src="/Scripts/flattsware.filters.min.js?v=0.3.63.85&lg=en"></script>
586
+ <script src="/Scripts/flattsware.enums.min.js?v=0.3.63.85&lg=en"></script>
587
+ <script src="/Scripts/flattsware.standings.min.js?v=0.3.63.85&lg=en"></script>
588
+ <script src="/Scripts/flattsware.datatables.min.js?v=0.3.63.85&lg=en"></script>
589
+ <script src="/Scripts/flattsware.datetime.min.js?v=0.3.63.85&lg=en"></script>
590
+ <script src="/Scripts/flattsware.encode.min.js?v=0.3.63.85&lg=en"></script>
591
+ <script src="/Scripts/flattsware.regex.min.js?v=0.3.63.85&lg=en"></script>
592
+ <script src="/Scripts/flattsware.notify.min.js?v=0.3.63.85&lg=en"></script>
593
+ <script src="/Scripts/flattsware.spinner.min.js?v=0.3.63.85&lg=en"></script>
594
+ <script src="/Scripts/flattsware.forms.min.js?v=0.3.63.85&lg=en"></script>
595
+ <script src="/Scripts/flattsware.decklist.min.js?v=0.3.63.85&lg=en"></script>
596
+ <script src="/Scripts/flattsware.idle.min.js?v=0.3.63.85&lg=en"></script>
597
+ <script src="/Scripts/flattsware.hovercard.min.js?v=0.3.63.85&lg=en"></script>
598
+ <script src="/Scripts/flattsware.chart.min.js?v=0.3.63.85&lg=en"></script>
599
+ <script src="/Scripts/flattsware.formats.min.js?v=0.3.63.85&lg=en"></script>
600
+ <script src="/Scripts/flattsware.star-rating.min.js?v=0.3.63.85&lg=en"></script>
601
+ <script src="/Scripts/flattsware.progress.min.js?v=0.3.63.85&lg=en"></script>
602
+ <script src="/Scripts/flattsware.location.min.js?v=0.3.63.85&lg=en"></script>
603
+ <script src="/Scripts/flattsware.players.min.js?v=0.3.63.85&lg=en"></script>
604
+ <script src="/signalr/hubs?v=0.3.63.85"></script>
605
+
606
+
607
+
608
+
609
+ <script src="/Scripts/wp-banners.min.js?v=0.3.63.85&lg=en"></script>
603
610
  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-162951615-1"></script>
604
- <script src="/Scripts/google-analytics.min.js?v=0.3.62.22&lg=en"></script>
611
+ <script src="/Scripts/google-analytics.min.js?v=0.3.63.85&lg=en"></script>
605
612
 
606
613
  <!-- Datadog RUM (CDN async) -->
607
614
  <script>
@@ -1461,7 +1468,9 @@
1461
1468
  <a class="mega-menu-dropdown-link" href="/Organization/Index"><i class="fas fa-caret-right"></i><span class="ml-3">All Organizers</span></a>
1462
1469
  <a class="mega-menu-dropdown-link" href="/Profile/Organizations"><i class="fas fa-caret-right"></i><span class="ml-3">Your Organizations</span></a>
1463
1470
  <a class="mega-menu-dropdown-link" href="/Organization/Dashboard"><i class="fas fa-caret-right"></i><span class="ml-3">Your Organizer Dashboard</span></a>
1464
- <a class="mega-menu-dropdown-link" href="/Tournament/Edit"><i class="fas fa-caret-right"></i><span class="ml-3">Create a Tournament</span></a>
1471
+ <a class="mega-menu-dropdown-link tournament-create-modal" href="#">
1472
+ <i class="fas fa-caret-right"></i><span class="ml-3">Create a Tournament</span>
1473
+ </a>
1465
1474
  <a class="mega-menu-dropdown-link" href="/TournamentHub/Edit"><i class="fas fa-caret-right"></i><span class="ml-3">Create a Tournament Hub</span></a>
1466
1475
  </div>
1467
1476
  </div>
@@ -1781,7 +1790,7 @@ $(() => {
1781
1790
  <div class="footer-corp">
1782
1791
  <img width="40" height="54" src="/images/keyrune-logo.png"/>
1783
1792
  <span>
1784
- All original content on this page is &copy; 2019-2026 Keyrune Incorporated, its licensors, or its partners and may not be used or reproduced without explicit permission. All trademarks are the property of their respective owners. v0.3.62.22
1793
+ All original content on this page is &copy; 2019-2026 Keyrune Incorporated, its licensors, or its partners and may not be used or reproduced without explicit permission. All trademarks are the property of their respective owners. v0.3.63.85
1785
1794
  </span>
1786
1795
  </div>
1787
1796
 
@@ -1800,6 +1809,12 @@ $(() => {
1800
1809
  </div>
1801
1810
  </div>
1802
1811
 
1812
+ <script>
1813
+ $(document).on('click', '.add-organization-modal, .tournament-create-modal', (e) => {
1814
+ e.preventDefault();
1815
+ window.location.href = '/Account/SignIn';
1816
+ });
1817
+ </script>
1803
1818
 
1804
1819
  </footer>
1805
1820
 
@@ -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=1770645208359"></script><script>function viewTextDecklist(decklist, title, tournamentId = null, playerId = null, game = null) {
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=1770922016018"></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,7 +139,7 @@ gtag('config', 'G-56527VG23P');
139
139
  #viewDecklistOffcanvas {
140
140
  width: 660px !important;
141
141
  }
142
- }</style><!-- Hero Section with Cover Photo--><div class="position-relative overflow-hidden"><div class="position-relative" style="height: 280px; background-image: url(https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/aa6d70ad-de73-4c09-a4d7-1e64d5ed6d00/cover); background-size: cover; background-position: center;"><div class="position-absolute top-0 start-0 w-100 h-100 bg-dark" style="opacity: 0.2"></div></div><!-- Decorative wave divider--><div class="position-absolute bottom-0 w-100"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 100" preserveAspectRatio="none" style="height: 50px; width: 100%;"><path fill="#0a0e17" d="M0,32L60,42.7C120,53,240,75,360,74.7C480,75,600,53,720,42.7C840,32,960,32,1080,37.3C1200,43,1320,53,1380,58.7L1440,64L1440,100L1380,100C1320,100,1200,100,1080,100C960,100,840,100,720,100C600,100,480,100,360,100C240,100,120,100,60,100L0,100Z"></path></svg></div></div><!-- Profile Card--><div class="container position-relative"><div class="card bg-dark text-white shadow-lg border-0 rounded-4 mt-n5 position-relative" style="z-index: 2;"><div class="card-body py-4 px-md-4"><div class="row align-items-start"><!-- Avatar Column--><div class="col-lg-2 col-md-3 text-center text-md-start mb-4 mb-md-0"><div class="position-relative mx-auto" style="width: fit-content;"><img class="rounded-circle shadow-lg" src="https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/2a7b8d12-5924-4a58-5f9c-c0bf55766800/square" alt="Profile Picture" style="width: 140px; height: 140px; object-fit: cover; margin-top: -70px; border: 4px solid #0a0e17; background-color: #0a0e17;"></div></div><!-- Player Info & About--><div class="col-lg-5 col-md-9 my-sm-auto mb-4"><h2 class="text-white fw-bold mb-1">Björn Kimminich</h2><div class="d-flex flex-wrap mt-2 gap-2"><a class="btn btn-social bs-outline bs-twitter bs-dark me-2" href="https://twitter.com/bkimminich" target="_blank"><i class="fa-brands fa-twitter"></i></a></div><div class="d-flex flex-wrap gap-2 mt-3" id="badgeContainer"></div></div><!-- Stats Card--><div class="col-lg-5 mx-auto"><div class="card bg-dark border-0 shadow-lg rounded-4 position-relative overflow-hidden"><!-- Decorative gradient background--><div class="position-absolute top-0 start-0 w-100 h-100" style="background: linear-gradient(45deg, rgba(90, 79, 158, 0.2), rgba(0, 0, 0, 0)); opacity: 0.7; z-index: 0;"></div><div class="card-body position-relative p-4" style="z-index: 1;"><h4 class="text-white fw-bold mb-4" id="statsTitle">Player Stats</h4><div class="row g-3"><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-trophy text-warning fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="totalTournaments">0</h5><p class="text-light small mb-0">Tournaments</p></div></div></div><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-chart-line text-success fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="overallRecord">0-0-0</h5><p class="text-light small mb-0">Record</p></div></div></div><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-percentage text-info fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="overallWinRate">0%</h5><p class="text-light small mb-0">Win Rate</p></div></div></div><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-bolt text-danger fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="conversionRate">0%</h5><p class="text-light small mb-0">Conversion</p></div></div></div></div></div></div></div></div></div></div><!-- Modern Pill Tabs--><div class="card bg-dark border-0 shadow-sm rounded-4 mt-4 p-3"><div class="card-body p-0"><ul class="nav nav-pills gap-2 mb-0" role="tablist"><li class="nav-item"><a class="nav-link active py-3 rounded-3" href="#history" data-bs-toggle="tab"><i class="fa-solid fa-trophy me-2"></i>Tournaments</a></li></ul></div></div><!-- Content tabs--><div class="tab-content mt-4 mb-5"><!-- Tournament History Tab--><div class="tab-pane fade show active" id="history"><div class="card bg-dark border-0 rounded-4 shadow-lg py-4 px-3 px-sm-4"><!-- Filters Section--><div class="d-flex flex-wrap gap-3 mb-4 align-items-center"><!-- Format Dropdown - Modern style--><div class="dropdown"><button class="btn btn-outline-secondary dropdown-toggle" id="formatDropdown" type="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fa-solid fa-layer-group me-2"></i><span id="formatDropdownLabel">All Formats</span></button><ul class="dropdown-menu border-0 shadow"><li><a class="dropdown-item" href="#" data-value="all">All Formats</a></li></ul></div><!-- Year Dropdown - Modern style--><div class="dropdown"><button class="btn btn-outline-secondary dropdown-toggle" id="yearDropdown" type="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fa-solid fa-calendar-alt me-2"></i><span id="yearDropdownLabel">All Years</span></button><ul class="dropdown-menu border-0 shadow"><li><a class="dropdown-item" href="#" data-value="all">All Years</a></li></ul></div></div><h3 class="card-title text-white fw-bold"><i class="fa-solid fa-history me-2 text-info"></i>Tournament History</h3><div class="tournament-list" id="tournamentList"></div></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#4e2d21203a2f2d3a0e3a213e2a2b2d25602929">Contact Us</a></li><li><a class="widget-link" href="/cdn-cgi/l/email-protection#98f5fdfcf1f9d8ecf7e8fcfdfbf3b6ffff">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>document.addEventListener('DOMContentLoaded', function () {
142
+ }</style><!-- Hero Section with Cover Photo--><div class="position-relative overflow-hidden"><div class="position-relative" style="height: 280px; background-image: url(https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/aa6d70ad-de73-4c09-a4d7-1e64d5ed6d00/cover); background-size: cover; background-position: center;"><div class="position-absolute top-0 start-0 w-100 h-100 bg-dark" style="opacity: 0.2"></div></div><!-- Decorative wave divider--><div class="position-absolute bottom-0 w-100"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 100" preserveAspectRatio="none" style="height: 50px; width: 100%;"><path fill="#0a0e17" d="M0,32L60,42.7C120,53,240,75,360,74.7C480,75,600,53,720,42.7C840,32,960,32,1080,37.3C1200,43,1320,53,1380,58.7L1440,64L1440,100L1380,100C1320,100,1200,100,1080,100C960,100,840,100,720,100C600,100,480,100,360,100C240,100,120,100,60,100L0,100Z"></path></svg></div></div><!-- Profile Card--><div class="container position-relative"><div class="card bg-dark text-white shadow-lg border-0 rounded-4 mt-n5 position-relative" style="z-index: 2;"><div class="card-body py-4 px-md-4"><div class="row align-items-start"><!-- Avatar Column--><div class="col-lg-2 col-md-3 text-center text-md-start mb-4 mb-md-0"><div class="position-relative mx-auto" style="width: fit-content;"><img class="rounded-circle shadow-lg" src="https://imagedelivery.net/kN_u_RUfFF6xsGMKYWhO1g/2a7b8d12-5924-4a58-5f9c-c0bf55766800/square" alt="Profile Picture" style="width: 140px; height: 140px; object-fit: cover; margin-top: -70px; border: 4px solid #0a0e17; background-color: #0a0e17;"></div></div><!-- Player Info & About--><div class="col-lg-5 col-md-9 my-sm-auto mb-4"><h2 class="text-white fw-bold mb-1">Björn Kimminich</h2><div class="d-flex flex-wrap mt-2 gap-2"><a class="btn btn-social bs-outline bs-twitter bs-dark me-2" href="https://twitter.com/bkimminich" target="_blank"><i class="fa-brands fa-twitter"></i></a></div><div class="d-flex flex-wrap gap-2 mt-3" id="badgeContainer"></div></div><!-- Stats Card--><div class="col-lg-5 mx-auto"><div class="card bg-dark border-0 shadow-lg rounded-4 position-relative overflow-hidden"><!-- Decorative gradient background--><div class="position-absolute top-0 start-0 w-100 h-100" style="background: linear-gradient(45deg, rgba(90, 79, 158, 0.2), rgba(0, 0, 0, 0)); opacity: 0.7; z-index: 0;"></div><div class="card-body position-relative p-4" style="z-index: 1;"><h4 class="text-white fw-bold mb-4" id="statsTitle">Player Stats</h4><div class="row g-3"><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-trophy text-warning fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="totalTournaments">0</h5><p class="text-light small mb-0">Tournaments</p></div></div></div><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-chart-line text-success fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="overallRecord">0-0-0</h5><p class="text-light small mb-0">Record</p></div></div></div><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-percentage text-info fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="overallWinRate">0%</h5><p class="text-light small mb-0">Win Rate</p></div></div></div><div class="col-6"><div class="d-flex align-items-center"><i class="fa-solid fa-bolt text-danger fs-3 me-3"></i><div><h5 class="text-white mb-0 fw-bold" id="conversionRate">0%</h5><p class="text-light small mb-0">Conversion</p></div></div></div></div></div></div></div></div></div></div><!-- Modern Pill Tabs--><div class="card bg-dark border-0 shadow-sm rounded-4 mt-4 p-3"><div class="card-body p-0"><ul class="nav nav-pills gap-2 mb-0" role="tablist"><li class="nav-item"><a class="nav-link active py-3 rounded-3" href="#history" data-bs-toggle="tab"><i class="fa-solid fa-trophy me-2"></i>Tournaments</a></li></ul></div></div><!-- Content tabs--><div class="tab-content mt-4 mb-5"><!-- Tournament History Tab--><div class="tab-pane fade show active" id="history"><div class="card bg-dark border-0 rounded-4 shadow-lg py-4 px-3 px-sm-4"><!-- Filters Section--><div class="d-flex flex-wrap gap-3 mb-4 align-items-center"><!-- Format Dropdown - Modern style--><div class="dropdown"><button class="btn btn-outline-secondary dropdown-toggle" id="formatDropdown" type="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fa-solid fa-layer-group me-2"></i><span id="formatDropdownLabel">All Formats</span></button><ul class="dropdown-menu border-0 shadow"><li><a class="dropdown-item" href="#" data-value="all">All Formats</a></li></ul></div><!-- Year Dropdown - Modern style--><div class="dropdown"><button class="btn btn-outline-secondary dropdown-toggle" id="yearDropdown" type="button" data-bs-toggle="dropdown" aria-expanded="false"><i class="fa-solid fa-calendar-alt me-2"></i><span id="yearDropdownLabel">All Years</span></button><ul class="dropdown-menu border-0 shadow"><li><a class="dropdown-item" href="#" data-value="all">All Years</a></li></ul></div></div><h3 class="card-title text-white fw-bold"><i class="fa-solid fa-history me-2 text-info"></i>Tournament History</h3><div class="tournament-list" id="tournamentList"></div></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#f695999882979582b68299869293959dd89191">Contact Us</a></li><li><a class="widget-link" href="/cdn-cgi/l/email-protection#c5a8a0a1aca485b1aab5a1a0a6aeeba2a2">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>document.addEventListener('DOMContentLoaded', function () {
143
143
  // Template variables for decklist viewing
144
144
  const playerUsername = "@k0shiii";
145
145
  const playerId = "m4VSTJShiXR1PCSCWaM9TBY0rcg1";
@@ -1 +1 @@
1
- {"gameFormats":{"Magic: The Gathering: Modern":[{"id":"modern-championship-buden-brawl-open-2025-copy","name":"Modern Championship @ Buden Brawl Open 2025","date":"2025-03-29T09:00:00.000Z","record":"4-2-0","placement":"16th","placementNumber":16,"size":54,"game":"Magic: The Gathering","bracketLink":"https://topdeck.gg/bracket/modern-championship-buden-brawl-open-2025-copy","topCut":8,"rawFormat":"Modern"}],"Magic: The Gathering: EDH":[{"id":"the-invasion-2025-cedh-championship","name":"The Invasion 2025 - cEDH Championship","date":"2025-10-04T06:00:00.000Z","record":"0-4-1","placement":"118th","placementNumber":118,"size":124,"game":"Magic: The Gathering","bracketLink":"https://topdeck.gg/bracket/the-invasion-2025-cedh-championship","topCut":40,"rawFormat":"EDH"}]},"topFinishes":{"Magic: The Gathering: Modern":{"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0},"Magic: The Gathering: EDH":{"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0}},"yearlyStats":{"2025":{"Magic: The Gathering: Modern":{"totalTournaments":1,"topCutEligible":1,"wins":4,"losses":2,"draws":0,"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0},"Magic: The Gathering: EDH":{"totalTournaments":1,"topCutEligible":1,"wins":0,"losses":4,"draws":1,"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0},"overall":{"totalTournaments":2,"topCutEligible":2,"wins":4,"losses":6,"draws":1,"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0}}},"tdcsData":null,"leaguesData":null}
1
+ {"gameFormats":{"Magic: The Gathering: Modern":[{"id":"modern-championship-buden-brawl-open-2025-copy","name":"Modern Championship @ Buden Brawl Open 2025","date":"2025-03-29T09:00:00.000Z","record":"4-2-0","placement":"16th","placementNumber":16,"size":54,"game":"Magic: The Gathering","bracketLink":"https://topdeck.gg/bracket/modern-championship-buden-brawl-open-2025-copy","topCut":8,"rawFormat":"Modern"}],"Magic: The Gathering: EDH":[{"id":"the-invasion-2025-cedh-championship","name":"The Invasion 2025 - cEDH Championship","date":"2025-10-04T06:00:00.000Z","record":"0-4-1","placement":"118th","placementNumber":118,"size":124,"game":"Magic: The Gathering","bracketLink":"https://topdeck.gg/bracket/the-invasion-2025-cedh-championship","topCut":40,"rawFormat":"EDH"}]},"topFinishes":{"Magic: The Gathering: Modern":{"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0},"Magic: The Gathering: EDH":{"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0}},"yearlyStats":{"2025":{"Magic: The Gathering: Modern":{"totalTournaments":1,"topCutEligible":1,"wins":4,"losses":2,"draws":0,"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0},"Magic: The Gathering: EDH":{"totalTournaments":1,"topCutEligible":1,"wins":0,"losses":4,"draws":1,"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0},"overall":{"totalTournaments":2,"topCutEligible":2,"wins":4,"losses":6,"draws":1,"firstPlaceFinishes":0,"top2":0,"top4":0,"top8":0,"top10":0,"top16":0}}},"tdcsData":null,"leaguesData":null}