Skip to content

Instantly share code, notes, and snippets.

@joshbedo
Created December 5, 2024 18:49
Show Gist options
  • Save joshbedo/6169cf6ddaf66f4be6cf8bd49db02903 to your computer and use it in GitHub Desktop.
Save joshbedo/6169cf6ddaf66f4be6cf8bd49db02903 to your computer and use it in GitHub Desktop.
magic
<!DOCTYPE html>
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="UTF-8" />
<script type="text/javascript">/* wpack.io publicPath */window.__wpackIodpIntroToursdist='https://mtg-packs.com/wp-content/plugins/dp-intro-tours/dist/';</script><meta name="viewport" content="width=device-width, initial-scale=1" />
<style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style>
<!-- Jetpack Site Verification Tags -->
<meta name="google-site-verification" content="0cV2nle2CWV1Gc__ZivCZNUDPyympnRqD8cfT4bmbPo" />
<meta name="yandex-verification" content="0339afbdd7769580" />
<meta name="facebook-domain-verification" content="e311vtvk6cd30j4y9u3i9dwif363gy" />
<!-- Google tag (gtag.js) Consent Mode dataLayer added by Site Kit -->
<script id="google_gtagjs-js-consent-mode-data-layer">
window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {"ad_personalization":"denied","ad_storage":"denied","ad_user_data":"denied","analytics_storage":"denied","functionality_storage":"denied","security_storage":"denied","personalization_storage":"denied","region":["AT","BE","BG","CH","CY","CZ","DE","DK","EE","ES","FI","FR","GB","GR","HR","HU","IE","IS","IT","LI","LT","LU","LV","MT","NL","NO","PL","PT","RO","SE","SI","SK"],"wait_for_update":500});
window._googlesitekitConsentCategoryMap = {"statistics":["analytics_storage"],"marketing":["ad_storage","ad_user_data","ad_personalization"],"functional":["functionality_storage","security_storage"],"preferences":["personalization_storage"]};
window._googlesitekitConsents = {"ad_personalization":"denied","ad_storage":"denied","ad_user_data":"denied","analytics_storage":"denied","functionality_storage":"denied","security_storage":"denied","personalization_storage":"denied","region":["AT","BE","BG","CH","CY","CZ","DE","DK","EE","ES","FI","FR","GB","GR","HR","HU","IE","IS","IT","LI","LT","LU","LV","MT","NL","NO","PL","PT","RO","SE","SI","SK"],"wait_for_update":500};
</script>
<!-- End Google tag (gtag.js) Consent Mode dataLayer added by Site Kit -->
<!-- Search Engine Optimization by Rank Math - https://rankmath.com/ -->
<meta name="robots" content="follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large"/>
<link rel="canonical" href="https://mtg-packs.com/" />
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
<meta property="og:title" content="- Magic the Gathering (MTG) Pack Simulator" />
<meta property="og:description" content="MTG Pack Simulator MTG Pack Simulator Getting Started with the MTG Pack Simulator: Select a Set: Begin by choosing the set you wish to explore. Our simulator features a wide range of sets, ensuring you find one that piques your interest. Choose a Pack Type: Next, decide on the type of pack you want to [&hellip;]" />
<meta property="og:url" content="https://mtg-packs.com/" />
<meta property="og:site_name" content="Magic the Gathering (MTG) Pack Simulator" />
<meta property="og:updated_time" content="2024-12-02T17:16:51-05:00" />
<meta property="article:published_time" content="2023-08-24T14:49:36-04:00" />
<meta property="article:modified_time" content="2024-12-02T17:16:51-05:00" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="- Magic the Gathering (MTG) Pack Simulator" />
<meta name="twitter:description" content="MTG Pack Simulator MTG Pack Simulator Getting Started with the MTG Pack Simulator: Select a Set: Begin by choosing the set you wish to explore. Our simulator features a wide range of sets, ensuring you find one that piques your interest. Choose a Pack Type: Next, decide on the type of pack you want to [&hellip;]" />
<meta name="twitter:label1" content="Written by" />
<meta name="twitter:data1" content="Willingswan" />
<meta name="twitter:label2" content="Time to read" />
<meta name="twitter:data2" content="1 minute" />
<script type="application/ld+json" class="rank-math-schema">{"@context":"https://schema.org","@graph":[{"@type":["HobbyShop","Organization"],"@id":"https://mtg-packs.com/#organization","name":"Magic the Gathering (MTG) Pack Simulator","url":"https://mtg-packs.com","sameAs":["https://www.facebook.com/profile.php?id=61558866720988"],"logo":{"@type":"ImageObject","@id":"https://mtg-packs.com/#logo","url":"https://mtg-packs.com/wp-content/uploads/2023/12/DALL\u00b7E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png","contentUrl":"https://mtg-packs.com/wp-content/uploads/2023/12/DALL\u00b7E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png","caption":"Magic the Gathering (MTG) Pack Simulator","inLanguage":"en-US","width":"1024","height":"1024"},"openingHours":["Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday 09:00-17:00"],"image":{"@id":"https://mtg-packs.com/#logo"}},{"@type":"WebSite","@id":"https://mtg-packs.com/#website","url":"https://mtg-packs.com","name":"Magic the Gathering (MTG) Pack Simulator","alternateName":"MTG Packs","publisher":{"@id":"https://mtg-packs.com/#organization"},"inLanguage":"en-US","potentialAction":{"@type":"SearchAction","target":"https://mtg-packs.com/?s={search_term_string}","query-input":"required name=search_term_string"}},{"@type":"ImageObject","@id":"//a.impactradius-go.com/display-ad/21018-2220337","url":"//a.impactradius-go.com/display-ad/21018-2220337","width":"200","height":"200","inLanguage":"en-US"},{"@type":"WebPage","@id":"https://mtg-packs.com/#webpage","url":"https://mtg-packs.com/","name":"- Magic the Gathering (MTG) Pack Simulator","datePublished":"2023-08-24T14:49:36-04:00","dateModified":"2024-12-02T17:16:51-05:00","about":{"@id":"https://mtg-packs.com/#organization"},"isPartOf":{"@id":"https://mtg-packs.com/#website"},"primaryImageOfPage":{"@id":"//a.impactradius-go.com/display-ad/21018-2220337"},"inLanguage":"en-US"},{"@type":"Person","@id":"https://mtg-packs.com/author/leettoothpaste/","name":"Willingswan","url":"https://mtg-packs.com/author/leettoothpaste/","image":{"@type":"ImageObject","@id":"https://secure.gravatar.com/avatar/45ef2dd70cd0eb831d4d5191e366a2e1?s=96&amp;d=identicon&amp;r=g","url":"https://secure.gravatar.com/avatar/45ef2dd70cd0eb831d4d5191e366a2e1?s=96&amp;d=identicon&amp;r=g","caption":"Willingswan","inLanguage":"en-US"},"sameAs":["http://mtg-packs.com"],"worksFor":{"@id":"https://mtg-packs.com/#organization"}},{"@type":"Article","headline":"- Magic the Gathering (MTG) Pack Simulator","datePublished":"2023-08-24T14:49:36-04:00","dateModified":"2024-12-02T17:16:51-05:00","author":{"@id":"https://mtg-packs.com/author/leettoothpaste/","name":"Willingswan"},"publisher":{"@id":"https://mtg-packs.com/#organization"},"description":"/* Additional Media Queries for Smaller Screens */","name":"- Magic the Gathering (MTG) Pack Simulator","@id":"https://mtg-packs.com/#richSnippet","isPartOf":{"@id":"https://mtg-packs.com/#webpage"},"image":{"@id":"//a.impactradius-go.com/display-ad/21018-2220337"},"inLanguage":"en-US","mainEntityOfPage":{"@id":"https://mtg-packs.com/#webpage"}}]}</script>
<!-- /Rank Math WordPress SEO plugin -->
<title>- Magic the Gathering (MTG) Pack Simulator</title>
<link rel='dns-prefetch' href='//secure.gravatar.com' />
<link rel='dns-prefetch' href='//www.googletagmanager.com' />
<link rel='dns-prefetch' href='//stats.wp.com' />
<link rel='dns-prefetch' href='//widgets.wp.com' />
<link rel='dns-prefetch' href='//jetpack.wordpress.com' />
<link rel='dns-prefetch' href='//s0.wp.com' />
<link rel='dns-prefetch' href='//public-api.wordpress.com' />
<link rel='dns-prefetch' href='//0.gravatar.com' />
<link rel='dns-prefetch' href='//1.gravatar.com' />
<link rel='dns-prefetch' href='//2.gravatar.com' />
<link rel='dns-prefetch' href='//pagead2.googlesyndication.com' />
<link rel='preconnect' href='//i0.wp.com' />
<link rel='preconnect' href='//c0.wp.com' />
<link rel="alternate" type="application/octet-stream" title="Magic the Gathering (MTG) Pack Simulator &raquo; Feed" href="https://mtg-packs.com/feed/" />
<link rel="alternate" type="application/octet-stream" title="Magic the Gathering (MTG) Pack Simulator &raquo; Comments Feed" href="https://mtg-packs.com/comments/feed/" />
<script>
window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.0.3\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/mtg-packs.com\/wp-includes\/js\/wp-emoji-release.min.js?ver=6.7.1"}};
/*! This file is auto-generated */
!function(i,n){var o,s,e;function c(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function p(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data),r=(e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0),new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data));return t.every(function(e,t){return e===r[t]})}function u(e,t,n){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\uddfa\ud83c\uddf3","\ud83c\uddfa\u200b\ud83c\uddf3")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!n(e,"\ud83d\udc26\u200d\u2b1b","\ud83d\udc26\u200b\u2b1b")}return!1}function f(e,t,n){var r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):i.createElement("canvas"),a=r.getContext("2d",{willReadFrequently:!0}),o=(a.textBaseline="top",a.font="600 32px Arial",{});return e.forEach(function(e){o[e]=t(a,e,n)}),o}function t(e){var t=i.createElement("script");t.src=e,t.defer=!0,i.head.appendChild(t)}"undefined"!=typeof Promise&&(o="wpEmojiSettingsSupports",s=["flag","emoji"],n.supports={everything:!0,everythingExceptFlag:!0},e=new Promise(function(e){i.addEventListener("DOMContentLoaded",e,{once:!0})}),new Promise(function(t){var n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"}),a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=function(e){c(n=e.data),a.terminate(),t(n)})}catch(e){}c(n=f(s,u,p))}t(n)}).then(function(e){for(var t in e)n.supports[t]=e[t],n.supports.everything=n.supports.everything&&n.supports[t],"flag"!==t&&(n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&n.supports[t]);n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&!n.supports.flag,n.DOMReady=!1,n.readyCallback=function(){n.DOMReady=!0}}).then(function(){return e}).then(function(){var e;n.supports.everything||(n.readyCallback(),(e=n.source||{}).concatemoji?t(e.concatemoji):e.wpemoji&&e.twemoji&&(t(e.twemoji),t(e.wpemoji)))}))}((window,document),window._wpemojiSettings);
</script>
<link rel='stylesheet' id='all-css-1279f808a52d2e71614de31ad9c8b5c4' href='https://mtg-packs.com/_static/??-eJydkttOwzAQRH+IrQkpIjwgPgX5skmX+CbvOlH/HjeAkILah75YGnlmvHvkNYNNUTCKyr5OFFl9omRtZxWSqx5ZFfRa0EFOLDt1sMwP6/+KqTZpsEzKVPJOGZ/sDJ5M0eX8rVhFvdCkhVJULGeP18psSjMhxCRkUTWTGkuzHALFaxGXgaKUBJJqaZJYVNAU2wUJGM0I25PwbI/GDs7cXUQW5ITht68bXseu6+21vqzJQcDQ2PCJMkMu6W8ljA1VG+7+9KILbUg/un3JNmajWfBiuI18/wU8ze28GWEShIIL4cpKM6P8BBo1HHX1ckm+h7fupX8aHoehP34Bd87xIQ==' type='text/css' media='all' />
<style id='wpackio_dpIntroToursmain_main_dpit_base_style_5c4bc8db_css_style-inline-css'>
:root{--dp-z-index-base: 16777200;}
</style>
<style id='site-reviews-inline-css'>
:root{--glsr-star-empty:url(https://mtg-packs.com/wp-content/plugins/site-reviews/assets/images/stars/default/star-empty.svg);--glsr-star-error:url(https://mtg-packs.com/wp-content/plugins/site-reviews/assets/images/stars/default/star-error.svg);--glsr-star-full:url(https://mtg-packs.com/wp-content/plugins/site-reviews/assets/images/stars/default/star-full.svg);--glsr-star-half:url(https://mtg-packs.com/wp-content/plugins/site-reviews/assets/images/stars/default/star-half.svg)}
</style>
<style id='wp-block-group-inline-css'>
.wp-block-group{box-sizing:border-box}:where(.wp-block-group.wp-block-group-is-layout-constrained){position:relative}
</style>
<style id='wp-block-navigation-link-inline-css'>
.wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none}.link-ui-tools{border-top:1px solid #f0f0f0;padding:8px}.link-ui-block-inserter{padding-top:8px}.link-ui-block-inserter__back{margin-left:8px;text-transform:uppercase}
</style>
<style id='wp-block-paragraph-inline-css'>
.is-small-text{font-size:.875em}.is-regular-text{font-size:1em}.is-large-text{font-size:2.25em}.is-larger-text{font-size:3em}.has-drop-cap:not(:focus):first-letter{float:left;font-size:8.4em;font-style:normal;font-weight:100;line-height:.68;margin:.05em .1em 0 0;text-transform:uppercase}body.rtl .has-drop-cap:not(:focus):first-letter{float:none;margin-left:.1em}p.has-drop-cap.has-background{overflow:hidden}:root :where(p.has-background){padding:1.25em 2.375em}:where(p.has-text-color:not(.has-link-color)) a{color:inherit}p.has-text-align-left[style*="writing-mode:vertical-lr"],p.has-text-align-right[style*="writing-mode:vertical-rl"]{rotate:180deg}
</style>
<style id='wp-block-post-title-inline-css'>
.wp-block-post-title{box-sizing:border-box;word-break:break-word}.wp-block-post-title :where(a){display:inline-block;font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;text-decoration:inherit}
</style>
<style id='wp-block-post-featured-image-inline-css'>
.wp-block-post-featured-image{margin-left:0;margin-right:0}.wp-block-post-featured-image a{display:block;height:100%}.wp-block-post-featured-image :where(img){box-sizing:border-box;height:auto;max-width:100%;vertical-align:bottom;width:100%}.wp-block-post-featured-image.alignfull img,.wp-block-post-featured-image.alignwide img{width:100%}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim{background-color:#000;inset:0;position:absolute}.wp-block-post-featured-image{position:relative}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-gradient{background-color:initial}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-0{opacity:0}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-10{opacity:.1}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-20{opacity:.2}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-30{opacity:.3}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-40{opacity:.4}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-50{opacity:.5}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-60{opacity:.6}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-70{opacity:.7}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-80{opacity:.8}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-90{opacity:.9}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-100{opacity:1}.wp-block-post-featured-image:where(.alignleft,.alignright){width:100%}
</style>
<style id='wp-block-post-content-inline-css'>
.wp-block-post-content{display:flow-root}
</style>
<style id='wp-block-spacer-inline-css'>
.wp-block-spacer{clear:both}
</style>
<style id='wp-emoji-styles-inline-css'>
img.wp-smiley, img.emoji {
display: inline !important;
border: none !important;
box-shadow: none !important;
height: 1em !important;
width: 1em !important;
margin: 0 0.07em !important;
vertical-align: -0.1em !important;
background: none !important;
padding: 0 !important;
}
</style>
<style id='wp-block-library-inline-css'>
:root{--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,161;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px;--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color)}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-element-button{cursor:pointer}:root{--wp--preset--font-size--normal:16px;--wp--preset--font-size--huge:42px}:root .has-very-light-gray-background-color{background-color:#eee}:root .has-very-dark-gray-background-color{background-color:#313131}:root .has-very-light-gray-color{color:#eee}:root .has-very-dark-gray-color{color:#313131}:root .has-vivid-green-cyan-to-vivid-cyan-blue-gradient-background{background:linear-gradient(135deg,#00d084,#0693e3)}:root .has-purple-crush-gradient-background{background:linear-gradient(135deg,#34e2e4,#4721fb 50%,#ab1dfe)}:root .has-hazy-dawn-gradient-background{background:linear-gradient(135deg,#faaca8,#dad0ec)}:root .has-subdued-olive-gradient-background{background:linear-gradient(135deg,#fafae1,#67a671)}:root .has-atomic-cream-gradient-background{background:linear-gradient(135deg,#fdd79a,#004a59)}:root .has-nightshade-gradient-background{background:linear-gradient(135deg,#330968,#31cdcf)}:root .has-midnight-gradient-background{background:linear-gradient(135deg,#020381,#2874fc)}.has-regular-font-size{font-size:1em}.has-larger-font-size{font-size:2.625em}.has-normal-font-size{font-size:var(--wp--preset--font-size--normal)}.has-huge-font-size{font-size:var(--wp--preset--font-size--huge)}.has-text-align-center{text-align:center}.has-text-align-left{text-align:left}.has-text-align-right{text-align:right}#end-resizable-editor-section{display:none}.aligncenter{clear:both}.items-justified-left{justify-content:flex-start}.items-justified-center{justify-content:center}.items-justified-right{justify-content:flex-end}.items-justified-space-between{justify-content:space-between}.screen-reader-text{word-wrap:normal!important;border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.screen-reader-text:focus{background-color:#ddd;clip-path:none;color:#444;display:block;font-size:1em;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}html :where(.has-border-color){border-style:solid}html :where([style*=border-top-color]){border-top-style:solid}html :where([style*=border-right-color]){border-right-style:solid}html :where([style*=border-bottom-color]){border-bottom-style:solid}html :where([style*=border-left-color]){border-left-style:solid}html :where([style*=border-width]){border-style:solid}html :where([style*=border-top-width]){border-top-style:solid}html :where([style*=border-right-width]){border-right-style:solid}html :where([style*=border-bottom-width]){border-bottom-style:solid}html :where([style*=border-left-width]){border-left-style:solid}html :where(img[class*=wp-image-]){height:auto;max-width:100%}:where(figure){margin:0 0 1em}html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:var(--wp-admin--admin-bar--height,0px)}@media screen and (max-width:600px){html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:0px}}
.has-text-align-justify{text-align:justify;}
</style>
<style id='wp-block-template-skip-link-inline-css'>
.skip-link.screen-reader-text {
border: 0;
clip: rect(1px,1px,1px,1px);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute !important;
width: 1px;
word-wrap: normal !important;
}
.skip-link.screen-reader-text:focus {
background-color: #eee;
clip: auto !important;
clip-path: none;
color: #444;
display: block;
font-size: 1em;
height: auto;
left: 5px;
line-height: normal;
padding: 15px 23px 14px;
text-decoration: none;
top: 5px;
width: auto;
z-index: 100000;
}
</style>
<style id='global-styles-inline-css'>
:root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--primary: #11181F;--wp--preset--color--secondary: #005ae1;--wp--preset--color--foreground: #474747;--wp--preset--color--background: #ffffff;--wp--preset--color--tertiary: #f7f9fd;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: clamp(0.825rem, 0.825rem + ((1vw - 0.2rem) * 0.433), 1.0625rem);--wp--preset--font-size--medium: clamp(1rem, 1rem + ((1vw - 0.2rem) * 0.455), 1.25rem);--wp--preset--font-size--large: clamp(1.75rem, 1.75rem + ((1vw - 0.2rem) * 0.455), 2rem);--wp--preset--font-size--x-large: clamp(2.5rem, 2.5rem + ((1vw - 0.2rem) * 0.909), 3rem);--wp--preset--font-family--albert-sans: 'Albert Sans', sans-serif;--wp--preset--font-family--alegreya: Alegreya, serif;--wp--preset--font-family--arvo: Arvo, serif;--wp--preset--font-family--bodoni-moda: 'Bodoni Moda', serif;--wp--preset--font-family--bricolage-grotesque: 'Bricolage Grotesque', sans-serif;--wp--preset--font-family--cabin: Cabin, sans-serif;--wp--preset--font-family--chivo: Chivo, sans-serif;--wp--preset--font-family--commissioner: Commissioner, sans-serif;--wp--preset--font-family--cormorant: Cormorant, serif;--wp--preset--font-family--courier-prime: 'Courier Prime', monospace;--wp--preset--font-family--crimson-pro: 'Crimson Pro', serif;--wp--preset--font-family--dm-mono: 'DM Mono', monospace;--wp--preset--font-family--dm-sans: 'DM Sans', sans-serif;--wp--preset--font-family--dm-serif-display: 'DM Serif Display', serif;--wp--preset--font-family--domine: Domine, serif;--wp--preset--font-family--eb-garamond: 'EB Garamond', serif;--wp--preset--font-family--epilogue: Epilogue, sans-serif;--wp--preset--font-family--fahkwang: Fahkwang, sans-serif;--wp--preset--font-family--figtree: Figtree, sans-serif;--wp--preset--font-family--fira-sans: 'Fira Sans', sans-serif;--wp--preset--font-family--fjalla-one: 'Fjalla One', sans-serif;--wp--preset--font-family--fraunces: Fraunces, serif;--wp--preset--font-family--gabarito: Gabarito, system-ui;--wp--preset--font-family--ibm-plex-mono: 'IBM Plex Mono', monospace;--wp--preset--font-family--ibm-plex-sans: 'IBM Plex Sans', sans-serif;--wp--preset--font-family--ibarra-real-nova: 'Ibarra Real Nova', serif;--wp--preset--font-family--instrument-serif: 'Instrument Serif', serif;--wp--preset--font-family--inter: Inter;--wp--preset--font-family--josefin-sans: 'Josefin Sans', sans-serif;--wp--preset--font-family--jost: Jost, sans-serif;--wp--preset--font-family--libre-baskerville: 'Libre Baskerville', serif;--wp--preset--font-family--libre-franklin: 'Libre Franklin', sans-serif;--wp--preset--font-family--literata: Literata;--wp--preset--font-family--lora: Lora, serif;--wp--preset--font-family--merriweather: Merriweather, serif;--wp--preset--font-family--montserrat: Montserrat, sans-serif;--wp--preset--font-family--newsreader: Newsreader, serif;--wp--preset--font-family--noto-sans-mono: 'Noto Sans Mono', sans-serif;--wp--preset--font-family--nunito: Nunito, sans-serif;--wp--preset--font-family--open-sans: 'Open Sans', sans-serif;--wp--preset--font-family--overpass: Overpass, sans-serif;--wp--preset--font-family--pt-serif: 'PT Serif', serif;--wp--preset--font-family--petrona: Petrona, serif;--wp--preset--font-family--piazzolla: Piazzolla, serif;--wp--preset--font-family--playfair-display: 'Playfair Display', serif;--wp--preset--font-family--plus-jakarta-sans: 'Plus Jakarta Sans', sans-serif;--wp--preset--font-family--poppins: Poppins, sans-serif;--wp--preset--font-family--raleway: Raleway, sans-serif;--wp--preset--font-family--roboto: Roboto, sans-serif;--wp--preset--font-family--roboto-slab: 'Roboto Slab', serif;--wp--preset--font-family--rubik: Rubik, sans-serif;--wp--preset--font-family--rufina: Rufina, serif;--wp--preset--font-family--sora: Sora, sans-serif;--wp--preset--font-family--source-sans-3: 'Source Sans 3', sans-serif;--wp--preset--font-family--source-serif-4: 'Source Serif 4', serif;--wp--preset--font-family--space-mono: 'Space Mono', monospace;--wp--preset--font-family--syne: Syne, sans-serif;--wp--preset--font-family--texturina: Texturina, serif;--wp--preset--font-family--urbanist: Urbanist, sans-serif;--wp--preset--font-family--work-sans: 'Work Sans', sans-serif;--wp--preset--font-family--system-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;--wp--preset--font-family--literata-60-pt: Literata 60pt;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.5rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: clamp(1.5rem, 2.4096386vw, 2.0rem);--wp--preset--spacing--60: clamp(1.5rem, 3.6144578vw, 3.0rem);--wp--preset--spacing--70: clamp(2.0rem, 4.8192771vw, 4.0rem);--wp--preset--spacing--80: clamp(3.0rem, 7.2289157vw, 6.0rem);--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:root { --wp--style--global--content-size: 620px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--wp--preset--spacing--50); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--wp--preset--spacing--50); }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: var(--wp--preset--spacing--50);margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: var(--wp--preset--spacing--50);margin-block-end: 0;}:root :where(.is-layout-flex){gap: var(--wp--preset--spacing--50);}:root :where(.is-layout-grid){gap: var(--wp--preset--spacing--50);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{background-color: #272b30;color: #e2e2e2;font-family: var(--wp--preset--font-family--inter);font-size: var(--wp--preset--font-size--small);font-style: normal;font-weight: 400;line-height: 1.6;--wp--style--root--padding-top: 0px;--wp--style--root--padding-right: 40px;--wp--style--root--padding-bottom: 0px;--wp--style--root--padding-left: 40px;}a:where(:not(.wp-element-button)){color: var(--wp--preset--color--secondary);text-decoration: underline;}:root :where(a:where(:not(.wp-element-button)):hover){color: var(--wp--preset--color--primary);text-decoration: none;}h1, h2, h3, h4, h5, h6{background-color: #272b30;font-family: var(--wp--preset--font-family--inter);font-style: normal;font-weight: 700;line-height: 1.2;}h1{font-size: clamp(1.743rem, 1.743rem + ((1vw - 0.2rem) * 2.285), 3rem);}h2{font-size: clamp(1.563rem, 1.563rem + ((1vw - 0.2rem) * 1.931), 2.625rem);}h3{font-size: clamp(1.378rem, 1.378rem + ((1vw - 0.2rem) * 1.585), 2.25rem);}h4{font-size: clamp(1.185rem, 1.185rem + ((1vw - 0.2rem) * 1.255), 1.875rem);}h5{font-size: clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.682), 1.25rem);}h6{font-size: var(--wp--preset--font-size--small);}:root :where(.wp-element-button, .wp-block-button__link){background-color: var(--wp--preset--color--primary);border-radius: 0.25rem;border-width: 0;color: var(--wp--preset--color--background);font-family: inherit;font-size: inherit;line-height: inherit;padding-top: calc(0.667em + 2px);padding-right: calc(1.333em + 2px);padding-bottom: calc(0.667em + 2px);padding-left: calc(1.333em + 2px);text-decoration: none;}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){background-color: var(--wp--preset--color--secondary);color: var(--wp--preset--color--background);}:root :where(.wp-element-button:focus, .wp-block-button__link:focus){background-color: var(--wp--preset--color--primary);color: var(--wp--preset--color--background);outline-color: var(--wp--preset--color--primary);outline-offset: 2px;outline-style: dotted;outline-width: 1px;}:root :where(.wp-element-button:active, .wp-block-button__link:active){background-color: var(--wp--preset--color--primary);color: var(--wp--preset--color--background);}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-primary-color{color: var(--wp--preset--color--primary) !important;}.has-secondary-color{color: var(--wp--preset--color--secondary) !important;}.has-foreground-color{color: var(--wp--preset--color--foreground) !important;}.has-background-color{color: var(--wp--preset--color--background) !important;}.has-tertiary-color{color: var(--wp--preset--color--tertiary) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-primary-background-color{background-color: var(--wp--preset--color--primary) !important;}.has-secondary-background-color{background-color: var(--wp--preset--color--secondary) !important;}.has-foreground-background-color{background-color: var(--wp--preset--color--foreground) !important;}.has-background-background-color{background-color: var(--wp--preset--color--background) !important;}.has-tertiary-background-color{background-color: var(--wp--preset--color--tertiary) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-primary-border-color{border-color: var(--wp--preset--color--primary) !important;}.has-secondary-border-color{border-color: var(--wp--preset--color--secondary) !important;}.has-foreground-border-color{border-color: var(--wp--preset--color--foreground) !important;}.has-background-border-color{border-color: var(--wp--preset--color--background) !important;}.has-tertiary-border-color{border-color: var(--wp--preset--color--tertiary) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-albert-sans-font-family{font-family: var(--wp--preset--font-family--albert-sans) !important;}.has-alegreya-font-family{font-family: var(--wp--preset--font-family--alegreya) !important;}.has-arvo-font-family{font-family: var(--wp--preset--font-family--arvo) !important;}.has-bodoni-moda-font-family{font-family: var(--wp--preset--font-family--bodoni-moda) !important;}.has-bricolage-grotesque-font-family{font-family: var(--wp--preset--font-family--bricolage-grotesque) !important;}.has-cabin-font-family{font-family: var(--wp--preset--font-family--cabin) !important;}.has-chivo-font-family{font-family: var(--wp--preset--font-family--chivo) !important;}.has-commissioner-font-family{font-family: var(--wp--preset--font-family--commissioner) !important;}.has-cormorant-font-family{font-family: var(--wp--preset--font-family--cormorant) !important;}.has-courier-prime-font-family{font-family: var(--wp--preset--font-family--courier-prime) !important;}.has-crimson-pro-font-family{font-family: var(--wp--preset--font-family--crimson-pro) !important;}.has-dm-mono-font-family{font-family: var(--wp--preset--font-family--dm-mono) !important;}.has-dm-sans-font-family{font-family: var(--wp--preset--font-family--dm-sans) !important;}.has-dm-serif-display-font-family{font-family: var(--wp--preset--font-family--dm-serif-display) !important;}.has-domine-font-family{font-family: var(--wp--preset--font-family--domine) !important;}.has-eb-garamond-font-family{font-family: var(--wp--preset--font-family--eb-garamond) !important;}.has-epilogue-font-family{font-family: var(--wp--preset--font-family--epilogue) !important;}.has-fahkwang-font-family{font-family: var(--wp--preset--font-family--fahkwang) !important;}.has-figtree-font-family{font-family: var(--wp--preset--font-family--figtree) !important;}.has-fira-sans-font-family{font-family: var(--wp--preset--font-family--fira-sans) !important;}.has-fjalla-one-font-family{font-family: var(--wp--preset--font-family--fjalla-one) !important;}.has-fraunces-font-family{font-family: var(--wp--preset--font-family--fraunces) !important;}.has-gabarito-font-family{font-family: var(--wp--preset--font-family--gabarito) !important;}.has-ibm-plex-mono-font-family{font-family: var(--wp--preset--font-family--ibm-plex-mono) !important;}.has-ibm-plex-sans-font-family{font-family: var(--wp--preset--font-family--ibm-plex-sans) !important;}.has-ibarra-real-nova-font-family{font-family: var(--wp--preset--font-family--ibarra-real-nova) !important;}.has-instrument-serif-font-family{font-family: var(--wp--preset--font-family--instrument-serif) !important;}.has-inter-font-family{font-family: var(--wp--preset--font-family--inter) !important;}.has-josefin-sans-font-family{font-family: var(--wp--preset--font-family--josefin-sans) !important;}.has-jost-font-family{font-family: var(--wp--preset--font-family--jost) !important;}.has-libre-baskerville-font-family{font-family: var(--wp--preset--font-family--libre-baskerville) !important;}.has-libre-franklin-font-family{font-family: var(--wp--preset--font-family--libre-franklin) !important;}.has-literata-font-family{font-family: var(--wp--preset--font-family--literata) !important;}.has-lora-font-family{font-family: var(--wp--preset--font-family--lora) !important;}.has-merriweather-font-family{font-family: var(--wp--preset--font-family--merriweather) !important;}.has-montserrat-font-family{font-family: var(--wp--preset--font-family--montserrat) !important;}.has-newsreader-font-family{font-family: var(--wp--preset--font-family--newsreader) !important;}.has-noto-sans-mono-font-family{font-family: var(--wp--preset--font-family--noto-sans-mono) !important;}.has-nunito-font-family{font-family: var(--wp--preset--font-family--nunito) !important;}.has-open-sans-font-family{font-family: var(--wp--preset--font-family--open-sans) !important;}.has-overpass-font-family{font-family: var(--wp--preset--font-family--overpass) !important;}.has-pt-serif-font-family{font-family: var(--wp--preset--font-family--pt-serif) !important;}.has-petrona-font-family{font-family: var(--wp--preset--font-family--petrona) !important;}.has-piazzolla-font-family{font-family: var(--wp--preset--font-family--piazzolla) !important;}.has-playfair-display-font-family{font-family: var(--wp--preset--font-family--playfair-display) !important;}.has-plus-jakarta-sans-font-family{font-family: var(--wp--preset--font-family--plus-jakarta-sans) !important;}.has-poppins-font-family{font-family: var(--wp--preset--font-family--poppins) !important;}.has-raleway-font-family{font-family: var(--wp--preset--font-family--raleway) !important;}.has-roboto-font-family{font-family: var(--wp--preset--font-family--roboto) !important;}.has-roboto-slab-font-family{font-family: var(--wp--preset--font-family--roboto-slab) !important;}.has-rubik-font-family{font-family: var(--wp--preset--font-family--rubik) !important;}.has-rufina-font-family{font-family: var(--wp--preset--font-family--rufina) !important;}.has-sora-font-family{font-family: var(--wp--preset--font-family--sora) !important;}.has-source-sans-3-font-family{font-family: var(--wp--preset--font-family--source-sans-3) !important;}.has-source-serif-4-font-family{font-family: var(--wp--preset--font-family--source-serif-4) !important;}.has-space-mono-font-family{font-family: var(--wp--preset--font-family--space-mono) !important;}.has-syne-font-family{font-family: var(--wp--preset--font-family--syne) !important;}.has-texturina-font-family{font-family: var(--wp--preset--font-family--texturina) !important;}.has-urbanist-font-family{font-family: var(--wp--preset--font-family--urbanist) !important;}.has-work-sans-font-family{font-family: var(--wp--preset--font-family--work-sans) !important;}.has-system-font-font-family{font-family: var(--wp--preset--font-family--system-font) !important;}.has-literata-60-pt-font-family{font-family: var(--wp--preset--font-family--literata-60-pt) !important;}body {
background-color: #272B30;
color: #E2E2E2;
font-family: 'Open Sans', sans-serif;
text-align: center;
}
/* Main Page/Post Titles */
h1.entry-title, h2.entry-title {
color: #E2E2E2;
font-family: 'Cinzel', serif;
font-size: 2.5em;
margin-bottom: 20px;
}
/* Broad Titles */
h1 {
color: #E2E2E2;
}
/* Updated H2 Color */
h2 {
color: #F7A046; /* A warm orange, similar to your hover effects, for better visibility */
}
/* Specific Date Styling (Assuming you add a class or specific selector for dates) */
.date-class { /* Replace '.date-class' with your actual class or selector for dates */
color: #C4C4C4; /* A lighter grey to distinguish dates without overpowering */
}
/* WordPress Block Post Title */
h2.wp-block-post-title {
color: #F7A046;
padding-top: 60px;
padding-bottom: 20px;
}
/* Global Footer Styles */
.footer {
background-color: #272B30;
color: #E2E2E2;
padding: 40px;
text-align: center;
}
/* Global Header Styles */
.header {
background-color: #272B30; /* Matching the footer and body background */
color: #E2E2E2; /* Text color */
padding: 20px 40px; /* Adjust padding as needed */
font-family: 'Open Sans', sans-serif; /* Consistent font with the body */
text-align: center;
}
/* Adjust navigation links inside the header if necessary */
.header nav a {
color: #E2E2E2; /* Link color */
padding: 5px 10px; /* Spacing around links */
text-decoration: none; /* Optional: removes underline from links */
}
/* Additional styling for hover effects on links */
.header nav a:hover {
color: #F7A046; /* Change color on hover, adjust as needed */
}
/* Existing global CSS */
/* ... Your existing CSS code ... */
/* Responsive Menu Styles */
.wp-block-navigation__responsive-container-content {
background-color: #272B30; /* Matching body background color */
color: #E2E2E2; /* Text color as per body */
font-family: 'Open Sans', sans-serif; /* Consistency with body font */
text-align: left; /* Aligning text to the left for better readability in menus */
padding: 20px; /* Adding some padding for spacing */
}
/* Styling the individual menu items */
.wp-block-navigation__container .wp-block-navigation-item a {
color: #E2E2E2; /* Keeping text color consistent with the theme */
padding: 10px 20px; /* Spacing for each menu item */
text-decoration: none; /* Removing underline from links */
display: block; /* Making each link fill the horizontal space for easier touch */
}
/* Styling for the current menu item */
.wp-block-navigation__container .wp-block-navigation-item.current-menu-item a,
.wp-block-navigation__container .wp-block-navigation-item a:hover {
background-color: #3A3F44; /* Slightly lighter than the menu background for contrast */
color: #F7A046; /* Highlight color, similar to the hover effect in your header */
}
/* Existing global CSS */
/* ... Your existing CSS code ... */
/* Responsive Menu Container */
.wp-block-navigation__responsive-container {
background-color: #272B30; /* Ensuring the background matches your theme */
}
/* Close Button SVG Color */
.wp-block-navigation__responsive-container-close svg {
fill: #E2E2E2; /* Changing SVG icon color to match your text color */
}
/* Menu Item Link Color */
.wp-block-navigation__responsive-container a {
color: #E2E2E2; /* Ensuring text color consistency */
}
/* Removing general hover and focus styles from all menu items */
.wp-block-navigation__responsive-container a:hover,
.wp-block-navigation__responsive-container a:focus {
color: #E2E2E2; /* Keeping the same color on hover and focus */
background-color: transparent; /* No background change on hover */
}
/* Styling for 'Home' menu item on hover and focus */
.wp-block-navigation__responsive-container .wp-block-home-link a:hover,
.wp-block-navigation__responsive-container .wp-block-home-link a:focus {
color: #F7A046; /* Highlight color, similar to your header hover effect */
background-color: #3A3F44; /* Optional: background color change on hover */
}
/* Additional styling for current 'Home' menu item */
.wp-block-navigation__responsive-container .wp-block-home-link.current-menu-item a {
background-color: #3A3F44; /* Slightly lighter background for contrast */
color: #F7A046; /* Highlight color for the current 'Home' menu item */
}
.has-secondary-background-color {
background-color: #272B30 !important;
}
/* Category Styling to match theme */
.taxonomy-category {
background-color: #3A3F44; /* Slightly lighter than body for contrast, adjust as needed */
color: #E2E2E2; /* Consistent text color with the rest of the site */
font-family: 'Open Sans', sans-serif; /* Consistent font family */
padding: 6px; /* Adjusted padding for consistency */
text-transform: uppercase; /* Keeping uppercase styling */
font-size: 0.8rem; /* Keeping font size as is */
border-radius: 5px; /* Optional: adding a slight border-radius for a modern look */
display: inline-block; /* Ensures the background only covers the text area */
margin: 0 5px; /* Adds a bit of margin for spacing between multiple categories */
}
.taxonomy-category a {
color: #E2E2E2; /* Ensures link color matches the text */
text-decoration: none; /* Removes underline from links */
}
.taxonomy-category a:hover {
color: #F7A046; /* Adds a hover effect to match your theme's hover color */
}
/* Remove block gap between first-level blocks */ :where(.wp-site-blocks) > * { margin-block-start: 0; margin-block-end: 0; }
/*Membership CSS
/* Background color for the Membership Levels page */
body.page-id-1517 {
background-color: #272B30; /* Dark theme background */
color: #E2E2E2; /* Light text color */
}
/* Membership levels container */
.page-id-1517 .pmpro_levels-wrap {
background-color: #3A3F44; /* Lighter gray for contrast */
padding: 20px;
border-radius: 5px;
}
/* Headings */
.page-id-1517 .pmpro_levels-wrap h2 {
color: #F7A046; /* Accent color */
font-family: 'Cinzel', sans-serif; /* Match your site's font */
}
/* Membership level boxes */
.page-id-1517 .pmpro_level {
background-color: #3A3F44; /* Match container background */
border: 1px solid #F7A046; /* Accent border color */
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
/* Buttons */
.page-id-1517 .pmpro_btn,
.page-id-1517 .pmpro_btn:visited {
background-color: #F7A046; /* Accent color for buttons */
color: #272B30; /* Text color on buttons */
font-family: 'Open Sans', sans-serif; /* Match your site's font */
border: none;
padding: 10px 20px;
text-transform: uppercase;
border-radius: 5px;
transition: background-color 0.3s;
}
.page-id-1517 .pmpro_btn:hover {
background-color: #e6953f; /* Slightly darker accent color on hover */
}
/* Links */
.page-id-1517 .pmpro_content a {
color: #F7A046; /* Link color to match theme */
}
.page-id-1517 .pmpro_content a:hover {
color: #e6953f; /* Hover color for links */
}
:root :where(.wp-block-navigation){font-size: var(--wp--preset--font-size--small);}
:root :where(.wp-block-navigation a:where(:not(.wp-element-button))){text-decoration: none;}
:root :where(.wp-block-navigation a:where(:not(.wp-element-button)):hover){text-decoration: underline;}
:root :where(.wp-block-post-title){color: var(--wp--preset--color--primary);margin-bottom: 0;}
:root :where(.wp-block-post-title a:where(:not(.wp-element-button))){color: var(--wp--preset--color--primary);text-decoration: none;}
:root :where(.wp-block-post-title a:where(:not(.wp-element-button)):hover){color: var(--wp--preset--color--secondary);text-decoration: underline;}
</style>
<style id='core-block-supports-inline-css'>
.wp-container-core-group-is-layout-2{flex-wrap:nowrap;gap:40px;}.wp-container-core-group-is-layout-3{justify-content:center;}.wp-container-core-group-is-layout-4 > .alignfull{margin-right:calc(40px * -1);margin-left:calc(40px * -1);}.wp-container-core-group-is-layout-5 > .alignfull{margin-right:calc(40px * -1);margin-left:calc(40px * -1);}
</style>
<style id='wp-block-button-inline-css'>
.wp-block-button__link{align-content:center;box-sizing:border-box;cursor:pointer;display:inline-block;height:100%;text-align:center;width:100%;word-break:break-word}.wp-block-button__link.aligncenter{text-align:center}.wp-block-button__link.alignright{text-align:right}:where(.wp-block-button__link){border-radius:9999px;box-shadow:none;padding:calc(.667em + 2px) calc(1.333em + 2px);text-decoration:none}.wp-block-button[style*=text-decoration] .wp-block-button__link{text-decoration:inherit}.wp-block-buttons>.wp-block-button.has-custom-width{max-width:none}.wp-block-buttons>.wp-block-button.has-custom-width .wp-block-button__link{width:100%}.wp-block-buttons>.wp-block-button.has-custom-font-size .wp-block-button__link{font-size:inherit}.wp-block-buttons>.wp-block-button.wp-block-button__width-25{width:calc(25% - var(--wp--style--block-gap, .5em)*.75)}.wp-block-buttons>.wp-block-button.wp-block-button__width-50{width:calc(50% - var(--wp--style--block-gap, .5em)*.5)}.wp-block-buttons>.wp-block-button.wp-block-button__width-75{width:calc(75% - var(--wp--style--block-gap, .5em)*.25)}.wp-block-buttons>.wp-block-button.wp-block-button__width-100{flex-basis:100%;width:100%}.wp-block-buttons.is-vertical>.wp-block-button.wp-block-button__width-25{width:25%}.wp-block-buttons.is-vertical>.wp-block-button.wp-block-button__width-50{width:50%}.wp-block-buttons.is-vertical>.wp-block-button.wp-block-button__width-75{width:75%}.wp-block-button.is-style-squared,.wp-block-button__link.wp-block-button.is-style-squared{border-radius:0}.wp-block-button.no-border-radius,.wp-block-button__link.no-border-radius{border-radius:0!important}:root :where(.wp-block-button .wp-block-button__link.is-style-outline),:root :where(.wp-block-button.is-style-outline>.wp-block-button__link){border:2px solid;padding:.667em 1.333em}:root :where(.wp-block-button .wp-block-button__link.is-style-outline:not(.has-text-color)),:root :where(.wp-block-button.is-style-outline>.wp-block-button__link:not(.has-text-color)){color:currentColor}:root :where(.wp-block-button .wp-block-button__link.is-style-outline:not(.has-background)),:root :where(.wp-block-button.is-style-outline>.wp-block-button__link:not(.has-background)){background-color:initial;background-image:none}
</style>
<style id='wp-block-search-inline-css'>
.wp-block-search__button{margin-left:10px;word-break:normal}.wp-block-search__button.has-icon{line-height:0}.wp-block-search__button svg{fill:currentColor;height:1.25em;min-height:24px;min-width:24px;vertical-align:text-bottom;width:1.25em}:where(.wp-block-search__button){border:1px solid #ccc;padding:6px 10px}.wp-block-search__inside-wrapper{display:flex;flex:auto;flex-wrap:nowrap;max-width:100%}.wp-block-search__label{width:100%}.wp-block-search__input{appearance:none;border:1px solid #949494;flex-grow:1;margin-left:0;margin-right:0;min-width:3rem;padding:8px;text-decoration:unset!important}.wp-block-search.wp-block-search__button-only .wp-block-search__button{flex-shrink:0;margin-left:0;max-width:100%}.wp-block-search.wp-block-search__button-only .wp-block-search__button[aria-expanded=true]{max-width:calc(100% - 100px)}.wp-block-search.wp-block-search__button-only .wp-block-search__inside-wrapper{min-width:0!important;transition-property:width}.wp-block-search.wp-block-search__button-only .wp-block-search__input{flex-basis:100%;transition-duration:.3s}.wp-block-search.wp-block-search__button-only.wp-block-search__searchfield-hidden,.wp-block-search.wp-block-search__button-only.wp-block-search__searchfield-hidden .wp-block-search__inside-wrapper{overflow:hidden}.wp-block-search.wp-block-search__button-only.wp-block-search__searchfield-hidden .wp-block-search__input{border-left-width:0!important;border-right-width:0!important;flex-basis:0;flex-grow:0;margin:0;min-width:0!important;padding-left:0!important;padding-right:0!important;width:0!important}:where(.wp-block-search__input){font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;text-transform:inherit}:where(.wp-block-search__button-inside .wp-block-search__inside-wrapper){border:1px solid #949494;box-sizing:border-box;padding:4px}:where(.wp-block-search__button-inside .wp-block-search__inside-wrapper) .wp-block-search__input{border:none;border-radius:0;padding:0 4px}:where(.wp-block-search__button-inside .wp-block-search__inside-wrapper) .wp-block-search__input:focus{outline:none}:where(.wp-block-search__button-inside .wp-block-search__inside-wrapper) :where(.wp-block-search__button){padding:4px 8px}.wp-block-search.aligncenter .wp-block-search__inside-wrapper{margin:auto}.wp-block[data-align=right] .wp-block-search.wp-block-search__button-only .wp-block-search__inside-wrapper{float:right}
</style>
<style id='jetpack-global-styles-frontend-style-inline-css'>
:root { --font-headings: unset; --font-base: unset; --font-headings-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; --font-base-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;}
</style>
<script id="jetpack-mu-wpcom-settings-js-before">
var JETPACK_MU_WPCOM_SETTINGS = {"assetsUrl":"https:\/\/mtg-packs.com\/wp-content\/mu-plugins\/wpcomsh\/vendor\/automattic\/jetpack-mu-wpcom\/src\/build\/"};
</script>
<script id="cookie-notice-front-js-before">
var cnArgs = {"ajaxUrl":"https:\/\/mtg-packs.com\/wp-admin\/admin-ajax.php","nonce":"91b1107cac","hideEffect":"fade","position":"bottom","onScroll":false,"onScrollOffset":100,"onClick":false,"cookieName":"cookie_notice_accepted","cookieTime":2592000,"cookieTimeRejected":2592000,"globalCookie":false,"redirection":false,"cache":true,"revokeCookies":false,"revokeCookiesOpt":"automatic"};
</script>
<script src="https://mtg-packs.com/wp-content/plugins/cookie-notice/js/front.min.js?ver=2.5.4" id="cookie-notice-front-js"></script>
<script src="https://mtg-packs.com/wp-includes/js/jquery/jquery.min.js?ver=3.7.1" id="jquery-core-js"></script>
<script type='text/javascript' src='https://mtg-packs.com/wp-includes/js/jquery/jquery-migrate.min.js?m=1686289764'></script>
<!-- Google tag (gtag.js) snippet added by Site Kit -->
<!-- Google Analytics snippet added by Site Kit -->
<script src="https://www.googletagmanager.com/gtag/js?id=GT-T9K6NML" id="google_gtagjs-js" async></script>
<script id="google_gtagjs-js-after">
window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}
gtag("set","linker",{"domains":["mtg-packs.com"]});
gtag("js", new Date());
gtag("set", "developer_id.dZTNiMT", true);
gtag("config", "GT-T9K6NML");
</script>
<!-- End Google tag (gtag.js) snippet added by Site Kit -->
<link rel="https://api.w.org/" href="https://mtg-packs.com/wp-json/" /><link rel="alternate" title="JSON" type="application/json" href="https://mtg-packs.com/wp-json/wp/v2/pages/6" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://mtg-packs.com/xmlrpc.php?rsd" />
<link rel='shortlink' href='https://wp.me/Pf4Alt-6' />
<link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://mtg-packs.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fmtg-packs.com%2F" />
<link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://mtg-packs.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fmtg-packs.com%2F&#038;format=xml" />
<meta name="generator" content="Site Kit by Google 1.141.0" /><style id="pmpro_colors">:root {
--pmpro--color--base: #272b30;
--pmpro--color--contrast: #e2e2e2;
--pmpro--color--accent: #3a3f44;
--pmpro--color--accent--variation: hsl( 210,8%,37.5% );
--pmpro--color--border--variation: hsl( 213,10%,30% );
}</style><!-- SEO Meta Tags for Magic the Gathering (MTG) Pack Simulator -->
<meta name="description" content="Experience Magic The Gathering like never before with the best virtual MTG Pack Simulator online. Simulate the thrill of opening MTG draft, set, play, and collector boosters online. Modern Horizons 3 (MH3) and Bloomburg now available!">
<meta name="keywords" content="MTG Pack Simulator, Magic The Gathering Pack Simulator, MTG draft simulator, MTG set simulator, MTG play booster simulator, MTG collector booster simulator, Best, MTG Packs, Magic the Gathering Packs, Simulation, Opening, Booster">
<meta name="author" content="MTG Packs">
<meta property="og:title" content="Magic the Gathering (MTG) Pack Simulator - Experience the Magic of Opening MTG Packs Online">
<meta property="og:description" content="Join our community-driven platform for an immersive MTG pack opening experience. Simulate, explore, and discover your next MTG treasures online.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://mtg-packs.com/">
<meta property="og:image" content="https://mtg-packs.com/wp-content/uploads/2023/12/DALL·E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png">
<meta property="og:site_name" content="Magic the Gathering (MTG) Pack Simulator">
<meta property="og:locale" content="en_US">
<link rel="canonical" href="https://mtg-packs.com/">
<meta name="robots" content="index, follow">
<!-- RSS Feed -->
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="https://mtg-packs.com/feed/gn" />
<!-- Structured Data (JSON-LD) -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"url": "https://mtg-packs.com/",
"name": "Magic the Gathering (MTG) Pack Simulator",
"description": "Experience Magic The Gathering like never before with the best virtual MTG Pack Simulator online. Simulate the thrill of opening MTG draft, set, play, and collector boosters online.",
"image": "https://mtg-packs.com/wp-content/uploads/2023/12/DALL·E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png",
"sameAs": [
"https://www.youtube.com/channel/UCOBWcpFcYuMGnlhp37Wqjbg",
"https://www.tiktok.com/@mtgpacks6"
]
}
</script>
<!-- SheetJS (XLSX.js) for Excel Parsing -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.0/xlsx.full.min.js"></script>
<style>img#wpstats{display:none}</style>
<script type="importmap" id="wp-importmap">
{"imports":{"@wordpress\/interactivity":"https:\/\/mtg-packs.com\/wp-content\/plugins\/gutenberg\/build-module\/interactivity\/index.min.js?ver=63df923685080be7c130"}}
</script>
<script type="module" src="https://mtg-packs.com/wp-content/plugins/gutenberg/build-module/block-library/navigation/view.min.js?ver=7b370e821516feba4955" id="@wordpress/block-library/navigation/view-js-module"></script>
<link rel="modulepreload" href="https://mtg-packs.com/wp-content/plugins/gutenberg/build-module/interactivity/index.min.js?ver=63df923685080be7c130" id="@wordpress/interactivity-js-modulepreload">
<!-- Google AdSense meta tags added by Site Kit -->
<meta name="google-adsense-platform-account" content="ca-host-pub-2644536267352236">
<meta name="google-adsense-platform-domain" content="sitekit.withgoogle.com">
<!-- End Google AdSense meta tags added by Site Kit -->
<!-- Google AdSense snippet added by Site Kit -->
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-0748287243620731&amp;host=ca-host-pub-2644536267352236" crossorigin="anonymous"></script>
<!-- End Google AdSense snippet added by Site Kit -->
<!-- Google Tag Manager snippet added by Site Kit -->
<script>
( function( w, d, s, l, i ) {
w[l] = w[l] || [];
w[l].push( {'gtm.start': new Date().getTime(), event: 'gtm.js'} );
var f = d.getElementsByTagName( s )[0],
j = d.createElement( s ), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore( j, f );
} )( window, document, 'script', 'dataLayer', 'GTM-PPBL6832' );
</script>
<!-- End Google Tag Manager snippet added by Site Kit -->
<style class='wp-fonts-local'>
@font-face{font-family:Inter;font-style:normal;font-weight:100;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyeMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:200;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuDyfMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:300;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuOKfMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuGKYMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:800;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuDyYMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:900;font-display:fallback;src:url('https://fonts.wp.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuBWYMZ1rib2Bg-4.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:200;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbJG_F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:300;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbE-_F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:400;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbBG_F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:500;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbCO_F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:600;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbM-4F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:700;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbPa4F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:800;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbJG4F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:normal;font-weight:900;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3PQ6P12-iJxAIgLa78DkrbXsDgk0oVDaDPYLanFLHpPf2TbLi4F_PcTWCWp8g.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:200;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8f7XWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:300;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8obXWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:400;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8_7XWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:500;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8zbXWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:600;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8IbLWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:700;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8GLLWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:800;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8f7LWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Literata;font-style:italic;font-weight:900;font-display:fallback;src:url('https://fonts.wp.com/s/literata/v35/or3NQ6P12-iJxAIgLYT1PLs1Zd0nfUwAbeGVKoRYzNiCp1OUedn8VrLWTEKTt8iVow.woff2') format('woff2');}
@font-face{font-family:Inter;font-style:normal;font-weight:700;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/inter_normal_700.ttf') format('truetype');}
@font-face{font-family:Inter;font-style:normal;font-weight:500;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/inter_normal_500.ttf') format('truetype');}
@font-face{font-family:Inter;font-style:normal;font-weight:600;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/inter_normal_600.ttf') format('truetype');}
@font-face{font-family:Inter;font-style:normal;font-weight:400;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/inter_normal_400.ttf') format('truetype');}
@font-face{font-family:Literata;font-style:normal;font-weight:500;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/literata_normal_500.ttf') format('truetype');}
@font-face{font-family:Literata;font-style:italic;font-weight:500;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/literata_italic_500.ttf') format('truetype');}
@font-face{font-family:Literata;font-style:italic;font-weight:400;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/literata_italic_400.ttf') format('truetype');}
@font-face{font-family:Literata;font-style:normal;font-weight:400;font-display:fallback;src:url('https://mtg-packs.com/wp-content/themes/creatio/assets/fonts/literata_normal_400.ttf') format('truetype');}
</style>
<link rel="icon" href="https://i0.wp.com/mtg-packs.com/wp-content/uploads/2023/12/DALL%C2%B7E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png?fit=32%2C32&#038;ssl=1" sizes="32x32" />
<link rel="icon" href="https://i0.wp.com/mtg-packs.com/wp-content/uploads/2023/12/DALL%C2%B7E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png?fit=192%2C192&#038;ssl=1" sizes="192x192" />
<link rel="apple-touch-icon" href="https://i0.wp.com/mtg-packs.com/wp-content/uploads/2023/12/DALL%C2%B7E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png?fit=180%2C180&#038;ssl=1" />
<meta name="msapplication-TileImage" content="https://i0.wp.com/mtg-packs.com/wp-content/uploads/2023/12/DALL%C2%B7E-2023-12-12-12.40.59-Logo-design-for-a-website-named-MTG-Pack-Simulator.-The-logo-should-be-vibrant-and-engaging-reflecting-the-theme-of-Magic-The-Gathering-a-popular-.png?fit=270%2C270&#038;ssl=1" />
<link rel="stylesheet" type="text/css" id="wp-custom-css" href="https://mtg-packs.com/?custom-css=9026eaad40" /> <!-- Jetpack Google Analytics -->
<script async src='https://www.googletagmanager.com/gtag/js?id=G-NJMTY9G3DX'></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push( arguments ); }
gtag( 'js', new Date() );
gtag( 'config', "G-NJMTY9G3DX" );
</script>
<!-- End Jetpack Google Analytics -->
</head>
<body class="pmpro-variation_1 home page-template-default page page-id-6 wp-embed-responsive cookies-not-set pmpro-body-has-access">
<!-- Google Tag Manager (noscript) snippet added by Site Kit -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PPBL6832" height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) snippet added by Site Kit -->
<div class="wp-site-blocks"><header class="wp-block-template-part">
<div class="wp-block-group is-horizontal is-content-justification-center is-layout-flex wp-container-core-group-is-layout-3 wp-block-group-is-layout-flex" style="padding-top:60px;padding-bottom:20px">
<div class="wp-block-group is-layout-flex wp-block-group-is-layout-flex"></div>
<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-2 wp-block-group-is-layout-flex"><nav class="is-responsive wp-block-navigation is-horizontal is-layout-flex wp-block-navigation-is-layout-flex" aria-label="Navigation"
data-wp-interactive="core/navigation" data-wp-context='{"overlayOpenedBy":{"click":false,"hover":false,"focus":false},"type":"overlay","roleAttribute":"","ariaLabel":"Menu"}'><button aria-haspopup="dialog" aria-label="Open menu" class="wp-block-navigation__responsive-container-open "
data-wp-on-async--click="actions.openMenuOnClick"
data-wp-on--keydown="actions.handleMenuKeydown"
><svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="4" y="7.5" width="16" height="1.5" /><rect x="4" y="15" width="16" height="1.5" /></svg></button>
<div class="wp-block-navigation__responsive-container has-text-color has-background-color has-background has-secondary-background-color" id="modal-1"
data-wp-class--has-modal-open="state.isMenuOpen"
data-wp-class--is-menu-open="state.isMenuOpen"
data-wp-watch="callbacks.initMenu"
data-wp-on--keydown="actions.handleMenuKeydown"
data-wp-on-async--focusout="actions.handleMenuFocusout"
tabindex="-1"
>
<div class="wp-block-navigation__responsive-close" tabindex="-1">
<div class="wp-block-navigation__responsive-dialog"
data-wp-bind--aria-modal="state.ariaModal"
data-wp-bind--aria-label="state.ariaLabel"
data-wp-bind--role="state.roleAttribute"
>
<button aria-label="Close menu" class="wp-block-navigation__responsive-container-close"
data-wp-on-async--click="actions.closeMenuOnClick"
><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="m13.06 12 6.47-6.47-1.06-1.06L12 10.94 5.53 4.47 4.47 5.53 10.94 12l-6.47 6.47 1.06 1.06L12 13.06l6.47 6.47 1.06-1.06L13.06 12Z"></path></svg></button>
<div class="wp-block-navigation__responsive-container-content"
data-wp-watch="callbacks.focusFirstElement"
id="modal-1-content">
<ul class="wp-block-navigation__container is-responsive wp-block-navigation"><li class="wp-block-navigation-item current-menu-item wp-block-home-link"><a class="wp-block-home-link__content wp-block-navigation-item__content" href="https://mtg-packs.com" rel="home" aria-current="page">Home</a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/about-2/"><span class="wp-block-navigation-item__label">About</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/news/"><span class="wp-block-navigation-item__label">News</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/mtg-booster-types/"><span class="wp-block-navigation-item__label">MTG Booster Types</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/mtg-pack-overview/"><span class="wp-block-navigation-item__label">MTG Set Overview</span></a></li><li class=" wp-block-navigation-item current-menu-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/" aria-current="page"><span class="wp-block-navigation-item__label">MTG Pack Simulator</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/463-2/"><span class="wp-block-navigation-item__label">Community</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/disclaimer/"><span class="wp-block-navigation-item__label">Privacy Policy</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/login/"><span class="wp-block-navigation-item__label">Log In</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/membership-levels/"><span class="wp-block-navigation-item__label">Become a Member</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="https://mtg-packs.com/membership-account/"><span class="wp-block-navigation-item__label">Membership Account</span></a></li></ul>
</div>
</div>
</div>
</div></nav></div>
</div>
<p></p>
</header>
<div class="wp-block-group has-global-padding is-layout-constrained wp-container-core-group-is-layout-5 wp-block-group-is-layout-constrained" style="padding-right:40px;padding-left:40px">
<div class="wp-block-group alignfull has-global-padding is-layout-constrained wp-container-core-group-is-layout-4 wp-block-group-is-layout-constrained" style="padding-right:40px;padding-left:40px"><div class="entry-content alignfull wp-block-post-content has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MTG Pack Simulator</title>
<!-- Include Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&#038;family=Open+Sans&#038;display=swap" rel="stylesheet">
<!-- ======= STYLING / CSS SECTION START ======= -->
<style>
/* Global Styles */
/* Change cursor to pointer on link hover */
a:hover {
cursor: pointer;
}
body {
background-color: #272B30;
color: #E2E2E2;
font-family: 'Open Sans', sans-serif;
text-align: center;
}
h1 {
font-family: 'Cinzel', serif;
font-size: 2.5em;
margin-bottom: 20px;
}
/* Help Button Styling */
#helpButton {
position: fixed;
top: 20px;
right: 20px;
background-color: #0D1B2A;
color: #E0AFA0;
border: 2px solid #748CAB;
padding: 10px 15px;
border-radius: 50%;
font-size: 16px;
cursor: pointer;
z-index: 1000;
}
#helpButton:hover {
background-color: #112D4E;
color: #F9F7F7;
}
/* Sorting and Filtering Section */
.sorting-container {
display: flex;
justify-content: center;
margin: 20px 0;
}
.sorting-container label {
margin-right: 10px;
font-weight: bold;
font-size: 1em;
color: #F7A046;
}
.sorting-container select {
background-color: #333;
color: #fff;
border: 1px solid #555;
padding: 5px;
margin-right: 20px;
}
.filter-container {
margin-top: 10px;
text-align: center;
}
.filter-container input[type="checkbox"] {
margin-right: 5px;
}
.filter-container label {
font-size: 1em;
margin-right: 20px;
}
/* Sizing and Layout Container Styles */
.sizing-container, .layout-container {
text-align: center;
margin: 20px auto;
max-width: 480px; /* Increase max-width to allow for 3 buttons across */
}
/* Buttons Container Style */
.buttons-container {
display: flex;
flex-wrap: wrap; /* Ensure buttons wrap on smaller screens */
justify-content: center; /* Center the buttons */
align-items: center; /* Vertically center the buttons */
gap: 15px; /* Increase gap for more spacing between buttons */
max-width: 100%; /* Prevent overflow */
}
/* Apply consistent size, padding, and style for all Size Buttons */
#smallSizeBtn, #normalSizeBtn, #largeSizeBtn{
margin: 0 5px;
padding: 5px 10px;
font-size: 0.9em;
border: none;
background-color: #555;
color: #fff;
border-radius: 5px;
transition: background-color 0.3s;
width: 80px;
height: 30px;
cursor: pointer;
}
/* Apply consistent size, padding, and style for all layout buttons, including disabled ones */
.layout-button, #gridLayout, #packLayout, #lineLayout, #draftLayout, #sealedLayout {
margin: 0 5px;
padding: 5px 10px;
font-size: 0.9em;
border: none;
background-color: #555;
color: #fff;
border-radius: 5px;
transition: background-color 0.3s;
width: 80px;
height: 30px;
cursor: pointer;
}
/* Disabled buttons (ensure they share the same style but are greyed out) */
.layout-button.disabled-button, button:disabled {
background-color: #ccc;
color: #666;
cursor: not-allowed;
border-radius: 5px;
width: 80px;
height: 30px;
padding: 5px 10px;
margin: 0 5px;
font-size: 0.9em;
transition: background-color 0.3s;
}
/* Hover effect for enabled buttons only */
.layout-button:hover:not(.disabled-button) {
background-color: #777;
}
/* Disabled buttons should have no hover effect */
button:disabled:hover {
background-color: #ccc;
}
/* Generate Pack and CSV Selection Styles */
#generatePackBtn, #generateCsvBtn {
margin: 5px auto;
}
/* Pack Display Styles */
#packDisplay {
position: relative;
width: 100%;
min-height: 700px;
overflow: auto;
}
/* Pack Container Styles */
.packContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 300px;
}
#packTitle {
font-size: 1.5em;
margin-bottom: 20px;
text-align: center;
}
/* Card Container Base Style */
#packDisplay .card-container {
display: none;
position: relative; /* Changed from absolute to relative */
left: 0; /* Resetting the position */
transform: none; /* Resetting the transform */
width: auto; /* Resetting the width */
}
/* Active Card Container Style for Pack View */
#packDisplay.packView .card-container.active {
display: block;
}
/* Pack View Styles */
#packDisplay.packView {
display: flex;
flex-direction: column;
align-items: center;
}
/* Line View Styles */
#packDisplay.lineView {
display: flex;
flex-direction: column;
align-items: center; /* Center all cards in the line view horizontally */
}
#packDisplay.lineView .card-container {
display: flex;
flex-direction: column; /* Stack the card image and its details vertically */
align-items: center; /* Center the card container and its contents */
justify-content: center;
width: 100%; /* Full width for line view */
margin: 10px 0; /* Margin for spacing */
}
#packDisplay.lineView .card-container img {
max-width: 100%; /* Ensure the image scales properly */
width: auto; /* Ensure width is adjusted automatically */
margin: 10px 0; /* Add margin for space between the image and other elements */
}
#packDisplay.lineView .card-info,
#packDisplay.lineView .tcgplayer-affiliate-link {
text-align: center; /* Ensure text content is centered */
margin: 10px 0; /* Add margin for spacing */
width: auto; /* Let the width adjust automatically */
}
/* General Container Styles for Grid, Draft, and Sealed Views */
#packDisplay.gridView, #packDisplay.draftView, #packDisplay.sealedView {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(125px, 1fr)); /* Responsive columns */
gap: 10px;
width: 100%;
max-width: 1600px; /* Max container width */
justify-content: center;
padding: 10px;
margin: 0 auto;
}
/* Responsive Column Limiting */
@media (min-width: 768px) {
#packDisplay.gridView, #packDisplay.draftView, #packDisplay.sealedView {
grid-template-columns: repeat(5, minmax(125px, 1fr)); /* Limit to a maximum of 5 columns */
}
}
/* Card Container Styles */
.card-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
text-align: center;
width: 100%;
margin: 0 auto;
}
/* Card Image Styles for Different Sizes */
.card-container img {
display: block;
width: 100%; /* Full width of container */
height: auto; /* Maintain aspect ratio */
margin: 0 auto;
}
/* Small, Normal, Large Sizing Options */
.card-container.small img {
max-width: 175px;
}
.card-container.normal img {
max-width: 200px;
}
.card-container.large img {
max-width: 225px;
}
/* Consistent Alignment of Text Under Cards */
.card-container .card-text {
margin-top: 5px;
min-height: 50px;
font-size: 14px;
line-height: 1.4;
}
/* Additional Media Queries for Smaller Screens */
/* Medium Screens (Tablets) */
@media (max-width: 1200px) {
#packDisplay.gridView, #packDisplay.draftView, #packDisplay.sealedView {
grid-template-columns: repeat(4, minmax(125px, 1fr)); /* 4 columns max */
}
}
/* Small Screens (Mobile Landscape) */
@media (max-width: 992px) {
#packDisplay.gridView, #packDisplay.draftView, #packDisplay.sealedView {
grid-template-columns: repeat(3, minmax(125px, 1fr)); /* 3 columns max */
}
}
/* Extra Small Screens (Mobile Portrait) */
@media (max-width: 768px) {
#packDisplay.gridView, #packDisplay.draftView, #packDisplay.sealedView {
grid-template-columns: repeat(2, minmax(125px, 1fr)); /* 2 columns max */
}
}
/* Very Small Screens */
@media (max-width: 576px) {
#packDisplay.gridView, #packDisplay.draftView, #packDisplay.sealedView {
grid-template-columns: 1fr; /* 1 column max */
}
}
/* CSS for the overlay */
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
z-index: 1000; /* Ensure it's below the pop-up card but above other content */
}
/* CSS for the card pop-up */
.card-popup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1001;
background-color: transparent; /* No background */
border: none; /* Remove border */
padding: 0; /* Remove padding */
box-shadow: none; /* Remove shadow */
box-sizing: border-box;
}
/* CSS to prevent scrolling when the pop-up is open */
body.no-scroll {
overflow: hidden !important;
}
#packDisplay.draftView .card-container, #packDisplay.sealedView .card-container {
display: inline-block;
width: auto; /* Resetting the width */
vertical-align: top;
margin: 15px; /* Adds some spacing between cards */
}
/* Adjustments for smaller screens */
@media (max-width: 1024px) {
#packDisplay.gridView {
grid-template-columns: repeat(3, 1fr); /* 3 columns for tablets and smaller laptops */
gap: 10px; /* Reduced gap */
}
}
@media (max-width: 768px) {
#packDisplay.gridView {
grid-template-columns: repeat(2, 1fr); /* 2 columns for larger phones */
gap: 10px; /* Further reduced gap */
}
}
@media (max-width: 480px) {
#packDisplay.gridView {
grid-template-columns: 1fr; /* Single column for small devices */
gap: 5px;
}
}
/* Refine end-of-pack options for better visibility and interaction on small devices */
.end-of-pack-options {
text-align: center;
margin-top: 20px;
}
.end-of-pack-options button {
margin: 0 10px; /* Ensure buttons don't touch each other */
}
/* Ensure buttons and links are easily clickable on touch devices */
button, .navigation-btn, .next-card-btn {
min-width: 120px; /* Minimum width for easier tapping */
padding: 10px 15px;
}
/* Ensure body and html tags take full width and height of the viewport */
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow-x: hidden; /* Prevent horizontal scroll */
}
/* Button Styles */
#packDisplay button, #generatePackBtn, #generateCsvBtn, #resetCalculatorBtn {
margin: 10px 0;
padding: 10px 15px;
font-size: 1em;
cursor: pointer;
border: none;
background-color: #555;
color: #fff;
border-radius: 5px;
transition: background-color 0.3s;
}
#packDisplay button:hover, #generatePackBtn:hover, #generateCsvBtn:hover, #resetCalculatorBtn:hover {
background-color: #777;
}
/* Selector Container */
.selectors-container {
display: flex;
flex-direction: column; /* Stack dropdowns vertically */
align-items: center; /* Center them horizontally */
gap: 10px; /* Add space between the dropdowns */
width: 100%;
max-width: 480px; /* Keep the max width for selectors */
}
/* Styling for disabled options */
.selectors-container select option:disabled {
color: #ccc; /* Lighter grey for better readability */
font-style: italic; /* Add italic to emphasize it's not selectable */
background-color: #555; /* Match background color to other options */
opacity: 0.8; /* Slightly dim the disabled option */
}
/* Dropdown Styling (Matching Button Styles but Larger) */
.selectors-container select {
margin: 0 5px; /* Same margin as buttons */
padding: 5px 10px; /* Matching padding */
font-size: 0.9em; /* Same font size as buttons */
border: none; /* Remove default border */
background-color: #555; /* Same background color as buttons */
color: #fff; /* White text color */
border-radius: 5px; /* Rounded corners */
transition: background-color 0.3s; /* Smooth transition on hover */
width: 250px; /* Increase width for better display */
height: 35px; /* Adjust height to match the larger size */
cursor: pointer;
/* Centering text within the select */
text-align: center; /* Center text horizontally */
}
/* Change background color on hover (for selectors) */
.selectors-container select:hover {
background-color: #777; /* Slightly lighter background on hover */
}
/* Responsive Design: Stack the selectors vertically on small screens */
@media (max-width: 600px) {
.selectors-container {
width: 90%; /* Ensure they stay responsive on mobile */
max-width: 100%; /* Remove fixed width on small screens */
}
.selectors-container select {
max-width: 100%; /* Full width on mobile */
}
}
/* Card Info Styles */
.card-info, .card-price {
text-align: center;
margin-top: 5px;
display: block;
}
/* Pack Value Info Styles */
#packValueInfo {
margin-top: 20px;
background-color: #333539;
border-radius: 5px;
padding: 10px 20px;
display: inline-block;
}
#packValueInfo h3 {
margin: 0;
margin-bottom: 10px;
font-size: 1.3em;
color: #F7A046;
text-decoration: underline;
}
#packValueInfo p {
margin: 5px 0;
font-size: 1em;
}
/* Next Card Button Styles */
.next-card-btn {
padding: 10px 15px;
margin-top: 10px;
font-size: 1em;
cursor: pointer;
border: none;
background-color: #555;
color: #fff;
border-radius: 5px;
transition: background-color 0.3s;
}
.next-card-btn:hover {
background-color: #777;
}
/* Card Navigation Buttons Styles */
.card-navigation-buttons {
display: none; /* Hide by default */
justify-content: center;
margin-top: 20px;
}
.navigation-btn {
display: inline-block; /* Align buttons inline */
padding: 10px 15px;
margin: 0 10px;
font-size: 1em;
cursor: pointer;
border: none;
background-color: #555;
color: #fff;
border-radius: 5px;
transition: background-color 0.3s;
}
.navigation-btn:hover {
background-color: #777;
}
.left-aligned-list {
text-align: left;
margin-left: auto;
margin-right: auto;
display: table; /* This centers the list while aligning the text to the left */
}
.section-spacing {
margin-bottom: 50px; /* Adds space after the Getting Started section */
}
/* Ad Container Styles */
.ad-container {
width: 100%; /* Ensures the container is responsive and fills the width of its parent */
height: 300px; /* Fixed height to reserve space for the ad */
display: flex;
justify-content: center;
align-items: center;
}
.adsbygoogle {
width: 100% !important; /* Forces the ad to fill the container */
min-height: 250px; /* Optional: Adjust based on the typical height of your ads to prevent layout shift */
}
/* Adjustments for smaller screens */
@media (max-width: 768px) {
.ad-container {
min-height: 200px; /* Adjusted for smaller screens */
padding-left: 10px; /* Adds some space on the left */
padding-right: 10px; /* Adds some space on the right */
}
.adsbygoogle {
min-height: 150px; /* Adjust if necessary based on the ad's appearance on mobile */
}
}
.amazon-button, .tcgplayer-button {
display: inline-flex;
align-items: center;
justify-content: center;
margin: 10px;
padding: 10px 20px;
font-size: 1.2em;
cursor: pointer;
border: none;
background-color: #ff9900;
color: #fff;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
}
.amazon-button img, .tcgplayer-button img {
height: 30px;
padding-left: 10px; /* Adds space between text and image */
vertical-align: middle; /* Aligns the image vertically in the middle */
}
.tcgplayer-button {
background-color: #336699; /* Assuming TCG Player's color scheme */
}
#packFinanceCalculator {
position: fixed;
bottom: 60px;
left: 20px;
background-color: #3A3F44;
color: #E2E2E2;
padding: 15px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
font-family: 'Open Sans', sans-serif;
width: 250px;
text-align: center;
display: none;
z-index: 1000;
box-sizing: border-box;
}
#packFinanceCalculator.minimized {
display: none;
}
#calculatorToggle {
position: fixed;
bottom: 20px;
left: 20px;
background-color: #F7A046;
color: #272B30;
padding: 10px;
border-radius: 50%;
font-size: 16px;
cursor: pointer;
z-index: 1001;
}
@media (max-width: 768px) {
#packFinanceCalculator,
#calculatorToggle {
display: none;
}
}
#packFinanceCalculator h3#packTitleDisplay {
color: #F7A046;
font-family: 'Cinzel', serif;
font-size: 1.5em;
margin-bottom: 20px;
text-align: center;
text-shadow: none; /* Remove shadow */
background: none; /* Remove background */
}
.column-title {
color: #E2E2E2;
font-size: 1.2em;
margin-bottom: 10px;
text-shadow: none; /* Remove shadow */
background: none; /* Remove background */
}
.calculator-columns {
display: grid;
grid-template-columns: repeat(2, 1fr); /* 2 columns */
gap: 10px;
text-align: center;
margin-top: 15px;
grid-template-areas:
"foil average"
"nonfoil greatest"
"expected least";
}
.grid-item:nth-child(1) { grid-area: foil; }
.grid-item:nth-child(2) { grid-area: nonfoil; }
.grid-item:nth-child(3) { grid-area: expected; }
.grid-item:nth-child(4) { grid-area: average; }
.grid-item:nth-child(5) { grid-area: greatest; }
.grid-item:nth-child(6) { grid-area: least; }
.grid-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.grid-item .label {
font-weight: normal;
}
.grid-item .value {
color: #F7A046;
font-weight: bold;
margin-top: 4px;
}
.bold {
font-weight: bold;
}
.affiliate-link {
font-size: 0.8em;
margin-top: 15px;
color: #F7A046;
}
.affiliate-link a {
color: #F7A046;
text-decoration: none;
}
.affiliate-link a:hover {
text-decoration: underline;
}
/* New styles for the market price and buy link */
#packFinanceCalculator .market-price {
margin-top: 15px;
font-size: 1em;
color: #F7A046;
font-weight: bold;
}
#packFinanceCalculator .buy-link {
font-size: 0.9em;
margin-top: 10px;
color: #F7A046;
}
#packFinanceCalculator .buy-link a {
color: #F7A046;
text-decoration: none;
}
#packFinanceCalculator .buy-link a:hover {
text-decoration: underline;
}
.filter-and-sort-container {
display: none; /* Hide by default */
}
/* Thematic Banner Styles */
#thematicBanner {
background-color: #3c3c3c; /* Dark background color */
color: #ffffff; /* Light text color */
padding: 15px 20px;
text-align: center;
font-size: 18px;
font-weight: bold;
position: relative;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
width: 100%;
z-index: 1000; /* Make sure it's on top */
}
/* Banner Text Styling */
.banner-text {
display: inline-block;
margin-right: 20px;
}
/* Close Button Styling */
.close-banner {
background: none;
border: none;
color: #ffffff;
font-size: 22px;
font-weight: bold;
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
padding: 0;
line-height: 1;
}
.close-banner:hover {
color: #ff0000; /* Change color on hover for feedback */
}
/* Filter and Sort Section for Draft and Sealed Views */
#draft-sealed-filters {
padding: 15px;
background-color: inherit; /* Matches website's background */
border: 1px solid #3c3c3c;
border-radius: 8px;
margin: 20px auto; /* Adds vertical spacing */
max-width: 600px; /* Limits width to keep it compact */
text-align: center;
color: #E2E2E2; /* Matches overall text color */
}
/* Heading Style */
#draft-sealed-filters h3 {
font-size: 1.4em;
margin-bottom: 10px;
color: #F7A046; /* Matches accent color for headings */
}
/* Filter and Sort Option Containers */
#color-filters, #sort-options {
margin-bottom: 15px;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
}
/* Filter Checkboxes */
#color-filters label,
#sort-options label {
font-size: 1em;
color: #E2E2E2;
display: inline-flex;
align-items: center;
gap: 5px;
}
/* Sort Dropdown Style */
#sort-type {
padding: 5px 10px;
background-color: #333;
color: #fff;
border: 1px solid #555;
border-radius: 5px;
transition: background-color 0.3s;
font-size: 1em;
}
/* Apply Filters Button */
#apply-filters {
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
transition: background-color 0.3s ease;
margin-top: 15px;
}
#apply-filters:hover {
background-color: #0056b3;
}
/* Responsive Adjustments */
@media (max-width: 600px) {
#draft-sealed-filters {
padding: 10px;
}
#apply-filters {
width: 100%; /* Full-width button on smaller screens */
}
#color-filters, #sort-options {
flex-direction: column; /* Stack filter options vertically on smaller screens */
gap: 5px;
}
}
</style>
<!-- ======= STYLING / CSS SECTION END ======= -->
</head>
<body>
<!-- Affiliate Marketing and Google Ads for Non-Members -->
<div class="ad-container" style="display: flex; flex-direction: column; gap: 20px; margin-top: 60px; max-width: 728px; margin-left: auto; margin-right: auto;">
<!-- TCGPlayer Ad -->
<div id="affiliateBanner" class="banner" style="width: 100%; text-align: center;">
<a href="https://tcgplayer.pxf.io/c/5066134/2220337/21018" target="_top" rel="noopener">
<img decoding="async" src="//a.impactradius-go.com/display-ad/21018-2220337" alt="TCGPlayer Ad" style="width: 100%; max-width: 728px; height: auto; border: 0;" />
</a>
</div>
<!-- Google Ad -->
<div style="width: 100%; text-align: center;">
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-0748287243620731" crossorigin="anonymous"></script>
<!-- Primary Ad MTG Packs -->
<ins class="adsbygoogle" style="display: block; width: 100%; max-width: 728px; margin: 0 auto;" data-ad-client="ca-pub-0748287243620731" data-ad-slot="3364108828" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script> (adsbygoogle = window.adsbygoogle || []).push({}); </script>
</div>
</div>
<!-- Heading -->
<h2>MTG Pack Simulator</h2>
<!-- Getting Started Section -->
<!-- Getting Started Section -->
<div class="intro-section section-spacing">
<p><strong>Getting Started with the MTG Pack Simulator:</strong></p>
<ol class="left-aligned-list">
<li>
<strong>Select a Set:</strong> Begin by choosing the set you wish to explore. Our simulator features a wide range of sets, ensuring you find one that piques your interest.
</li>
<li>
<strong>Choose a Pack Type:</strong> Next, decide on the type of pack you want to open. Whether it&#8217;s a draft booster pack or a collector&#8217;s pack, the choice is yours.
</li>
<li>
<strong>Select a Layout:</strong> Choose how you want to view your simulated cards: in a pack (default), in a grid, or in a vertical line. This allows you to customize your experience to your preference.
</li>
<li>
<strong>Generate Your Pack:</strong> With your set, pack type, and layout selected, click the &#8220;Generate&#8221; button to start the simulation. Prepare yourself for the excitement of what you might discover!
</li>
<li>
<strong>Reveal Your Cards:</strong> Click on the card to reveal the next one in the pack. Each click brings a new surprise, mimicking the suspense and excitement of opening a physical pack.
</li>
</ol>
</div>
<button id="helpButton">?</button>
<!-- Set and Booster Type Selection -->
<div class="selectors-container">
<!-- Current Set Label -->
<span id="currentSetLabel">Current Set: $Set</span>
<select id="setSelection">
<!-- Only show Duskmourn/Foundations for members with ID 1 or 2 -->
<!-- Show message to non-members (ID 0) -->
<option disabled>Foundations (Become a member to gain access to Foundations!)</option>
<option disabled>Duskmourn: House of Horror (Become a member to gain access to Duskmourn!)</option>
<option value="BLB">BloomBurrow</option>
<option value="ACR">Assassin&#8217;s Creed</option>
<option value="MH3">Modern Horizons 3</option>
<option value="OTJ">Outlaws of Thunder Junction</option>
<option value="PIP">Fallout</option>
<option value="MKM">Murders at Karlov Manor</option>
<option value="RVR">Ravnica Remastered</option>
<option value="LCI">Lost Caverns of Ixalan</option>
<option value="WHO">Dr. Who</option>
<option value="CMM">Commander Masters</option>
<option value="MOM">March of the Machine</option>
<option value="ONE">Phyrexia: All will be One</option>
<option value="WOE">Wilds of Eldraine</option>
<option value="DMR">Dominaria Remastered</option>
<option value="BRO">The Brother&#8217;s War</option>
<option value="DMU">Dominaria United</option>
<option value="2X2">Double Masters 2022</option>
<option value="CLB">Commander Legends: Battle for Baldur&#8217;s Gate</option>
<option value="NEO">Kamigawa: Neon Dynasty</option>
</select>
<!-- Current Pack Type Label -->
<span id="currentPackTypeLabel">Current Pack Type: $PackType</span>
<select id="boosterTypeSelection">
<option value="beyond">Beyond Booster</option>
<option value="draft">Draft Booster</option>
<option value="play" selected>Play Booster</option>
<option value="set">Set Booster</option>
<option value="collector">Collector&#8217;s Booster</option>
</select>
</div>
<!-- Layout -->
<!-- Layout Container -->
<div class="layout-container">
<!-- Current Layout Label -->
<span id="selectedLayoutLabel">Current Layout: Pack</span>
<!-- Layout Buttons -->
<div class="buttons-container">
<button id="packLayout" class="layout-button">Pack</button>
<button id="lineLayout" class="layout-button">Line</button>
<button id="gridLayout" class="layout-button">Grid</button>
<!-- New Draft and Sealed view buttons for members -->
<!-- Show greyed-out message for non-members -->
<button class="layout-button disabled-button" disabled title="Sign up to gain access to the Draft View">Draft</button>
<button class="layout-button disabled-button" disabled title="Sign up to gain access to the Sealed View">Sealed</button>
</div>
</div>
<!-- Sizing Buttons -->
<div class="sizing-container">
<!-- Current Size Label -->
<span id="selectedSizeLabel">Current size: Small</span>
<!-- Buttons Container -->
<div class="buttons-container">
<button id="smallSizeBtn">Small</button>
<button id="normalSizeBtn">Normal</button>
<button id="largeSizeBtn">Large</button>
</div>
</div>
<!-- Generate Pack Button and Display Area -->
<button id="generatePackBtn">Generate Pack</button>
<!-- New Generate CSV Button -->
<button id="generateCsvBtn">Generate CSV</button>
<div id="affiliateLinksContainer"></div>
<!-- Filter and Sort Options for Draft and Sealed Views - Only for Members -->
<!-- "Your Pack" Text -->
<h2 id="packTitle">Your Pack</h2>
<!-- Total Pack Value Display Area -->
<div id="packValueInfo" style="display: none;">
<h3>Your Pack&#8217;s Total Value</h3>
<p>Non Foil: $<span id="nonFoilValue">0.00</span></p>
<p>Foil: $<span id="foilValue">0.00</span></p>
</div>
<!-- Card Navigation Buttons -->
<div class="card-navigation-buttons">
<button id="prevCardBtn" class="navigation-btn">Previous Card</button>
<button id="nextCardBtn" class="navigation-btn">Next Card</button>
</div>
<div id="packDisplay">
<div class="card-container">
<!-- All cards for the pack will be placed here -->
</div>
</div>
<!-- Finance Calculator: Only show to members with ID 1 or 2 -->
</body>
</html>
<p></p>
<p></p>
<p></p>
<!-- /wp:paragraph --></div></div>
<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>
</div>
</div>
<!-- wpcom_wp_footer -->
<script defer id="bilmur" data-customproperties="{&quot;woo_active&quot;:&quot;0&quot;}" data-provider="wordpress.com" data-service="atomic" src="https://s0.wp.com/wp-content/js/bilmur.min.js?m=202449"></script>
<!-- Memberships powered by Paid Memberships Pro v3.3.1. -->
<!-- Section 2: JavaScript -->
<script>
// Section Set categories
// Foundations - FDN
const FoundationsCategories = {
regularCards: {
set: "FDN",
ranges: [
{ min: 1, max: 133 },
{ min: 134, max: 258 },
{ min: 262, max: 262 },
{ min: 264, max: 264 },
{ min: 267, max: 267 }
]
},
basicLands: {
set: "FDN",
ranges: [
{ min: 272, max: 281 }
]
},
fullArtBasicLands: {
set: "FDN",
ranges: [
{ min: 282, max: 291 }
]
},
commonDualLands: {
set: "FDN",
ranges: [
{ min: 259, max: 261 },
{ min: 263, max: 263 },
{ min: 265, max: 266 },
{ min: 268, max: 271 }
]
},
borderless: {
set: "FDN",
ranges: [
{ min: 292, max: 361 }
]
},
manaFoil: {
set: "FDN",
ranges: [
{ min: 362, max: 421 }
]
},
japaneseShowcase: {
set: "FDN",
ranges: [
{ min: 422, max: 431 }
]
},
fractureFoils: {
set: "FDN",
ranges: [
{ min: 432, max: 441 }
]
},
extendedArt: {
set: "FDN",
ranges: [
{ min: 442, max: 487 }
]
},
specialGuest: {
set: "SPG",
ranges: [
{ min: 74, max: 83 }
]
}
};
// Dominaria United - DMU
const DominariaUnitedCategories = {
normalCards: {
set: "DMU",
ranges: [
{ min: 1, max: 261 }
]
},
basicLands: {
set: "DMU",
ranges: [
{ min: 262, max: 276 }
]
},
stainedGlassLands: {
set: "DMU",
ranges: [
{ min: 277, max: 281 }
]
},
jumpstartCards: {
set: "DMU",
ranges: [
{ min: 282, max: 286 }
]
},
showcase: {
set: "DMU",
ranges: [
{ min: 287, max: 327 }
]
},
texturedFoil: {
set: "DMU",
ranges: [
{ min: 328, max: 368 }
]
},
phyrexian: {
set: "DMU",
ranges: [
{ min: 369, max: 370 }
]
},
ajaniPlaneswalker: {
set: "DMU",
ranges: [
{ min: 371, max: 371 }
]
},
borderlessPlaneswalker: {
set: "DMU",
ranges: [
{ min: 372, max: 376 }
]
},
alternateArtBorderlessLands: {
set: "DMU",
ranges: [
{ min: 377, max: 382 }
]
},
extendedArt: {
set: "DMU",
ranges: [
{ min: 383, max: 427 }
]
},
setExtension: {
set: "DMU",
ranges: [
{ min: 435, max: 436 }
]
},
// Commander-specific cards (from the DMC set)
commanderNew: {
set: "DMC",
ranges: [
{ min: 1, max: 20 }
]
},
commanderSetBoosters: {
set: "DMC",
ranges: [
{ min: 21, max: 28 }
]
},
commanderLegendsRetold: {
set: "DMC",
ranges: [
{ min: 29, max: 48 }
]
},
commanderEtchedFoil: {
set: "DMC",
ranges: [
{ min: 49, max: 70 }
]
},
commanderExtendedArt: {
set: "DMC",
ranges: [
{ min: 71, max: 96 }
]
},
// Lost Legends cards from the LEG set
lostLegends: {
set: "LEG",
ranges: [
{ min: 1, max: 310 }
]
}
};
// Duskmourne: House of Horros DSK
const DuskmournCategories = {
normalCards: {
set: "DSK",
ranges: [
{ min: 1, max: 254 },
{ min: 269, max: 269 },
{ min: 271, max: 271 }
]
},
fullArtLands: {
set: "DSK",
ranges: [
{ min: 272, max: 276 }
]
},
basicLands: {
set: "DSK",
ranges: [
{ min: 277, max: 286 }
]
},
lurkingEvil: {
set: "DSK",
ranges: [
{ min: 287, max: 301 }
]
},
showcase: {
set: "DSK",
ranges: [
{ min: 302, max: 327 }
]
},
borderless: {
set: "DSK",
ranges: [
{ min: 328, max: 350 }
]
},
doubleExposure: {
set: "DSK",
ranges: [
{ min: 351, max: 367 }
]
},
extendedArt: {
set: "DSK",
ranges: [
{ min: 368, max: 385 }
]
},
japaneseShowcase: {
set: "DSK",
ranges: [
{ min: 386, max: 395 }
]
},
fracturedFoils: {
set: "DSK",
ranges: [
{ min: 396, max: 405 }
]
},
texturedFinish: {
set: "DSK",
ranges: [
{ min: 406, max: 410 }
]
},
commonDualLands: {
set: "DSK",
ranges: [
{ min: 255, max: 255 },
{ min: 257, max: 258 },
{ min: 262, max: 268 }
]
},
rareDualLands: {
set: "DSK",
ranges: [
{ min: 256, max: 256 },
{ min: 259, max: 261 },
{ min: 270, max: 270 }
]
},
// Special Guest Cards
specialGuest: {
set: "SPG",
ranges: [
{ min: 64, max: 73 }
]
},
// Duskmourn Commander Cards
fullArtCommanders: {
set: "DSC",
ranges: [
{ min: 1, max: 8 }
]
},
newCommanderCards: {
set: "DSC",
ranges: [
{ min: 9, max: 40 }
]
},
extendedArtCommander: {
set: "DSC",
ranges: [
{ min: 41, max: 67 }
]
},
newArtwork: {
set: "DSC",
ranges: [
{ min: 68, max: 96 }
]
}
};
// Bloomburrow BLB
const BloomBurrowCategories = {
generalCardPool: {
set: "BLB",
ranges: [
{ min: 1, max: 261 }
]
},
springLands: {
set: "BLB",
ranges: [
{ min: 262, max: 262 },
{ min: 266, max: 266 },
{ min: 270, max: 270 },
{ min: 274, max: 274 },
{ min: 278, max: 278 }
]
},
summerLands: {
set: "BLB",
ranges: [
{ min: 263, max: 263 },
{ min: 267, max: 267 },
{ min: 271, max: 271 },
{ min: 275, max: 275 },
{ min: 279, max: 279 }
]
},
fallLands: {
set: "BLB",
ranges: [
{ min: 264, max: 264 },
{ min: 268, max: 268 },
{ min: 272, max: 272 },
{ min: 276, max: 276 },
{ min: 280, max: 280 }
]
},
winterLands: {
set: "BLB",
ranges: [
{ min: 265, max: 265 },
{ min: 269, max: 269 },
{ min: 273, max: 273 },
{ min: 277, max: 277 },
{ min: 281, max: 281 }
]
},
borderless: {
set: "BLB",
ranges: [
{ min: 282, max: 286 },
{ min: 337, max: 342 }
]
},
borderlessFieldNotes: {
set: "BLB",
ranges: [
{ min: 287, max: 294 }
]
},
showcaseWoodland: {
set: "BLB",
ranges: [
{ min: 295, max: 336 }
]
},
courageousCritters: {
set: "BLC",
ranges: [
{ min: 73, max: 100 }
]
},
raisedFoils: {
set: "BLC",
ranges: [
{ min: 93, max: 96 }
],
alternateRanges: [
{ set: "BLB", ranges: [
{ min: 343, max: 355 }
]}
]
},
extendedArt: {
set: "BLB",
ranges: [
{ min: 356, max: 368 }
]
},
extendedArtCommander: {
set: "BLC",
ranges: [
{ min: 41, max: 72 }
]
},
specialGuests: {
set: "SPG",
ranges: [
{ min: 54, max: 63 }
]
}
};
// Assassin's Creed - ACR
const AssassinsCreedCategories = {
regularCards: {
set: "ACR",
ranges: [
{ min: 1, max: 100 }
]
},
fullArtLands: {
set: "ACR",
ranges: [
{ min: 101, max: 110 }
]
},
starterKit: {
set: "ACR",
ranges: [
{ min: 274, max: 301 }
]
},
basicLand: {
set: "ACR",
ranges: [
{ min: 302, max: 305 }
]
},
sceneLands: {
set: "ACR",
ranges: [
{ min: 111, max: 112 },
{ min: 114, max: 116 }
]
},
sceneCard: {
set: "ACR",
ranges: [
{ min: 113, max: 113 }
]
},
borderless: {
set: "ACR",
ranges: [
{ min: 117, max: 126 }
]
},
showcase: {
set: "ACR",
ranges: [
{ min: 127, max: 154 }
]
},
texturedFoil: {
set: "ACR",
ranges: [
{ min: 267, max: 271 }
]
},
extendedArt: {
set: "ACR",
ranges: [
{ min: 155, max: 171 }
]
},
serialized: {
set: "ACR",
ranges: [
{ min: 272, max: 273 }
]
},
etchedFoil: {
set: "ACR",
ranges: [
{ min: 172, max: 266 }
]
}
};
// Modern Horizons 3 - MH3
const ModernHorizonsIIICategories = {
generalCardPool: {
set: "MH3",
ranges: [
{ min: 1, max: 261 }
]
},
newToModern: {
set: "MH3",
ranges: [
{ min: 262, max: 303 }
]
},
fullArtLand: {
set: "MH3",
ranges: [
{ min: 304, max: 308 }
]
},
fullArtSnowCoveredWaste: {
set: "MH3",
ranges: [
{ min: 309, max: 309 }
]
},
basicLand: {
set: "MH3",
ranges: [
{ min: 310, max: 319 }
]
},
borderlessFramebreak: {
set: "MH3",
ranges: [
{ min: 320, max: 349 }
]
},
borderlessLands: {
set: "MH3",
ranges: [
{ min: 350, max: 361 }
]
},
borderlessPlaneswalkers: {
set: "MH3",
ranges: [
{ min: 442, max: 446 }
]
},
borderlessConceptEldrazi: {
set: "MH3",
specificCollectorNumbers: [381, 382, 383]
},
borderlessProfile: {
set: "MH3",
ranges: [
{ min: 362, max: 380 }
]
},
retro: {
set: "MH3",
ranges: [
{ min: 384, max: 441 }
]
},
extendedArt: {
set: "MH3",
ranges: [
{ min: 447, max: 467 }
]
},
texturedFoil: {
set: "MH3",
ranges: [
{ min: 468, max: 472 }
]
},
etchedFoil: {
set: "MH3",
ranges: [
{ min: 473, max: 494 }
]
},
timeshift: {
set: "H2R",
ranges: [
{ min: 1, max: 16 }
]
},
specialGuests: {
set: "SPG",
ranges: [
{ min: 39, max: 53 }
]
},
commanders: {
set: "M3C",
ranges: [
{ min: 1, max: 8 },
{ min: 9, max: 16 }
]
},
newCards: {
set: "M3C",
specificCollectorNumbers: [32, 33, 34, 35, 36, 37, 38, 39, 51, 53, 57, 63, 92, 93, 94, 95, 96, 97, 99, 100, 101, 102, 104, 106, 107, 108, 109, 110, 111, 112, 113, 114, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135]
},
extendedArtCommanders: {
set: "M3C",
ranges: [
{ min: 25, max: 31 },
{ min: 40, max: 50 },
{ min: 52, max: 56 },
{ min: 58, max: 62 },
{ min: 64, max: 83 }
]
}
};
// March of the Machine (MOM)
const MarchOfTheMachineCategories = {
generalCardPool: {
set: "MOM",
ranges: [
{ min: 1, max: 276 }
]
},
basicLands: {
set: "MOM",
ranges: [
{ min: 277, max: 281 }
]
},
fullArtLands: {
set: "MOM",
ranges: [
{ min: 282, max: 291 }
]
},
showcase: {
set: "MOM",
ranges: [
{ min: 292, max: 319 }
]
},
borderlessPlaneswalkers: {
set: "MOM",
ranges: [
{ min: 320, max: 322 }
]
},
jumpstartCards: {
set: "MOM",
ranges: [
{ min: 323, max: 337 }
]
},
serializedPhyrexians: {
set: "MOM",
ranges: [
{ min: 338, max: 342 }
]
},
extendedArt: {
set: "MOM",
ranges: [
{ min: 343, max: 380 }
]
},
multiverseLegendsShowcase: {
set: "MUL",
ranges: [
{ min: 1, max: 65 }
]
},
multiverseLegendsFoilEtched: {
set: "MUL",
ranges: [
{ min: 66, max: 130 }
]
},
multiverseLegendsHaloFoil: {
set: "MUL",
ranges: [
{ min: 131, max: 195 }
]
},
multiverseLegendsDoubleRainbowFoilSerialized: {
set: "MUL",
ranges: [
{ min: 131, max: 195, suffix: 'z' }
]
},
newCommander: {
set: "MOC",
ranges: [
{ min: 1, max: 46 }
]
},
setBoosterCommander: {
set: "MOC",
ranges: [
{ min: 72, max: 79 }
]
},
extendedArtCommander: {
set: "MOC",
ranges: [
{ min: 80, max: 133 }
]
}
};
// Kamigawa: Neon Dynasty (NEO)
const NeonDynastyCategories = {
generalCardPool: {
set: "NEO",
ranges: [
{ min: 1, max: 282 }
]
},
basicLands: {
set: "NEO",
ranges: [
{ min: 283, max: 292 }
]
},
ukiyoeLands: {
set: "NEO",
ranges: [
{ min: 293, max: 302 }
]
},
borderlessPlaneswalkers: {
set: "NEO",
ranges: [
{ min: 303, max: 306 }
]
},
phyrexian: {
set: "NEO",
ranges: [
{ min: 307, max: 308 }
]
},
samurai: {
set: "NEO",
ranges: [
{ min: 309, max: 330 }
]
},
ninja: {
set: "NEO",
ranges: [
{ min: 331, max: 353 }
]
},
softGlow: {
set: "NEO",
ranges: [
{ min: 354, max: 405 }
]
},
altArtBorderless: {
set: "NEO",
ranges: [
{ min: 406, max: 416 }
]
},
etchedFoil: {
set: "NEO",
ranges: [
{ min: 417, max: 428 }
]
},
neonInk: {
set: "NEO",
ranges: [
{ min: 429, max: 432 }
]
},
extendedArt: {
set: "NEO",
ranges: [
{ min: 433, max: 505 }
]
},
setExtension: {
set: "NEO",
ranges: [
{ min: 513, max: 514 }
]
},
newCommander: {
set: "NEC",
ranges: [
{ min: 1, max: 30 }
]
},
setBoosterCommander: {
set: "NEC",
ranges: [
{ min: 31, max: 38 }
]
},
extendedArtCommander: {
set: "NEC",
ranges: [
{ min: 39, max: 76 }
]
}
};
// Double Masters 2x2
const DoubleMastersCategories = {
generalCardPool: {
set: "2X2",
ranges: [
{ min: 1, max: 331 }
]
},
crypticSpires: {
set: "2X2",
ranges: [
{ min: 332, max: 332 }
]
},
borderless: {
set: "2X2",
ranges: [
{ min: 333, max: 412 }
]
},
etchedFoil: {
set: "2X2",
ranges: [
{ min: 413, max: 572 }
]
},
texturedFoil: {
set: "2X2",
ranges: [
{ min: 573, max: 577 }
]
}
};
// Outlaws of Thunder Junction OTJ
const OTJCategories = {
regularCards: {
set: "OTJ",
ranges: [
{ min: 1, max: 271 }
]
},
fullArtBasicLands: {
set: "OTJ",
ranges: [
{ min: 272, max: 276 }
]
},
wantedCards: {
set: "OTJ",
ranges: [
{ min: 287, max: 299 }
]
},
borderlessNormal: {
set: "OTJ",
ranges: [
{ min: 300, max: 306 }
]
},
extendedArtNormal: {
set: "OTJ",
ranges: [
{ min: 307, max: 367 }
]
},
basicLandsNormal: {
set: "OTJ",
ranges: [
{ min: 277, max: 286 }
]
},
breakingNewsProsperityShowcase: {
set: "OTP",
ranges: [
{ min: 1, max: 65 }
]
},
breakingNewsProsperityShowcaseTexturedFoil: {
set: "OTP",
ranges: [
{ min: 66, max: 80 }
]
},
bigScoreNormal: {
set: "BIG",
ranges: [
{ min: 1, max: 30 }
]
},
bigScoreVaultFrames: {
set: "BIG",
ranges: [
{ min: 31, max: 60 }
]
},
bigScoreVaultFrameAndRaisedFoil: {
set: "BIG",
ranges: [
{ min: 61, max: 65 }
]
},
bigScoreExtendedArt: {
set: "BIG",
ranges: [
{ min: 66, max: 95 }
]
},
outlawsOfThunderJunctionCommander: {
set: "OTC",
ranges: [
{ min: 1, max: 40 }
]
},
outlawsOfThunderJunctionSpecialGuest: {
set: "SPG",
ranges: [
{ min: 29, max: 38 }
]
},
outlawsOfThunderJunctionCommanderExtendedArt: {
set: "OTC",
ranges: [
{ min: 41, max: 76 }
]
}
};
// Fallout PIP
const PIPCategories = {
basicLands: {
set: "PIP",
ranges: [
{ min: 317, max: 326 }
]
},
newCards: {
set: "PIP",
ranges: [
{ min: 1, max: 154 }
]
},
reprints: {
set: "PIP",
ranges: [
{ min: 155, max: 316 }
]
},
extendedArtNew: {
set: "PIP",
ranges: [
{ min: 362, max: 446 }
]
},
extendedArtReprint: {
set: "PIP",
ranges: [
{ min: 447, max: 528 }
]
},
surgefoilWildcard1: {
set: "PIP",
ranges: [
{ min: 529, max: 844 }
]
},
surgefoilWildcard2: {
set: "PIP",
ranges: [
{ min: 890, max: 1056 }
]
},
borderlessVaultBoy: {
set: "PIP",
ranges: [
{ min: 353, max: 361 }
]
},
showcase: {
set: "PIP",
ranges: [
{ min: 327, max: 352 }
]
}
};
const MKMCategories = {
regularSetCards: {
set: "MKM",
ranges: [
{ min: 1, max: 258 },
{ min: 261, max: 261 },
{ min: 265, max: 265 },
{ min: 267, max: 267 }
]
},
regularDualLands: {
set: "MKM",
specificCollectorNumbers: [259, 260, 262, 263, 264, 266, 268, 269, 270, 271]
},
impossibleLands: {
set: "MKM",
ranges: [
{ min: 272, max: 276 }
]
},
basicLands: {
set: "MKM",
ranges: [
{ min: 277, max: 286 }
]
},
borderlessPlaneswalker: {
set: "MKM",
ranges: [
{ min: 334, max: 335 }
]
},
borderlessDualLands: {
set: "MKM",
ranges: [
{ min: 324, max: 333 }
]
},
magnifiedShowcase: {
set: "MKM",
ranges: [
{ min: 287, max: 316 }
]
},
dossierShowcase: {
set: "MKM",
ranges: [
{ min: 336, max: 376 }
]
},
invisibleInkShowcase: {
set: "MKM",
ranges: [
{ min: 377, max: 389 }
]
},
ravnicaCityShowcase: {
set: "MKM",
ranges: [
{ min: 317, max: 323 }
]
},
serializedRavnicaCityShowcase: {
set: "MKM",
specificCollectorNumbers: ['317z', '318z', '319z', '320z', '321z', '322z', '323z']
},
extendedArt: {
set: "MKM",
ranges: [
{ min: 390, max: 422 }
]
},
specialGuests: {
set: "SPG",
ranges: [
{ min: 19, max: 28 }
]
},
foilEtchedCommander: {
set: "MKC",
ranges: [
{ min: 19, max: 28 }
]
},
extendedArtCommander: {
set: "MKC",
ranges: [
{ min: 312, max: 358 }
]
},
generalCommanderCardPool: {
set: "MKC",
ranges: [
{ min: 9, max: 48 }
]
}
};
// Ravnica Remastered RVR
const RVRCategories = {
regularSetCards: {
set: "RVR",
ranges: [
{ min: 1, max: 291 } // General Card Pool
]
},
borderlessShocklands: {
set: "RVR",
ranges: [
{ min: 292, max: 301 } // Borderless Shocklands
]
},
borderlessAnime: {
set: "RVR",
ranges: [
{ min: 416, max: 445 } // Borderless Anime
]
},
retroFrame: {
set: "RVR",
ranges: [
{ min: 302, max: 415 } // Borderless Anime
]
},
RetroFrameTwo: {
set: "RVR",
ranges: [
{ min: 446, max: 467 } // Borderless Anime
]
}
};
// Lost Caverns of Ixalan Categories
const LCICategories = {
specialGuests: {
set: "SPG",
ranges: [
{ min: 1, max: 18 }
]
},
jurassicPark: {
set: "REX",
ranges: [
{ min: 1, max: 20 }
]
},
jurassicParkLands: {
set: "REX",
ranges: [
{ min: 21, max: 26 }
]
},
LCICommanderReprints: {
set: "LCC",
ranges: [
{ min: 125, max: 370 }
]
},
LCICommanderExtendedArt: {
set: "LCC",
ranges: [
{ min: 21, max: 68 }
]
},
LCICommanderBoxToppers: {
set: "LCC",
ranges: [
{ min: 101, max: 120 }
]
},
LCICommanderNewCardsGroup1: {
set: "LCC",
ranges: [
{ min: 9, max: 16 }
]
},
LCICommanderNewCardsGroup2: {
set: "LCC",
ranges: [
{ min: 69, max: 100 }
]
},
LCICommanderNewCardsGroup3Commanders: {
set: "LCC",
ranges: [
{ min: 1, max: 8 }
]
},
LCICommanderShowcase: {
set: "LCC",
ranges: [
{ min: 17, max: 20 }
]
},
general: {
set: "LCI",
ranges: [
{ min: 1, max: 286 }
]
},
fullArtLands: {
set: "LCI",
ranges: [
{ min: 287, max: 291 }
]
},
showcase: {
set: "LCI",
ranges: [
{ min: 292, max: 319 }
]
},
borderless: {
set: "LCI",
ranges: [
{ min: 320, max: 352 }
]
},
extendedArt: {
set: "LCI",
ranges: [
{ min: 353, max: 392 }
]
},
basicLands: {
set: "LCI",
ranges: [
{ min: 393, max: 402 }
]
},
neonInk: {
set: "LCI",
ranges: [
{ min: 410, max: 410 }
]
}
};
// Doctor Who
const WHOCategories = {
commanders: {
set: "WHO",
ranges: [
{ min: 1, max: 8 }
]
},
generalCardSet: {
set: "WHO",
ranges: [
{ min: 9, max: 191 }
]
},
tardisShowcase: {
set: "WHO",
ranges: [
{ min: 535, max: 564 }
]
},
basicLands: {
set: "WHO",
ranges: [
{ min: 196, max: 205 }
]
},
reprints: {
set: "WHO",
ranges: [
{ min: 206, max: 331 }
]
},
extendedArtNew: {
set: "WHO",
ranges: [
{ min: 332, max: 463 }
]
},
extendedArtOld: {
set: "WHO",
ranges: [
{ min: 464, max: 534 }
]
},
surgeFoil: {
set: "WHO",
ranges: [
{ min: 606, max: 1125 }
]
},
surgeTardis: {
set: "WHO",
ranges: [
{ min: 1126, max: 1155 }
]
},
surgeFoilBasicLands: {
set: "WHO",
ranges: [
{ min: 1156, max: 1165 }
]
}
};
WHOCategories.theDoctors = {
set: "WHO",
specificCollectorNumbers: [128, 156, 162, 2, 127, 159, 158, 124, 148, 3, 125, 164, 4]
};
// Baldur's Gate
const CLBCategories = {
regularSetCards: {
set: "CLB",
ranges: [
{ min: 1, max: 361 }
]
},
borderless: {
set: "CLB",
ranges: [
{ min: 362, max: 374 }
]
},
showcase: {
set: "CLB",
ranges: [
{ min: 375, max: 450 }
]
},
basicLands: {
set: "CLB",
ranges: [
{ min: 451, max: 470 }
]
},
foilEtched: {
set: "CLB",
ranges: [
{ min: 471, max: 552 }
]
},
extendedArt: {
set: "CLB",
ranges: [
{ min: 553, max: 606 }
]
},
commanderExtendedArt: {
set: "CLB",
ranges: [
{ min: 607, max: 645 }
]
},
commanderCards: {
set: "CLB",
ranges: [
{ min: 646, max: 930 }
]
}
};
// Brother's War
const BROCategories = {
generalCardPool: {
set: "BRO",
ranges: [
{ min: 1, max: 267 }
]
},
basicLands: {
set: "BRO",
ranges: [
{ min: 268, max: 277 }
]
},
fullArtLands: {
set: "BRO",
ranges: [
{ min: 278, max: 287 }
]
},
alternateArtBorderless: {
set: "BRO",
ranges: [
{ min: 293, max: 300 }
]
},
extendedArt: {
set: "BRO",
ranges: [
{ min: 301, max: 377 }
]
}
};
const BRRCategories = {
retroFrameArtifacts: {
set: "BRR",
ranges: [
{ min: 1, max: 63 }
]
},
retroSchematicArtifacts: {
set: "BRR",
ranges: [
{ min: 64, max: 126 }
]
}
};
const BOTCategories = {
generalTransformers: {
set: "BOT",
ranges: [
{ min: 1, max: 15 }
]
},
shatteredGlassTransformers: {
set: "BOT",
ranges: [
{ min: 16, max: 29 }
]
}
};
const BRCCategories = {
generalcards: {
set: "BRC",
ranges: [
{ min: 1, max: 211 }
]
},
brcextendedart: {
set: "BRC",
ranges: [
{ min: 41, max: 67 }
]
}
};
const DMRCategories = {
generalCardPool: {
set: "DMR",
ranges: [
{ min: 1, max: 261 }
]
},
basicLandCardPool: {
set: "DMR",
ranges: [
{ min: 402, max: 411 }
]
},
oldFramePool: {
set: "DMR",
ranges: [
{ min: 262, max: 401 }
]
},
alternateArtBorderless: {
set: "DMR",
ranges: [
{ min: 412, max: 456 }
]
}
};
const WOECategories = {
generalCardPool: {
set: "WOE",
ranges: [
{ min: 1, max: 261 }
]
},
alternateArtBorderless: {
set: "WOE",
ranges: [
{ min: 297, max: 307 }
]
},
showcase: {
set: "WOE",
ranges: [
{ min: 277, max: 296 }
]
},
extendedArt: {
set: "WOE",
ranges: [
{ min: 323, max: 374 }
]
},
basicLands: {
set: "WOE",
ranges: [
{ min: 267, max: 276 }
]
},
fullArtLands: {
set: "WOE",
ranges: [
{ min: 262, max: 266 }
]
},
allBasicLands: {
set: "WOE",
ranges: [
{ min: 262, max: 276 }
]
}
};
const WOTCategories = {
generalCardPool: {
set: "WOT",
ranges: [
{ min: 1, max: 63 }
]
},
anime: {
set: "WOT",
ranges: [
{ min: 64, max: 103 }
]
}
};
const ONECategories = {
generalCardPool: {
set: "ONE",
ranges: [
{ min: 1, max: 261 }
]
},
panoramaLands: {
set: "ONE",
ranges: [
{ min: 262, max: 266 }
]
},
phyrexianLands: {
set: "ONE",
ranges: [
{ min: 267, max: 271 }
]
},
showcase: {
set: "ONE",
ranges: [
{ min: 285, max: 334 }
],
frameEffects: ['showcase']
},
borderlessPlaneswalkers: {
set: "ONE",
ranges: [
{ min: 335, max: 344 }
]
},
alternateArtBorderless: {
set: "ONE",
ranges: [
{ min: 370, max: 374 }
]
},
extendedArtCards: {
set: "ONE",
ranges: [
{ min: 375, max: 413 }
]
},
EleshNorn: {
set: 'ONE',
specificCollectorNumbers: [10, 298, 414, 415, 416, 418, 419]
},
compleatFoils: {
set: "ONE",
ranges: [
{ min: 417, max: 479 }
]
}
};
const ONCCategories = {
commander: {
set: "ONC",
ranges: [
{ min: 1, max: 28 }
]
},
commanderExtended: {
set: "ONC",
ranges: [
{ min: 31, max: 58 }
]
},
}
const CMMCategories = {
generalCardPool: {
set: "CMM",
ranges: [
{ min: 1, max: 436 }
]
},
basicLandCardPool: {
set: "CMM",
ranges: [
{ min: 437, max: 451 }
]
},
profileCardPool: {
set: "CMM",
ranges: [
{ min: 668, max: 691 }
]
},
commanderCards: {
set: "CMM",
ranges: [
{ min: 704, max: 743 }
]
},
borderlessCards: {
set: "CMM",
ranges: [
{ min: 622, max: 667 },
{ min: 692, max: 703 }
]
},
extendedArtCards: {
set: "CMM",
ranges: [
{ min: 744, max: 778 }
]
},
etchedFoils: {
set: "CMM",
ranges: [
{ min: 452, max: 621 }
]
},
texturedFoils: {
set: "CMM",
ranges: [
{ min: 1057, max: 1066 }
]
}
};
// Global Declarations
let currentCardIndex = 0;
// General Fetch Functions Section
function onSetSelectionChange(event) {
const selectedSet = event.target.value;
// Logic to update the simulator based on the selected set
console.log('Set selected:', selectedSet);
}
// DOMContentLoaded event listener for set selection change
document.addEventListener('DOMContentLoaded', function () {
const setSelection = document.getElementById('setSelection');
if (setSelection) {
setSelection.addEventListener('change', onSetSelectionChange);
console.log('Event listener added to setSelection.');
} else {
console.log('setSelection element not found on this page.');
}
});
// Fetch cards from a specific category
async function fetchCardsFromCategory(category) {
let fetchedCards = [];
if (category.ranges) {
for (const range of category.ranges) {
const cardsWithRanges = await fetchCardsWithRanges(category.set, range.min, range.max);
fetchedCards = [...fetchedCards, ...cardsWithRanges];
}
}
if (category.alternateRanges) {
for (const alternate of category.alternateRanges) {
for (const range of alternate.ranges) {
const cardsWithRanges = await fetchCardsWithRanges(alternate.set, range.min, range.max);
fetchedCards = [...fetchedCards, ...cardsWithRanges];
}
}
}
if (category.specificCollectorNumbers && Array.isArray(category.specificCollectorNumbers)) {
for (const collectorNumber of category.specificCollectorNumbers) {
const specificCard = await fetchSpecificCard(category.set, collectorNumber);
if (specificCard) {
fetchedCards.push(specificCard);
}
}
}
return fetchedCards;
}
// Fetch a specific card by set and collector number, excluding "A-" versions
async function fetchSpecificCard(set, collectorNumber) {
const endpoint = `https://api.scryfall.com/cards/${set.toLowerCase()}/${collectorNumber}`;
try {
const response = await fetch(endpoint);
if (!response.ok) {
console.error(`Failed to fetch card from set: ${set} with collectorNumber: ${collectorNumber} :`, response.statusText);
return null;
}
const card = await response.json();
// Exclude Alchemy versions (collector_number starting with "A-")
if (card.collector_number.startsWith('A-')) {
console.log(`Excluded Alchemy card: ${card.name}`);
return null;
}
// Initialize images array
let images = [];
// Handle double-faced cards with `card_faces`
if ((card.layout === 'modal_dfc' || card.layout === 'transform' || card.layout === 'double_faced_token')
&& card.card_faces && card.card_faces.length > 1) {
images = [
card.card_faces[0].image_uris?.normal || '',
card.card_faces[1].image_uris?.normal || ''
].filter(Boolean); // Filter out any undefined or empty strings
}
// Handle single-faced cards
else if (card.image_uris && card.image_uris.normal) {
images = [card.image_uris.normal];
} else {
console.warn(`No valid image found for card: ${card.name}`);
}
card.images = images; // Assign images to the card object
return card;
} catch (error) {
console.error(`Error fetching specific card: ${error.message}`);
return null;
}
}
// Fetch cards within a specified range, excluding "A-" versions
async function fetchCardsWithRanges(setName, min, max) {
let cards = [];
let endpoint = `https://api.scryfall.com/cards/search?q=set:${setName}+cn>=${min}+cn<=${max}`;
try {
do {
const response = await fetch(endpoint);
if (!response.ok) {
console.error(`Failed to fetch cards for set ${setName} for range ${min}-${max} :`, response.statusText);
break; // Stop further requests if an error occurs
}
const data = await response.json();
const processedCards = data.data
.filter(card => {
// Exclude cards with collector numbers starting with 'A-'
const isExcluded = card.collector_number.startsWith('A-');
if (isExcluded) {
console.log(`Excluded card with collector number starting with 'A-': ${card.name}`);
}
return !isExcluded;
})
.map(card => {
let images = [];
// Handle different card layouts
if ((card.layout === 'transform' || card.layout === 'modal_dfc' || card.layout === 'double_faced_token')
&& card.card_faces && card.card_faces.length > 0) {
images = [card.card_faces[0].image_uris?.normal || ''];
} else if (card.layout === 'reversible_card' && card.card_faces && card.card_faces.length > 0) {
images = [card.card_faces[0].image_uris?.normal || ''];
} else if (card.image_uris && card.image_uris.normal) {
images = [card.image_uris.normal];
} else {
console.warn(`No valid image URI for card: ${card.name}`);
images = []; // Ensure no image is added if none are found
}
// Add images to the card object for easy access later in display functions
card.images = images;
return card;
});
// Combine processed cards into the main card array
cards = cards.concat(processedCards);
if (data.has_more) {
endpoint = data.next_page;
} else {
break;
}
} while (true);
console.log(`Fetched ${cards.length} cards for set ${setName} within range ${min}-${max}`);
} catch (error) {
console.error(`Error fetching cards: ${error.message}`);
return []; // Stop further requests if an error occurs
}
return cards;
}
async function fetchDomUnitedListCard() {
const excelUrl = 'https://mtg-packs.com/wp-content/uploads/2024/10/dominaria_list_converted.xlsx'; // URL to your uploaded Excel file
// Step 1: Fetch and parse the Excel file
const response = await fetch(excelUrl);
const arrayBuffer = await response.arrayBuffer();
// Use the SheetJS library (https://cdnjs.com/libraries/xlsx) to parse the Excel file
const workbook = XLSX.read(arrayBuffer, { type: 'array' });
const sheetName = workbook.SheetNames[0]; // First sheet in the Excel file
const sheet = workbook.Sheets[sheetName];
const listCards = XLSX.utils.sheet_to_json(sheet);
// Step 2: Randomly select a card from "The List"
const randomIndex = Math.floor(Math.random() * listCards.length);
const selectedCard = listCards[randomIndex];
const cardName = selectedCard['Card Name'];
const cardSet = selectedCard['Set'];
// Step 3: Use Scryfall API to fetch the card details
const scryfallApiUrl = `https://api.scryfall.com/cards/named?exact=${encodeURIComponent(cardName)}&set=${encodeURIComponent(cardSet)}`;
try {
const scryfallResponse = await fetch(scryfallApiUrl);
if (!scryfallResponse.ok) {
throw new Error(`Error fetching card from Scryfall: ${scryfallResponse.status}`);
}
const cardData = await scryfallResponse.json();
return cardData;
} catch (error) {
console.error('Failed to fetch card details from Scryfall:', error);
return null;
}
}
async function fetchDominariaUnitedLegendsCard() {
const excelUrl = 'https://mtg-packs.com/wp-content/uploads/2024/10/Dominaria-United-Legends-Cards.xlsx'; // Updated URL to your uploaded Excel file
// Step 1: Fetch and parse the Excel file
const response = await fetch(excelUrl);
const arrayBuffer = await response.arrayBuffer();
// Use the SheetJS library (https://cdnjs.com/libraries/xlsx) to parse the Excel file
const workbook = XLSX.read(arrayBuffer, { type: 'array' });
const sheetName = workbook.SheetNames[0]; // First sheet in the Excel file
const sheet = workbook.Sheets[sheetName];
const listCards = XLSX.utils.sheet_to_json(sheet);
// Step 2: Randomly select a card from the list
const randomIndex = Math.floor(Math.random() * listCards.length);
const selectedCard = listCards[randomIndex];
const cardName = selectedCard['Card Name'].trim(); // Ensures the exact name is pulled without extra spaces
const cardSet = 'LEG'; // Hardcode the set to 'LEG' (Legends)
// Step 3: Use Scryfall API to fetch the card details
const scryfallApiUrl = `https://api.scryfall.com/cards/named?exact=${encodeURIComponent(cardName)}&set=${encodeURIComponent(cardSet)}`;
try {
const scryfallResponse = await fetch(scryfallApiUrl);
if (!response.ok) {
throw new Error(`Error fetching card from Scryfall: ${scryfallResponse.status}`);
}
const cardData = await scryfallResponse.json();
return cardData;
} catch (error) {
console.error('Failed to fetch card details from Scryfall:', error);
return null;
}
}
// Generate serialized numbers with a suffix
function generateSerializedNumbers(min, max, suffix) {
const serializedNumbers = [];
for (let i = min; i <= max; i++) {
serializedNumbers.push(`${i}${suffix}`);
}
return serializedNumbers;
}
// Fetch serialized cards based on collector numbers
async function fetchSerializedCards(set, collectorNumbers) {
let serializedCards = [];
for (const collectorNumber of collectorNumbers) {
const specificCard = await fetchSpecificCard(set, collectorNumber);
if (specificCard) {
serializedCards.push(specificCard);
}
}
return serializedCards;
}
// Determine if a card should appear as a surge foil
function shouldAppearAsSurgeFoil(probability) {
const randomValue = Math.random();
return randomValue < probability;
}
//Section Specific Fetch Functions for each set
// Fetch functions for each category in Foundations (FDN)
async function fetchFDNRegularCards() {
return await fetchCardsFromCategory(FoundationsCategories.regularCards);
}
async function fetchFDNBasicLands() {
return await fetchCardsFromCategory(FoundationsCategories.basicLands);
}
async function fetchFDNFullArtBasicLands() {
return await fetchCardsFromCategory(FoundationsCategories.fullArtBasicLands);
}
async function fetchFDNCommonDualLands() {
return await fetchCardsFromCategory(FoundationsCategories.commonDualLands);
}
async function fetchFDNBorderless() {
return await fetchCardsFromCategory(FoundationsCategories.borderless);
}
async function fetchFDNManaFoil() {
return await fetchCardsFromCategory(FoundationsCategories.manaFoil);
}
async function fetchFDNJapaneseShowcase() {
return await fetchCardsFromCategory(FoundationsCategories.japaneseShowcase);
}
async function fetchFDNFractureFoils() {
return await fetchCardsFromCategory(FoundationsCategories.fractureFoils);
}
async function fetchFDNExtendedArt() {
return await fetchCardsFromCategory(FoundationsCategories.extendedArt);
}
async function fetchFDNSpecialGuest() {
return await fetchCardsFromCategory(FoundationsCategories.specialGuest);
}
// Fetch functions for each category in Dominaria United (DMU)
async function fetchDMUNormalCards() {
return await fetchCardsFromCategory(DominariaUnitedCategories.normalCards);
}
async function fetchDMUBasicLands() {
return await fetchCardsFromCategory(DominariaUnitedCategories.basicLands);
}
async function fetchDMUStainedGlassLands() {
return await fetchCardsFromCategory(DominariaUnitedCategories.stainedGlassLands);
}
async function fetchDMUJumpstartCards() {
return await fetchCardsFromCategory(DominariaUnitedCategories.jumpstartCards);
}
async function fetchDMUShowcase() {
return await fetchCardsFromCategory(DominariaUnitedCategories.showcase);
}
async function fetchDMUTexturedFoil() {
return await fetchCardsFromCategory(DominariaUnitedCategories.texturedFoil);
}
async function fetchDMUPhyrexian() {
return await fetchCardsFromCategory(DominariaUnitedCategories.phyrexian);
}
async function fetchDMUAjaniPlaneswalker() {
return await fetchCardsFromCategory(DominariaUnitedCategories.ajaniPlaneswalker);
}
async function fetchDMUBorderlessPlaneswalker() {
return await fetchCardsFromCategory(DominariaUnitedCategories.borderlessPlaneswalker);
}
async function fetchDMUAlternateArtBorderlessLands() {
return await fetchCardsFromCategory(DominariaUnitedCategories.alternateArtBorderlessLands);
}
async function fetchDMUExtendedArt() {
return await fetchCardsFromCategory(DominariaUnitedCategories.extendedArt);
}
async function fetchDMUSetExtension() {
return await fetchCardsFromCategory(DominariaUnitedCategories.setExtension);
}
// Fetch functions for Commander-specific cards (DMC)
async function fetchDMCCommanderNew() {
return await fetchCardsFromCategory(DominariaUnitedCategories.commanderNew);
}
async function fetchDMCCommanderSetBoosters() {
return await fetchCardsFromCategory(DominariaUnitedCategories.commanderSetBoosters);
}
async function fetchDMCCommanderLegendsRetold() {
return await fetchCardsFromCategory(DominariaUnitedCategories.commanderLegendsRetold);
}
async function fetchDMCCommanderEtchedFoil() {
return await fetchCardsFromCategory(DominariaUnitedCategories.commanderEtchedFoil);
}
async function fetchDMCCommanderExtendedArt() {
return await fetchCardsFromCategory(DominariaUnitedCategories.commanderExtendedArt);
}
// Fetch functions for Lost Legends (LEG)
async function fetchLEGLostLegends() {
return await fetchCardsFromCategory(DominariaUnitedCategories.lostLegends);
}
// Fetch functions for each category in Duskmourn (DSK)
async function fetchDSKNormalCards() {
return await fetchCardsFromCategory(DuskmournCategories.normalCards);
}
async function fetchDSKFullArtLands() {
return await fetchCardsFromCategory(DuskmournCategories.fullArtLands);
}
async function fetchDSKBasicLands() {
return await fetchCardsFromCategory(DuskmournCategories.basicLands);
}
async function fetchDSKLurkingEvil() {
return await fetchCardsFromCategory(DuskmournCategories.lurkingEvil);
}
async function fetchDSKShowcase() {
return await fetchCardsFromCategory(DuskmournCategories.showcase);
}
async function fetchDSKBorderless() {
return await fetchCardsFromCategory(DuskmournCategories.borderless);
}
async function fetchDSKDoubleExposure() {
return await fetchCardsFromCategory(DuskmournCategories.doubleExposure);
}
async function fetchDSKTexturedFinish() {
return await fetchCardsFromCategory(DuskmournCategories.texturedFinish);
}
async function fetchDSKJapaneseShowcase() {
return await fetchCardsFromCategory(DuskmournCategories.japaneseShowcase);
}
async function fetchDSKFracturedFoils() {
return await fetchCardsFromCategory(DuskmournCategories.fracturedFoils);
}
async function fetchDSKExtendedArt() {
return await fetchCardsFromCategory(DuskmournCategories.extendedArt);
}
async function fetchDSKCommonDualLands() {
return await fetchCardsFromCategory(DuskmournCategories.commonDualLands);
}
async function fetchDSKRareDualLands() {
return await fetchCardsFromCategory(DuskmournCategories.rareDualLands);
}
// Fetch functions for Special Guest cards
async function fetchSPGSpecialGuest() {
return await fetchCardsFromCategory(DuskmournCategories.specialGuest);
}
// Fetch functions for Duskmourn Commander cards (DSC)
async function fetchDSCFullArtCommanders() {
return await fetchCardsFromCategory(DuskmournCategories.fullArtCommanders);
}
async function fetchDSCNewCommanderCards() {
return await fetchCardsFromCategory(DuskmournCategories.newCommanderCards);
}
async function fetchDSCExtendedArtCommander() {
return await fetchCardsFromCategory(DuskmournCategories.extendedArtCommander);
}
async function fetchDSCNewArtwork() {
return await fetchCardsFromCategory(DuskmournCategories.newArtwork);
}
// Fetch functions for each category in Bloom Burrow (BLB)
async function fetchBLBGeneralCardPool() {
return await fetchCardsFromCategory(BloomBurrowCategories.generalCardPool);
}
async function fetchBLBSpringLands() {
return await fetchCardsFromCategory(BloomBurrowCategories.springLands);
}
async function fetchBLBSummerLands() {
return await fetchCardsFromCategory(BloomBurrowCategories.summerLands);
}
async function fetchBLBFallLands() {
return await fetchCardsFromCategory(BloomBurrowCategories.fallLands);
}
async function fetchBLBWinterLands() {
return await fetchCardsFromCategory(BloomBurrowCategories.winterLands);
}
async function fetchBLBBorderless() {
return await fetchCardsFromCategory(BloomBurrowCategories.borderless);
}
async function fetchBLBBorderlessFieldNotes() {
return await fetchCardsFromCategory(BloomBurrowCategories.borderlessFieldNotes);
}
async function fetchBLBShowcaseWoodland() {
return await fetchCardsFromCategory(BloomBurrowCategories.showcaseWoodland);
}
async function fetchBLBCourageousCritters() {
return await fetchCardsFromCategory(BloomBurrowCategories.courageousCritters);
}
async function fetchBLBRaisedFoils() {
return await fetchCardsFromCategory(BloomBurrowCategories.raisedFoils);
}
async function fetchBLBExtendedArtCommander() {
return await fetchCardsFromCategory(BloomBurrowCategories.extendedArtCommander);
}
async function fetchBLBExtendedArt() {
return await fetchCardsFromCategory(BloomBurrowCategories.extendedArt);
}
async function fetchBLBSpecialGuests() {
return await fetchCardsFromCategory(BloomBurrowCategories.specialGuests);
}
// Fetch functions for each category in Assassin's Creed (ACR)
async function fetchACRRegularCards() {
return await fetchCardsFromCategory(AssassinsCreedCategories.regularCards);
}
async function fetchACRFullArtLands() {
return await fetchCardsFromCategory(AssassinsCreedCategories.fullArtLands);
}
async function fetchACRStarterKit() {
return await fetchCardsFromCategory(AssassinsCreedCategories.starterKit);
}
async function fetchACRBasicLand() {
return await fetchCardsFromCategory(AssassinsCreedCategories.basicLand);
}
async function fetchACRSceneLands() {
return await fetchCardsFromCategory(AssassinsCreedCategories.sceneLands);
}
async function fetchACRSceneCard() {
return await fetchCardsFromCategory(AssassinsCreedCategories.sceneCard);
}
async function fetchACRBorderless() {
return await fetchCardsFromCategory(AssassinsCreedCategories.borderless);
}
async function fetchACRShowcase() {
return await fetchCardsFromCategory(AssassinsCreedCategories.showcase);
}
async function fetchACRTexturedFoil() {
return await fetchCardsFromCategory(AssassinsCreedCategories.texturedFoil);
}
async function fetchACRExtendedArt() {
return await fetchCardsFromCategory(AssassinsCreedCategories.extendedArt);
}
async function fetchACRSerialized() {
return await fetchCardsFromCategory(AssassinsCreedCategories.serialized);
}
async function fetchACREtchedFoil() {
return await fetchCardsFromCategory(AssassinsCreedCategories.etchedFoil);
}
// Fetch functions for each category in Modern Horizons III (MH3)
async function fetchMH3GeneralCardPool() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.generalCardPool);
}
async function fetchMH3NewToModern() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.newToModern);
}
async function fetchMH3FullArtLand() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.fullArtLand);
}
async function fetchMH3FullArtSnowCoveredWaste() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.fullArtSnowCoveredWaste);
}
async function fetchMH3BasicLand() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.basicLand);
}
async function fetchMH3BorderlessFramebreak() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.borderlessFramebreak);
}
async function fetchMH3BorderlessLands() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.borderlessLands);
}
async function fetchMH3BorderlessPlaneswalkers() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.borderlessPlaneswalkers);
}
async function fetchMH3BorderlessConceptEldrazi() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.borderlessConceptEldrazi);
}
async function fetchMH3BorderlessProfile() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.borderlessProfile);
}
async function fetchMH3Retro() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.retro);
}
async function fetchMH3ExtendedArt() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.extendedArt);
}
async function fetchMH3TexturedFoil() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.texturedFoil);
}
async function fetchMH3EtchedFoil() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.etchedFoil);
}
async function fetchH2RTimeshift() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.timeshift);
}
async function fetchSPGSpecialGuests() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.specialGuests);
}
async function fetchM3CCommanders() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.commanders);
}
async function fetchM3CNewCards() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.newCards);
}
async function fetchM3CExtendedArtCommanders() {
return await fetchCardsFromCategory(ModernHorizonsIIICategories.extendedArtCommanders);
}
// Section Specific Fetch Functions for March of the Machine (MOM)
async function fetchMOMGeneralCardPool() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.generalCardPool);
}
async function fetchMOMBasicLands() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.basicLands);
}
async function fetchMOMFullArtLands() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.fullArtLands);
}
async function fetchMOMShowcase() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.showcase);
}
async function fetchMOMBorderlessPlaneswalkers() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.borderlessPlaneswalkers);
}
async function fetchMOMJumpstartCards() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.jumpstartCards);
}
async function fetchMOMSerializedPhyrexians() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.serializedPhyrexians);
}
async function fetchMOMExtendedArt() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.extendedArt);
}
async function fetchMOMMultiverseLegendsShowcase() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.multiverseLegendsShowcase);
}
async function fetchMOMMultiverseLegendsFoilEtched() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.multiverseLegendsFoilEtched);
}
async function fetchMOMMultiverseLegendsHaloFoil() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.multiverseLegendsHaloFoil);
}
async function fetchMOMMultiverseLegendsDoubleRainbowFoilSerialized() {
const serializedNumbers = generateSerializedNumbers(131, 195, 'z');
return await fetchSerializedCards('mul', serializedNumbers);
}
async function fetchMOMNewCommander() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.newCommander);
}
async function fetchMOMSetBoosterCommander() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.setBoosterCommander);
}
async function fetchMOMExtendedArtCommander() {
return await fetchCardsFromCategory(MarchOfTheMachineCategories.extendedArtCommander);
}
// Section Specific Fetch Functions for Kamigawa: Neon Dynasty (NEO)
async function fetchNEOGeneralCardPool() {
return await fetchCardsFromCategory(NeonDynastyCategories.generalCardPool);
}
async function fetchNEOBasicLands() {
return await fetchCardsFromCategory(NeonDynastyCategories.basicLands);
}
async function fetchNEOUkiyoeLands() {
return await fetchCardsFromCategory(NeonDynastyCategories.ukiyoeLands);
}
async function fetchNEOBorderlessPlaneswalkers() {
return await fetchCardsFromCategory(NeonDynastyCategories.borderlessPlaneswalkers);
}
async function fetchNEOPhyrexian() {
return await fetchCardsFromCategory(NeonDynastyCategories.phyrexian);
}
async function fetchNEOSamurai() {
return await fetchCardsFromCategory(NeonDynastyCategories.samurai);
}
async function fetchNEONinja() {
return await fetchCardsFromCategory(NeonDynastyCategories.ninja);
}
async function fetchNEOSoftGlow() {
return await fetchCardsFromCategory(NeonDynastyCategories.softGlow);
}
async function fetchNEOAltArtBorderless() {
return await fetchCardsFromCategory(NeonDynastyCategories.altArtBorderless);
}
async function fetchNEOEtchedFoil() {
return await fetchCardsFromCategory(NeonDynastyCategories.etchedFoil);
}
async function fetchNEONeonInk() {
return await fetchCardsFromCategory(NeonDynastyCategories.neonInk);
}
async function fetchNEOExtendedArt() {
return await fetchCardsFromCategory(NeonDynastyCategories.extendedArt);
}
async function fetchNEOSetExtension() {
return await fetchCardsFromCategory(NeonDynastyCategories.setExtension);
}
async function fetchNEONewCommander() {
return await fetchCardsFromCategory(NeonDynastyCategories.newCommander);
}
async function fetchNEOSetBoosterCommander() {
return await fetchCardsFromCategory(NeonDynastyCategories.setBoosterCommander);
}
async function fetchNEOExtendedArtCommander() {
return await fetchCardsFromCategory(NeonDynastyCategories.extendedArtCommander);
}
// Fetch functions for each category in Double Masters 2022 (2X2)
async function fetch2X2GeneralCardPool() {
return await fetchCardsFromCategory(DoubleMastersCategories.generalCardPool);
}
async function fetch2X2CrypticSpires() {
return await fetchCardsFromCategory(DoubleMastersCategories.crypticSpires);
}
async function fetch2X2Borderless() {
return await fetchCardsFromCategory(DoubleMastersCategories.borderless);
}
async function fetch2X2EtchedFoil() {
return await fetchCardsFromCategory(DoubleMastersCategories.etchedFoil);
}
async function fetch2X2TexturedFoil() {
return await fetchCardsFromCategory(DoubleMastersCategories.texturedFoil);
}
// OTJ Fetch Functions
async function fetchOTJRegularCards() {
return await fetchCardsFromCategory(OTJCategories.regularCards);
}
async function fetchOTJFullArtBasicLands() {
return await fetchCardsFromCategory(OTJCategories.fullArtBasicLands);
}
async function fetchOTJWantedCards() {
return await fetchCardsFromCategory(OTJCategories.wantedCards);
}
async function fetchOTJBorderlessNormal() {
return await fetchCardsFromCategory(OTJCategories.borderlessNormal);
}
async function fetchOTJExtendedArtNormal() {
return await fetchCardsFromCategory(OTJCategories.extendedArtNormal);
}
async function fetchOTJBasicLandsNormal() {
return await fetchCardsFromCategory(OTJCategories.basicLandsNormal);
}
async function fetchOTJBreakingNewsProsperityShowcase() {
return await fetchCardsFromCategory(OTJCategories.breakingNewsProsperityShowcase);
}
async function fetchOTJBreakingNewsProsperityShowcaseTexturedFoil() {
return await fetchCardsFromCategory(OTJCategories.breakingNewsProsperityShowcaseTexturedFoil);
}
async function fetchBigScoreNormal() {
return await fetchCardsFromCategory(OTJCategories.bigScoreNormal);
}
async function fetchBigScoreVaultFrames() {
return await fetchCardsFromCategory(OTJCategories.bigScoreVaultFrames);
}
async function fetchBigScoreVaultFrameAndRaisedFoil() {
return await fetchCardsFromCategory(OTJCategories.bigScoreVaultFrameAndRaisedFoil);
}
async function fetchBigScoreExtendedArt() {
return await fetchCardsFromCategory(OTJCategories.bigScoreExtendedArt);
}
async function fetchOutlawsOfThunderJunctionSpecialGuest() {
return await fetchCardsFromCategory(OTJCategories.outlawsOfThunderJunctionSpecialGuest);
}
async function fetchOutlawsOfThunderJunctionCommander() {
return await fetchCardsFromCategory(OTJCategories.outlawsOfThunderJunctionCommander);
}
async function fetchOutlawsOfThunderJunctionCommanderExtendedArt() {
return await fetchCardsFromCategory(OTJCategories.outlawsOfThunderJunctionCommanderExtendedArt);
}
// PIP Fetch Functions
async function fetchPIPBasicLands() {
return await fetchCardsFromCategory(PIPCategories.basicLands);
}
async function fetchPIPNewCards() {
return await fetchCardsFromCategory(PIPCategories.newCards);
}
async function fetchPIPReprints() {
return await fetchCardsFromCategory(PIPCategories.reprints);
}
async function fetchPIPExtendedArtNew() {
return await fetchCardsFromCategory(PIPCategories.extendedArtNew);
}
async function fetchPIPExtendedArtReprint() {
return await fetchCardsFromCategory(PIPCategories.extendedArtReprint);
}
async function fetchPIPSurgefoilWildcard1() {
return await fetchCardsFromCategory(PIPCategories.surgefoilWildcard1);
}
async function fetchPIPSurgefoilWildcard2() {
return await fetchCardsFromCategory(PIPCategories.surgefoilWildcard2);
}
async function fetchPIPBorderlessVaultBoy() {
return await fetchCardsFromCategory(PIPCategories.borderlessVaultBoy);
}
async function fetchPIPShowcase() {
return await fetchCardsFromCategory(PIPCategories.showcase);
}
// MKM Fetch Functions
async function fetchMKMRegularSetCards() {
return await fetchCardsFromCategory(MKMCategories.regularSetCards);
}
async function fetchMKMRegularDualLands() {
return await fetchCardsFromCategory(MKMCategories.regularDualLands);
}
async function fetchMKMImpossibleLands() {
return await fetchCardsFromCategory(MKMCategories.impossibleLands);
}
async function fetchMKMBasicLands() {
return await fetchCardsFromCategory(MKMCategories.basicLands);
}
async function fetchMKMBorderlessPlaneswalker() {
return await fetchCardsFromCategory(MKMCategories.borderlessPlaneswalker);
}
async function fetchMKMBorderlessDualLands() {
return await fetchCardsFromCategory(MKMCategories.borderlessDualLands);
}
async function fetchMKMMagnifiedShowcase() {
return await fetchCardsFromCategory(MKMCategories.magnifiedShowcase);
}
async function fetchMKMDossierShowcase() {
return await fetchCardsFromCategory(MKMCategories.dossierShowcase);
}
async function fetchMKMInvisibleInkShowcase() {
return await fetchCardsFromCategory(MKMCategories.invisibleInkShowcase);
}
async function fetchMKMRavnicaCityShowcase() {
return await fetchCardsFromCategory(MKMCategories.ravnicaCityShowcase);
}
async function fetchMKMSerializedRavnicaCityShowcase() {
return await fetchCardsFromCategory(MKMCategories.serializedRavnicaCityShowcase);
}
async function fetchMKMExtendedArt() {
return await fetchCardsFromCategory(MKMCategories.extendedArt);
}
async function fetchMKMSpecialGuests() {
return await fetchCardsFromCategory(MKMCategories.specialGuests);
}
async function fetchMKMFoilEtchedCommander() {
return await fetchCardsFromCategory(MKMCategories.foilEtchedCommander);
}
async function fetchMKMExtendedArtCommander() {
return await fetchCardsFromCategory(MKMCategories.extendedArtCommander);
}
async function fetchMKMGeneralCommanderCardPool() {
return await fetchCardsFromCategory(MKMCategories.generalCommanderCardPool);
}
// Ravnica Remastered RVR
async function fetchRVRCards(category) {
return await fetchCardsFromCategory(RVRCategories[category]);
}
// Fetch functions for each category in Ravnica Remastered
async function fetchRVRGeneralSetCards() {
return await fetchRVRCards('regularSetCards');
}
async function fetchRVRBorderlessShocklands() {
return await fetchRVRCards('borderlessShocklands');
}
async function fetchRVRBorderlessAnime() {
return await fetchRVRCards('borderlessAnime');
}
async function fetchRVRRetroFrame() {
return await fetchRVRCards('retroFrame');
}
async function fetchRVRRetroFrameTwo() {
return await fetchRVRCards('RetroFrameTwo');
}
// Section 3 Specific Fetch Functions for Lost Caverns of Ixalan
async function fetchLCISpecialGuests() {
return await fetchCardsFromCategory(LCICategories.specialGuests);
}
async function fetchLCIJurassicPark() {
return await fetchCardsFromCategory(LCICategories.jurassicPark);
}
async function fetchLCIJurassicParkLands() {
return await fetchCardsFromCategory(LCICategories.jurassicParkLands);
}
async function fetchLCICommanderReprints() {
return await fetchCardsFromCategory(LCICategories.LCICommanderReprints);
}
async function fetchLCICommanderExtendedArt() {
return await fetchCardsFromCategory(LCICategories.LCICommanderExtendedArt);
}
async function fetchLCICommanderBoxToppers() {
return await fetchCardsFromCategory(LCICategories.LCICommanderBoxToppers);
}
async function fetchLCICommanderNewCardsGroup1() {
return await fetchCardsFromCategory(LCICategories.LCICommanderNewCardsGroup1);
}
async function fetchLCICommanderNewCardsGroup2() {
return await fetchCardsFromCategory(LCICategories.LCICommanderNewCardsGroup2);
}
async function fetchLCICommanderNewCardsGroup3Commanders() {
return await fetchCardsFromCategory(LCICategories.LCICommanderNewCardsGroup3Commanders);
}
async function fetchLCICommanderShowcase() {
return await fetchCardsFromCategory(LCICategories.LCICommanderShowcase);
}
async function fetchLCIGeneral() {
return await fetchCardsFromCategory(LCICategories.general);
}
async function fetchLCIFullArtLands() {
return await fetchCardsFromCategory(LCICategories.fullArtLands);
}
async function fetchLCIShowcase() {
return await fetchCardsFromCategory(LCICategories.showcase);
}
async function fetchLCIBorderless() {
return await fetchCardsFromCategory(LCICategories.borderless);
}
async function fetchLCIExtendedArt() {
return await fetchCardsFromCategory(LCICategories.extendedArt);
}
async function fetchLCIBasicLands() {
return await fetchCardsFromCategory(LCICategories.basicLands);
}
async function fetchLCINeonInk() {
return await fetchCardsFromCategory(LCICategories.neonInk);
}
//Commander Masters
async function fetchCMMGeneralCardPool() {
return await fetchCardsFromCategory(CMMCategories.generalCardPool);
}
async function fetchCMMBasicLandCardPool() {
return await fetchCardsFromCategory(CMMCategories.basicLandCardPool);
}
async function fetchCMMProfileCardPool() {
return await fetchCardsFromCategory(CMMCategories.profileCardPool);
}
async function fetchCMMCommanderCards() {
return await fetchCardsFromCategory(CMMCategories.commanderCards);
}
async function fetchCMMBorderlessCards() {
return await fetchCardsFromCategory(CMMCategories.borderlessCards);
}
async function fetchCMMExtendedArtCards() {
return await fetchCardsFromCategory(CMMCategories.extendedArtCards);
}
async function fetchCMMEtchedFoils() {
return await fetchCardsFromCategory(CMMCategories.etchedFoils);
}
async function fetchCMMTexturedFoils() {
return await fetchCardsFromCategory(CMMCategories.texturedFoils);
}
// Specific Fetch Functions for WHO
async function fetchWHOCommanders() {
return await fetchCardsFromCategory(WHOCategories.commanders);
}
async function fetchWHOGeneralCardSet() {
return await fetchCardsFromCategory(WHOCategories.generalCardSet);
}
async function fetchWHOTardisShowcase() {
return await fetchCardsFromCategory(WHOCategories.tardisShowcase);
}
async function fetchWHOBasicLands() {
return await fetchCardsFromCategory(WHOCategories.basicLands);
}
async function fetchWHOReprints() {
return await fetchCardsFromCategory(WHOCategories.reprints);
}
async function fetchWHOExtendedArtNew() {
return await fetchCardsFromCategory(WHOCategories.extendedArtNew);
}
async function fetchWHOExtendedArtOld() {
return await fetchCardsFromCategory(WHOCategories.extendedArtOld);
}
async function fetchWHOSurgeFoil() {
return await fetchCardsFromCategory(WHOCategories.surgeFoil);
}
async function fetchWHOSurgeTardis() {
return await fetchCardsFromCategory(WHOCategories.surgeTardis);
}
async function fetchWHOSurgeFoilBasicLands() {
return await fetchCardsFromCategory(WHOCategories.surgeFoilBasicLands);
}
async function fetchRandomDoctor() {
const doctorsCategory = WHOCategories.theDoctors;
if (doctorsCategory && doctorsCategory.specificCollectorNumbers && Array.isArray(doctorsCategory.specificCollectorNumbers)) {
const randomIndex = Math.floor(Math.random() * doctorsCategory.specificCollectorNumbers.length);
const collectorNumber = doctorsCategory.specificCollectorNumbers[randomIndex];
const card = await fetchSpecificCard(doctorsCategory.set, collectorNumber);
if (card) {
return [card];
}
}
console.error("The Doctors category is not properly defined or card not found.");
return []; // Return empty array if not found
}
async function fetchSurgeFoilByName(cardName) {
console.log("Trying to fetch surge foil for:", cardName);
const allSurgeFoils = await fetchWHOSurgeFoil();
const matchingCard = allSurgeFoils.find(card => card.name === cardName);
if (matchingCard) {
return [matchingCard];
} else {
console.error(`Could not find surge foil card with name: ${cardName}`);
return []; // Return empty array if not found
}
}
// Section for Specific Fetch Functions for DMR
async function fetchDMRGeneralCardPool() {
return await fetchCardsFromCategory(DMRCategories.generalCardPool);
}
async function fetchDMRBasicLandCardPool() {
return await fetchCardsFromCategory(DMRCategories.basicLandCardPool);
}
async function fetchDMROldFramePool() {
return await fetchCardsFromCategory(DMRCategories.oldFramePool);
}
async function fetchDMRAlternateArtBorderless() {
return await fetchCardsFromCategory(DMRCategories.alternateArtBorderless);
}
// Section for Baldur's Gate
async function fetchCLBRegularSetCards() {
return await fetchCardsFromCategory(CLBCategories.regularSetCards);
}
async function fetchCLBBorderless() {
return await fetchCardsFromCategory(CLBCategories.borderless);
}
async function fetchCLBShowcase() {
return await fetchCardsFromCategory(CLBCategories.showcase);
}
async function fetchCLBBasicLands() {
return await fetchCardsFromCategory(CLBCategories.basicLands);
}
async function fetchCLBFoilEtched() {
return await fetchCardsFromCategory(CLBCategories.foilEtched);
}
async function fetchCLBExtendedArt() {
return await fetchCardsFromCategory(CLBCategories.extendedArt);
}
async function fetchCLBCommanderExtendedArt() {
return await fetchCardsFromCategory(CLBCategories.commanderExtendedArt);
}
async function fetchCLBCommanderCards() {
return await fetchCardsFromCategory(CLBCategories.commanderCards);
}
// Section for ONE Fetch Functions
async function fetchONEGeneralCardPool() {
return await fetchCardsFromCategory(ONECategories.generalCardPool);
}
async function fetchONEPanoramaLands() {
return await fetchCardsFromCategory(ONECategories.panoramaLands);
}
async function fetchONEPhyrexianLands() {
return await fetchCardsFromCategory(ONECategories.phyrexianLands);
}
async function fetchONEShowcase() {
return await fetchCardsFromCategory(ONECategories.showcase);
}
async function fetchONEBorderlessPlaneswalkers() {
return await fetchCardsFromCategory(ONECategories.borderlessPlaneswalkers);
}
async function fetchONEAlternateArtBorderless() {
return await fetchCardsFromCategory(ONECategories.alternateArtBorderless);
}
async function fetchONEExtendedArtCards() {
return await fetchCardsFromCategory(ONECategories.extendedArtCards);
}
async function fetchONECompleatFoils() {
return await fetchCardsFromCategory(ONECategories.compleatFoils);
}
async function fetchONEEleshNorn() {
const eleshNornCard = await fetchCardsFromCategory(ONECategories.EleshNorn);
return eleshNornCard;
}
// One Commander Fetch Function ONC
async function fetchONCCommander() {
return await fetchCardsFromCategory(ONCCategories.commander);
}
async function fetchONCCommanderExtended() {
return await fetchCardsFromCategory(ONCCategories.commanderExtended);
}
// WOE Fetch Functions
async function fetchWOEGeneralCardPool() {
return await fetchCardsFromCategory(WOECategories.generalCardPool);
}
async function fetchWOEBasicLands() {
return await fetchCardsFromCategory(WOECategories.basicLands);
}
async function fetchWOEFullArtLands() {
return await fetchCardsFromCategory(WOECategories.fullArtLands);
}
async function fetchWOEAllBasicLands() {
return await fetchCardsFromCategory(WOECategories.allBasicLands);
}
async function fetchWOEAlternateArtBorderless() {
return await fetchCardsFromCategory(WOECategories.alternateArtBorderless);
}
async function fetchWOEShowcase() {
return await fetchCardsFromCategory(WOECategories.showcase);
}
async function fetchWOEExtendedArt() {
return await fetchCardsFromCategory(WOECategories.extendedArt);
}
// WOT Fetch Functions
async function fetchWOTGeneralCardPool() {
return await fetchCardsFromCategory(WOTCategories.generalCardPool);
}
async function fetchWOTAnime() {
return await fetchCardsFromCategory(WOTCategories.anime);
}
// Section: Fetch Functions for BRO
async function fetchBROGeneralCardPool() {
return await fetchCardsFromCategory(BROCategories.generalCardPool);
}
async function fetchBROBasicLands() {
return await fetchCardsFromCategory(BROCategories.basicLands);
}
async function fetchBROFullArtLands() {
return await fetchCardsFromCategory(BROCategories.fullArtLands);
}
async function fetchBROAlternateArtBorderless() {
return await fetchCardsFromCategory(BROCategories.alternateArtBorderless);
}
async function fetchBROExtendedArt() {
return await fetchCardsFromCategory(BROCategories.extendedArt);
}
// Section: Fetch Functions for BRR
async function fetchBRRRetroFrameArtifacts() {
return await fetchCardsFromCategory(BRRCategories.retroFrameArtifacts);
}
async function fetchBRRRetroSchematicArtifacts() {
return await fetchCardsFromCategory(BRRCategories.retroSchematicArtifacts);
}
// Fetch functions for BOT
async function fetchBOTGeneralTransformers() {
return await fetchCardsFromCategory(BOTCategories.generalTransformers);
}
async function fetchBOTShatteredGlassTransformers() {
return await fetchCardsFromCategory(BOTCategories.shatteredGlassTransformers);
}
// Fetch functions for BRC
async function fetchBRCGeneralCards() {
return await fetchCardsFromCategory(BRCCategories.generalcards);
}
async function fetchBRCExtendedArts() {
return await fetchCardsFromCategory(BRCCategories.brcextendedart);
}
// Pack Overview Section
(function() {
// Function to fetch card data from Scryfall API based on set code and booster type
async function fetchCardData(setCode, boosterType) {
try {
let allData = [];
let page = 1;
while (true) {
const apiUrl = `https://api.scryfall.com/cards/search?q=set:${setCode}+is:${boosterType}&page=${page}`;
const response = await fetch(apiUrl);
const { data, has_more } = await response.json();
allData = allData.concat(data);
if (!has_more) {
break;
}
page++;
}
return allData;
} catch (error) {
console.error(`Error fetching card data for set ${setCode} and booster type ${boosterType}:`, error);
return null;
}
}
// Function to create a card element for display
function createCardElement(cardData) {
const cardContainer = document.createElement('div');
cardContainer.className = 'card'; // Use the same class as Top 10 cards
// Create an image element for the card
const cardImage = document.createElement('img');
// Check if the card is double-faced and has card_faces[0]
if (cardData.card_faces && cardData.card_faces[0] && cardData.card_faces[0].image_uris) {
cardImage.src = cardData.card_faces[0].image_uris.normal; // Use the normal image URI of card_faces[0]
cardImage.alt = cardData.card_faces[0].name;
} else if (cardData.image_uris) {
cardImage.src = cardData.image_uris.normal;
cardImage.alt = cardData.name;
} else {
// Use a default image URI for single-faced cards
cardImage.src = 'https://cards.scryfall.io/normal/front/5/0/50f8e2b6-98c7-4f28-bb39-e1fbe841f1ee.jpg?1699044315';
cardImage.alt = cardData.name;
}
// Add card name with styling
const cardName = document.createElement('div');
cardName.classList.add('card-name'); // Apply card name styling
cardName.textContent = cardData.name;
// Add pricing information with styling
const cardPrice = document.createElement('div');
cardPrice.classList.add('card-price'); // Apply pricing info styling
cardPrice.textContent = `USD: $${cardData.prices?.usd || 'N/A'}`;
// Add foil pricing information with styling
let foilPriceLabel = 'USD Foil';
let foilPriceValue = cardData.prices?.usd_foil || 'N/A';
// Check for etched price and modify label and value accordingly
if (cardData.prices?.usd_etched) {
foilPriceLabel = 'USD Etched';
foilPriceValue = cardData.prices.usd_etched;
}
const cardFoilPrice = document.createElement('div');
cardFoilPrice.classList.add('card-price'); // Apply pricing info styling
cardFoilPrice.textContent = `${foilPriceLabel}: $${foilPriceValue}`;
// Append card elements to the card container
cardContainer.appendChild(cardImage);
cardContainer.appendChild(cardName);
cardContainer.appendChild(cardPrice);
cardContainer.appendChild(cardFoilPrice);
// Create and append the affiliate link
const encodedCardName = encodeURIComponent(cardData.name.replace(/ /g, "+"));
const affiliateLink = `https://tcgplayer.pxf.io/c/5066134/1780961/21018?u=https%3A%2F%2Fwww.tcgplayer.com%2Fsearch%2Fall%2Fproduct%3Fq%3D${encodedCardName}`;
let buyLink = document.createElement('a');
buyLink.href = affiliateLink;
buyLink.target = '_blank';
buyLink.className = 'tcgplayer-affiliate-link';
buyLink.textContent = `Buy ${cardData.name} on TCG Player`;
cardContainer.appendChild(buyLink);
return cardContainer;
}
function showPopupCard(imageUrl, isRoom = false) {
console.log("Popup triggered for card.");
console.log("Image URL:", imageUrl);
console.log("Is this card a Room?", isRoom);
// Remove existing pop-up card or overlay
const existingPopupCard = document.querySelector('.card-popup');
const existingOverlay = document.querySelector('.overlay');
if (existingPopupCard) existingPopupCard.remove();
if (existingOverlay) existingOverlay.remove();
// Create overlay and pop-up container
const overlay = document.createElement('div');
overlay.classList.add('overlay');
const popupCard = document.createElement('div');
popupCard.classList.add('card-popup');
// Create the card image
const cardImage = document.createElement('img');
cardImage.src = imageUrl;
cardImage.alt = 'Card Image';
cardImage.style.maxWidth = '90%';
cardImage.style.maxHeight = '90%';
if (isRoom) {
console.log("Rotating Room card in popup.");
cardImage.style.transform = 'rotate(90deg)';
}
// Close pop-up on click
overlay.addEventListener('click', () => {
overlay.remove();
popupCard.remove();
});
cardImage.addEventListener('click', () => {
overlay.remove();
popupCard.remove();
});
popupCard.appendChild(cardImage);
document.body.appendChild(overlay);
document.body.appendChild(popupCard);
}
// Function to organize cards by rarity
function organizeCardsByRarity(cards) {
const organizedCards = {
'Mythic': [],
'Rare': [],
'Uncommon': [],
'Common': []
};
cards.forEach(card => {
if (card.rarity === 'mythic') {
organizedCards['Mythic'].push(card);
} else if (card.rarity === 'rare') {
organizedCards['Rare'].push(card);
} else if (card.rarity === 'uncommon') {
organizedCards['Uncommon'].push(card);
} else if (card.rarity === 'common') {
organizedCards['Common'].push(card);
}
});
return organizedCards;
}
function onSetSelectionChange() {
const setSelectionElement = document.getElementById('setSelection');
const selectedOptionElement = setSelectionElement.options[setSelectionElement.selectedIndex];
// Accessing the set code directly
const setCode = setSelectionElement.value;
// Accessing the set name from the selected option's text content
const setName = selectedOptionElement.text;
console.log("Selected Set Code:", setCode); // For example, "PIP"
console.log("Selected Set Name:", setName); // For example, "Fallout"
// Now you can use setCode and setName in your application
// For example, fetch data related to the selected set or update the UI accordingly
}
async function fetchSetInformation(setCode) {
try {
const response = await fetch(`https://api.scryfall.com/sets/${setCode.toLowerCase()}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const setData = await response.json();
return setData; // Ensure this is the expected data structure
} catch (error) {
console.error(`Error fetching set information: ${error}`);
throw error; // Rethrow to be caught by the caller
}
}
function displaySetDetails(setData) {
let setDetailsContent = document.getElementById('setDetailsContent');
// Dynamically create the container if it does not exist
if (!setDetailsContent) {
const additionalInfoSection = document.getElementById('additionalInfoSection') || document.body;
setDetailsContent = document.createElement('div');
setDetailsContent.id = 'setDetailsContent';
additionalInfoSection.appendChild(setDetailsContent);
}
// Clear existing content and add a title
setDetailsContent.innerHTML = '<h2>Set Details</h2>';
// Set Name
const setName = document.createElement('p');
setName.textContent = `Set Name: ${setData.name}`;
setDetailsContent.appendChild(setName);
// Set Code
const setCode = document.createElement('p');
setCode.textContent = `Set Code: ${setData.code}`;
setDetailsContent.appendChild(setCode);
// Set Block (or type if block is not available)
const setBlock = document.createElement('p');
setBlock.textContent = `Set Block/Type: ${setData.block ? setData.block : setData.set_type}`;
setDetailsContent.appendChild(setBlock);
// Date Released
const releaseDate = document.createElement('p');
releaseDate.textContent = `Date Released: ${setData.released_at}`;
setDetailsContent.appendChild(releaseDate);
// Number of cards in set
const cardCount = document.createElement('p');
cardCount.textContent = `Number of Cards: ${setData.card_count}`;
setDetailsContent.appendChild(cardCount);
}
async function fetchAndCategorizeCardsBySet(setCode) {
let page = 1;
let hasMore = true;
const cardTypes = {
Creature: 0,
Land: 0,
Instant: 0,
Sorcery: 0,
Artifact: 0,
Enchantment: 0,
Planeswalker: 0,
Battle: 0,
};
const totalCards = { count: 0 };
console.log(`Starting to fetch cards for set: ${setCode}`);
while (hasMore) {
console.log(`Fetching page ${page}`);
const response = await fetch(`https://api.scryfall.com/cards/search?order=set&q=e%3A${setCode}&unique=prints&page=${page}`);
if (!response.ok) {
throw new Error(`Failed to fetch page ${page} for set ${setCode}`);
}
const data = await response.json();
console.log(`Fetched ${data.data.length} cards on page ${page}`);
categorizeCards(data.data, cardTypes, totalCards);
console.log('Current card type counts:', cardTypes);
hasMore = data.has_more;
page++;
}
return calculatePercentages(cardTypes, totalCards.count);
}
function categorizeCards(cards, cardTypes, totalCards) {
cards.forEach(card => {
totalCards.count++;
if (card.type_line) {
Object.keys(cardTypes).forEach(type => {
if (card.type_line.includes(type)) {
cardTypes[type]++;
}
});
}
});
}
function calculatePercentages(cardTypes, totalCount) {
const percentages = {};
Object.keys(cardTypes).forEach(type => {
percentages[type] = ((cardTypes[type] / totalCount) * 100).toFixed(2) + '%';
});
return percentages;
}
function displayCardTypeBreakdown(percentages) {
let cardTypeBreakdownContainer = document.getElementById('cardTypeBreakdownContent');
// If the container doesn't exist, create it dynamically
if (!cardTypeBreakdownContainer) {
const additionalInfoSection = document.getElementById('additionalInfoSection');
// Ensure the parent container exists
if (!additionalInfoSection) {
console.error('Additional Info Section does not exist.');
return;
}
cardTypeBreakdownContainer = document.createElement('div');
cardTypeBreakdownContainer.id = 'cardTypeBreakdownContent';
additionalInfoSection.appendChild(cardTypeBreakdownContainer);
}
// Clear existing content and add a title
cardTypeBreakdownContainer.innerHTML = '<h2>Card Type Breakdown</h2>';
Object.entries(percentages).forEach(([type, percentage]) => {
const lineItem = document.createElement('p');
lineItem.textContent = `${type}: ${percentage}`;
cardTypeBreakdownContainer.appendChild(lineItem);
});
}
async function displayAllCards() {
const setSelection = document.getElementById('setSelection');
const cardDisplay = document.getElementById('packOverview');
const additionalInfoSection = document.getElementById('additionalInfoSection');
if (!setSelection || !cardDisplay || !additionalInfoSection) {
console.error("Required elements not found.");
return; // Exit if essential elements are not found
}
// Display a processing message
additionalInfoSection.innerHTML = '<p>Processing detailed set information...</p>';
additionalInfoSection.style.display = 'flex'; // Adjust to flex for the processing message
additionalInfoSection.style.justifyContent = 'center'; // Center horizontally
additionalInfoSection.style.height = '100%'; // Ensure the container is full height
// Clear previous content in cardDisplay but do not hide it yet to avoid flickering
cardDisplay.innerHTML = '';
const setCode = setSelection.value;
try {
// Prepare promises for fetching information
const fetchSetInfoPromise = fetchSetInformation(setCode);
const fetchCardDataPromise = fetchCardData(setCode);
const fetchCardTypeBreakdownPromise = fetchAndCategorizeCardsBySet(setCode);
// Wait for all promises to resolve
const [setData, cardData, cardTypePercentages] = await Promise.all([
fetchSetInfoPromise,
fetchCardDataPromise,
fetchCardTypeBreakdownPromise,
]);
// Once data is fetched, clear the processing message
additionalInfoSection.innerHTML = '';
// Now, display the fetched and processed data
displaySetDetails(setData); // Display set details
displayCardTypeBreakdown(cardTypePercentages); // Display card type breakdown
displayTop10MostExpensiveCards(cardData, cardDisplay); // Display top 10 most expensive cards
// Organize and display cards by rarity
const organizedCards = organizeCardsByRarity(cardData);
Object.entries(organizedCards).forEach(([rarity, cards]) => {
const section = createRaritySection(rarity, cards);
cardDisplay.appendChild(section);
// Add event listeners to cards for pop-up display with rotation for Room cards
cards.forEach(card => {
const imageUrl = card.image_uris ? card.image_uris.normal : null;
const isRoom = isRoomCard(card); // Use utility function
console.log(`Card Name: ${card.name}`);
console.log(`Type Line: ${card.type_line}`);
console.log(`Is Room Identified?`, isRoom);
if (imageUrl) {
const cardImage = document.createElement('img');
cardImage.src = imageUrl;
cardImage.alt = card.name || 'Unknown Card';
cardImage.style.maxWidth = '100%'; // Adjust size as needed
cardImage.className = 'card-image';
// Add event listener for pop-up with room handling
cardImage.addEventListener('click', () => showPopupCard(imageUrl, isRoom));
section.appendChild(cardImage);
}
});
});
displayPurchaseOptions(setCode); // Display Next Step Links
// Now, reveal all sections simultaneously
cardDisplay.style.display = 'flex';
additionalInfoSection.style.display = 'flex';
} catch (error) {
console.error("Error loading data:", error);
// Display error message to the user
additionalInfoSection.innerHTML = `<p>Error loading data. Please try again later.</p>`;
additionalInfoSection.style.display = 'flex';
}
}
function isRoomCard(card) {
if (!card) return false;
// Check type_line
if (card.type_line && card.type_line.toLowerCase().includes('room')) {
return true;
}
// Check card_faces for split or modal cards
if (card.card_faces) {
return card.card_faces.some(face =>
face.type_line && face.type_line.toLowerCase().includes('room')
);
}
return false;
}
function displayPurchaseOptions() {
const setSelectionElement = document.getElementById('setSelection');
const selectedOptionElement = setSelectionElement.options[setSelectionElement.selectedIndex];
// Directly access the set code and set name
const setCode = setSelectionElement.value;
const setName = selectedOptionElement.text;
let linkContainer = document.getElementById('tcgLinkContainer');
// If the link container doesn't exist, create it
if (!linkContainer) {
linkContainer = document.createElement('div');
linkContainer.id = 'tcgLinkContainer';
linkContainer.style.textAlign = 'center';
const selectionContainer = document.querySelector('.button-and-selection-container');
selectionContainer.parentNode.insertBefore(linkContainer, selectionContainer.nextSibling);
}
// Clear the previous content
linkContainer.innerHTML = '';
// Create and append the Amazon link with affiliate parameters and image
const amazonAffiliateLink = `https://www.amazon.com/s?k=${encodeURIComponent(`${setName} Magic the Gathering`)}&linkCode=ll2&tag=mtgpacks1337-20&linkId=6d347a7186f750a21dd775ddd7440b4d&language=en_US&ref_=as_li_ss_tl`;
addLinkButtonWithImage(linkContainer, amazonAffiliateLink, `Buy ${setName} on Amazon`, "https://mtg-packs.com/wp-content/uploads/2024/07/available_at_amazon_US_EN_logo_stacked_RGB_WHITE.png", 'amazon-button');
// Create and append the TCGPlayer link with affiliate parameters and image
const tcgPlayerBaseLink = "https://tcgplayer.pxf.io/c/5066134/1780961/21018?u=";
const searchQuery = encodeURIComponent(`${setName} Magic the Gathering`);
const tcgPlayerFullLink = `${tcgPlayerBaseLink}https%3A%2F%2Fwww.tcgplayer.com%2Fsearch%2Fall%2Fproduct%3Fq%3D${searchQuery}`;
addLinkButtonWithImage(linkContainer, tcgPlayerFullLink, `Buy ${setName} on TCG Player`, "https://mtg-packs.com/wp-content/uploads/2024/08/TCGplayer-Primary-RGB_300px.png", 'tcgplayer-button');
// Add the MTG Pack Simulator link
const simulatorLink = document.createElement('a');
simulatorLink.href = `https://mtg-packs.com?set=${encodeURIComponent(setName)}`;
simulatorLink.target = '_blank';
simulatorLink.className = 'simulator-button';
const simulatorTextNode = document.createTextNode(`Simulate ${setName} on MTG Pack Simulator`);
simulatorLink.appendChild(simulatorTextNode);
linkContainer.appendChild(simulatorLink);
}
// Generic function to add a link button with an image
function addLinkButtonWithImage(container, url, text, imageUrl, buttonClass) {
const button = document.createElement('a');
button.href = url;
button.target = '_blank';
button.className = buttonClass;
const textNode = document.createTextNode(text);
button.appendChild(textNode);
const img = document.createElement('img');
img.src = imageUrl;
img.alt = text;
button.appendChild(img);
container.appendChild(button);
}
function displayTop10MostExpensiveCards(cardData, cardDisplay) {
// Ensure cardData is correctly populated before proceeding
if (!cardData || cardData.length === 0) {
console.error('No card data available for displaying top 10 most expensive cards.');
return;
}
const top10Cards = cardData
.filter(card => card.prices && card.prices.usd)
.sort((a, b) => parseFloat(b.prices.usd) - parseFloat(a.prices.usd))
.slice(0, 10);
// Create a new container for the top 10 section
let top10Container = document.createElement('div');
top10Container.className = 'top10-container';
// Create and append the title
let title = document.createElement('h2');
title.textContent = 'Top 10 Most Expensive Cards';
title.className = 'top10-title'; // Assign a class for potential styling
top10Container.appendChild(title);
// Create the grid container specifically for the cards
let gridContainer = document.createElement('div');
gridContainer.className = 'card-grid';
top10Cards.forEach(card => {
const cardElement = createCardElement(card);
gridContainer.appendChild(cardElement);
});
// Append the grid container to the top10Container
top10Container.appendChild(gridContainer);
// Append or prepend the top10Container to the cardDisplay as needed
cardDisplay.prepend(top10Container);
}
// Function to create a rarity section with centered title and card grid
function createRaritySection(rarity, cards) {
const section = document.createElement('div');
section.className = 'rarity-section';
// Create a centered title for the rarity category
const title = document.createElement('h2');
title.textContent = rarity;
title.className = 'centered-title'; // Apply centered title styling
section.appendChild(title);
// Create a card grid container for the rarity
const cardGridContainer = document.createElement('div');
cardGridContainer.className = 'card-grid';
// Sort the cards alphabetically within the rarity
cards.sort((a, b) => a.name.localeCompare(b.name));
// Create card elements for each card in the rarity
cards.forEach((card) => {
const cardElement = createCardElement(card); // Use createCardElement function
cardGridContainer.appendChild(cardElement);
});
section.appendChild(cardGridContainer);
return section;
}
// Function to display cards grouped by rarity with centered titles and a card grid (updated to handle double-sided cards)
function displayCardsByRarityWithGrid(cardDisplay, organizedCards) {
for (const rarity in organizedCards) {
if (organizedCards.hasOwnProperty(rarity)) {
const cardsInRarity = organizedCards[rarity];
if (cardsInRarity.length > 0) {
// Create a container for each rarity category
const rarityContainer = document.createElement('div');
rarityContainer.className = 'rarity-container';
// Create a centered title for the rarity category
const rarityHeader = document.createElement('h2');
rarityHeader.textContent = rarity;
rarityHeader.className = 'centered-title'; // Apply centered title styling
rarityContainer.appendChild(rarityHeader);
// Create a card grid container for the rarity
const cardGridContainer = document.createElement('div');
cardGridContainer.className = 'card-grid';
// Sort the cards alphabetically within the rarity
cardsInRarity.sort((a, b) => a.name.localeCompare(b.name));
// Create card elements for each card in the rarity
cardsInRarity.forEach((card) => {
const cardContainer = createCardElement(card); // Use createCardElement function
// Determine if the card is a "Room"
const isRoom = card.type_line.toLowerCase().includes('room');
cardContainer.dataset.isRoom = isRoom ? 'true' : 'false'; // Store this information in the element
const imageUrl = card.image_uris ? card.image_uris.normal : null;
if (imageUrl) {
// Add event listener for pop-up with room handling
const cardImage = cardContainer.querySelector('img');
if (cardImage) {
cardImage.addEventListener('click', () => showPopupCard(imageUrl, isRoom));
}
}
// Append the card container to the grid
cardGridContainer.appendChild(cardContainer);
});
// Add the card grid container to the rarity container
rarityContainer.appendChild(cardGridContainer);
// Add the rarity container to the card display
cardDisplay.appendChild(rarityContainer);
}
}
}
}
// Event listener for the "Generate Set Overview" button click
const generateSetOverviewBtn = document.getElementById('generateSetOverviewBtn');
if (generateSetOverviewBtn) {
generateSetOverviewBtn.addEventListener('click', displayAllCards);
}
// Event listener for card clicks in the pack overview section
const packOverview = document.getElementById('packOverview');
if (packOverview) {
packOverview.addEventListener('click', handleCardClick);
}
// Function to handle card clicks
function handleCardClick(event) {
// Check if the clicked element is an image element
if (event.target.tagName === 'IMG') {
const cardElement = event.target.closest('.card-container');
// Check if the card element has the "isRoom" data attribute
const isRoom = cardElement && cardElement.dataset.isRoom === 'true';
// Get the image URL from the clicked image element
const imageUrl = event.target.src;
// Call the showPopupCard function with the image URL and isRoom flag
showPopupCard(imageUrl, isRoom);
}
}
})();
// Section for the Set and Booster Type Selectors
document.addEventListener('DOMContentLoaded', () => {
// Initialize the labels on page load
initializeLabels();
// Add event listeners for set and booster type selectors
const setSelection = document.getElementById('setSelection');
const boosterTypeSelection = document.getElementById('boosterTypeSelection');
if (setSelection) {
setSelection.addEventListener('change', () => {
updateSetLabel();
updateLayout(window.selectedLayout); // Reapply layout after changing set
});
}
if (boosterTypeSelection) {
boosterTypeSelection.addEventListener('change', () => {
updatePackTypeLabel();
updateLayout(window.selectedLayout); // Reapply layout after changing pack type
});
}
});
// Function to initialize labels on page load
function initializeLabels() {
updateSetLabel();
updatePackTypeLabel();
}
// Function to update the set label
function updateSetLabel() {
const setSelection = document.getElementById('setSelection');
const selectedSet = setSelection.options[setSelection.selectedIndex].text;
document.getElementById('currentSetLabel').textContent = `Current Set: ${selectedSet}`;
}
// Function to update the pack type label
function updatePackTypeLabel() {
const boosterTypeSelection = document.getElementById('boosterTypeSelection');
const selectedPackType = boosterTypeSelection.options[boosterTypeSelection.selectedIndex].text;
document.getElementById('currentPackTypeLabel').textContent = `Current Pack Type: ${selectedPackType}`;
}
// Section 6 Additional Functions - Card Size Selectors, Generate Packs, and Set/Booster Selector
document.addEventListener('DOMContentLoaded', function () {
const calculator = document.getElementById('packFinanceCalculator');
const toggleButton = document.getElementById('calculatorToggle');
if (calculator && toggleButton) {
toggleButton.addEventListener('click', function () {
if (calculator.classList.contains('minimized')) {
calculator.classList.remove('minimized');
calculator.style.display = 'block';
toggleButton.innerText = 'Close Calculator'; // Change button to close text
} else {
calculator.classList.add('minimized');
calculator.style.display = 'none';
toggleButton.innerText = 'Finance Calculator'; // Change button to open text
}
});
// Ensure the calculator is hidden on mobile devices
function checkMobile() {
if (window.innerWidth <= 768) {
calculator.style.display = 'none';
toggleButton.style.display = 'none';
} else if (!calculator.classList.contains('minimized')) {
calculator.style.display = 'block';
toggleButton.style.display = 'block';
}
}
window.addEventListener('resize', checkMobile);
checkMobile(); // Initial check on page load
} else {
console.log("Finance calculator or toggle button is not available for this user or view.");
}
});
function updatePackFinanceCalculator(packs = []) {
// Check if the finance calculator elements exist
const foilValueElement = document.querySelector('.grid-item:nth-child(1) .value');
const nonFoilValueElement = document.querySelector('.grid-item:nth-child(2) .value');
const expectedValueElement = document.querySelector('.grid-item:nth-child(3) .value');
const averageExpectedValueElement = document.querySelector('.grid-item:nth-child(4) .value');
const greatestExpectedValueElement = document.querySelector('.grid-item:nth-child(5) .value');
const leastExpectedValueElement = document.querySelector('.grid-item:nth-child(6) .value');
const totalExpectedValueElement = document.getElementById('totalExpectedValueDisplay');
const packsOpenedDisplayElement = document.getElementById('packsOpenedDisplay');
// If any of the elements are missing, exit the function
if (!foilValueElement || !nonFoilValueElement || !expectedValueElement || !averageExpectedValueElement || !greatestExpectedValueElement || !leastExpectedValueElement || !totalExpectedValueElement || !packsOpenedDisplayElement) {
console.log("Finance calculator elements are not available for non-members.");
return;
}
// Initialize cumulative values for multiple packs
let foilValueTotal = 0;
let nonFoilValueTotal = 0;
let expectedValueTotal = 0;
let expectedValues = [];
// Loop through each pack and accumulate values
packs.forEach(pack => {
const foilValue = parseFloat(pack.foilTotalValue) || 0;
const nonFoilValue = parseFloat(pack.nonFoilTotalValue) || 0;
const expectedValue = (foilValue + nonFoilValue) / 2;
foilValueTotal += foilValue;
nonFoilValueTotal += nonFoilValue;
expectedValueTotal += expectedValue;
// Store the expected value for this pack to determine min/max later
expectedValues.push(expectedValue);
});
// Fetch existing values from sessionStorage
let totalPacks = parseInt(sessionStorage.getItem('totalPacks')) || 0;
let totalExpectedValue = parseFloat(sessionStorage.getItem('totalExpectedValue')) || 0;
let greatestExpectedValue = parseFloat(sessionStorage.getItem('greatestExpectedValue')) || 0;
let leastExpectedValue = parseFloat(sessionStorage.getItem('leastExpectedValue')) || Infinity;
// Update totals based on the number of packs
totalPacks += packs.length;
totalExpectedValue += expectedValueTotal;
// Calculate the greatest and least expected values based on the individual pack values
const currentGreatestExpectedValue = Math.max(...expectedValues);
const currentLeastExpectedValue = Math.min(...expectedValues);
// Update the stored greatest and least expected values if necessary
greatestExpectedValue = Math.max(greatestExpectedValue, currentGreatestExpectedValue);
leastExpectedValue = Math.min(leastExpectedValue, currentLeastExpectedValue);
// Store updated values back in sessionStorage
sessionStorage.setItem('totalPacks', totalPacks);
sessionStorage.setItem('totalExpectedValue', totalExpectedValue.toFixed(2));
sessionStorage.setItem('greatestExpectedValue', greatestExpectedValue.toFixed(2));
sessionStorage.setItem('leastExpectedValue', leastExpectedValue.toFixed(2));
// Calculate the average expected value
let averageExpectedValue = totalExpectedValue / totalPacks;
// Calculate the Total Expected Value
let totalExpectedValueCalculated = averageExpectedValue * totalPacks;
// Update the left-side calculator values based on the number of packs
if (packs.length === 1) {
// Single pack: show specific values
const pack = packs[0];
foilValueElement.innerText = `$${parseFloat(pack.foilTotalValue).toFixed(2)}`;
nonFoilValueElement.innerText = `$${parseFloat(pack.nonFoilTotalValue).toFixed(2)}`;
expectedValueElement.innerText = `$${((parseFloat(pack.foilTotalValue) + parseFloat(pack.nonFoilTotalValue)) / 2).toFixed(2)}`;
} else {
// Multiple packs: show "N/A"
foilValueElement.innerText = 'N/A';
nonFoilValueElement.innerText = 'N/A';
expectedValueElement.innerText = 'N/A';
}
// Update the right-side calculator values with the aggregated data
averageExpectedValueElement.innerText = `$${averageExpectedValue.toFixed(2)}`;
greatestExpectedValueElement.innerText = `$${greatestExpectedValue.toFixed(2)}`;
leastExpectedValueElement.innerText = `$${leastExpectedValue.toFixed(2)}`;
totalExpectedValueElement.innerText = `$${totalExpectedValueCalculated.toFixed(2)}`;
// Update the packs opened display
packsOpenedDisplayElement.innerText = `${totalPacks}`;
}
function resetPackFinanceCalculator() {
// Reset session storage values
sessionStorage.setItem('totalPacks', 0);
sessionStorage.setItem('totalExpectedValue', 0);
sessionStorage.setItem('greatestExpectedValue', 0);
sessionStorage.setItem('leastExpectedValue', Infinity);
// Check if finance calculator elements exist before trying to reset them
const gridItems = document.querySelectorAll('.grid-item .value');
const packsOpenedDisplay = document.getElementById('packsOpenedDisplay');
const totalExpectedValueDisplay = document.getElementById('totalExpectedValueDisplay');
if (gridItems.length >= 6) {
// Reset the on-screen calculator display for the 6 grid items
gridItems[0].innerText = "$0.00"; // Foil Value
gridItems[1].innerText = "$0.00"; // Non-Foil Value
gridItems[2].innerText = "$0.00"; // Expected Value
gridItems[3].innerText = "$0.00"; // Average Expected Value
gridItems[4].innerText = "$0.00"; // Greatest Expected Value
gridItems[5].innerText = "$0.00"; // Least Expected Value
} else {
console.warn('Finance calculator grid items are not available.');
}
// Reset the packs opened display
if (packsOpenedDisplay) {
packsOpenedDisplay.innerText = "0";
} else {
console.warn('packsOpenedDisplay element is not available.');
}
// Reset the Total Expected Value display
if (totalExpectedValueDisplay) {
totalExpectedValueDisplay.innerText = "$0.00";
} else {
console.warn('totalExpectedValueDisplay element is not available.');
}
}
function updatePackTitle(setCode, boosterType) {
const setSelectionElement = document.getElementById('setSelection');
const selectedSetName = setSelectionElement.options[setSelectionElement.selectedIndex].text;
const capitalizedBoosterType = boosterType.charAt(0).toUpperCase() + boosterType.slice(1);
const title = `${selectedSetName} ${capitalizedBoosterType} Booster`;
// Check if the packTitleDisplay element exists before trying to update it
const packTitleDisplayElement = document.getElementById('packTitleDisplay');
if (packTitleDisplayElement) {
packTitleDisplayElement.innerText = title;
} else {
console.warn('packTitleDisplay element is not available.');
}
}
// Define the group ID mapping based on the setCode at a global scope
const groupIdMapping = {
'BLB': '23447', // Bloomburrow
'ACR': '23446', // Universes Beyond: Assassin's Creed
'MH3': '23444', // Modern Horizons 3
'OTJ': '23439', // Outlaws of Thunder Junction
'PIP': '23337', // Universes Beyond: Fallout
'MKM': '23361', // Murders at Karlov Manor
'RVR': '23319', // Ravnica Remastered
'LCI': '23312', // The Lost Caverns of Ixalan
'WHO': '23165', // Universes Beyond: Doctor Who
'CMM': '23020', // Commander Masters
'MOM': '22875', // March of the Machine
'ONE': '17684', // Phyrexia: All Will Be One
'WOE': '23163', // Wilds of Eldraine
'DMR': '17670', // Dominaria Remastered
'BRO': '3157', // The Brothers' War
'2X2': '2655', // Double Masters 2022
'CLB': '3047', // Commander Legends: Battle for Baldur's Gate
'NEO': '2965', // Kamigawa: Neon Dynasty
'DSK': '23550', // Duskmourn: House of Horror
'DMU': '3102', // Dominaria United
'FDN': '23556', // Foundations
// Add other mappings as necessary
};
async function fetchProductData(setCode, boosterType) {
const groupId = groupIdMapping[setCode];
if (!groupId) {
console.error('Group ID not found for the selected set.');
return null;
}
console.log(`Fetching product data for group ID: ${groupId} and booster type: ${boosterType}`);
const productUrl = `https://tcgcsv.com/1/${groupId}/products`;
try {
const response = await fetch(productUrl);
if (response.ok) {
const productsData = await response.json();
console.log('Fetched products response:', productsData);
const products = productsData.results;
if (Array.isArray(products)) {
// Improved booster type mapping for name matching
const boosterTypeMapping = {
'draft': ['draft booster', 'draft booster pack'],
'play': ['play booster', 'play booster pack'],
'collector': ['collector booster', 'collector booster pack'],
'booster': ['booster pack', 'booster'],
// Add additional mappings for other booster types as needed
};
const expectedNames = boosterTypeMapping[boosterType.toLowerCase()] || [boosterType];
// Try to find a product where the cleanName contains any of the expected names
const product = products.find(p => expectedNames.some(name => p.cleanName.toLowerCase().includes(name)));
if (product) {
console.log(`Found product ID: ${product.productId} for booster type: ${boosterType}`);
return product;
} else {
console.warn(`No product found for booster type: ${boosterType}`);
}
} else {
console.error('Products data is not an array as expected:', products);
}
} else {
console.error('Failed to fetch product data.');
}
} catch (error) {
console.error('Error fetching product data:', error);
}
return null;
}
async function fetchPricingData(groupId, productId) {
const priceUrl = `https://tcgcsv.com/1/${groupId}/prices`;
console.log(`Fetching pricing data for group ID: ${groupId} and product ID: ${productId}`);
try {
const response = await fetch(priceUrl);
if (response.ok) {
const pricingData = await response.json();
console.log('Fetched pricing data:', pricingData);
const productPricing = pricingData.results.find(p => p.productId === productId);
if (productPricing) {
console.log(`Market price for product ID ${productId}: $${productPricing.marketPrice}`);
return productPricing.marketPrice;
} else {
console.warn(`No pricing data found for product ID: ${productId}`);
}
} else {
console.error('Failed to fetch pricing data.');
}
} catch (error) {
console.error('Error fetching pricing data:', error);
}
return null;
}
async function updatePackFinanceCalculatorWithMarketPrice(setCode, boosterType) {
console.log(`Updating Pack Finance Calculator for set: ${setCode}, booster type: ${boosterType}`);
// Check if the finance calculator elements exist before attempting to update
const marketPriceElement = document.getElementById('marketPriceValue');
const buyBoosterLinkElement = document.getElementById('buyBoosterLink');
if (!marketPriceElement || !buyBoosterLinkElement) {
console.warn('Finance calculator elements are not available.');
return; // Exit the function if the elements don't exist
}
try {
const product = await fetchProductData(setCode, boosterType);
if (product) {
const groupId = groupIdMapping[setCode];
const marketPrice = await fetchPricingData(groupId, product.productId);
if (marketPrice !== null && !isNaN(marketPrice)) {
// Update the market price in the UI with a dollar symbol
marketPriceElement.innerText = `$${marketPrice.toFixed(2)}`;
// Update the Buy Booster link specifically in the finance calculator
const productLink = `https://www.tcgplayer.com/product/${product.productId}/Magic-${encodeURIComponent(product.cleanName.replace(/s+/g, '-'))}`;
const affiliateLink = `https://tcgplayer.pxf.io/75VM1y?u=${encodeURIComponent(productLink)}`;
buyBoosterLinkElement.href = affiliateLink;
buyBoosterLinkElement.style.display = 'inline'; // Ensure the link is visible
console.log(`Updated market price: $${marketPrice.toFixed(2)}`);
console.log(`Buy Booster Link: ${affiliateLink}`);
} else {
marketPriceElement.innerText = 'N/A';
buyBoosterLinkElement.href = '#';
console.warn('Market price is not available.');
}
} else {
console.error('Product not found for the given set and booster type.');
marketPriceElement.innerText = 'N/A';
buyBoosterLinkElement.href = '#';
}
} catch (error) {
console.error('Error updating market price:', error);
marketPriceElement.innerText = 'N/A';
buyBoosterLinkElement.href = '#';
}
}
// Trigger update when the pack is generated, but only if the finance calculator is visible
document.getElementById('generatePackBtn').addEventListener('click', function () {
const setCode = document.getElementById('setSelection').value;
const boosterType = document.getElementById('boosterTypeSelection').value;
const selectedLayout = window.selectedLayout || 'packView';
// Check if the finance calculator elements exist before updating
const marketPriceElement = document.getElementById('marketPriceValue');
const buyBoosterLinkElement = document.getElementById('buyBoosterLink');
// Update only if elements exist and the layout is 'packView'
if (marketPriceElement && buyBoosterLinkElement) {
if (selectedLayout === 'packView') {
updatePackFinanceCalculatorWithMarketPrice(setCode, boosterType);
buyBoosterLinkElement.style.display = 'block'; // Show the link in pack view
} else {
marketPriceElement.innerText = 'N/A';
buyBoosterLinkElement.style.display = 'none'; // Hide the link in non-pack views
}
} else {
console.log("Finance calculator is not available for this user or layout.");
}
});
// Reset calculator button setup
const resetButton = document.getElementById('resetCalculatorBtn');
if (resetButton) {
resetButton.addEventListener('click', function () {
resetPackFinanceCalculator();
});
}
document.addEventListener('DOMContentLoaded', function () {
// Initialize Help Button
initializeHelpButton();
// Initialize Card Size Buttons
initializeCardSizeButtons();
});
// Function to initialize the help button
function initializeHelpButton() {
const helpButton = document.getElementById('helpButton');
if (helpButton && window.location.pathname === "/") {
helpButton.addEventListener('click', function () {
if (window.tour) {
window.tour.start();
} else {
console.log('Tour is not defined');
}
});
} else {
console.log('Help button not found or not on the homepage');
}
}
function updateLayout(view) {
const displayArea = document.getElementById('packDisplay');
const cardContainers = displayArea ? displayArea.querySelectorAll('.card-container') : null;
const filtersContainer = document.getElementById('draft-sealed-filters');
const maxWidth = selectedCardSize === 'Small' ? '175px' : selectedCardSize === 'Normal' ? '200px' : '225px';
if (!displayArea) {
console.warn("Display area 'packDisplay' not found.");
return;
}
// Clear existing layout classes
displayArea.className = '';
displayArea.removeEventListener('click', showNextCard);
if (cardContainers) {
// Reset styles and remove any existing event listeners
cardContainers.forEach(card => {
const cardImage = card.querySelector('img');
if (cardImage) {
const newCardImage = cardImage.cloneNode(true); // Clone to remove old listeners
const isRoom = card.dataset.isRoom === 'true'; // Check if the card is a Room
newCardImage.addEventListener('click', () => showPopupCard(newCardImage.src, isRoom));
card.replaceChild(newCardImage, cardImage); // Replace with the cloned node
}
card.style.position = '';
card.style.left = '';
card.style.transform = '';
card.style.display = 'none';
card.style.width = '';
card.style.verticalAlign = '';
card.style.margin = '';
});
}
if (filtersContainer) {
filtersContainer.style.display = "none"; // Initially hide filters
}
if (view === 'packView') {
displayArea.classList.add('packView');
if (cardContainers && cardContainers[0]) {
cardContainers[0].style.display = 'block'; // Show only the first card
cardContainers[0].style.width = maxWidth;
}
updateNavigationButtons();
document.getElementById('selectedLayoutLabel').textContent = 'Current Layout: Pack';
displayArea.addEventListener('click', showNextCard);
} else if (view === 'lineView') {
displayArea.classList.add('lineView');
if (cardContainers) {
cardContainers.forEach(card => {
card.style.display = 'block';
card.style.width = '100%';
card.style.margin = '10px 0';
});
}
document.getElementById('selectedLayoutLabel').textContent = 'Current Layout: Line';
} else if (view === 'gridView') {
displayArea.classList.add('gridView');
if (cardContainers) {
cardContainers.forEach(card => {
card.style.display = 'inline-block';
card.style.width = maxWidth;
card.style.verticalAlign = 'top';
card.style.margin = '15px';
const cardImage = card.querySelector('img');
if (cardImage) {
const isRoom = card.dataset.isRoom === 'true'; // Retrieve Room info
cardImage.addEventListener('click', () => showPopupCard(cardImage.src, isRoom));
}
});
}
document.getElementById('selectedLayoutLabel').textContent = 'Current Layout: Grid';
} else if (view === 'draftView') {
displayArea.classList.add('draftView');
if (cardContainers) {
cardContainers.forEach(card => {
card.style.display = 'block';
});
reorderCardsByRarityAndColor();
}
document.getElementById('selectedLayoutLabel').textContent = 'Current Layout: Draft';
if (filtersContainer) {
filtersContainer.style.display = "block";
}
} else if (view === 'sealedView') {
displayArea.classList.add('sealedView');
if (cardContainers) {
cardContainers.forEach(card => {
card.style.display = 'block';
});
reorderCardsByRarityAndColor();
}
document.getElementById('selectedLayoutLabel').textContent = 'Current Layout: Sealed';
if (filtersContainer) {
filtersContainer.style.display = "block";
}
}
if (cardContainers) {
cardContainers.forEach(card => {
card.style.width = maxWidth; // Apply width
});
}
}
function showAffiliateLinks(container) {
const setSelectionElement = document.getElementById('setSelection');
const boosterTypeElement = document.getElementById('boosterTypeSelection');
const selectedOptionElement = setSelectionElement.options[setSelectionElement.selectedIndex];
const setName = selectedOptionElement.text;
const boosterType = boosterTypeElement.options[boosterTypeElement.selectedIndex].text;
const encodedSetName = encodeURIComponent(setName.replace(/ /g, "+"));
// Amazon Affiliate Link
const amazonAffiliateLink = `https://www.amazon.com/s?k=${encodedSetName}+Magic+the+Gathering&linkCode=ll2&tag=mtgpacks1337-20&linkId=6d347a7186f750a21dd775ddd7440b4d&language=en_US&ref_=as_li_ss_tl`;
addLinkButtonWithImage(container, amazonAffiliateLink, `Buy ${setName} on Amazon`, "https://mtg-packs.com/wp-content/uploads/2024/07/available_at_amazon_US_EN_logo_stacked_RGB_WHITE.png", 'amazon-button');
// TCG Player Affiliate Link (General Set Search)
const tcgPlayerLink = `https://tcgplayer.pxf.io/c/5066134/1780961/21018?u=https%3A%2F%2Fwww.tcgplayer.com%2Fsearch%2Fall%2Fproduct%3Fq%3D${encodedSetName}`;
addLinkButtonWithImage(container, tcgPlayerLink, `Buy ${setName} on TCG Player`, "https://mtg-packs.com/wp-content/uploads/2024/08/TCGplayer-Primary-RGB_300px.png", 'tcgplayer-button');
// Fetch product data to get the specific pack market price
fetchProductData(setSelectionElement.value, boosterTypeElement.value).then(product => {
if (product) {
const groupId = groupIdMapping[setSelectionElement.value];
fetchPricingData(groupId, product.productId).then(marketPrice => {
if (marketPrice !== null) {
const marketPriceDisplay = document.createElement('div');
marketPriceDisplay.className = 'market-price';
marketPriceDisplay.style.fontSize = '1.2em'; // Increase font size
marketPriceDisplay.innerHTML = `<strong>${setName} ${boosterType} Market Price:</strong> $${marketPrice.toFixed(2)}`;
container.appendChild(marketPriceDisplay);
} else {
console.warn('Market price is not available.');
}
});
} else {
console.error('Product ID not found.');
}
});
}
function showPopupCard(imageUrl, isRoom = false) {
console.log("Popup triggered for card.");
console.log("Image URL:", imageUrl);
console.log("Is this card a Room?", isRoom);
// Remove existing pop-up card or overlay
const existingPopupCard = document.querySelector('.card-popup');
const existingOverlay = document.querySelector('.overlay');
if (existingPopupCard) existingPopupCard.remove();
if (existingOverlay) existingOverlay.remove();
// Create overlay and pop-up container
const overlay = document.createElement('div');
overlay.classList.add('overlay');
const popupCard = document.createElement('div');
popupCard.classList.add('card-popup');
// Create the card image
const cardImage = document.createElement('img');
cardImage.src = imageUrl;
cardImage.alt = 'Card Image';
cardImage.style.maxWidth = '90%';
cardImage.style.maxHeight = '90%';
if (isRoom) {
console.log("Rotating Room card in popup.");
cardImage.style.transform = 'rotate(90deg)';
}
// Close pop-up on click
overlay.addEventListener('click', () => {
overlay.remove();
popupCard.remove();
});
cardImage.addEventListener('click', () => {
overlay.remove();
popupCard.remove();
});
popupCard.appendChild(cardImage);
document.body.appendChild(overlay);
document.body.appendChild(popupCard);
}
// Global variable to store the selected card size
let selectedCardSize = 'Small';
// Function to update the card size
function updateCardSize(size) {
const cardContainers = document.querySelectorAll('.card-container img');
const maxWidth = size === 'Small' ? '200px' : size === 'Normal' ? '250px' : '300px';
cardContainers.forEach(container => {
container.style.maxWidth = maxWidth;
});
const selectedSizeLabel = document.getElementById('selectedSizeLabel');
if (selectedSizeLabel) {
selectedSizeLabel.textContent = `Current size: ${capitalizeFirstLetter(size)}`;
}
selectedCardSize = size;
}
// Function to add event listeners to the size buttons
function initializeCardSizeButtons() {
const sizeButtons = ['Small', 'Normal', 'Large'];
sizeButtons.forEach(size => {
const button = document.getElementById(`${size.toLowerCase()}SizeBtn`);
if (button) {
button.addEventListener('click', function () {
updateCardSize(size);
});
}
});
// Initialize card size to Small if size buttons exist
if (document.getElementById('smallSizeBtn') && document.getElementById('normalSizeBtn') && document.getElementById('largeSizeBtn')) {
updateCardSize('Small');
}
}
// Global Functions
async function fetchAllCards(setCode) {
let allCards = [];
let nextPage = `https://api.scryfall.com/cards/search?q=set:${setCode}&format=json&pretty=true&order=set&page=1`;
while (nextPage) {
const response = await fetch(nextPage);
const data = await response.json();
allCards.push(...data.data);
nextPage = data.next_page;
}
return allCards;
}
// Utility function to capitalize the first letter of a string
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function showNextCard(eventOrDirection) {
console.log("Show Next Card called with:", eventOrDirection);
let direction = 'next';
const cardContainers = document.querySelectorAll('#packDisplay .card-container');
const selectedLayout = window.selectedLayout || 'packView'; // Get the current view/layout
const totalPacks = (selectedLayout === 'draftView') ? 3 : (selectedLayout === 'sealedView') ? 6 : 1; // Adjust based on view
if (typeof eventOrDirection === 'string') {
direction = eventOrDirection;
} else if (eventOrDirection && eventOrDirection.target) {
if (eventOrDirection.target.id === 'prevCardBtn') {
direction = 'prev';
}
}
const totalCards = cardContainers.length; // Get total number of cards
console.log("Direction:", direction);
console.log("Current Card Index:", currentCardIndex);
console.log("Total Cards:", totalCards);
console.log("Total Packs:", totalPacks);
// Remove the active class and hide the current card
if (cardContainers[currentCardIndex]) {
cardContainers[currentCardIndex].classList.remove('active');
cardContainers[currentCardIndex].style.display = 'none';
}
if (direction === 'next') {
if (currentCardIndex < totalCards - 1) {
currentCardIndex++; // Move to the next card
} else {
// Reached the end of the cards
if (selectedLayout === 'packView') {
endOfPackOptions(); // Display end-of-pack options
}
return;
}
} else if (direction === 'prev' && currentCardIndex > 0) {
currentCardIndex--; // Move to the previous card
}
// Set the new active card and display it
if (cardContainers[currentCardIndex]) {
cardContainers[currentCardIndex].classList.add('active');
cardContainers[currentCardIndex].style.display = 'block';
// Ensure the width of the card is based on the selected size
const maxWidth = selectedCardSize === 'Small' ? '175px' : selectedCardSize === 'Normal' ? '225px' : '275px';
cardContainers[currentCardIndex].style.width = maxWidth;
}
// Update navigation buttons based on the current layout
updateNavigationButtons(selectedLayout);
console.log("Updated Card Index:", currentCardIndex);
}
function updateNavigationButtons() {
const nextCardButton = document.getElementById('nextCardBtn');
const prevCardButton = document.getElementById('prevCardBtn');
const cardContainers = document.querySelectorAll('#packDisplay .card-container');
const selectedLayout = window.selectedLayout || 'packView'; // Get the selected layout, defaulting to pack view
const totalCards = cardContainers.length;
// Only show navigation buttons in 'Pack View'
if (selectedLayout === 'packView') {
nextCardButton.style.display = 'block';
prevCardButton.style.display = 'block';
// Disable/enable buttons based on the current card index
if (currentCardIndex === 0) {
prevCardButton.disabled = true; // Disable 'Prev' button if at the first card
} else {
prevCardButton.disabled = false;
}
if (currentCardIndex === totalCards - 1) {
nextCardButton.disabled = true; // Disable 'Next' button if at the last card
} else {
nextCardButton.disabled = false;
}
} else {
// Hide buttons in other views (Grid, Line, Draft, Sealed)
nextCardButton.style.display = 'none';
prevCardButton.style.display = 'none';
}
}
let generatedPackCards = []; // Array to store only the cards generated in the current pack
async function generatePack() {
const displayArea = document.getElementById("packDisplay");
const affiliateLinksContainer = document.getElementById('affiliateLinksContainer');
const filtersContainer = document.getElementById("draft-sealed-filters");
// Reset display area and hide filters initially
displayArea.innerHTML = "<p>Your pack will be displayed shortly.</p>";
displayArea.classList.remove('end-of-pack-displayed');
affiliateLinksContainer.innerHTML = ''; // Clear any existing affiliate links
// Check if filtersContainer exists before trying to hide it
if (filtersContainer) {
filtersContainer.style.display = "none"; // Hide filters initially
}
try {
currentCardIndex = 0;
await updateCardSize(selectedCardSize);
const setCode = document.getElementById('setSelection').value;
const boosterType = document.getElementById('boosterTypeSelection').value;
// Update pack title in the finance calculator
updatePackTitle(setCode, boosterType);
// Store the current set and booster type in sessionStorage
sessionStorage.setItem('lastSetCode', setCode);
sessionStorage.setItem('lastBoosterType', boosterType);
console.log("Set code:", setCode);
console.log("Booster type:", boosterType);
// Fetch and categorize all cards, then assign to global allCards variable
allCards = await fetchAllCards(setCode);
const cardCategories = categorizeCards(allCards);
document.querySelector('.card-navigation-buttons').style.display = 'flex';
const selectedLayout = window.selectedLayout || 'packView';
// Determine how many packs to generate based on the layout
let numPacks = selectedLayout === 'draftView' ? 3 : selectedLayout === 'sealedView' ? 6 : 1;
// Generate the appropriate number of packs using generateMultiplePacks
const packs = await generateMultiplePacks(numPacks, setCode, boosterType, cardCategories);
// Flatten all packs into a single array and store them in generatedPackCards
generatedPackCards = packs.flat();
// Log for debugging
console.log("Generated Pack Cards:", generatedPackCards);
// Display the generated cards in the selected layout
await displayPacks(packs); // This will now handle multiple packs
// Show filters for Draft and Sealed views
if ((selectedLayout === 'draftView' || selectedLayout === 'sealedView') && filtersContainer) {
filtersContainer.style.display = "block";
displayFilteredCards(generatedPackCards); // Show only the generated cards initially
}
// Apply the user's selected layout
updateLayout(selectedLayout);
// Show affiliate links after packs are generated
showAffiliateLinks(affiliateLinksContainer);
// Update the pack finance calculator with the generated packs
updatePackFinanceCalculator(packs); // Pass the packs array here
return packs;
} catch (error) {
console.error("An error occurred during the generate pack function:", error);
displayArea.innerHTML = "<p>Error generating the pack. Please try again.</p>";
}
return [];
}
async function generateMultiplePacks(numPacks, setCode, boosterType, cardCategories) {
let packs = [];
for (let i = 0; i < numPacks; i++) {
const pack = await decideBoosterPackType(setCode, boosterType, cardCategories); // Generate a single pack
packs.push(pack);
}
return packs;
}
function reorderCardsByRarityAndColor() {
const allCardContainers = document.querySelectorAll('#packDisplay .card-container');
// Define the order of rarity and color
const rarityOrder = { 'mythic': 1, 'rare': 2, 'uncommon': 3, 'common': 4 };
const colorOrder = ['white', 'blue', 'black', 'red', 'green', 'colorless', 'multicolor'];
// Convert the NodeList of card containers into an array to manipulate it
const cardArray = Array.from(allCardContainers);
// Sort the cards based on rarity and color
cardArray.sort((a, b) => {
const rarityA = a.dataset.rarity || 'common'; // Default to 'common' if no rarity is set
const rarityB = b.dataset.rarity || 'common';
const rarityDifference = rarityOrder[rarityA] - rarityOrder[rarityB];
if (rarityDifference !== 0) {
return rarityDifference; // Sort by rarity first
}
const colorA = a.dataset.color || 'colorless'; // Default to 'colorless' if no color is set
const colorB = b.dataset.color || 'colorless';
return colorOrder.indexOf(colorA) - colorOrder.indexOf(colorB); // Then sort by color
});
// Clear the current content of #packDisplay and re-append the sorted cards
const displayArea = document.getElementById('packDisplay');
displayArea.innerHTML = ''; // Clear the current content
// Re-insert the sorted cards back into the display area
cardArray.forEach(card => displayArea.appendChild(card));
}
function categorizeCards(allCards) {
return {
mythics: allCards.filter(card => card.rarity === 'mythic'),
rares: allCards.filter(card => card.rarity === 'rare'),
uncommons: allCards.filter(card => card.rarity === 'uncommon'),
commons: allCards.filter(card => card.rarity === 'common'),
lands: allCards.filter(card => ['Forest', 'Island', 'Mountain', 'Swamp', 'Plains'].includes(card.name))
};
}
async function decideBoosterPackType(setCode, boosterType, cardCategories) {
try {
const functionName = `generate${setCode}${capitalizeFirstLetter(boosterType)}Booster`;
if (typeof window.cardGenerators[functionName] === "function") {
return await window.cardGenerators[functionName](...Object.values(cardCategories)); // Return the generated pack
} else {
alert(`Sorry! ${capitalizeFirstLetter(boosterType)} Booster is not available for ${setCode}`);
}
} catch (error) {
console.error("Error in deciding pack type:", error);
}
return [];
}
// Section 6 Pack Generators
window.cardGenerators = {
// Foundations - FDN
// Foundations - FDN - Play Booster Pack
generateFDNPlayBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear the display area
// Fetching card pools
const regularCards = await fetchFDNRegularCards();
const specialGuests = await fetchFDNSpecialGuest();
const fullArtLands = await fetchFDNFullArtBasicLands();
const basicLands = await fetchFDNBasicLands();
const commonDualLands = await fetchFDNCommonDualLands();
const borderless = await fetchFDNBorderless();
let boosterPack = [];
// Utility function to get a random card and remove it from the pool
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Function to add cards to the booster pack with optional filter
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count && filteredCards.length > 0; i++) {
const card = getRandomCard(filteredCards);
if (card) boosterPack.push(card);
}
};
// Land Slot
const landChance = Math.random();
if (landChance < 0.25) {
addCardsToBoosterPack(fullArtLands, 1);
} else if (landChance < 0.75) {
addCardsToBoosterPack(commonDualLands, 1);
} else {
addCardsToBoosterPack(basicLands, 1);
}
// Determine if a Special Guest card should replace a common (1.5% chance)
const specialGuestChance = Math.random() < 0.015;
const numCommons = specialGuestChance ? 6 : 7;
// Add commons to the booster
addCardsToBoosterPack(regularCards, numCommons, card => card.rarity === 'common');
// Add uncommons to the booster
addCardsToBoosterPack(regularCards, 3, card => card.rarity === 'uncommon');
// Rare Slot
const rareSlotChance = Math.random();
if (rareSlotChance < 0.78) {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'rare');
} else if (rareSlotChance < 0.906) {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'mythic');
} else if (rareSlotChance < 0.983) {
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'rare');
} else {
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'mythic');
}
// Wild Cards (2 cards)
for (let i = 0; i < 2; i++) {
const wildCardChance = Math.random();
if (wildCardChance < 0.167) {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'common');
} else if (wildCardChance < 0.75) {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'uncommon');
} else if (wildCardChance < 0.913) {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'rare');
} else if (wildCardChance < 0.939) {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'mythic');
} else if (wildCardChance < 0.955) {
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'rare');
} else if (wildCardChance < 0.958) {
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'mythic');
} else if (wildCardChance < 0.976) {
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'common');
} else {
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'uncommon');
}
}
// If a Special Guest card should be added, add it to the end of the pack
if (specialGuestChance) {
boosterPack.push(getRandomCard(specialGuests));
}
// Display Pack
console.log('Generated FDN Play Booster:', boosterPack);
displayPack(boosterPack); // Assuming displayPack is a function to show the pack to the user
return boosterPack; // Return the booster pack
},
// Foundations - FDN - Collector Booster Pack
generateFDNCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear the display area
// Fetching card pools
const regularCards = await fetchFDNRegularCards();
const fullArtLands = await fetchFDNFullArtBasicLands();
const basicLands = await fetchFDNBasicLands();
const commonDualLands = await fetchFDNCommonDualLands();
const borderless = await fetchFDNBorderless();
const extendedArt = await fetchFDNExtendedArt();
const manaFoil = await fetchFDNManaFoil();
const japaneseShowcase = await fetchFDNJapaneseShowcase();
const fracturedFoils = await fetchFDNFractureFoils();
const specialGuests = await fetchFDNSpecialGuest();
let boosterPack = [];
// Utility function to get a random card and remove it from the pool
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Add 5 commons with weighted probabilities
for (let i = 0; i < 5; i++) {
const commonRoll = Math.random();
if (commonRoll < 0.021) {
// 2.1% chance to be from the borderless category
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'common');
} else if (commonRoll < 0.13) {
// 10.9% chance to be from the common dual land category
addCardsToBoosterPack(commonDualLands, 1, card => card.rarity === 'common');
} else {
// 87% chance to be from the regular card pool
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'common');
}
}
// Add 4 uncommons with weighted probabilities
for (let i = 0; i < 4; i++) {
const uncommonRoll = Math.random();
if (uncommonRoll < 0.073) {
// 7.3% chance to be from the borderless category
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'uncommon');
} else {
// 92.7% chance to be from the regular card pool
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'uncommon');
}
}
// Add 1 full art land
boosterPack.push(getRandomCard(fullArtLands));
// Add 2 rares or mythic rares from the regular card set
for (let i = 0; i < 2; i++) {
const rareChance = Math.random();
if (rareChance < 0.857) {
// 85.7% chance for rare
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'rare');
} else {
// 14.3% chance for mythic rare
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'mythic');
}
}
// Add 2 more rares or mythic rares with specific probabilities
for (let i = 0; i < 2; i++) {
const rareOdds = Math.random();
if (rareOdds < 0.462) {
// 46.2% chance for borderless rare
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'rare');
} else if (rareOdds < 0.554) {
// 9.2% chance for borderless mythic rare
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'mythic');
} else if (rareOdds < 0.952) {
// 39.8% chance for extended art rare
addCardsToBoosterPack(extendedArt, 1, card => card.rarity === 'rare');
} else {
// 4.8% chance for extended art mythic rare
addCardsToBoosterPack(extendedArt, 1, card => card.rarity === 'mythic');
}
}
// Add one last rare or mythic rare with complex probabilities
const lastCardChance = Math.random();
if (lastCardChance < 0.345) {
// 34.5% chance for borderless rare
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'rare');
} else if (lastCardChance < 0.413) {
// 6.8% chance for borderless mythic rare
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'mythic');
} else if (lastCardChance < 0.709) {
// 29.6% chance for extended art rare
addCardsToBoosterPack(extendedArt, 1, card => card.rarity === 'rare');
} else if (lastCardChance < 0.745) {
// 3.6% chance for extended art mythic rare
addCardsToBoosterPack(extendedArt, 1, card => card.rarity === 'mythic');
} else if (lastCardChance < 0.829) {
// 8.4% chance for mana foil rare
addCardsToBoosterPack(manaFoil, 1, card => card.rarity === 'rare');
} else if (lastCardChance < 0.845) {
// 1.6% chance for mana foil mythic rare
addCardsToBoosterPack(manaFoil, 1, card => card.rarity === 'mythic');
} else if (lastCardChance < 0.9) {
// 5.5% chance for special guest
addCardsToBoosterPack(specialGuests, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (lastCardChance < 0.99) {
// 9% chance for Japanese showcase
addCardsToBoosterPack(japaneseShowcase, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else {
// 1% chance for fractured foil
addCardsToBoosterPack(fracturedFoils, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// Display Pack
console.log('Generated FDN Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack; // Return the booster pack
},
// Dominaria United - DMU
// DMU Collector Booster
generateDMUCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear display area
// Fetching card pools
const normalCards = await fetchDMUNormalCards();
const stainedGlassLands = await fetchDMUStainedGlassLands();
const showcaseCards = await fetchDMUShowcase();
const commanderLegendsRetold = await fetchDMCCommanderLegendsRetold();
const commanderEtchedFoil = await fetchDMCCommanderEtchedFoil();
const texturedFoil = await fetchDMUTexturedFoil();
const extendedArtCards = await fetchDMUExtendedArt();
const borderlessPlaneswalker = await fetchDMUBorderlessPlaneswalker(); // Corrected to singular
const borderlessLands = await fetchDMUAlternateArtBorderlessLands(); // Corrected name
const ajaniPlaneswalker = await fetchDMUAjaniPlaneswalker();
const setExtension = await fetchDMUSetExtension();
const phyrexianCards = await fetchDMUPhyrexian();
const lostLegends = await fetchLEGLostLegends(); // Correct Lost Legends fetch function
let boosterPack = [];
// Utility function to get a random card from a card set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Variable to track if a Lost Legends card is added
let addLostLegendCardAtEnd = false;
// 1. Add 4 commons from the normal cards (3% chance to replace a common with a Lost Legends card)
let commonsCount = 4;
if (Math.random() < 0.03) {
// If 3% chance hits, flag to add Lost Legends card at the end and reduce commons count by 1
addLostLegendCardAtEnd = true;
commonsCount -= 1;
}
addCardsToBoosterPack(normalCards, commonsCount, card => card.rarity === 'common');
// 2. Add 2 uncommons from the normal cards
addCardsToBoosterPack(normalCards, 2, card => card.rarity === 'uncommon');
// 3. Add 1 full art stained glass land
boosterPack.push(getRandomCard(stainedGlassLands));
// 4. Add 1 uncommon showcase
addCardsToBoosterPack(showcaseCards, 1, card => card.rarity === 'uncommon');
// 5. Add 1 uncommon from Commander Legends Retold or Commander Etched Foil
const commanderSource = Math.random() < 0.5 ? commanderLegendsRetold : commanderEtchedFoil;
addCardsToBoosterPack(commanderSource, 1, card => card.rarity === 'uncommon');
// 6. Add 1 card of any rarity from the textured foil category
addCardsToBoosterPack(texturedFoil, 1);
// 7. Add 1 rare or mythic rare from the normal card category (no 1/8 mythic chance, just random rare or mythic)
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
// 8. Add 1 extended art rare or mythic rare
addCardsToBoosterPack(extendedArtCards, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
// 9. Add 2 rares or mythic rares from showcase, borderless planeswalker, alternate art borderless lands, Ajani Planeswalker, foil etched commander, or legends retold commander
for (let i = 0; i < 2; i++) {
const specialSourceChance = Math.random();
if (specialSourceChance < 0.94) {
// 94% chance for main categories
const sources = [showcaseCards, borderlessLands, commanderEtchedFoil, commanderLegendsRetold];
const selectedSource = getRandomCard(sources);
addCardsToBoosterPack(selectedSource, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (specialSourceChance < 0.97) {
// 3% chance for borderless planeswalkers
addCardsToBoosterPack(borderlessPlaneswalker, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (specialSourceChance < 0.98) {
// 1% chance for Ajani planeswalker
addCardsToBoosterPack(ajaniPlaneswalker, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (specialSourceChance < 0.99) {
// 1% chance for set extension
addCardsToBoosterPack(setExtension, 1);
} else {
// 1% chance for phyrexian
addCardsToBoosterPack(phyrexianCards, 1);
}
}
// 10. Add 1 rare or mythic rare from extended art, showcase, borderless planeswalker, or borderless alternate lands
const finalRareSourceChance = Math.random();
if (finalRareSourceChance < 0.93) {
// 93% chance for normal sources
const sources = [extendedArtCards, showcaseCards, borderlessLands];
const selectedSource = getRandomCard(sources);
addCardsToBoosterPack(selectedSource, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (finalRareSourceChance < 0.98) {
// 5% chance for borderless planeswalkers
addCardsToBoosterPack(borderlessPlaneswalker, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (finalRareSourceChance < 0.99) {
// 1% chance for set extension
addCardsToBoosterPack(setExtension, 1);
} else {
// 1% chance for phyrexian
addCardsToBoosterPack(phyrexianCards, 1);
}
// If flagged, add the Lost Legends card as the last card
if (addLostLegendCardAtEnd) {
const lostLegendCard = await fetchDominariaUnitedLegendsCard();
if (lostLegendCard) {
boosterPack.push(lostLegendCard); // Add the fetched Lost Legends card to the pack
} else {
console.error('Failed to fetch a Lost Legends card.');
}
}
// Display pack in the UI or log the result
console.log('Generated DMU Collector Booster:', boosterPack);
displayPack(boosterPack);
// Apply the user's selected layout
updateLayout(window.selectedLayout || 'packView');
return boosterPack;
},
// DMU Set Booster
generateDMUSetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear display area
// Fetching card pools
const normalCards = await fetchDMUNormalCards();
const basicLands = await fetchDMUBasicLands();
const stainedGlassLands = await fetchDMUStainedGlassLands();
const showcaseCards = await fetchDMUShowcase();
const jumpstartCards = await fetchDMUJumpstartCards(); // Corrected function name
const commanderCards = await fetchDMCCommanderNew(); // Commander New & Set
const phyrexianCards = await fetchDMUPhyrexian();
const borderlessPlaneswalker = await fetchDMUBorderlessPlaneswalker(); // Corrected to singular
const borderlessLands = await fetchDMUAlternateArtBorderlessLands(); // Corrected function name
const ajaniPlaneswalker = await fetchDMUAjaniPlaneswalker();
let boosterPack = [];
// Utility function to get a random card from a card set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// 1. Add 1 basic land (25% chance to be a stained glass land)
const landChance = Math.random();
if (landChance < 0.25) {
boosterPack.push(getRandomCard(stainedGlassLands));
} else {
boosterPack.push(getRandomCard(basicLands));
}
// 2. Add 3 commons from the normal cards
addCardsToBoosterPack(normalCards, 3, card => card.rarity === 'common');
// 3. Add 3 uncommons from the normal cards
addCardsToBoosterPack(normalCards, 3, card => card.rarity === 'uncommon');
// 4. Add 1 showcase uncommon legendary creature
addCardsToBoosterPack(showcaseCards, 1, card => card.rarity === 'uncommon' && card.type_line.includes('Legendary Creature'));
// 5. Add 2 wildcards (with rarity determination)
for (let i = 0; i < 2; i++) {
const rarityChance = Math.random();
const isRareOrMythic = rarityChance < 0.10; // 10% chance to be rare or mythic
let rarityFilter = isRareOrMythic ? ['rare', 'mythic'] : ['common', 'uncommon'];
const wildcardSourceChance = Math.random();
let wildcardCards = []; // To store the filtered cards
if (wildcardSourceChance < 0.70) {
// 70% from normal cards
wildcardCards = normalCards.filter(card => rarityFilter.includes(card.rarity));
} else if (wildcardSourceChance < 0.80) {
// 10% from showcase
wildcardCards = showcaseCards.filter(card => rarityFilter.includes(card.rarity));
} else if (wildcardSourceChance < 0.90) {
// 10% from Jumpstart (only rares)
if (isRareOrMythic) {
wildcardCards = jumpstartCards.filter(card => card.rarity === 'rare');
}
} else {
// 10% from Commander New/Set (only rare or mythic)
if (isRareOrMythic) {
wildcardCards = commanderCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic');
}
}
// Fallback to ensure a wildcard is always added
if (wildcardCards.length === 0) {
// If no card found, fallback to adding a common/uncommon from normal cards
wildcardCards = normalCards.filter(card => rarityFilter.includes(card.rarity));
}
// Select a random card from the filtered wildcard cards
if (wildcardCards.length > 0) {
const randomWildcardIndex = Math.floor(Math.random() * wildcardCards.length);
boosterPack.push(wildcardCards[randomWildcardIndex]);
}
}
// 6. Add 1 wildcard with additional categories
const wildcardCategoryChance = Math.random();
if (wildcardCategoryChance < 0.88) {
// 88% from normal cards
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'common' || card.rarity === 'uncommon');
} else if (wildcardCategoryChance < 0.90) {
// 2% from Phyrexian category
addCardsToBoosterPack(phyrexianCards, 1);
} else if (wildcardCategoryChance < 0.92) {
// 2% from showcase category
addCardsToBoosterPack(showcaseCards, 1);
} else if (wildcardCategoryChance < 0.94) {
// 2% from borderless planeswalker
addCardsToBoosterPack(borderlessPlaneswalker, 1);
} else if (wildcardCategoryChance < 0.96) {
// 2% from borderless lands
addCardsToBoosterPack(borderlessLands, 1);
} else if (wildcardCategoryChance < 0.98) {
// 2% Ajani Planeswalker
addCardsToBoosterPack(ajaniPlaneswalker, 1);
} else {
// 2% rare or mythic rare from the normal card set
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// 7. Always add 1 rare or mythic rare from the normal card set (1 in 8 packs is mythic)
const isMythic = Math.random() < (1 / 8); // 1 in 8 chance for mythic
// Filter the cards to get only the matching rarity
let rareOrMythicCards = normalCards.filter(card => card.rarity === (isMythic ? 'mythic' : 'rare'));
// Ensure there's at least one card in the filtered array
if (rareOrMythicCards.length > 0) {
// Select a random card from the filtered list
const randomIndex = Math.floor(Math.random() * rareOrMythicCards.length);
boosterPack.push(rareOrMythicCards[randomIndex]);
} else {
// If no mythic or rare found (edge case), fallback to any rare card
let fallbackRares = normalCards.filter(card => card.rarity === 'rare');
if (fallbackRares.length > 0) {
const randomFallbackIndex = Math.floor(Math.random() * fallbackRares.length);
boosterPack.push(fallbackRares[randomFallbackIndex]);
}
}
// 8. 25% chance to include a card from "The List"
if (Math.random() < 0.25) {
const listCard = await fetchDomUnitedListCard(); // Correct function for fetching card from "The List"
if (listCard) {
boosterPack.push(listCard);
}
}
// Display pack in the UI or log the result
console.log('Generated DMU Set Booster:', boosterPack);
displayPack(boosterPack);
// Apply the user's selected layout
updateLayout(window.selectedLayout || 'packView');
return boosterPack;
},
// DMU Draft Booster
generateDMUDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear the display area
// Fetching card pools
const normalCards = await fetchDMUNormalCards();
const basicLands = await fetchDMUBasicLands();
const stainedGlassLands = await fetchDMUStainedGlassLands();
const showcaseCards = await fetchDMUShowcase();
const phyrexianCards = await fetchDMUPhyrexian(); // Corrected function name
const borderlessPlaneswalkers = await fetchDMUBorderlessPlaneswalker(); // Corrected function name
const borderlessLands = await fetchDMUAlternateArtBorderlessLands(); // Corrected function name
let boosterPack = [];
// Utility function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// 1. Add 1 basic land (80% chance for a basic land, 20% chance for a stained glass land)
const landChance = Math.random();
if (landChance < 0.20) {
// 20% chance for a stained glass land
boosterPack.push(getRandomCard(stainedGlassLands));
} else {
// 80% chance for a basic land from the basic lands category
boosterPack.push(getRandomCard(basicLands));
}
// 2. Add commons from the normal card pool
const commonReplacement = Math.random() < 0.33; // 33% chance to replace a common with a wildcard
if (commonReplacement) {
// Add 9 commons if we're replacing one with a wildcard
addCardsToBoosterPack(normalCards, 9, card => card.rarity === 'common');
} else {
// Otherwise, add 10 commons
addCardsToBoosterPack(normalCards, 10, card => card.rarity === 'common');
}
// 3. Add 2 uncommons from the normal category (that are not legendary)
addCardsToBoosterPack(normalCards, 2, card => card.rarity === 'uncommon' && !card.type_line.includes('Legendary Creature'));
// 4. Add 1 rare or uncommon legendary creature
const legendaryCreatureChance = Math.random();
if (legendaryCreatureChance < 0.90) {
// 90% chance for an uncommon legendary creature
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'uncommon' && card.type_line.includes('Legendary Creature'));
} else if (legendaryCreatureChance < 0.97) {
// 10% chance for a rare legendary creature
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'rare' && card.type_line.includes('Legendary Creature'));
} else {
// 3% chance for a showcase legendary creature
addCardsToBoosterPack(showcaseCards, 1, card => card.type_line.includes('Legendary Creature'));
}
// 5. Add 1 rare or mythic rare from the normal card pool
const mythicChance = Math.random() < (1 / 8); // 1 in 8 packs will have a mythic rare
if (mythicChance) {
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'mythic');
} else {
const specialRareChance = Math.random();
if (specialRareChance < 0.96) {
// 96% chance for a normal rare
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'rare');
} else if (specialRareChance < 0.97) {
// 1% chance for a showcase rare
addCardsToBoosterPack(showcaseCards, 1, card => card.rarity === 'rare');
} else if (specialRareChance < 0.98) {
// 1% chance for a borderless planeswalker
addCardsToBoosterPack(borderlessPlaneswalkers, 1);
} else if (specialRareChance < 0.99) {
// 1% chance for a borderless land
addCardsToBoosterPack(borderlessLands, 1);
} else {
// 1% chance for a phyrexian language card
addCardsToBoosterPack(phyrexianCards, 1);
}
}
// 6. Add the wildcard at the very end if common replacement happened
if (commonReplacement) {
// Step 1: Determine the rarity of the wildcard
const rarityRoll = Math.random();
let wildcardRarity = 'common';
if (rarityRoll < 0.80) {
// 80% chance for a common
wildcardRarity = 'common';
} else if (rarityRoll < 0.95) {
// 15% chance for an uncommon
wildcardRarity = 'uncommon';
} else if (rarityRoll < 0.995) {
// 4.5% chance for a rare
wildcardRarity = 'rare';
} else {
// 0.5% chance for a mythic rare
wildcardRarity = 'mythic';
}
// Step 2: Choose the card based on rarity and category
const wildCardChance = Math.random();
if (wildcardRarity === 'common' || wildcardRarity === 'uncommon') {
// Common or uncommon, choose from normal cards
addCardsToBoosterPack(normalCards, 1, card => card.rarity === wildcardRarity);
} else {
// If rare or mythic rare, decide from special categories or normal cards
if (wildCardChance < 0.80) {
// 80% chance for a normal rare/mythic card
addCardsToBoosterPack(normalCards, 1, card => card.rarity === wildcardRarity);
} else if (wildCardChance < 0.81) {
// 1% chance for a showcase card
addCardsToBoosterPack(showcaseCards, 1, card => card.rarity === wildcardRarity);
} else if (wildCardChance < 0.82) {
// 1% chance for a Phyrexian card
addCardsToBoosterPack(phyrexianCards, 1, card => card.rarity === wildcardRarity);
} else if (wildCardChance < 0.83) {
// 1% chance for a borderless planeswalker
addCardsToBoosterPack(borderlessPlaneswalkers, 1);
} else if (wildCardChance < 0.84) {
// 1% chance for a borderless land
addCardsToBoosterPack(borderlessLands, 1);
} else if (wildCardChance < 0.85) {
// 1% chance for Ajani Planeswalker
addCardsToBoosterPack(await fetchDMUAjaniPlaneswalker(), 1);
} else {
// 1% chance for a rare or mythic rare from the normal set
addCardsToBoosterPack(normalCards, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
}
}
// Display Pack
console.log('Generated DMU Draft Booster:', boosterPack);
displayPack(boosterPack);
// Apply the user's selected layout
updateLayout(window.selectedLayout || 'packView');
return boosterPack; // Return the booster pack
},
// Duskmourn - DSK - Play Booster Pack 23% to have 2 1% to have 3 and less than 1% to have 4 rares or mythic rares
generateDSKPlayBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear the display area
// Fetching card pools
const generalCardPool = await fetchDSKNormalCards();
const specialGuests = await fetchSPGSpecialGuest();
const lurkingEvil = await fetchDSKLurkingEvil();
const showcase = await fetchDSKShowcase(); // Assuming showcase category contains the showcase variants
const borderless = await fetchDSKBorderless(); // Assuming borderless category is correctly defined
const doubleExposure = await fetchDSKDoubleExposure(); // Assuming double exposure category is correctly defined
const fullArtLands = await fetchDSKFullArtLands(); // Fetch the full art lands category
const basicLands = await fetchDSKBasicLands(); // Fetch the basic lands category
const commonDualLands = await fetchDSKCommonDualLands(); // Fetch the common dual lands category
const rareDualLands = await fetchDSKRareDualLands(); // Fetch the rare dual lands category
let boosterPack = [];
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Updated addCardsToBoosterPack function to return a boolean indicating success
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
if (filteredCards.length === 0 || count <= 0) {
return false; // Return false if no card can be added
}
for (let i = 0; i < count; i++) {
const card = getRandomCard(filteredCards);
if (card) {
boosterPack.push(card);
}
}
return true; // Return true if card(s) added successfully
};
// Determine if a Special Guest card should replace a common (1/64 chance)
const specialGuestChance = Math.random() < (1 / 64);
// Number of commons to add (6 if Special Guest, otherwise 7)
const numCommons = specialGuestChance ? 6 : 7;
// Add commons from the general card pool
for (let i = 0; i < numCommons; i++) {
let commonCard = getRandomCard(generalCardPool.filter(card => card.rarity === 'common'));
// Check if the card is either 15 or 130 and has a chance to be replaced with its Lurking Evil version
if (commonCard.collector_number === 15 && Math.random() < 0.25) {
// Replace with Lurking Evil version (collector number 287)
commonCard = lurkingEvil.find(card => card.collector_number === 287);
} else if (commonCard.collector_number === 130 && Math.random() < 0.25) {
// Replace with Lurking Evil version (collector number 295)
commonCard = lurkingEvil.find(card => card.collector_number === 295);
}
boosterPack.push(commonCard);
}
// Add uncommons to the play booster
for (let i = 0; i < 3; i++) {
let uncommonCard = getRandomCard(generalCardPool.filter(card => card.rarity === 'uncommon'));
// Check for specific collector numbers and apply 25% chance to swap with alternate versions
if (uncommonCard.collector_number === 21 && Math.random() < 0.25) {
// Replace with Lurking Evil version (collector number 288)
uncommonCard = lurkingEvil.find(card => card.collector_number === 288);
} else if (uncommonCard.collector_number === 74 && Math.random() < 0.25) {
// Replace with Lurking Evil version (collector number 291)
uncommonCard = lurkingEvil.find(card => card.collector_number === 291);
} else if (uncommonCard.collector_number === 145 && Math.random() < 0.25) {
// Replace with Lurking Evil version (collector number 297)
uncommonCard = lurkingEvil.find(card => card.collector_number === 297);
} else if (uncommonCard.collector_number === 225 && Math.random() < 0.25) {
// Replace with Lurking Evil version (collector number 300)
uncommonCard = lurkingEvil.find(card => card.collector_number === 300);
} else if (uncommonCard.collector_number === 39 && Math.random() < 0.25) {
// Replace with Showcase version (collector number 306)
uncommonCard = showcase.find(card => card.collector_number === 306);
} else if (uncommonCard.collector_number === 124 && Math.random() < 0.25) {
// Replace with Showcase version (collector number 313)
uncommonCard = showcase.find(card => card.collector_number === 313);
} else if (uncommonCard.collector_number === 186 && Math.random() < 0.25) {
// Replace with Showcase version (collector number 321)
uncommonCard = showcase.find(card => card.collector_number === 321);
} else if (uncommonCard.collector_number === 203 && Math.random() < 0.25) {
// Replace with Showcase version (collector number 323)
uncommonCard = showcase.find(card => card.collector_number === 323);
}
// Add the (potentially replaced) uncommon card to the booster pack
boosterPack.push(uncommonCard);
}
// Determine the rarity or Booster Fun card to add
const rareSlotChance = Math.random();
if (rareSlotChance < 0.81) {
// 81% chance: Add a rare or mythic rare from the general card pool
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareSlotChance < 0.87) {
// 6% chance: Add a rare dual land
addCardsToBoosterPack(rareDualLands, 1, card => card.rarity === 'rare');
} else if (rareSlotChance < 0.90) {
// 3% chance: Add a rare or mythic rare from the Lurking Evil category
addCardsToBoosterPack(lurkingEvil, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else {
// 10% chance: Add a rare or mythic rare from the Booster Fun categories
const boosterFunRoll = Math.random();
const totalCardsInBoosterFun = 17 + 23 + 22; // Total cards in Double Exposure, Borderless, Showcase
// Weighted probabilities for each category
const doubleExposureChance = 17 / totalCardsInBoosterFun; // Chance for Double Exposure
const borderlessChance = 23 / totalCardsInBoosterFun; // Chance for Borderless
if (boosterFunRoll < doubleExposureChance) {
// Select from Double Exposure
addCardsToBoosterPack(doubleExposure, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (boosterFunRoll < doubleExposureChance + borderlessChance) {
// Select from Borderless
addCardsToBoosterPack(borderless, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else {
// Select from Showcase
addCardsToBoosterPack(showcase, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
}
// Calculate the total number of cards across all categories
const totalCards = 256 + 15 + 26 + 23 + 17 + 10 + 5; // Total cards across updated categories
// Array of categories and their sizes for easier processing
const wildcardCategories = [
{ set: generalCardPool, size: 256 },
{ set: lurkingEvil, size: 15 },
{ set: showcase, size: 26 },
{ set: borderless, size: 23 },
{ set: doubleExposure, size: 17 },
{ set: commonDualLands, size: 10 },
{ set: rareDualLands, size: 5 }
];
// Function to select a category based on weights
const selectWeightedCategory = () => {
const roll = Math.random() * totalCards; // Random number from 0 to totalCards
let cumulativeWeight = 0;
for (const category of wildcardCategories) {
cumulativeWeight += category.size;
if (roll < cumulativeWeight) {
return category.set;
}
}
};
// Function to add a single wildcard card with specified logic
const addWildcardCard = () => {
const wildcardCategory = selectWeightedCategory(); // Select a category based on weights
const rarityChance = Math.random(); // Roll for a rare or mythic rare chance
if (rarityChance < 0.11) {
// 11% chance to select a rare or mythic
if (!addCardsToBoosterPack(wildcardCategory, 1, card => card.rarity === 'rare' || card.rarity === 'mythic')) {
// If no rare/mythic in the selected category, fallback to general card pool
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
} else {
// Attempt to add a common or uncommon from the selected category
if (!addCardsToBoosterPack(wildcardCategory, 1, card => card.rarity === 'common' || card.rarity === 'uncommon')) {
// If no common/uncommon in the selected category, fallback to general card pool
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'common' || card.rarity === 'uncommon');
}
}
};
// Add exactly two wildcard cards
addWildcardCard(); // Add the first wildcard
addWildcardCard(); // Add the second wildcard
// Add the land slot
const landChance = Math.random();
if (landChance < 0.16) {
// 16% chance: Add a land from the full art category
addCardsToBoosterPack(fullArtLands, 1);
} else if (landChance < 0.49) { // 16% + 33% = 49%
// 33% chance: Add a land from the basic land category
addCardsToBoosterPack(basicLands, 1);
} else {
// 51% chance: Add a land from the common dual lands category
addCardsToBoosterPack(commonDualLands, 1);
}
// If a Special Guest card should be added, add it to the pack
if (specialGuestChance) {
boosterPack.push(getRandomCard(specialGuests));
}
// Display Pack
console.log('Generated DSK Play Booster:', boosterPack);
displayPack(boosterPack); // Assuming displayPack is a function you have for showing the pack to the user
return boosterPack; // Return the booster pack
},
// Duskmourn Collector Booster Pack
generateDSKCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear the display area
// Fetching card pools
const generalCardPool = await fetchDSKNormalCards();
const extendedArt = await fetchDSKExtendedArt();
const lurkingEvil = await fetchDSKLurkingEvil();
const showcase = await fetchDSKShowcase();
const borderless = await fetchDSKBorderless();
const doubleExposure = await fetchDSKDoubleExposure();
const fullArtLands = await fetchDSKFullArtLands();
const commonDualLands = await fetchDSKCommonDualLands();
const rareDualLands = await fetchDSKRareDualLands();
const duskmournCommanderFullArt = await fetchDSCFullArtCommanders(); // Updated to use fetchDSCFullArtCommanders
const duskmournCommanderExtendedArt = await fetchDSCExtendedArtCommander(); // Updated to use fetchDSCExtendedArtCommander
const japaneseShowcase = await fetchDSKJapaneseShowcase();
const fracturedFoils = await fetchDSKFracturedFoils();
const texturedFinish = await fetchDSKTexturedFinish();
const specialGuests = await fetchSPGSpecialGuest();
let boosterPack = [];
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Add 5 commons with weighted probabilities
for (let i = 0; i < 5; i++) {
const commonRoll = Math.random();
const totalCommonCards = 81 + 10 + 2; // Total commons: general (81), common dual lands (10), lurking evil (2)
if (commonRoll < 2 / totalCommonCards) {
// 2/93 chance for lurking evil commons
addCardsToBoosterPack(lurkingEvil, 1, card => card.rarity === 'common');
} else if (commonRoll < (2 + 10) / totalCommonCards) {
// 10/93 chance for common dual lands
addCardsToBoosterPack(commonDualLands, 1, card => card.rarity === 'common');
} else {
// Remaining chance for general card pool commons
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'common');
}
}
// Add 4 uncommons with weighted probabilities
for (let i = 0; i < 4; i++) {
const uncommonRoll = Math.random();
const totalUncommonCards = 100 + 4 + 4; // Total uncommons: general (100), paranormal (4), lurking evil (4)
if (uncommonRoll < 4 / totalUncommonCards) {
// 4/108 chance for paranormal uncommons
addCardsToBoosterPack(showcase, 1, card => card.rarity === 'uncommon');
} else if (uncommonRoll < (4 + 4) / totalUncommonCards) {
// 4/108 chance for lurking evil uncommons
addCardsToBoosterPack(lurkingEvil, 1, card => card.rarity === 'uncommon');
} else {
// Remaining chance for general card pool uncommons
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'uncommon');
}
}
// Add 1 full art land
boosterPack.push(getRandomCard(fullArtLands));
// Add 1 rare or mythic rare
const rareChance = Math.random();
if (rareChance < 0.90) {
// 90% chance for general card pool
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else {
// 10% chance for lurking evil
addCardsToBoosterPack(lurkingEvil, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// Add 1 Duskmourn commander rare or mythic rare
const commanderChance = Math.random();
if (commanderChance < 0.18) {
// 18% chance for full art commander
boosterPack.push(getRandomCard(duskmournCommanderFullArt, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else {
// 82% chance for extended art commander
boosterPack.push(getRandomCard(duskmournCommanderExtendedArt, card => card.rarity === 'rare' || card.rarity === 'mythic'));
}
// Add 2 rare or mythic rares with specified probabilities
for (let i = 0; i < 2; i++) {
const rareOdds = Math.random();
if (rareOdds < 0.25) {
// 25% chance for extended art
boosterPack.push(getRandomCard(extendedArt, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else if (rareOdds < 0.50) {
// 25% chance for borderless
boosterPack.push(getRandomCard(borderless, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else if (rareOdds < 0.80) {
// 30% chance for showcase
boosterPack.push(getRandomCard(showcase, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else {
// 20% chance for double exposure
boosterPack.push(getRandomCard(doubleExposure, card => card.rarity === 'rare' || card.rarity === 'mythic'));
}
}
// Add 1 rare or mythic rare with complex probabilities
const lastCardChance = Math.random();
if (lastCardChance < 0.09) {
// 9% chance for Japanese showcase
boosterPack.push(getRandomCard(japaneseShowcase, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else if (lastCardChance < 0.10) {
// 1% chance for fractured foil
boosterPack.push(getRandomCard(fracturedFoils, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else if (lastCardChance < 0.11) {
// 1% chance for textured finish
boosterPack.push(getRandomCard(texturedFinish, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else if (lastCardChance < 0.14) {
// 3% chance for special guests
boosterPack.push(getRandomCard(specialGuests, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else {
// 85% chance to fall into the final set of options
const finalOdds = Math.random();
if (finalOdds < 0.25) {
// 25% chance for extended art
boosterPack.push(getRandomCard(extendedArt, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else if (finalOdds < 0.50) {
// 25% chance for borderless
boosterPack.push(getRandomCard(borderless, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else if (finalOdds < 0.80) {
// 30% chance for showcase
boosterPack.push(getRandomCard(showcase, card => card.rarity === 'rare' || card.rarity === 'mythic'));
} else {
// 20% chance for double exposure
boosterPack.push(getRandomCard(doubleExposure, card => card.rarity === 'rare' || card.rarity === 'mythic'));
}
}
// Display Pack
console.log('Generated DSK Collector Booster:', boosterPack);
displayPack(boosterPack);
// Apply the user's selected layout
updateLayout(window.selectedLayout || 'packView');
return boosterPack; // Return the booster pack
},
//Bloomburrow Collector
generateBLBCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear the display area
// Fetching card pools
const generalCardPool = await fetchBLBGeneralCardPool();
const springLands = await fetchBLBSpringLands();
const summerLands = await fetchBLBSummerLands();
const fallLands = await fetchBLBFallLands();
const winterLands = await fetchBLBWinterLands();
const borderless = await fetchBLBBorderless();
const borderlessFieldNotes = await fetchBLBBorderlessFieldNotes();
const showcaseWoodland = await fetchBLBShowcaseWoodland();
const courageousCritters = await fetchBLBCourageousCritters();
const extendedArt = await fetchBLBExtendedArt();
const extendedArtCommander = await fetchBLBExtendedArtCommander();
const specialGuests = await fetchBLBSpecialGuests();
const raisedFoils = await fetchBLBRaisedFoils();
let boosterPack = [];
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Add 5 commons from the general card pool
addCardsToBoosterPack(generalCardPool, 5, card => card.rarity === 'common');
// Add 4 uncommons from the general card pool
addCardsToBoosterPack(generalCardPool, 4, card => card.rarity === 'uncommon');
// Add 1 land with specified probabilities
const landOdds = Math.random();
let landCard;
if (landOdds < 0.40) {
landCard = getRandomCard(springLands);
} else if (landOdds < 0.70) {
landCard = getRandomCard(summerLands);
} else if (landOdds < 0.90) {
landCard = getRandomCard(fallLands);
} else {
landCard = getRandomCard(winterLands);
}
boosterPack.push(landCard);
// Add 1 rare or mythic rare from the general card pool
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
// Add 1 card from the extended art commander category
boosterPack.push(getRandomCard(extendedArtCommander));
// Add 2 rare or mythic rares with specified odds
for (let i = 0; i < 2; i++) {
const odds = Math.random();
if (odds < 0.05) {
boosterPack.push(getRandomCard(borderless));
} else if (odds < 0.10) {
boosterPack.push(getRandomCard(borderlessFieldNotes));
} else if (odds < 0.60) {
boosterPack.push(getRandomCard(showcaseWoodland));
} else if (odds < 0.78) {
boosterPack.push(getRandomCard(extendedArt));
} else {
boosterPack.push(getRandomCard(courageousCritters));
}
}
// Add 1 rare or mythic rare with specified odds
const lastCardOdds = Math.random();
if (lastCardOdds < 0.05) {
boosterPack.push(getRandomCard(borderless));
} else if (lastCardOdds < 0.10) {
boosterPack.push(getRandomCard(borderlessFieldNotes));
} else if (lastCardOdds < 0.57) {
boosterPack.push(getRandomCard(showcaseWoodland));
} else if (lastCardOdds < 0.74) {
boosterPack.push(getRandomCard(extendedArt));
} else if (lastCardOdds < 0.94) {
boosterPack.push(getRandomCard(courageousCritters));
} else if (lastCardOdds < 0.97) {
boosterPack.push(getRandomCard(specialGuests));
} else {
boosterPack.push(getRandomCard(raisedFoils));
}
// Ensure the pack has 15 cards total (if needed)
if (boosterPack.length < 15) {
addCardsToBoosterPack(generalCardPool, 15 - boosterPack.length);
}
// Display Pack
console.log('Generated BLB Collector Booster:', boosterPack);
displayPack(boosterPack); // Assuming displayPack is a function you have for showing the pack to the user
// Apply the user's selected layout
updateLayout(window.selectedLayout || 'packView');
return boosterPack; // Return the booster pack
},
// BloomBurrow - BLB - Play Booster Pack
generateBLBPlayBooster: async function() {
const displayArea = document.getElementById('packDisplay');
resetDisplayArea(); // Clear the display area
// Fetching card pools
const generalCardPool = await fetchBLBGeneralCardPool();
const springLands = await fetchBLBSpringLands();
const summerLands = await fetchBLBSummerLands();
const fallLands = await fetchBLBFallLands();
const winterLands = await fetchBLBWinterLands();
const borderlessFieldNotes = await fetchBLBBorderlessFieldNotes();
const showcaseWoodland = await fetchBLBShowcaseWoodland();
const specialGuests = await fetchBLBSpecialGuests();
let boosterPack = [];
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Add 1 land with specified probabilities
const landOdds = Math.random();
let landCard;
if (landOdds < 0.40) {
landCard = getRandomCard(springLands);
} else if (landOdds < 0.70) {
landCard = getRandomCard(summerLands);
} else if (landOdds < 0.90) {
landCard = getRandomCard(fallLands);
} else {
landCard = getRandomCard(winterLands);
}
boosterPack.push(landCard);
// Determine if a special guest card should be added (1.5% chance)
const specialGuestChance = Math.random() < 0.015;
if (specialGuestChance) {
addCardsToBoosterPack(generalCardPool, 6, card => card.rarity === 'common');
} else {
addCardsToBoosterPack(generalCardPool, 7, card => card.rarity === 'common');
}
// Add 3 uncommons from the general card pool
addCardsToBoosterPack(generalCardPool, 3, card => card.rarity === 'uncommon');
// Add 1 common or uncommon with an 11% chance to be a rare or mythic rare
const wildCard1Chance = Math.random();
if (wildCard1Chance < 0.11) {
const rareMythicChoice = Math.random();
if (rareMythicChoice < 0.34) {
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareMythicChoice < 0.67) {
boosterPack.push(getRandomCard(borderlessFieldNotes));
} else {
boosterPack.push(getRandomCard(showcaseWoodland));
}
} else {
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'common' || card.rarity === 'uncommon');
}
// Add 1 rare or mythic rare from the general card pool
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
// Add 1 common or uncommon with an 11% chance to be a rare or mythic rare
const wildCard2Chance = Math.random();
if (wildCard2Chance < 0.11) {
const rareMythicChoice = Math.random();
if (rareMythicChoice < 0.34) {
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareMythicChoice < 0.67) {
boosterPack.push(getRandomCard(borderlessFieldNotes));
} else {
boosterPack.push(getRandomCard(showcaseWoodland));
}
} else {
addCardsToBoosterPack(generalCardPool, 1, card => card.rarity === 'common' || card.rarity === 'uncommon');
}
// If a special guest card was determined, add it to the pack
if (specialGuestChance) {
boosterPack.push(getRandomCard(specialGuests));
}
// Ensure the pack has 14 cards total
if (boosterPack.length < 14) {
addCardsToBoosterPack(generalCardPool, 14 - boosterPack.length);
}
// Display Pack
console.log('Generated BLB Play Booster:', boosterPack);
displayPack(boosterPack); // Assuming displayPack is a function you have for showing the pack to the user
// Apply the user's selected layout
updateLayout(window.selectedLayout || 'packView');
return boosterPack; // Return the booster pack
},
// Assassin's Creed Beyond Booster Pack
generateACRBeyondBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
const regularCardPool = await fetchACRRegularCards();
const fullArtLands = await fetchACRFullArtLands();
const sceneLands = await fetchACRSceneLands();
const sceneCard = await fetchACRSceneCard();
const showcase = await fetchACRShowcase();
const borderless = await fetchACRBorderless();
// Helper function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add a number of cards to the booster pack
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a land card with specific probabilities
let selectedLand;
const landRoll = Math.random();
if (landRoll < 0.96) {
selectedLand = getRandomCard(fullArtLands);
} else if (landRoll < 0.99) {
selectedLand = getRandomCard(sceneLands);
} else {
selectedLand = getRandomCard(sceneCard);
}
// Filter cards by rarity from the regular card pool
const uncommons = regularCardPool.filter(card => card.rarity === 'uncommon');
const rares = regularCardPool.filter(card => card.rarity === 'rare');
const mythics = regularCardPool.filter(card => card.rarity === 'mythic');
// Select a rare or mythic card with specific probabilities
const rareOrMythicRoll = Math.random();
const rareOrMythic = rareOrMythicRoll < 0.82 ? getRandomCard(rares) : getRandomCard(mythics);
// Select a regular card with specific probabilities
const regularCardRoll = Math.random();
let regularCard;
if (regularCardRoll < 0.83) {
regularCard = getRandomCard(uncommons);
} else if (regularCardRoll < 0.96) {
regularCard = getRandomCard(rares);
} else {
regularCard = getRandomCard(mythics);
}
// Select a showcase or borderless card with specific probabilities
const showcaseOrBorderlessRoll = Math.random();
let showcaseOrBorderless;
if (showcaseOrBorderlessRoll < 0.83) {
showcaseOrBorderless = getRandomCard(showcase.filter(card => card.rarity === 'uncommon'));
} else if (showcaseOrBorderlessRoll < 0.85) {
showcaseOrBorderless = getRandomCard(borderless.filter(card => card.rarity === 'rare'));
} else if (showcaseOrBorderlessRoll < 0.88) {
showcaseOrBorderless = getRandomCard(borderless.filter(card => card.rarity === 'mythic'));
} else if (showcaseOrBorderlessRoll < 0.98) {
showcaseOrBorderless = getRandomCard(showcase.filter(card => card.rarity === 'rare'));
} else {
showcaseOrBorderless = getRandomCard(showcase.filter(card => card.rarity === 'mythic'));
}
// Construct the booster pack
let boosterPack = [];
addCardsToPack(uncommons, 3, boosterPack);
boosterPack.push(selectedLand);
boosterPack.push(rareOrMythic);
boosterPack.push(regularCard);
boosterPack.push(showcaseOrBorderless);
// Display Pack in the console and on the screen
console.log('Generated ACR Beyond Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack; // Return the booster pack
},
// Assassin's Creed Collector Booster Pack
generateACRCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
const regularCardPool = await fetchACRRegularCards();
const fullArtLands = await fetchACRFullArtLands();
const sceneLands = await fetchACRSceneLands();
const sceneCard = await fetchACRSceneCard();
const showcase = await fetchACRShowcase();
const borderless = await fetchACRBorderless();
const etchedFoil = await fetchACREtchedFoil();
const extendedArt = await fetchACRExtendedArt();
const texturedFoil = await fetchACRTexturedFoil();
const serialized = await fetchACRSerialized();
// Helper function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add a number of cards to the booster pack
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a land card with specific probabilities
let selectedLand;
const landRoll = Math.random();
if (landRoll < 0.86) {
selectedLand = getRandomCard(fullArtLands);
} else if (landRoll < 0.99) {
selectedLand = getRandomCard(sceneLands);
} else {
selectedLand = getRandomCard(sceneCard);
}
// Select a rare or mythic rare card with specific probabilities
const rareOrMythicRoll = Math.random();
const rareOrMythic = rareOrMythicRoll < 0.82 ? getRandomCard(regularCardPool.filter(card => card.rarity === 'rare')) : getRandomCard(regularCardPool.filter(card => card.rarity === 'mythic'));
// Select an extended art rare or mythic rare card with specific probabilities
const extendedArtRoll = Math.random();
const extendedArtCard = extendedArtRoll < 0.97 ? getRandomCard(extendedArt.filter(card => card.rarity === 'rare')) : getRandomCard(extendedArt.filter(card => card.rarity === 'mythic'));
// Select a card with various probabilities
const specialCardRoll = Math.random();
let specialCard;
if (specialCardRoll < 0.05) {
specialCard = getRandomCard(borderless.filter(card => card.rarity === 'rare'));
} else if (specialCardRoll < 0.15) {
specialCard = getRandomCard(borderless.filter(card => card.rarity === 'mythic'));
} else if (specialCardRoll < 0.49) {
specialCard = getRandomCard(showcase.filter(card => card.rarity === 'rare'));
} else if (specialCardRoll < 0.55) {
specialCard = getRandomCard(showcase.filter(card => card.rarity === 'mythic'));
} else if (specialCardRoll < 0.95) {
specialCard = getRandomCard(extendedArt.filter(card => card.rarity === 'rare'));
} else if (specialCardRoll < 0.96) {
specialCard = getRandomCard(extendedArt.filter(card => card.rarity === 'mythic'));
} else if (specialCardRoll < 0.9999) {
specialCard = getRandomCard(texturedFoil);
} else {
specialCard = getRandomCard(serialized);
}
// Select a foil etched rare or mythic rare card with specific probabilities
const foilEtchedRoll = Math.random();
const foilEtched = foilEtchedRoll < 0.82 ? getRandomCard(etchedFoil.filter(card => card.rarity === 'rare')) : getRandomCard(etchedFoil.filter(card => card.rarity === 'mythic'));
// Construct the booster pack
let boosterPack = [];
addCardsToPack(regularCardPool.filter(card => card.rarity === 'uncommon'), 3, boosterPack);
boosterPack.push(getRandomCard(showcase.filter(card => card.rarity === 'uncommon')));
boosterPack.push(getRandomCard(etchedFoil.filter(card => card.rarity === 'uncommon')));
boosterPack.push(selectedLand);
boosterPack.push(rareOrMythic);
boosterPack.push(extendedArtCard);
boosterPack.push(specialCard);
boosterPack.push(foilEtched);
// Display Pack in the console and on the screen
console.log('Generated ACR Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
// Modern Horizons III
// MH3 Collector Booster
generateMH3CollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetching card pools
const generalCardPool = await fetchMH3GeneralCardPool();
const newToModern = await fetchMH3NewToModern();
const fullArtLand = await fetchMH3FullArtLand();
const retro = await fetchMH3Retro();
const fullArtSnowCoveredWaste = await fetchMH3FullArtSnowCoveredWaste();
const commanders = await fetchM3CCommanders();
const extendedArt = await fetchMH3ExtendedArt();
const extendedArtCommanders = await fetchM3CExtendedArtCommanders();
const borderlessFramebreak = await fetchMH3BorderlessFramebreak();
const borderlessProfile = await fetchMH3BorderlessProfile();
const borderlessConceptEldrazi = await fetchMH3BorderlessConceptEldrazi();
const borderlessLands = await fetchMH3BorderlessLands();
const borderlessPlaneswalkers = await fetchMH3BorderlessPlaneswalkers();
const etchedFoil = await fetchMH3EtchedFoil();
const specialGuests = await fetchSPGSpecialGuests();
const texturedFoil = await fetchMH3TexturedFoil();
const timeshift = await fetchH2RTimeshift(); // Fetching the timeshift category
let boosterPack = [];
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Adding 4 commons from the general card pool
addCardsToPack(generalCardPool, 4, card => card.rarity === 'common');
// Adding 3 uncommons with a 50% chance for one to be from the new to Modern category
for (let i = 0; i < 3; i++) {
if (i === 0 && Math.random() < 0.5) {
// 50% chance to add one uncommon from new to Modern category
addCardsToPack(newToModern, 1, card => card.rarity === 'uncommon');
} else {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'uncommon');
}
}
// Adding 1 full art land
addCardsToPack(fullArtLand, 1);
// Adding 2 commons or uncommons from the retro or timeshift category (2.6% chance for snow covered waste)
for (let i = 0; i < 2; i++) {
const rand = Math.random();
if (rand < 0.026) {
addCardsToPack(fullArtSnowCoveredWaste, 1);
} else if (rand < 0.7) { // 67.4% chance to pull from retro
addCardsToPack(retro, 1, card => card.rarity === 'common' || card.rarity === 'uncommon');
} else { // 30% chance to pull from timeshift
addCardsToPack(timeshift, 1, card => card.rarity === 'common' || card.rarity === 'uncommon');
}
}
// Adding 1 rare or mythic rare with specific odds
const rareMythicOdds = Math.random();
if (rareMythicOdds < 0.778) { // 77.8% chance to pull from general card pool
addCardsToPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else { // 22.2% chance to pull from new to Modern category
addCardsToPack(newToModern, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// Adding 1 commander card
if (Math.random() < 0.12) {
addCardsToPack(commanders, 1);
} else {
addCardsToPack(extendedArtCommanders, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// Adding 2 rares or mythics with detailed odds
for (let i = 0; i < 2; i++) {
const rareMythicOdds = Math.random();
if (rareMythicOdds < 0.21) { // 21% extended-art rare
addCardsToPack(extendedArt, 1, card => card.rarity === 'rare');
} else if (rareMythicOdds < 0.22) { // 1% extended-art mythic rare
addCardsToPack(extendedArt, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.42) { // 20% borderless frame break rare
addCardsToPack(borderlessFramebreak, 1, card => card.rarity === 'rare');
} else if (rareMythicOdds < 0.44) { // 2% borderless frame break mythic rare
addCardsToPack(borderlessFramebreak, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.58) { // 14% borderless profile rare
addCardsToPack(borderlessProfile, 1, card => card.rarity === 'rare');
} else if (rareMythicOdds < 0.61) { // 3% borderless profile mythic rare
addCardsToPack(borderlessProfile, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.63) { // 2% borderless concept Eldrazi mythic rare
addCardsToPack(borderlessConceptEldrazi, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.66) { // 3% borderless fetch lands and other rare lands
addCardsToPack(borderlessLands, 1, card => card.rarity === 'rare');
} else if (rareMythicOdds < 0.69) { // 3% borderless DFC planeswalkers
addCardsToPack(borderlessPlaneswalkers, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.82) { // 14% new-to-Modern rare
addCardsToPack(newToModern, 1, card => card.rarity === 'rare');
} else if (rareMythicOdds < 0.83) { // 1% new-to-Modern mythic rare
addCardsToPack(newToModern, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.94) { // 11% retro frame rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'rare');
} else if (rareMythicOdds < 0.96) { // 2% retro frame mythic rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.97) { // 1% retro frame new-to-Modern rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'rare');
} else if (rareMythicOdds < 0.98) { // 1% retro frame new-to-Modern mythic rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'mythic');
} else if (rareMythicOdds < 0.99) { // 2% retro frame rares from MH2
addCardsToPack(timeshift, 1, card => card.rarity === 'rare');
} else { // 1% retro frame mythic rares from MH2
addCardsToPack(timeshift, 1, card => card.rarity === 'mythic');
}
}
// Adding 1 rare or mythic rare with specific odds
const finalRareMythicOdds = Math.random();
if (finalRareMythicOdds < 0.20) {
addCardsToPack(extendedArt, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (finalRareMythicOdds < 0.40) {
addCardsToPack(borderlessFramebreak, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (finalRareMythicOdds < 0.60) {
addCardsToPack(retro, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (finalRareMythicOdds < 0.72) {
addCardsToPack(etchedFoil, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (finalRareMythicOdds < 0.76) {
addCardsToPack(specialGuests, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (finalRareMythicOdds < 0.80) {
addCardsToPack(texturedFoil, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else {
// Using the previous rare or mythic rare slot odds
const additionalRareMythicOdds = Math.random();
if (additionalRareMythicOdds < 0.21) { // 21% extended-art rare
addCardsToPack(extendedArt, 1, card => card.rarity === 'rare');
} else if (additionalRareMythicOdds < 0.22) { // 1% extended-art mythic rare
addCardsToPack(extendedArt, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.42) { // 20% borderless frame break rare
addCardsToPack(borderlessFramebreak, 1, card => card.rarity === 'rare');
} else if (additionalRareMythicOdds < 0.44) { // 2% borderless frame break mythic rare
addCardsToPack(borderlessFramebreak, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.58) { // 14% borderless profile rare
addCardsToPack(borderlessProfile, 1, card => card.rarity === 'rare');
} else if (additionalRareMythicOdds < 0.61) { // 3% borderless profile mythic rare
addCardsToPack(borderlessProfile, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.63) { // 2% borderless concept Eldrazi mythic rare
addCardsToPack(borderlessConceptEldrazi, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.66) { // 3% borderless fetch lands and other rare lands
addCardsToPack(borderlessLands, 1, card => card.rarity === 'rare');
} else if (additionalRareMythicOdds < 0.69) { // 3% borderless DFC planeswalkers
addCardsToPack(borderlessPlaneswalkers, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.82) { // 14% new-to-Modern rare
addCardsToPack(newToModern, 1, card => card.rarity === 'rare');
} else if (additionalRareMythicOdds < 0.83) { // 1% new-to-Modern mythic rare
addCardsToPack(newToModern, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.94) { // 11% retro frame rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'rare');
} else if (additionalRareMythicOdds < 0.96) { // 2% retro frame mythic rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.97) { // 1% retro frame new-to-Modern rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'rare');
} else if (additionalRareMythicOdds < 0.98) { // 1% retro frame new-to-Modern mythic rares from MH3
addCardsToPack(retro, 1, card => card.rarity === 'mythic');
} else if (additionalRareMythicOdds < 0.99) { // 2% retro frame rares from MH2
addCardsToPack(timeshift, 1, card => card.rarity === 'rare');
} else { // 1% retro frame mythic rares from MH2
addCardsToPack(timeshift, 1, card => card.rarity === 'mythic');
}
}
// Ensure the pack has 15 cards total
if (boosterPack.length < 15) {
addCardsToPack(generalCardPool, 15 - boosterPack.length);
}
// Display Pack
console.log('Generated MH3 Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack; // Return the booster pack
},
// MH3 Play Booster
generateMH3PlayBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetching card pools
const generalCardPool = await fetchMH3GeneralCardPool();
const newToModern = await fetchMH3NewToModern();
const fullArtLand = await fetchMH3FullArtLand();
const basicLand = await fetchMH3BasicLand();
const borderlessFramebreak = await fetchMH3BorderlessFramebreak();
const borderlessLands = await fetchMH3BorderlessLands();
const borderlessPlaneswalkers = await fetchMH3BorderlessPlaneswalkers();
const borderlessConceptEldrazi = await fetchMH3BorderlessConceptEldrazi();
const borderlessProfile = await fetchMH3BorderlessProfile();
const retro = await fetchMH3Retro();
const extendedArt = await fetchMH3ExtendedArt();
const fullArtSnowCoveredWaste = await fetchMH3FullArtSnowCoveredWaste();
const specialGuests = await fetchSPGSpecialGuests();
const commanders = await fetchM3CCommanders();
let boosterPack = [];
let replaceSixthCommon = Math.random() < 1/64; // 1 in 64 chance
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Adding 1 land or common
const landOrCommonChance = Math.random();
if (landOrCommonChance < 0.5) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'common');
} else if (landOrCommonChance < 0.83) {
addCardsToPack(basicLand, 1);
} else {
addCardsToPack(fullArtLand, 1);
}
// Adding 6 commons from the general card pool
if (replaceSixthCommon) {
addCardsToPack(generalCardPool, 5, card => card.rarity === 'common');
} else {
addCardsToPack(generalCardPool, 6, card => card.rarity === 'common');
}
// Adding 3 uncommons from the general card pool
addCardsToPack(generalCardPool, 3, card => card.rarity === 'uncommon');
// Adding 1 wildcard
const wildcardChance = Math.random();
if (wildcardChance < 0.41) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'common');
} else if (wildcardChance < 0.77) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'uncommon');
} else if (wildcardChance < 0.83) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'rare');
} else if (wildcardChance < 0.88) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'mythic');
} else if (wildcardChance < 0.884) {
addCardsToPack(borderlessFramebreak, 1);
} else if (wildcardChance < 0.888) {
addCardsToPack(borderlessPlaneswalkers, 1);
} else if (wildcardChance < 0.892) {
addCardsToPack(borderlessConceptEldrazi, 1);
} else if (wildcardChance < 0.896) {
addCardsToPack(borderlessLands, 1);
} else if (wildcardChance < 0.938) {
addCardsToPack(retro, 1);
} else if (wildcardChance < 0.946) {
addCardsToPack(fullArtSnowCoveredWaste, 1);
} else {
addCardsToPack(commanders, 1);
}
// Adding 1 new to modern card of any rarity
const newToModernChance = Math.random();
if (newToModernChance < 0.75) {
addCardsToPack(newToModern, 1, card => card.rarity === 'uncommon');
} else if (newToModernChance < 0.95) {
addCardsToPack(newToModern, 1, card => card.rarity === 'rare');
} else {
addCardsToPack(newToModern, 1, card => card.rarity === 'mythic');
}
// Adding 1 rare or mythic rare
const rareMythicChance = Math.random();
if (rareMythicChance < 0.90) {
// 90% chance to pull rare or mythic from general card pool
addCardsToPack(generalCardPool, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareMythicChance < 0.95) {
// 5% chance to pull rare or mythic from retro
addCardsToPack(retro, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareMythicChance < 0.96) {
// 1% chance to pull from borderless lands
addCardsToPack(borderlessLands, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareMythicChance < 0.97) {
// 1% chance to pull from borderless concept eldrazi
addCardsToPack(borderlessConceptEldrazi, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareMythicChance < 0.98) {
// 1% chance to pull from borderless planeswalkers
addCardsToPack(borderlessPlaneswalkers, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (rareMythicChance < 0.99) {
// 1% chance to pull from borderless profile
addCardsToPack(borderlessProfile, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
} else {
// 1% chance to pull from borderless framebreak
addCardsToPack(borderlessFramebreak, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// Adding 1 wildcard foil card
const foilChance = Math.random();
if (foilChance < 0.41) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'common');
} else if (foilChance < 0.77) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'uncommon');
} else if (foilChance < 0.82) {
addCardsToPack(newToModern, 1);
} else if (foilChance < 0.88) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'rare');
} else if (foilChance < 0.93) {
addCardsToPack(generalCardPool, 1, card => card.rarity === 'mythic');
} else if (foilChance < 0.934) {
addCardsToPack(borderlessFramebreak, 1);
} else if (foilChance < 0.938) {
addCardsToPack(borderlessPlaneswalkers, 1);
} else if (foilChance < 0.942) {
addCardsToPack(borderlessConceptEldrazi, 1);
} else if (foilChance < 0.946) {
addCardsToPack(borderlessLands, 1);
} else if (foilChance < 0.988) {
addCardsToPack(retro, 1);
} else if (foilChance < 0.996) {
addCardsToPack(fullArtSnowCoveredWaste, 1);
} else {
addCardsToPack(commanders, 1);
}
// Adding the special guest card if applicable
if (replaceSixthCommon) {
boosterPack.push(getRandomCard(specialGuests));
}
// Ensure the pack has 14 cards total
if (boosterPack.length < 14) {
addCardsToPack(generalCardPool, 14 - boosterPack.length);
}
// Display Pack
console.log('Generated MH3 Play Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack; // Return the booster pack
},
// March of the Machine Draft Booster Pack
generateMOMDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
const basicLands = await fetchMOMBasicLands();
const fullArtLands = await fetchMOMFullArtLands();
const generalCardPool = await fetchMOMGeneralCardPool();
const battles = generalCardPool.filter(card => card.type_line.toLowerCase().includes('battle'));
const showcaseMultiverse = await fetchMOMMultiverseLegendsShowcase();
const doubleFacedNonBattleCards = generalCardPool.filter(card => card.layout === 'transform' && !card.type_line.toLowerCase().includes('battle'));
// Helper function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add a number of cards to the booster pack
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a random land
const selectedLand = Math.random() < 0.34 ? getRandomCard(fullArtLands) : getRandomCard(basicLands);
// Filter cards by rarity from the general card pool
const nonBattleCommons = generalCardPool.filter(card => card.rarity === 'common' && !card.type_line.toLowerCase().includes('battle'));
const nonBattleUncommons = generalCardPool.filter(card => card.rarity === 'uncommon' && !card.type_line.toLowerCase().includes('battle'));
const raresAndMythics = generalCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity));
const randomCards = [...generalCardPool];
// Decide the rare or mythic
const rareOrMythic = Math.random() < (1 / 8) ? getRandomCard(raresAndMythics.filter(card => card.rarity === 'mythic')) : getRandomCard(raresAndMythics.filter(card => card.rarity === 'rare'));
let boosterPack = [selectedLand];
addCardsToPack(nonBattleCommons, 8, boosterPack);
// 33% chance to replace the last common with a random card of any rarity
let wildcard = null;
if (Math.random() < 0.33) {
boosterPack.pop();
wildcard = getRandomCard(randomCards);
}
addCardsToPack(nonBattleUncommons, 2, boosterPack);
boosterPack.push(getRandomCard(doubleFacedNonBattleCards)); // 1 card of any rarity where the type is NOT battle and layout is set to transform
boosterPack.push(getRandomCard(battles)); // 1 battle of any rarity from the general card pool
boosterPack.push(rareOrMythic); // 1 rare or mythic rare from the general card pool
boosterPack.push(getRandomCard(showcaseMultiverse)); // 1 card from the showcase multiverse card pool
// If there's a wildcard, push it to the end of the pack
if (wildcard) {
boosterPack.push(wildcard);
}
// Display Pack in the console and on the screen
console.log('Generated MOM Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
// March of the Machine Set Booster Pack
generateMOMSetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
const basicLands = await fetchMOMBasicLands();
const fullArtLands = await fetchMOMFullArtLands();
const generalCardPool = await fetchMOMGeneralCardPool();
const battles = generalCardPool.filter(card => card.type_line.toLowerCase().includes('battle'));
const transformCards = generalCardPool.filter(card => card.layout === 'transform' && !card.type_line.toLowerCase().includes('battle'));
const commanderNew = await fetchMOMNewCommander();
const showcaseMultiverse = await fetchMOMMultiverseLegendsShowcase();
const jumpstartCards = await fetchMOMJumpstartCards();
const foilEtchedMultiverse = await fetchMOMMultiverseLegendsFoilEtched();
// Helper function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add a number of cards to the booster pack
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a random land
const selectedLand = Math.random() < 0.36 ? getRandomCard(fullArtLands) : getRandomCard(basicLands);
// Filter cards by rarity from the general card pool
const commons = generalCardPool.filter(card => card.rarity === 'common' && !card.type_line.toLowerCase().includes('battle'));
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon' && !card.type_line.toLowerCase().includes('battle'));
const rareOrMythics = generalCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity));
let boosterPack = [selectedLand];
addCardsToPack(commons, 2, boosterPack);
addCardsToPack(uncommons, 2, boosterPack);
boosterPack.push(getRandomCard(transformCards.filter(card => card.rarity === 'common' || card.rarity === 'uncommon'))); // 1 common or uncommon transform card
boosterPack.push(getRandomCard(battles.filter(card => card.rarity === 'uncommon'))); // 1 uncommon battle
// Add 2 cards of any rarity from various categories
for (let i = 0; i < 2; i++) {
const rand = Math.random();
if (rand < 0.25) {
boosterPack.push(getRandomCard(generalCardPool));
} else if (rand < 0.5) {
boosterPack.push(getRandomCard(commanderNew));
} else if (rand < 0.75) {
boosterPack.push(getRandomCard(showcaseMultiverse));
} else {
boosterPack.push(getRandomCard(jumpstartCards));
}
}
// Add 1 card of any rarity from specific categories
const randCard = Math.random();
if (randCard < 0.33) {
boosterPack.push(getRandomCard(generalCardPool));
} else if (randCard < 0.66) {
boosterPack.push(getRandomCard(showcaseMultiverse));
} else {
boosterPack.push(getRandomCard(foilEtchedMultiverse));
}
boosterPack.push(getRandomCard(showcaseMultiverse)); // 1 card of any rarity from the Multiverse Showcase
boosterPack.push(getRandomCard(rareOrMythics)); // 1 rare or mythic rare from the general card pool
// Display Pack in the console and on the screen
console.log('Generated MOM Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
// March of the Machine Collector Booster Pack
generateMOMCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
const fullArtLands = await fetchMOMFullArtLands();
const generalCardPool = await fetchMOMGeneralCardPool();
const showcaseMultiverse = await fetchMOMMultiverseLegendsShowcase();
const commanderExtended = await fetchMOMExtendedArtCommander();
const jumpstartCards = await fetchMOMJumpstartCards();
const borderlessPlaneswalkers = await fetchMOMBorderlessPlaneswalkers();
const foilEtchedMultiverse = await fetchMOMMultiverseLegendsFoilEtched();
const haloFoilMultiverse = await fetchMOMMultiverseLegendsHaloFoil();
const serializedPhyrexians = await fetchMOMSerializedPhyrexians();
const multiverseLegendsDoubleRainbowFoilSerialized = await fetchMOMMultiverseLegendsDoubleRainbowFoilSerialized();
// Helper function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add a number of cards to the booster pack
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
let boosterPack = [];
// Add 1 Full Art Land
boosterPack.push(getRandomCard(fullArtLands));
// Add 5 commons from the general card pool
const commons = generalCardPool.filter(card => card.rarity === 'common');
addCardsToPack(commons, 5, boosterPack);
// Add 2 uncommons from the general card pool
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
addCardsToPack(uncommons, 2, boosterPack);
// Add 1 uncommon from multiverse Showcase
const uncommonShowcase = showcaseMultiverse.filter(card => card.rarity === 'uncommon');
boosterPack.push(getRandomCard(uncommonShowcase));
// Add 1 rare or mythic rare from the general card pool
const raresAndMythics = generalCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(raresAndMythics));
// Add 1 card with specific probability
if (Math.random() < 0.5) {
boosterPack.push(getRandomCard(commanderExtended.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else {
boosterPack.push(getRandomCard(jumpstartCards.filter(card => card.rarity === 'rare')));
}
// Add 1 card with specific probability
const randCard1 = Math.random();
if (randCard1 < 0.45) {
boosterPack.push(getRandomCard(commanderExtended.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else if (randCard1 < 0.9) {
boosterPack.push(getRandomCard(showcaseMultiverse.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else {
boosterPack.push(getRandomCard(borderlessPlaneswalkers));
}
// Add 1 uncommon from the multiverse foil etched or halo foil category
const uncommonFoilEtchedOrHalo = [...foilEtchedMultiverse, ...haloFoilMultiverse].filter(card => card.rarity === 'uncommon');
boosterPack.push(getRandomCard(uncommonFoilEtchedOrHalo));
// Add 1 card with specific probability
const randCard2 = Math.random();
if (randCard2 < 0.45) {
boosterPack.push(getRandomCard(commanderExtended.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else if (randCard2 < 0.9) {
boosterPack.push(getRandomCard(showcaseMultiverse.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else if (randCard2 < 0.99) {
boosterPack.push(getRandomCard(borderlessPlaneswalkers.filter(card => card.rarity === 'mythic')));
} else {
boosterPack.push(getRandomCard(serializedPhyrexians));
}
// Add 1 card with specific probability
const randCard3 = Math.random();
if (randCard3 < 0.33) {
boosterPack.push(getRandomCard(showcaseMultiverse.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else if (randCard3 < 0.66) {
boosterPack.push(getRandomCard(foilEtchedMultiverse.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else if (randCard3 < 0.99) {
boosterPack.push(getRandomCard(haloFoilMultiverse.filter(card => ['rare', 'mythic'].includes(card.rarity))));
} else {
boosterPack.push(getRandomCard(multiverseLegendsDoubleRainbowFoilSerialized));
}
// Display Pack in the console and on the screen
console.log('Generated MOM Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
// Double Masters Draft Booster
generate2X2DraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Utility functions defined within the draft booster function
function getRandomCard(cardSet) {
const index = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(index, 1)[0]; // Remove the card from the array and return it
}
function addCardsToBoosterPack(cardSet, count, filterFunction = () => true) {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count && filteredCards.length > 0; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
}
// Fetching card pools
const generalCards = await fetch2X2GeneralCardPool();
const crypticSpires = await fetch2X2CrypticSpires();
const borderlessCards = await fetch2X2Borderless();
let boosterPack = [];
// Adding 1 Cryptic Spire
addCardsToBoosterPack(crypticSpires, 1);
// Adding commons from the general and borderless card pools
addCardsToBoosterPack(generalCards.filter(card => card.rarity === 'common'), 6);
addCardsToBoosterPack(borderlessCards.filter(card => card.rarity === 'common'), 2);
// Adding uncommons from the general and borderless card pools
addCardsToBoosterPack(generalCards.filter(card => card.rarity === 'uncommon'), 2);
addCardsToBoosterPack(borderlessCards.filter(card => card.rarity === 'uncommon'), 1);
// Adding 2 cards of any rarity from the general card pool, with a 1% chance each from the borderless card pool
addCardsToBoosterPack(generalCards, 2); // Adding any rarity cards from the general pool
for (let i = 0; i < 2; i++) { // Evaluate the 1% chance for each card independently
if (Math.random() < 0.01) {
addCardsToBoosterPack(borderlessCards, 1);
}
}
// Adding 2 rares or mythic rares, with a 6% chance each from the borderless card pool
for (let i = 0; i < 2; i++) { // Evaluate the 6% chance for each rare/mythic independently
if (Math.random() < 0.06) {
addCardsToBoosterPack(borderlessCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else {
addCardsToBoosterPack(generalCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
}
}
// Display the Pack
console.log('Generated 2X2 Draft Booster:', boosterPack);
displayPack(boosterPack); // Assuming displayPack is a function you've defined to show the pack
return boosterPack; // Return the booster pack
},
generate2X2CollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Utility functions defined within the collector booster function
function getRandomCard(cardSet) {
const index = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(index, 1)[0]; // Remove the card from the array and return it
}
function addRandomCards(cardSet, boosterPack, count) {
for (let i = 0; i < count; i++) {
if (cardSet.length > 0) {
boosterPack.push(getRandomCard(cardSet));
}
}
}
function addRandomCardWithChance(cardSet, boosterPack, chance, alternateSource) {
if (Math.random() < chance && alternateSource.length > 0) {
boosterPack.push(getRandomCard(alternateSource));
} else if (cardSet.length > 0) {
boosterPack.push(getRandomCard(cardSet));
}
}
// Fetching card pools
const generalCards = await fetch2X2GeneralCardPool();
const borderlessCards = await fetch2X2Borderless();
const etchedFoilCards = await fetch2X2EtchedFoil();
const texturedFoilCards = await fetch2X2TexturedFoil();
let boosterPack = [];
// 5 commons from general card pool
addRandomCards(generalCards.filter(card => card.rarity === 'common'), boosterPack, 5);
// 2 uncommons from general card pool
addRandomCards(generalCards.filter(card => card.rarity === 'uncommon'), boosterPack, 2);
// 4 commons or uncommons from borderless card pool
addRandomCards(borderlessCards.filter(card => card.rarity === 'common' || card.rarity === 'uncommon'), boosterPack, 4);
// 1 rare or mythic rare from general card pool
addRandomCards(generalCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), boosterPack, 1);
// 1 rare or mythic rare from borderless card pool
addRandomCards(borderlessCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), boosterPack, 1);
// 1 rare or mythic rare from foil etched card pool
addRandomCards(etchedFoilCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), boosterPack, 1);
// 1 rare or mythic rare from borderless card pool with a 3% chance for textured foil
addRandomCardWithChance(borderlessCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), boosterPack, 0.03, texturedFoilCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'));
// Display the Pack
console.log('Generated 2X2 Collector Booster:', boosterPack);
displayPack(boosterPack); // Assuming displayPack is a function you've defined to show the pack
return boosterPack; // Return the booster pack
},
// Outlaws of Thunder Junction OTJ
//OTJ Draft
generateOTJDraftBooster: async function() {
alert("Draft Boosters are not available for Outlaws of Thunder Junction");
},
//OTJ Set
generateOTJSetBooster: async function() {
alert("Set Boosters are not available for Outlaws of Thunder Junction");
},
// OTJ Play Booster
generateOTJPlayBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetching card pools
const regularCards = await fetchOTJRegularCards();
const wantedCards = await fetchOTJWantedCards();
const borderlessNormal = await fetchOTJBorderlessNormal();
const breakingNews = await fetchOTJBreakingNewsProsperityShowcase();
const specialGuest = await fetchOutlawsOfThunderJunctionSpecialGuest();
const bigScoreNormal = await fetchBigScoreNormal();
const bigScoreVaultFrames = await fetchBigScoreVaultFrames();
const bigScoreExtendedArt = await fetchBigScoreExtendedArt();
const basicLandsNormal = await fetchOTJBasicLandsNormal();
const extendedArtNormal = await fetchOTJExtendedArtNormal();
let boosterPack = [];
let hasSpecialOrBigScore = Math.random() < 0.2; // 20% chance for special guest or Big Score card
// Utility functions similar to the template
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, count, filterFunction = () => true) => {
const filteredCards = cardSet.filter(filterFunction);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredCards));
}
};
// Adding 6 commons by default
let commonCount = hasSpecialOrBigScore ? 5 : 6;
addCardsToBoosterPack(regularCards, commonCount, card => card.rarity === 'common');
// Adding 3 uncommons from the regular card category
addCardsToBoosterPack(regularCards, 3, card => card.rarity === 'uncommon');
// Adding Wild Card 1
const wildCard1Chance = Math.random();
if (wildCard1Chance < (1 / 12)) {
// 1/12 chance it is a rare or mythic rare
const rareMythicChoice = Math.random();
if (rareMythicChoice < 0.04) {
boosterPack.push(getRandomCard(borderlessNormal));
} else if (rareMythicChoice < 0.08) {
boosterPack.push(getRandomCard(wantedCards));
} else {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
} else {
// Otherwise, it's a common or uncommon from the general card pool
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'common' || card.rarity === 'uncommon');
}
// Adding one rare or mythic rare from the general card pool with a 2% chance it is from wanted or borderless normal
const rareMythicChance = Math.random();
if (rareMythicChance < 0.02) {
boosterPack.push(getRandomCard(wantedCards));
} else if (rareMythicChance < 0.04) {
boosterPack.push(getRandomCard(borderlessNormal));
} else {
addCardsToBoosterPack(regularCards, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// Adding a breaking news card with 66% chance for uncommon and 34% chance for rare or mythic
const breakingNewsCardRarityChance = Math.random();
if (breakingNewsCardRarityChance < 0.66) {
addCardsToBoosterPack(breakingNews, 1, card => card.rarity === 'uncommon');
} else {
addCardsToBoosterPack(breakingNews, 1, card => card.rarity === 'rare' || card.rarity === 'mythic');
}
// Adding Wild Card 2 with specified probabilities
const wildCard2Chance = Math.random();
if (wildCard2Chance < 0.77) {
boosterPack.push(getRandomCard(regularCards));
} else if (wildCard2Chance < 0.81) {
boosterPack.push(getRandomCard(wantedCards));
} else if (wildCard2Chance < 0.83) {
boosterPack.push(getRandomCard(borderlessNormal));
} else {
boosterPack.push(getRandomCard(breakingNews));
}
// Adding a land from basic lands normal, 17% chance from extended art normal
const landCard = Math.random() < 0.17 ? getRandomCard(extendedArtNormal) : getRandomCard(basicLandsNormal);
// Adding special guest or Big Score card at the end if applicable
if (hasSpecialOrBigScore) {
if (Math.random() < (1 / 13)) {
// 1/13 chance to be a special guest card
boosterPack.push(getRandomCard(specialGuest));
} else {
// Otherwise, it's a big score normal card
boosterPack.push(getRandomCard(bigScoreNormal));
}
}
boosterPack.push(landCard);
// Ensure the pack has 14 cards total
if (boosterPack.length < 14) {
addCardsToBoosterPack(regularCards, 14 - boosterPack.length);
}
// Display Pack
console.log('Generated OTJ Play Booster:', boosterPack);
displayPack(boosterPack); // Assuming displayPack is a function you have for showing the pack to the user
return boosterPack; // Return the booster pack
},
//OTJ Collector Booster
generateOTJCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetching card pools
const regularCards = await fetchOTJRegularCards();
const fullArtLands = await fetchOTJFullArtBasicLands();
const breakingNews = await fetchOTJBreakingNewsProsperityShowcase();
const wantedCards = await fetchOTJWantedCards();
const borderlessNormal = await fetchOTJBorderlessNormal();
const extendedArtNormal = await fetchOTJExtendedArtNormal();
const bigScoreNormal = await fetchBigScoreNormal();
const bigScoreVaultFrame = await fetchBigScoreVaultFrames();
const bigScoreExtendedArt = await fetchBigScoreExtendedArt();
const outlawsCommander = await fetchOutlawsOfThunderJunctionCommander();
const outlawsCommanderExtendedArt = await fetchOutlawsOfThunderJunctionCommanderExtendedArt();
const specialGuest = await fetchOutlawsOfThunderJunctionSpecialGuest();
const breakingNewsTexturedFoil = await fetchOTJBreakingNewsProsperityShowcaseTexturedFoil();
let boosterPack = [];
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Adding 4 commons from the regular card set
addCardsToPack(regularCards.filter(card => card.rarity === 'common'), 4);
// Adding 3 uncommons from the regular card set
addCardsToPack(regularCards.filter(card => card.rarity === 'uncommon'), 3);
// Adding 1 Full Art Land
addCardsToPack(fullArtLands, 1);
// Adding two uncommon breaking news prosperity showcase card
addCardsToPack(breakingNews.filter(card => card.rarity === 'uncommon'), 2);
// Adding one rare or mythic rare from the regular card set or BIG score normal
let rareMythicRegularOrBigScore = Math.random() < 0.5 ? regularCards : bigScoreNormal;
addCardsToPack(rareMythicRegularOrBigScore.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
// Adding one rare or mythic rare from the wanted cards, borderless normal, extended art normal, Big Score Vault Frame, Big score extended art
const rareMythicChoice = Math.random();
let rareMythicCategory;
if (rareMythicChoice < 0.25) {
rareMythicCategory = wantedCards;
} else if (rareMythicChoice < 0.5) {
rareMythicCategory = borderlessNormal;
} else if (rareMythicChoice < 0.75) {
rareMythicCategory = extendedArtNormal;
} else {
rareMythicCategory = Math.random() < 0.5 ? bigScoreVaultFrame : bigScoreExtendedArt;
}
addCardsToPack(rareMythicCategory.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
// Adding one rare or mythic rare from OTJ Commander or Commander Extended Art
let commanderCategory = Math.random() < 0.5 ? outlawsCommander : outlawsCommanderExtendedArt;
addCardsToPack(commanderCategory.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
// Adding one rare or mythic rare from breakingNewsProsperityShowcase
addCardsToPack(breakingNews.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
// Adding one rare or mythic rare with specified odds
const finalRareChoice = Math.random();
if (finalRareChoice < 0.44) {
addCardsToPack(extendedArtNormal.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else if (finalRareChoice < 0.73) {
addCardsToPack(breakingNews.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else if (finalRareChoice < 0.80) {
addCardsToPack(wantedCards.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else if (finalRareChoice < 0.86) {
addCardsToPack(bigScoreExtendedArt.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else if (finalRareChoice < 0.91) {
addCardsToPack(borderlessNormal.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else if (finalRareChoice < 0.95) {
addCardsToPack(specialGuest.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else if (finalRareChoice < 0.98) {
addCardsToPack(breakingNewsTexturedFoil.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
} else {
addCardsToPack(bigScoreVaultFrame.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
}
// Ensure the pack has 15 cards total
while (boosterPack.length < 15) {
boosterPack.push(getRandomCard(regularCards));
}
// Display Pack
console.log('Generated OTJ Collector Booster:', boosterPack);
displayPack(boosterPack); // Assuming `displayPack` is a function you've defined to show the pack
return boosterPack; // Return the booster pack
},
//Fallout PIP
generatePIPDraftBooster: async function() {
alert("Draft Boosters are not available for Fallout");
},
generatePIPSetBooster: async function() {
alert("Set Boosters are not available for Fallout");
},
generatePIPPlayBooster: async function() {
alert("Play Boosters are not available for Fallout");
},
generatePIPCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Initialize the display area for the pack
// Fetching cards from categories
const basicLands = await fetchPIPBasicLands();
const newCards = await fetchPIPNewCards();
const reprints = await fetchPIPReprints();
const extendedArtNew = await fetchPIPExtendedArtNew();
const extendedArtReprint = await fetchPIPExtendedArtReprint();
const surgefoilWildcard1 = await fetchPIPSurgefoilWildcard1();
const surgefoilWildcard2 = await fetchPIPSurgefoilWildcard2();
const showcase = await fetchPIPShowcase();
const borderlessVaultBoy = await fetchPIPBorderlessVaultBoy();
// Combining specific categories
const newAndReprints = newCards.concat(reprints);
const extendedArt = extendedArtNew.concat(extendedArtReprint);
const surgefoilWildcards = surgefoilWildcard1.concat(surgefoilWildcard2);
const showcaseAndBorderless = showcase.concat(borderlessVaultBoy);
const boosterPack = [];
// Function to get a random card from a set, removing it from the original array to simulate drawing
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Function to get a random rare or mythic from New Cards or Reprints
const getRareOrMythic = (cardSet) => {
const raresMythics = cardSet.filter(card => ['rare', 'mythic'].includes(card.rarity));
return getRandomCard(raresMythics);
};
// Populate pack according to Fallout Collector Booster requirements
boosterPack.push(getRandomCard(basicLands)); // 1 basic land
boosterPack.push(getRareOrMythic(newAndReprints)); // 1 rare or mythic from New Cards or Reprints
for (let i = 0; i < 4; i++) { // 4 random cards from New Cards or Reprints
boosterPack.push(getRandomCard(newAndReprints));
}
// Alternate between New Extended Art and Extended Art Reprint
for (let i = 0; i < 3; i++) {
boosterPack.push(getRandomCard(extendedArtNew));
boosterPack.push(getRandomCard(extendedArtReprint));
}
// 1 card from Surge Foil Category 1 or 2
boosterPack.push(getRandomCard(surgefoilWildcards));
// 2 cards from the Showcase or Borderless Vault Boy categories
for (let i = 0; i < 2; i++) {
boosterPack.push(getRandomCard(showcaseAndBorderless));
}
// Display or handle the pack as needed
console.log('Generated Fallout Collector Booster:', boosterPack);
displayPack(boosterPack); // Assuming `displayPack` is a function you've defined to show the pack
return boosterPack; // Return the booster pack
},
//Murders at Karlov Mannor MKM
generateMKMDraftBooster: async function() {
alert("Draft Boosters are not available for Murders at Karlov Manor");
},
generateMKMSetBooster: async function() {
alert("Set Boosters are not available for Murders at Karlov Manor");
},
generateMKMPlayBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetching card pools
const regularSetCards = await fetchMKMRegularSetCards();
const magnifiedShowcase = await fetchMKMMagnifiedShowcase();
const dossierShowcase = await fetchMKMDossierShowcase();
const invisibleInkShowcase = await fetchMKMInvisibleInkShowcase();
const ravnicaCityShowcase = await fetchMKMRavnicaCityShowcase();
const basicLands = await fetchMKMBasicLands();
const impossibleLands = await fetchMKMImpossibleLands();
const specialGuests = await fetchMKMSpecialGuests();
const borderlessPlaneswalker = await fetchMKMBorderlessPlaneswalker();
const borderlessDualLands = await fetchMKMBorderlessDualLands();
const extendedArt = await fetchMKMExtendedArt();
let boosterPack = [];
const dualLandCollectorNumbers = [259, 260, 262, 263, 264, 266, 268, 269, 270, 271];
const borderlessDualLandCollectorNumbers = [324, 325, 326, 327, 328, 329, 330, 331, 332, 333];
const serializedCollectorNumbers = ['317z', '318z', '319z', '320z', '321z', '322z', '323z'];
// Utility functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Adding commons
const hasSpecialGuest = Math.random() < 0.015;
let commonsPool = regularSetCards.filter(card => card.rarity === 'common');
if (Math.random() < 0.10) {
commonsPool = commonsPool.concat(magnifiedShowcase.filter(card => card.rarity === 'common'));
}
addCardsToPack(commonsPool, hasSpecialGuest ? 6 : 7);
// Adding uncommons
for (let i = 0; i < 3; i++) {
let uncommonPool = regularSetCards.filter(card => card.rarity === 'uncommon');
if (Math.random() < 0.10) {
uncommonPool = uncommonPool.concat(
magnifiedShowcase.filter(card => card.rarity === 'uncommon'),
dossierShowcase.filter(card => card.rarity === 'uncommon')
);
}
addCardsToPack(uncommonPool, 1);
}
// Adding rare/mythic rare
let rareMythicPool = regularSetCards.filter(card =>
(card.rarity === 'rare' || card.rarity === 'mythic') &&
!serializedCollectorNumbers.includes(card.collector_number)
);
if (Math.random() < 0.05) {
rareMythicPool = magnifiedShowcase.filter(card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (Math.random() < 0.05) {
rareMythicPool = dossierShowcase.filter(card => card.rarity === 'rare' || card.rarity === 'mythic');
} else if (Math.random() < 0.05) {
rareMythicPool = ravnicaCityShowcase.filter(card =>
(card.rarity === 'rare' || card.rarity === 'mythic') &&
!serializedCollectorNumbers.includes(card.collector_number)
);
} else if (Math.random() < 0.02) {
rareMythicPool = borderlessPlaneswalker;
}
boosterPack.push(getRandomCard(rareMythicPool));
// Adding Wildcard (with updated logic)
const addWildcard = () => {
let wildcard;
const dualLandsChance = Math.random();
if (dualLandsChance < 0.166) { // 1 in 6 chance for a dual land
const isRegularDualLand = dualLandsChance < (14.58 / 100); // 14.58% chance for regular dual land
const isBorderlessDualLand = dualLandsChance >= (14.58 / 100) && dualLandsChance < ((14.58 + 2.08) / 100); // 2.08% chance for borderless dual land
const dualLandPool = isRegularDualLand ? regularSetCards : isBorderlessDualLand ? borderlessDualLands : null;
const dualLandNumbers = isRegularDualLand
? dualLandCollectorNumbers
: isBorderlessDualLand
? borderlessDualLandCollectorNumbers
: [];
const filteredDualLands = dualLandPool ? dualLandPool.filter(card => dualLandNumbers.includes(card.collector_number)) : [];
wildcard = filteredDualLands.length > 0 ? getRandomCard(filteredDualLands) : getRandomCard(regularSetCards);
} else {
const otherCardCategories = [
{ category: regularSetCards, weight: 0.32 },
{ category: magnifiedShowcase.filter(card => !serializedCollectorNumbers.includes(card.collector_number)), weight: (1 - 0.166 - 0.32 - 0.03) / 3 },
{ category: dossierShowcase.filter(card => !serializedCollectorNumbers.includes(card.collector_number)), weight: (1 - 0.166 - 0.32 - 0.03) / 3 },
{ category: ravnicaCityShowcase.filter(card => !serializedCollectorNumbers.includes(card.collector_number)), weight: (1 - 0.166 - 0.32 - 0.03) / 3 },
{ category: borderlessPlaneswalker, weight: 0.03 }
];
const totalWeight = otherCardCategories.reduce((acc, curr) => acc + curr.weight, 0);
let randomWeight = Math.random() * totalWeight;
let selectedCategory = regularSetCards;
for (const category of otherCardCategories) {
if (randomWeight < category.weight) {
selectedCategory = category.category;
break;
}
randomWeight -= category.weight;
}
wildcard = getRandomCard(selectedCategory);
}
boosterPack.push(wildcard);
};
addWildcard();
// Adding basic/impossible land
boosterPack.push(Math.random() < 0.33 ? getRandomCard(impossibleLands) : getRandomCard(basicLands));
// Adding second wildcard (same logic as the first wildcard)
addWildcard();
// Adding Special Guest Card at the back if applicable
if (hasSpecialGuest) {
const specialGuestCard = getRandomCard(specialGuests);
boosterPack.push(specialGuestCard);
}
// Display Pack
console.log('Generated MKM Play Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack; // Return the booster pack
},
generateMKMCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetching card pools
const regularSetCards = await fetchMKMRegularSetCards();
const impossibleLands = await fetchMKMImpossibleLands();
const magnifiedShowcase = await fetchMKMMagnifiedShowcase();
const dossierShowcase = await fetchMKMDossierShowcase();
const ravnicaCityShowcase = await fetchMKMRavnicaCityShowcase();
const borderlessDualLands = await fetchMKMBorderlessDualLands();
const borderlessPlaneswalker = await fetchMKMBorderlessPlaneswalker();
const extendedArt = await fetchMKMExtendedArt();
const extendedArtCommander = await fetchMKMExtendedArtCommander();
const specialGuests = await fetchMKMSpecialGuests();
const invisibleInkShowcase = await fetchMKMInvisibleInkShowcase();
const serializedRavnicaCityShowcase = await fetchMKMSerializedRavnicaCityShowcase();
let boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
const selectedCard = cardSet.splice(idx, 1)[0];
console.log(`Selected card: ${selectedCard ? selectedCard.name : 'undefined'} with collector number ${selectedCard ? selectedCard.collector_number : 'undefined'}`);
return selectedCard;
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
const card = getRandomCard(cardSet);
if (card) {
boosterPack.push(card);
} else {
console.error('Failed to add a card to the pack. The selected card was undefined.');
}
}
};
// Adding 4 commons from general card pool
addCardsToPack(regularSetCards.filter(card => card.rarity === 'common'), 4);
// Adding 3 uncommons from general card pool
addCardsToPack(regularSetCards.filter(card => card.rarity === 'uncommon'), 3);
// Adding one impossible land
boosterPack.push(getRandomCard(impossibleLands));
// Adding two showcase magnified or dossier common/uncommon
for (let i = 0; i < 2; i++) {
const isUncommon = Math.random() < 0.38;
// If we need a common, we only pull from the magnifiedShowcase category
let showcasePool;
if (isUncommon) {
showcasePool = Math.random() < 0.5 ? magnifiedShowcase.filter(card => card.rarity === 'uncommon') : dossierShowcase.filter(card => card.rarity === 'uncommon');
} else {
showcasePool = magnifiedShowcase.filter(card => card.rarity === 'common');
}
addCardsToPack(showcasePool, 1);
}
// Adding one rare or mythic rare with specified odds
let rareOrMythic;
const rareChoice = Math.random();
if (rareChoice < 0.125) {
// 12.5% chance for a rare dual land
rareOrMythic = getRandomCard(borderlessDualLands.filter(card => card.rarity === 'rare'));
} else if (rareChoice < 0.25) {
// 12.5% chance for a traditional foil mythic rare from general card pool
rareOrMythic = getRandomCard(regularSetCards.filter(card => card.rarity === 'mythic' && card.finishes.includes('foil')));
} else {
// 75% chance for a rare from general card pool
rareOrMythic = getRandomCard(regularSetCards.filter(card => card.rarity === 'rare'));
}
boosterPack.push(rareOrMythic);
// Adding one extended art rare or mythic rare
addCardsToPack(extendedArt.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
// Adding one extended art rare or mythic rare from MKM Commander
addCardsToPack(extendedArtCommander.filter(card => card.rarity === 'rare' || card.rarity === 'mythic'), 1);
// Adding one rare or mythic rare with specified odds
let specialRareChoice = Math.random();
let specialRareCategory;
if (specialRareChoice < 0.20) {
specialRareCategory = magnifiedShowcase;
} else if (specialRareChoice < 0.26) {
specialRareCategory = ravnicaCityShowcase;
} else if (specialRareChoice < 0.70) {
specialRareCategory = dossierShowcase;
} else if (specialRareChoice < 0.98) {
specialRareCategory = borderlessDualLands;
} else {
specialRareCategory = borderlessPlaneswalker;
}
boosterPack.push(getRandomCard(specialRareCategory.filter(card => card.rarity === 'rare' || card.rarity === 'mythic')));
// Adding final rare or mythic rare with specified odds
let finalRareChoice = Math.random();
let finalRareCategory;
if (finalRareChoice < 0.0005) {
finalRareCategory = serializedRavnicaCityShowcase;
} else if (finalRareChoice < 0.085) {
finalRareCategory = invisibleInkShowcase;
} else if (finalRareChoice < 0.185) {
finalRareCategory = magnifiedShowcase;
} else if (finalRareChoice < 0.215) {
finalRareCategory = ravnicaCityShowcase;
} else if (finalRareChoice < 0.425) {
finalRareCategory = dossierShowcase;
} else if (finalRareChoice < 0.575) {
finalRareCategory = borderlessDualLands;
} else if (finalRareChoice < 0.585) {
finalRareCategory = borderlessPlaneswalker;
} else if (finalRareChoice < 0.615) {
finalRareCategory = specialGuests;
} else {
finalRareCategory = extendedArt;
}
boosterPack.push(getRandomCard(finalRareCategory.filter(card => card.rarity === 'rare' || card.rarity === 'mythic')));
// Display Pack
console.log('Generated MKM Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateCMMDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const setCode = 'CMM';
const allCards = await fetchCMMGeneralCardPool();
const basicLands = await fetchCMMBasicLandCardPool();
const borderlessCards = await fetchCMMBorderlessCards();
const texturedFoilsCards = await fetchCMMTexturedFoils();
const commons = allCards.filter(card => card.rarity === 'common' && !card.type_line.includes('Basic Land'));
const uncommons = allCards.filter(card => card.rarity === 'uncommon');
const rares = allCards.filter(card => card.rarity === 'rare');
const mythics = allCards.filter(card => card.rarity === 'mythic');
const legendaryUncommons = uncommons.filter(card => card.type_line.toLowerCase().includes('legendary'));
const legendaryRaresAndMythics = [...rares, ...mythics].filter(card => card.type_line.toLowerCase().includes('legendary'));
let boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRandomRareOrMythic = () => {
return Math.random() < 0.125 && mythics.length > 0 ? getRandomCard(mythics) : getRandomCard(rares);
};
const getRandomUncommonRareOrMythic = () => {
let cardPool = [...uncommons, ...rares, ...mythics];
return getRandomCard(cardPool);
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Populate pack
boosterPack.push(getRandomCard(basicLands));
addCardsToPack(commons, 11);
addCardsToPack(uncommons, 3);
addCardsToPack(legendaryUncommons, 2);
boosterPack.push(getRandomUncommonRareOrMythic()); // One Uncommon/Rare/Mythic
boosterPack.push(getRandomCard(allCards)); // One WildCard of any rarity
boosterPack.push(getRandomCard(legendaryRaresAndMythics)); // One Legendary Rare or Mythic
boosterPack.push(getRandomRareOrMythic());
// 1% chance for a bonus borderless mythic
if (Math.random() < 0.01) {
const borderlessMythic = borderlessCards.filter(card => card.rarity === 'mythic');
if (borderlessMythic.length) {
const commonIdx = pack.findIndex(card => card.rarity === 'common');
if (commonIdx !== -1) {
pack.splice(commonIdx, 1);
}
pack.push(getRandomCard(borderlessMythic));
}
}
// Display
console.log('Generated Commander Masters Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateCMMSetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const setCode = 'CMM';
const allCards = await fetchCMMGeneralCardPool();
const basicLands = await fetchCMMBasicLandCardPool();
const borderlessCards = await fetchCMMBorderlessCards();
const commons = allCards.filter(card => card.rarity === 'common' && !card.type_line.includes('Basic Land'));
const uncommons = allCards.filter(card => card.rarity === 'uncommon');
const rares = allCards.filter(card => card.rarity === 'rare');
const mythics = allCards.filter(card => card.rarity === 'mythic');
const legendaryUncommons = uncommons.filter(card => card.type_line.toLowerCase().includes('legendary'));
const legendaryRaresAndMythics = [...rares, ...mythics].filter(card => card.type_line.toLowerCase().includes('legendary'));
const borderlessCommonsUncommons = borderlessCards.filter(card => ['common', 'uncommon'].includes(card.rarity));
let boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRandomRareOrMythic = () => {
return Math.random() < 0.125 && mythics.length > 0 ? getRandomCard(mythics) : getRandomCard(rares);
};
const getRandomUncommonRareOrMythic = () => {
let cardPool = [...uncommons, ...rares, ...mythics];
return getRandomCard(cardPool);
};
const getRandomWildcard = () => {
const random = Math.random();
if (random < 0.125 && mythics.length > 0) {
return getRandomCard(mythics);
} else if (random < 0.625) { // Considering uncommons are roughly half the pool
return getRandomCard(uncommons);
} else {
return getRandomCard(rares);
}
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Populate pack
boosterPack.push(getRandomCard(basicLands));
addCardsToPack(commons, 4);
addCardsToPack(uncommons, 2);
boosterPack.push(getRandomCard(legendaryUncommons));
boosterPack.push(getRandomCard(borderlessCommonsUncommons));
boosterPack.push(getRandomUncommonRareOrMythic()); // One Uncommon/Rare/Mythic
for (let i = 0; i < 3; i++) {
boosterPack.push(getRandomWildcard()); // Three WildCards
}
boosterPack.push(getRandomRareOrMythic());
boosterPack.push(getRandomCard(legendaryRaresAndMythics));
// 1% chance for a bonus borderless mythic
if (Math.random() < 0.01) {
const borderlessMythic = borderlessCards.filter(card => card.rarity === 'mythic');
if (borderlessMythic.length) {
const commonIdx = boosterPack.findIndex(card => card.rarity === 'common');
if (commonIdx !== -1) {
boosterPack.splice(commonIdx, 1);
}
pboosterPackack.push(getRandomCard(borderlessMythic));
}
}
// Display
console.log('Generated Commander Masters Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateCMMCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const basicLands = await fetchCMMBasicLandCardPool();
const generalCardPool = await fetchCMMGeneralCardPool();
const borderlessCards = await fetchCMMBorderlessCards();
const etchedFoils = await fetchCMMEtchedFoils();
const commanderCards = await fetchCMMCommanderCards();
const texturedFoils = await fetchCMMTexturedFoils();
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
const borderlessCommonsUncommons = borderlessCards.filter(card => ['common', 'uncommon'].includes(card.rarity));
const borderlessRaresMythics = borderlessCards.filter(card => ['rare', 'mythic'].includes(card.rarity));
const commanderRaresMythics = commanderCards.filter(card => ['rare', 'mythic'].includes(card.rarity));
const etchedRaresMythics = etchedFoils.filter(card => ['rare', 'mythic'].includes(card.rarity));
const boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Populate pack
boosterPack.push(getRandomCard(basicLands));
for (let i = 0; i < 4; i++) boosterPack.push(getRandomCard(commons));
for (let i = 0; i < 2; i++) boosterPack.push(getRandomCard(uncommons));
for (let i = 0; i < 3; i++) boosterPack.push(getRandomCard(borderlessCommonsUncommons));
boosterPack.push(Math.random() < 0.125 && mythics.length ? getRandomCard(mythics) : getRandomCard(rares));
boosterPack.push(getRandomCard(etchedRaresMythics));
boosterPack.push(getRandomCard(commanderRaresMythics));
boosterPack.push(getRandomCard(borderlessRaresMythics));
// 4% chance for a textured foil
if (Math.random() < 0.04) {
boosterPack.push(getRandomCard(texturedFoils));
} else {
boosterPack.push(Math.random() < 0.125 && mythics.length ? getRandomCard(mythics) : getRandomCard(rares));
}
// Display
console.log('Generated Commander Masters Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
// Dr. Who Collector Booster Pack
generateWHOCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
const basicLands = await fetchWHOBasicLands();
const doctors = await fetchRandomDoctor();
const generalCards = await fetchWHOGeneralCardSet();
const reprints = await fetchWHOReprints();
const extendedArtNew = await fetchWHOExtendedArtNew();
const extendedArtOld = await fetchWHOExtendedArtOld();
const surgeFoils = await fetchWHOSurgeFoil();
const tardisCards = await fetchWHOTardisShowcase();
const boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
boosterPack.push(getRandomCard(basicLands));
boosterPack.push(getRandomCard(doctors));
for (let i = 0; i < 4; i++) {
boosterPack.push(Math.random() < 0.5 ? getRandomCard(generalCards) : getRandomCard(reprints));
}
boosterPack.push(getRandomCard(extendedArtNew));
boosterPack.push(getRandomCard(extendedArtNew));
boosterPack.push(getRandomCard(extendedArtOld));
boosterPack.push(getRandomCard(extendedArtOld));
boosterPack.push(getRandomCard(extendedArtNew));
boosterPack.push(getRandomCard(extendedArtOld));
boosterPack.push(getRandomCard(surgeFoils));
boosterPack.push(getRandomCard(tardisCards));
boosterPack.push(getRandomCard(tardisCards));
console.log('Generated WHO Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateWHOSetBooster: async function() {
alert("Set Boosters are not available for Dr. Who.");
},
generateWHODraftBooster: async function() {
alert("Draft Boosters are not available for Dr. Who.");
},
// Baldur's Gate Packs
generateCLBDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const setCode = 'CLB';
const allCards = await fetchCLBRegularSetCards();
const commons = allCards.filter(card => card.rarity === 'common' && !card.type_line.includes('Basic Land'));
const uncommons = allCards.filter(card => card.rarity === 'uncommon');
const rares = allCards.filter(card => card.rarity === 'rare');
const mythics = allCards.filter(card => card.rarity === 'mythic');
const legendaryBackgrounds = allCards.filter(card => card.type_line === 'Legendary Enchantment — Background' && card.rarity !== 'mythic');
const legendaryCreatures = allCards.filter(card => card.type_line.toLowerCase().includes('legendary') && card.type_line.toLowerCase().includes('creature'));
let boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRandomRareOrMythic = () => {
return Math.random() < 0.125 && mythics.length > 0 ? getRandomCard(mythics) : getRandomCard(rares);
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Populate pack
addCardsToPack(commons, 13);
addCardsToPack(uncommons, 3);
boosterPack.push(getRandomCard(allCards)); // One WildCard of any rarity
boosterPack.push(getRandomCard(legendaryBackgrounds)); // One Legendary Background
if (Math.random() < 0.31) {
let legendCreaturesRareMythic = legendaryCreatures.filter(card => card.rarity === 'rare' || card.rarity === 'mythic');
boosterPack.push(getRandomCard(legendCreaturesRareMythic));
} else {
let legendCreaturesUncommon = legendaryCreatures.filter(card => card.rarity === 'uncommon');
boosterPack.push(getRandomCard(legendCreaturesUncommon));
}
boosterPack.push(getRandomRareOrMythic());
// Display
console.log('Generated Commander Legends: Battle for Baldurs Gate Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack; // Return the booster pack
},
generateCLBSetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
const allCards = await fetchCLBRegularSetCards();
const basicLands = await fetchCLBBasicLands();
const showcaseCards = await fetchCLBShowcase();
const foilEtchedCards = await fetchCLBFoilEtched();
const commons = allCards.filter(card => card.rarity === 'common' && !card.type_line.includes('Basic Land'));
const uncommons = allCards.filter(card => card.rarity === 'uncommon');
const rares = allCards.filter(card => card.rarity === 'rare');
const mythics = allCards.filter(card => card.rarity === 'mythic');
const legendaryBackground = allCards.filter(card => card.type_line.toLowerCase().includes('legendary') && card.rarity !== 'mythic');
const legendaryUncommons = uncommons.filter(card => card.type_line.toLowerCase().includes('legendary'));
const legendaryRaresAndMythics = [...rares, ...mythics].filter(card => card.type_line.toLowerCase().includes('legendary'));
const legendaryAll = [...legendaryUncommons, ...legendaryRaresAndMythics];
let boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRandomRareOrMythic = () => {
return Math.random() < 0.125 && mythics.length > 0 ? getRandomCard(mythics) : getRandomCard(rares);
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Populate pack
boosterPack.push(getRandomCard(basicLands));
addCardsToPack(commons, 3);
addCardsToPack(uncommons, 3);
// Any rarity cards
let anyRarityPool = [...commons, ...uncommons, ...rares, ...mythics];
boosterPack.push(getRandomCard(anyRarityPool));
boosterPack.push(getRandomCard(anyRarityPool));
// Showcase card
const showcaseCommonsUncommons = showcaseCards.filter(card => ['common', 'uncommon'].includes(card.rarity));
boosterPack.push(getRandomCard(showcaseCommonsUncommons));
// Legendary background
if (Math.random() < 1/12) {
boosterPack.push(getRandomCard(legendaryBackground));
} else {
let legendaryAnyPool = [...legendaryUncommons, ...legendaryRaresAndMythics];
boosterPack.push(getRandomCard(legendaryAnyPool));
}
// Legendary rarity-based card
if (Math.random() < 0.5) {
boosterPack.push(getRandomCard(legendaryRaresAndMythics));
} else {
boosterPack.push(getRandomCard(legendaryUncommons));
}
// Rare or Mythic
boosterPack.push(getRandomRareOrMythic());
// Foil etched card
if (Math.random() < 1/3) {
const foilEtchedRaresAndMythics = foilEtchedCards.filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(foilEtchedRaresAndMythics));
} else {
const foilEtchedOthers = foilEtchedCards.filter(card => !['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(foilEtchedOthers));
}
// Display
console.log('Generated Baldurs Gate Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateCLBCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
const allCards = await fetchCLBRegularSetCards();
const basicLands = await fetchCLBBasicLands();
const showcaseCards = await fetchCLBShowcase();
const borderlessCards = await fetchCLBBorderless();
const foilEtchedCards = await fetchCLBFoilEtched();
const extendedArtCards = await fetchCLBExtendedArt();
const commanderExtendedArtCards = await fetchCLBCommanderExtendedArt();
const commons = allCards.filter(card => card.rarity === 'common' && !card.type_line.includes('Basic Land'));
const uncommons = allCards.filter(card => card.rarity === 'uncommon');
const rares = allCards.filter(card => card.rarity === 'rare');
const mythics = allCards.filter(card => card.rarity === 'mythic');
const legendaryCommons = commons.filter(card => card.type_line.toLowerCase().includes('legendary'));
const legendaryUncommons = uncommons.filter(card => card.type_line.toLowerCase().includes('legendary'));
let boosterPack = [];
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRandomRareOrMythic = () => {
return Math.random() < 0.125 && mythics.length > 0 ? getRandomCard(mythics) : getRandomCard(rares);
};
const addCardsToPack = (cardSet, count) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Populate pack
boosterPack.push(getRandomCard(basicLands));
addCardsToPack(commons, 3);
addCardsToPack(uncommons, 2);
// Showcase common or uncommon
const showcaseCommonsUncommons = showcaseCards.filter(card => ['common', 'uncommon'].includes(card.rarity));
boosterPack.push(getRandomCard(showcaseCommonsUncommons));
// Legendary common or uncommon
const legendaryCommonsUncommonsPool = [...legendaryCommons, ...legendaryUncommons];
boosterPack.push(getRandomCard(legendaryCommonsUncommonsPool));
// Rare or Mythic
boosterPack.push(getRandomRareOrMythic());
// Extended Art Commander Rare or Mythic Rare
const extendedArtCommanderRaresAndMythics = commanderExtendedArtCards.filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(extendedArtCommanderRaresAndMythics));
// Extended Art Rare or Mythic
const extendedArtRaresAndMythics = extendedArtCards.filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(extendedArtRaresAndMythics));
// Showcase or Borderless Rare or Mythic
const showcaseBorderlessRaresAndMythics = [...showcaseCards, ...borderlessCards].filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(showcaseBorderlessRaresAndMythics));
// Foil Etched Rare or Mythic
const foilEtchedRaresAndMythics = foilEtchedCards.filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(foilEtchedRaresAndMythics));
// Foil Etched Legendary Common or Uncommon
const foilEtchedLegendaryCommonsUncommons = foilEtchedCards.filter(card => ['common', 'uncommon'].includes(card.rarity) && card.type_line.toLowerCase().includes('legendary'));
boosterPack.push(getRandomCard(foilEtchedLegendaryCommonsUncommons));
// Showcase, Borderless, or Extended-Art Rare or Mythic
const showcaseBorderlessExtendedArtRaresAndMythics = [...showcaseCards, ...borderlessCards, ...extendedArtCards].filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(showcaseBorderlessExtendedArtRaresAndMythics));
// Display
console.log('Generated CLB Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
//Ravnica Remastered Boosters
// Ravnica Remastered Draft Boosters
generateRVRDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetch card pools
const generalCardPool = await fetchRVRGeneralSetCards();
const retroFramePool = await fetchRVRRetroFrame();
const borderlessAnimePool = await fetchRVRBorderlessAnime();
const borderlessAnimeRaresMythics = borderlessAnimePool.filter(card => ['rare', 'mythic'].includes(card.rarity));
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Fetch cards by rarity
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
let boosterPack = [];
const retroCard = getRandomCard(retroFramePool);
const retroCardRarity = retroCard.rarity;
// Add cards based on the rarity of the retro card
if (retroCardRarity === 'common') {
addCardsToPack(commons, 9, boosterPack);
boosterPack.push(retroCard); // Add Retro common
addCardsToPack(uncommons, 3, boosterPack);
} else if (retroCardRarity === 'uncommon') {
addCardsToPack(commons, 8, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
boosterPack.push(retroCard); // Add Retro uncommon
} else { // 'rare' or 'mythic'
addCardsToPack(commons, 10, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
}
// Add Mana Slot Card
const manaSlotCard = await this.fetchManaSlotCard();
boosterPack.push(manaSlotCard);
// Add a rare or mythic, or retro rare/mythic
if (retroCardRarity !== 'rare' && retroCardRarity !== 'mythic') {
const rareOrMythicCard = Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares);
boosterPack.push(rareOrMythicCard);
} else {
boosterPack.push(retroCard); // Add Retro rare/mythic if retro card is rare/mythic
}
// Display Pack
console.log('Generated RVR Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
fetchManaSlotCard: async function() {
// Logic for fetching Mana Slot Card
const randomPercentage = Math.random() * 100;
if (randomPercentage < 58) {
// Fetch a Guildgate
return await this.fetchGuildgate();
} else if (randomPercentage < 91) {
// Fetch a Signet
return await this.fetchSignet();
} else {
// Fetch Chromatic Lantern or a Shock Land
return await this.fetchChromaticLanternOrShockLand();
}
},
fetchGuildgate: async function() {
const guildgateNumbers = [272, 274, 276, 278, 279, 281, 282, 284, 286, 287];
const randomIndex = Math.floor(Math.random() * guildgateNumbers.length);
return await fetchSpecificCard('RVR', guildgateNumbers[randomIndex]);
},
fetchSignet: async function() {
const signetNumbers = [250, 251, 256, 258, 259, 261, 263, 265, 267, 269];
const randomIndex = Math.floor(Math.random() * signetNumbers.length);
return await fetchSpecificCard('RVR', signetNumbers[randomIndex]);
},
fetchChromaticLanternOrShockLand: async function() {
const chromaticLanternAndShockLandNumbers = [253, 273, 275, 277, 279, 283, 285, 288, 289, 290, 291];
const randomIndex = Math.floor(Math.random() * chromaticLanternAndShockLandNumbers.length);
return await fetchSpecificCard('RVR', chromaticLanternAndShockLandNumbers[randomIndex]);
},
// Ravnica Remastered Set Boosters
generateRVRSetBooster: async function() {
alert("Set Boosters are not available for Ravnica Remastered");
},
// Ravnica Remastered Collector Boosters
generateRVRCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetch card pools
const generalCardPool = await fetchRVRGeneralSetCards();
const retroFramePool = await fetchRVRRetroFrame();
const borderlessShockLandsPool = await fetchRVRBorderlessShocklands(); // Assumed function
const borderlessAnimePool = await fetchRVRBorderlessAnime();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack, rarityFilter = null) => {
const filteredSet = rarityFilter ? cardSet.filter(card => rarityFilter.includes(card.rarity)) : cardSet;
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredSet));
}
};
let boosterPack = [];
// Add 4 commons
addCardsToPack(generalCardPool, 4, boosterPack, ['common']);
// Add 3 uncommons
addCardsToPack(generalCardPool, 3, boosterPack, ['uncommon']);
// Add Mana Slot Card
const manaSlotCard = await this.fetchManaSlotCard();
boosterPack.push(manaSlotCard);
// Add 3 common or uncommon retro cards
addCardsToPack(retroFramePool, 3, boosterPack, ['common', 'uncommon']);
// Add 1 rare or mythic rare
addCardsToPack(generalCardPool, 1, boosterPack, ['rare', 'mythic']);
// Add 1 retro rare or mythic rare
addCardsToPack(retroFramePool, 1, boosterPack, ['rare', 'mythic']);
// Add 1 card from the borderlessShockLands or borderlessAnime category
const specialCardPool = [...borderlessShockLandsPool, ...borderlessAnimePool];
boosterPack.push(getRandomCard(specialCardPool));
// Add 1 rare or mythic from the retro, borderlessShockLands, or borderlessAnime Category
if (Math.random() < 0.5) {
// 50% chance for a retro frame rare
addCardsToPack(retroFramePool, 1, boosterPack, ['rare', 'mythic']);
} else {
// Otherwise, from either borderlessShockLands or borderlessAnime
boosterPack.push(getRandomCard([...borderlessShockLandsPool, ...borderlessAnimePool].filter(card => ['rare', 'mythic'].includes(card.rarity))));
}
// Display Pack
console.log('Generated RVR Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
//Dominara Remastered Boosters
generateDMRDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
const basicLandCards = await fetchDMRBasicLandCardPool();
const generalCardPool = await fetchDMRGeneralCardPool();
const alternateArtBorderless = await fetchDMRAlternateArtBorderless();
const oldFramePool = await fetchDMROldFramePool();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a random land
const selectedLand = getRandomCard(basicLandCards);
// Fetch cards by rarity
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
// Define other rarities
const oldFrameCommons = oldFramePool.filter(card => card.rarity === 'common');
const oldFrameUncommons = oldFramePool.filter(card => card.rarity === 'uncommon');
const oldFrameRaresAndMythics = oldFramePool.filter(card => ['rare', 'mythic'].includes(card.rarity));
const alternateArtRaresAndMythics = alternateArtBorderless.filter(card => ['rare', 'mythic'].includes(card.rarity));
// Decide the rare or mythic
const randomPool = [...rares, ...mythics, ...oldFrameRaresAndMythics, ...alternateArtRaresAndMythics];
const rareOrMythic = Math.random() < (1/8) ? mythics.splice(Math.floor(Math.random() * mythics.length), 1)[0] : getRandomCard(randomPool);
let boosterPack = [selectedLand];
addCardsToPack(commons, 9, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
// Replace an uncommon with a borderless common in 6% of the packs
if (Math.random() < 0.06) {
const borderlessCommon = getRandomCard(alternateArtBorderless.filter(card => card.rarity === 'common'));
boosterPack.splice(12, 1); // Remove one uncommon
boosterPack.push(borderlessCommon);
}
// Add common from general card pool or common/uncommon from old frame pool
const randomCommonChoice = Math.random() < 0.5 ? commons : [...oldFrameCommons, ...oldFrameUncommons];
boosterPack.push(getRandomCard(randomCommonChoice));
boosterPack.push(rareOrMythic);
// 33% chance to replace a common with a traditional foil card
if (Math.random() < 0.33) {
const randomFoil = Math.random() < 0.5 ? getRandomCard(generalCardPool) : getRandomCard(oldFramePool);
boosterPack.splice(2, 1); // Remove one common
boosterPack.push(randomFoil);
}
// Display Pack
console.log('Generated DMR Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateDMRSetBooster: async function() {
alert("Set Boosters are not available for Dominaria Remastered.");
},
generateDMRCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const basicLandCardPool = await fetchDMRBasicLandCardPool();
const generalCardPool = await fetchDMRGeneralCardPool();
const altArtBorderless = await fetchDMRAlternateArtBorderless();
const oldFrameCardPool = await fetchDMROldFramePool();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToBoosterPack = (cardSet, rarity, count, boosterPack) => {
const filteredSet = cardSet.filter(card => card.rarity === rarity);
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(filteredSet));
}
};
// Select a random land
const selectedLand = getRandomCard(basicLandCardPool);
// Fetch cards by rarity from the general card pool
const rareOrMythicGeneral = Math.random() < (1/8) ? 'mythic' : 'rare';
let boosterPack = [selectedLand];
addCardsToBoosterPack(generalCardPool, 'common', 5, boosterPack);
addCardsToBoosterPack(generalCardPool, 'uncommon', 2, boosterPack);
addCardsToBoosterPack(generalCardPool, rareOrMythicGeneral, 1, boosterPack);
// 2 common or uncommon from old frame pool
addCardsToBoosterPack(oldFrameCardPool, 'common', 1, boosterPack);
addCardsToBoosterPack(oldFrameCardPool, 'uncommon', 1, boosterPack);
// 1 common or uncommon from the old frame pool OR Alternate Art Borderless
const ninthCardPool = oldFrameCardPool.concat(altArtBorderless);
const ninthCard = getRandomCard(ninthCardPool.filter(card => ['common', 'uncommon'].includes(card.rarity)));
boosterPack.push(ninthCard);
// 1 rare or mythic from old frame pool
boosterPack.push(getRandomCard(oldFrameCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity))));
// 1 rare or mythic from alternate art borderless
boosterPack.push(getRandomCard(altArtBorderless.filter(card => ['rare', 'mythic'].includes(card.rarity))));
// 1 rare or mythic from old frame pool or Alternate Art Borderless
const eleventhCardPool = oldFrameCardPool.concat(altArtBorderless);
boosterPack.push(getRandomCard(eleventhCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity))));
// Display Pack
console.log('Generated DMR Collector Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
// Kamigawa: Neon Dynasty
generateNEODraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
const basicLands = await fetchNEOBasicLands();
const ukiyoeLands = await fetchNEOUkiyoeLands();
const generalCardPool = await fetchNEOGeneralCardPool();
// Helper function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add a number of cards to the booster pack
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
boosterPack.push(getRandomCard(cardSet));
}
};
// Filter out digital cards
const filterDigital = (cardSet) => cardSet.filter(card => !card.digital);
// Apply digital filter to the card pools
const filteredBasicLands = filterDigital(basicLands);
const filteredUkiyoeLands = filterDigital(ukiyoeLands);
const filteredGeneralCardPool = filterDigital(generalCardPool);
// Select a random land, with 33% chance of being UkiyoE Land
const selectedLand = Math.random() < 0.33 ? getRandomCard(filteredUkiyoeLands) : getRandomCard(filteredBasicLands);
// Filter cards by rarity from the filtered general card pool
const commons = filteredGeneralCardPool.filter(card => card.rarity === 'common');
const uncommons = filteredGeneralCardPool.filter(card => card.rarity === 'uncommon');
const raresAndMythics = filteredGeneralCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity));
// Setup initial pack with the selected land
let boosterPack = [selectedLand];
// Decide the rare or mythic
const rareOrMythic = Math.random() < (1/8) ? getRandomCard(raresAndMythics.filter(card => card.rarity === 'mythic')) : getRandomCard(raresAndMythics.filter(card => card.rarity === 'rare'));
// Add 9 commons to the pack
if (Math.random() < 0.33) {
// Add one less common and reserve space for a random card of any rarity
addCardsToPack(commons, 8, boosterPack);
} else {
// Regular scenario without replacement
addCardsToPack(commons, 9, boosterPack);
}
// Add 3 uncommons to the pack
addCardsToPack(uncommons, 3, boosterPack);
// Add 1 common or uncommon to the pack
boosterPack.push(Math.random() < 0.5 ? getRandomCard(commons) : getRandomCard(uncommons));
// Add the rare or mythic rare to the pack
boosterPack.push(rareOrMythic);
// If the 33% chance occurred, add one random card of any rarity to the back of the pack
if (boosterPack.length == 14) { // This checks if only 8 commons were added
boosterPack.push(getRandomCard(filteredGeneralCardPool)); // Adds a random card from the general pool
}
// Display Pack in the console and on the screen
console.log('Generated NEO Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateNEOSetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
// Fetching the card pools
const basicLands = await fetchNEOBasicLands();
const ukiyoeLands = await fetchNEOUkiyoeLands();
const generalCardPool = await fetchNEOGeneralCardPool();
const samurai = await fetchNEOSamurai();
const ninja = await fetchNEONinja();
const softGlow = await fetchNEOSoftGlow();
const altArtBorderless = await fetchNEOAltArtBorderless();
const borderlessPlaneswalkers = await fetchNEOBorderlessPlaneswalkers();
const extendedArt = await fetchNEOExtendedArt();
// Helper function to filter out digital cards
const filterDigital = (cardSet) => cardSet.filter(card => !card.digital);
// Apply digital filter to the card pools
const filteredBasicLands = filterDigital(basicLands);
const filteredUkiyoeLands = filterDigital(ukiyoeLands);
const filteredGeneralCardPool = filterDigital(generalCardPool);
const filteredSamurai = filterDigital(samurai);
const filteredNinja = filterDigital(ninja);
const filteredSoftGlow = filterDigital(softGlow);
const filteredAltArtBorderless = filterDigital(altArtBorderless);
const filteredBorderlessPlaneswalkers = filterDigital(borderlessPlaneswalkers);
const filteredExtendedArt = filterDigital(extendedArt);
// Helper functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRandomCards = (cardSet, count) => {
return Array.from({length: count}, () => getRandomCard(cardSet));
};
const getWeightedRandomCard = (weightedCards) => {
const totalWeight = weightedCards.reduce((total, wc) => total + wc.weight, 0);
let random = Math.random() * totalWeight;
for (const wc of weightedCards) {
if (random < wc.weight) {
return getRandomCard(wc.cards);
}
random -= wc.weight;
}
};
const boosterPack = [];
// Land selection
boosterPack.push(Math.random() < 0.33 ? getRandomCard(filteredUkiyoeLands) : getRandomCard(filteredBasicLands));
// Add commons and uncommons
const commons = filteredGeneralCardPool.filter(card => card.rarity === 'common');
const uncommons = filteredGeneralCardPool.filter(card => card.rarity === 'uncommon');
boosterPack.push(...getRandomCards(commons, 3)); // 3 commons
boosterPack.push(...getRandomCards(uncommons, 2)); // 2 uncommons
boosterPack.push(Math.random() < 0.5 ? getRandomCard(commons) : getRandomCard(uncommons)); // 1 common or uncommon
// 1 common or uncommon samurai or ninja
const samuraiAndNinjaCommonUncommon = [...filteredSamurai, ...filteredNinja].filter(card => ['common', 'uncommon'].includes(card.rarity));
boosterPack.push(getRandomCard(samuraiAndNinjaCommonUncommon));
// 2 cards of any rarity with specific odds
for (let i = 0; i < 2; i++) {
boosterPack.push(getWeightedRandomCard([
{ cards: filteredGeneralCardPool.filter(card => ['common', 'uncommon'].includes(card.rarity)), weight: 86 },
{ cards: filteredUkiyoeLands, weight: 9 },
{ cards: [...filteredSamurai, ...filteredNinja, ...filteredSoftGlow, ...filteredAltArtBorderless, ...filteredBorderlessPlaneswalkers].filter(card => ['rare', 'mythic'].includes(card.rarity)), weight: 5 }
]));
}
// 1 rare or mythic rare
const raresAndMythics = [...filteredGeneralCardPool, ...filteredSamurai, ...filteredNinja, ...filteredSoftGlow, ...filteredAltArtBorderless, ...filteredBorderlessPlaneswalkers].filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(Math.random() < 0.10 ? getRandomCard(raresAndMythics) : getRandomCard(filteredGeneralCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity))));
// 1 card of any rarity
boosterPack.push(getWeightedRandomCard([
{ cards: filteredGeneralCardPool.filter(card => ['common', 'uncommon'].includes(card.rarity)), weight: 95 },
{ cards: [...filteredSamurai, ...filteredNinja, ...filteredSoftGlow, ...filteredAltArtBorderless, ...filteredBorderlessPlaneswalkers].filter(card => card.rarity === 'rare'), weight: 5 }
]));
// Display Pack in the console and on the screen
console.log('Generated NEO Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateNEOCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
// Fetching the card pools
const ukiyoeLands = await fetchNEOUkiyoeLands();
const generalCardPool = await fetchNEOGeneralCardPool();
const samurai = await fetchNEOSamurai();
const ninja = await fetchNEONinja();
const softGlow = await fetchNEOSoftGlow();
const extendedArt = await fetchNEOExtendedArt();
const borderlessPlaneswalkers = await fetchNEOBorderlessPlaneswalkers();
const altArtBorderless = await fetchNEOAltArtBorderless();
const commanderExtendedArt = await fetchNEOExtendedArtCommander();
const phyrexian = await fetchNEOPhyrexian();
const neonInk = await fetchNEONeonInk();
const etchedFoil = await fetchNEOEtchedFoil();
// Helper function to apply digital filter to a card set
const filterOutDigital = (cardSet) => cardSet.filter(card => !card.digital);
// Apply the filter to all card pools
const filteredUkiyoeLands = filterOutDigital(ukiyoeLands);
const filteredGeneralCardPool = filterOutDigital(generalCardPool);
const filteredSamurai = filterOutDigital(samurai);
const filteredNinja = filterOutDigital(ninja);
const filteredSoftGlow = filterOutDigital(softGlow);
const filteredExtendedArt = filterOutDigital(extendedArt);
const filteredBorderlessPlaneswalkers = filterOutDigital(borderlessPlaneswalkers);
const filteredAltArtBorderless = filterOutDigital(altArtBorderless);
const filteredCommanderExtendedArt = filterOutDigital(commanderExtendedArt);
const filteredPhyrexian = filterOutDigital(phyrexian);
const filteredNeonInk = filterOutDigital(neonInk);
const filteredEtchedFoil = filterOutDigital(etchedFoil);
// Helper function to get a random card from a card set
const getRandomCard = (cardSet) => {
if (!cardSet || (Array.isArray(cardSet) && cardSet.length === 0)) {
console.error('Invalid cardSet:', cardSet);
return null;
}
if (Array.isArray(cardSet)) {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
} else {
return cardSet; // Return the single card if not an array
}
};
const getRandomCards = (cardSet, count) => {
return Array.from({length: count}, () => getRandomCard(cardSet));
};
const collectorBoosterPack = [];
collectorBoosterPack.push(getRandomCard(filteredUkiyoeLands));
collectorBoosterPack.push(...getRandomCards(filteredGeneralCardPool.filter(card => card.rarity === 'common'), 2));
collectorBoosterPack.push(...getRandomCards(filteredGeneralCardPool.filter(card => card.rarity === 'uncommon'), 2));
collectorBoosterPack.push(getRandomCard(filteredGeneralCardPool.filter(card => ['common', 'uncommon'].includes(card.rarity))));
collectorBoosterPack.push(...getRandomCards(filteredSamurai.filter(card => ['common', 'uncommon'].includes(card.rarity)), 2));
collectorBoosterPack.push(...getRandomCards(filteredNinja.filter(card => ['common', 'uncommon'].includes(card.rarity)), 2));
collectorBoosterPack.push(getRandomCard(filteredGeneralCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity)).find(card => Math.random() < 0.15 ? card.rarity === 'mythic' : card.rarity === 'rare')));
collectorBoosterPack.push(getRandomCard(filteredCommanderExtendedArt.filter(card => ['rare', 'mythic'].includes(card.rarity)).find(card => Math.random() < 0.15 ? card.rarity === 'mythic' : card.rarity === 'rare')));
collectorBoosterPack.push(getRandomCard([...filteredExtendedArt, ...filteredBorderlessPlaneswalkers, ...filteredAltArtBorderless].filter(card => ['rare', 'mythic'].includes(card.rarity))));
collectorBoosterPack.push(getRandomCard([...filteredNinja, ...filteredSamurai, ...filteredSoftGlow, ...filteredBorderlessPlaneswalkers, ...filteredAltArtBorderless, ...filteredPhyrexian].filter(card => ['rare', 'mythic'].includes(card.rarity))));
if (Math.random() < 0.01) {
collectorBoosterPack.push(getRandomCard(filteredNeonInk));
} else if (Math.random() < 0.01) {
collectorBoosterPack.push(getRandomCard(filteredEtchedFoil));
} else {
collectorBoosterPack.push(getRandomCard([...filteredNinja, ...filteredSamurai, ...filteredSoftGlow, ...filteredBorderlessPlaneswalkers, ...filteredAltArtBorderless, ...filteredPhyrexian].filter(card => ['rare', 'mythic'].includes(card.rarity))));
}
console.log('Generated NEO Collector Booster:', collectorBoosterPack);
displayPack(collectorBoosterPack);
return collectorBoosterPack;
},
// Lost Caverns of Ixalan
generateLCIDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display area is prepared for showing the pack
const fullArtLands = await fetchLCIFullArtLands();
const generalCardPool = await fetchLCIGeneral();
// Helper function to get a random card from a set
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add a number of cards to the booster pack
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a random land
const selectedLand = Math.random() < 0.3 ? getRandomCard(fullArtLands) : getRandomCard(generalCardPool.filter(card => card.type_line === "Land — Cave"));
// Filter cards by rarity from the general card pool
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const raresAndMythics = generalCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity));
// Decide the rare or mythic
const rareOrMythic = Math.random() < (1/8) ? getRandomCard(raresAndMythics.filter(card => card.rarity === 'mythic')) : getRandomCard(raresAndMythics.filter(card => card.rarity === 'rare'));
let boosterPack = [selectedLand];
addCardsToPack(commons, 10, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
boosterPack.push(rareOrMythic);
// Display Pack in the console and on the screen
console.log('Generated LCI Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateLCISetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
// Fetching the card pools
const fullArtLands = await fetchLCIFullArtLands();
const generalCardPool = await fetchLCIGeneral();
const borderlessJurassic = await fetchLCIBorderless();
// Helper functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const boosterPack = [];
// Land selection
boosterPack.push(Math.random() < 0.3 ? getRandomCard(fullArtLands) : getRandomCard(generalCardPool.filter(card => card.type_line === "Land — Cave")));
// 2 random cards from general or Jurassic World Borderless
for (let i = 0; i < 2; i++) {
boosterPack.push(Math.random() < 0.8 ? getRandomCard(generalCardPool) : getRandomCard(borderlessJurassic));
}
// 3 commons from general
const commons = generalCardPool.filter(card => card.rarity === 'common');
for (let i = 0; i < 3; i++) {
boosterPack.push(getRandomCard(commons));
}
// 3 uncommons from general
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
for (let i = 0; i < 3; i++) {
boosterPack.push(getRandomCard(uncommons));
}
// 1 common or uncommon
boosterPack.push(getRandomCard([...commons, ...uncommons]));
// 1 random card from general
boosterPack.push(getRandomCard(generalCardPool));
// 1 rare or mythic from general
const raresMythics = generalCardPool.filter(card => ['rare', 'mythic'].includes(card.rarity));
boosterPack.push(getRandomCard(raresMythics));
// Display Pack
console.log('Generated LCI Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateLCICollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
// Fetching the card pools
const fullArtLands = await fetchLCIFullArtLands();
const generalCardPool = await fetchLCIGeneral();
const showcase = await fetchLCIShowcase();
const jurassicPark = await fetchLCIJurassicPark();
const jurassicParkLands = await fetchLCIJurassicParkLands();
const extendedArt = await fetchLCIExtendedArt();
const commanderExtendedArt = await fetchLCICommanderExtendedArt();
const borderless = await fetchLCIBorderless();
const specialGuests = await fetchLCISpecialGuests();
const neonInk = await fetchLCINeonInk();
// Helper functions
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRandomCardByRarity = (cardSet, rarity) => {
const filteredSet = cardSet.filter(card => card.rarity === rarity);
return getRandomCard(filteredSet);
};
const collectorBoosterPack = [];
// 1 full art land
collectorBoosterPack.push(getRandomCard(fullArtLands));
// 4 commons from general
for (let i = 0; i < 4; i++) {
collectorBoosterPack.push(getRandomCardByRarity(generalCardPool, 'common'));
}
// 3 uncommons from general
for (let i = 0; i < 3; i++) {
collectorBoosterPack.push(getRandomCardByRarity(generalCardPool, 'uncommon'));
}
// 1 uncommon with varying probabilities
const uncommonRoll = Math.random();
if (uncommonRoll < 0.55) {
// 55% chance for a Showcase Legends of Ixalan uncommon
collectorBoosterPack.push(getRandomCardByRarity(showcase, 'uncommon'));
} else if (uncommonRoll < 0.96) {
// 41% chance for a Borderless Dinosaur uncommon
collectorBoosterPack.push(getRandomCardByRarity(borderless, 'uncommon'));
} else {
// 4% chance for a Borderless Special Guests uncommon
collectorBoosterPack.push(getRandomCardByRarity(specialGuests, 'uncommon'));
}
// 1 rare or mythic from general
collectorBoosterPack.push(getRandomCardByRarity(generalCardPool, Math.random() < (1/6) ? 'mythic' : 'rare'));
// 1 rare or mythic from extended art
collectorBoosterPack.push(getRandomCardByRarity(extendedArt, Math.random() < (1/10) ? 'mythic' : 'rare'));
// 1 rare or mythic from commander extended art
collectorBoosterPack.push(getRandomCardByRarity(commanderExtendedArt, Math.random() < (1/5) ? 'mythic' : 'rare'));
// 1 rare or mythic from showcase or borderless
const specificCardProbability = 0.014;
if (Math.random() < specificCardProbability && borderless.some(card => card.collector_number === '352')) {
collectorBoosterPack.push(borderless.find(card => card.collector_number === '352'));
} else {
const randomValue = Math.random();
let cumulativeProbability = 0;
const showcaseRaresProbability = 0.225;
const showcaseMythicRaresProbability = 0.148;
const borderlessRaresProbability = 0.507;
const borderlessMythicRaresProbability = 0.12;
if (randomValue < (cumulativeProbability += showcaseRaresProbability)) {
collectorBoosterPack.push(getRandomCardByRarity(showcase, 'rare'));
} else if (randomValue < (cumulativeProbability += showcaseMythicRaresProbability)) {
collectorBoosterPack.push(getRandomCardByRarity(showcase, 'mythic'));
} else if (randomValue < (cumulativeProbability += borderlessRaresProbability)) {
collectorBoosterPack.push(getRandomCardByRarity(borderless, 'rare'));
} else {
collectorBoosterPack.push(getRandomCardByRarity(borderless, 'mythic'));
}
}
// 1 card from jurassic park or lands
collectorBoosterPack.push(Math.random() < 0.452 ? getRandomCard(jurassicPark) : getRandomCard(jurassicParkLands));
// 1 rare or mythic varied selection
const rareMythicRoll = Math.random();
if (rareMythicRoll < 0.47) {
collectorBoosterPack.push(getRandomCardByRarity(extendedArt, 'rare'));
} else if (rareMythicRoll < 0.62) {
collectorBoosterPack.push(getRandomCardByRarity(showcase, 'rare'));
} else if (rareMythicRoll < 0.90) {
collectorBoosterPack.push(getRandomCardByRarity(borderless, 'rare'));
} else if (rareMythicRoll < 0.99) {
collectorBoosterPack.push(getRandomCard(specialGuests));
} else {
collectorBoosterPack.push(getRandomCard(neonInk));
}
// Display Pack
console.log('Generated LCI Collector Booster:', collectorBoosterPack);
displayPack(collectorBoosterPack);
return collectorBoosterPack;
},
// All Will be One Boosters
generateONEDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const panoramaLands = await fetchONEPanoramaLands();
const phyrexianLands = await fetchONEPhyrexianLands();
const generalCardPool = await fetchONEGeneralCardPool();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a random land
const lands = panoramaLands.concat(phyrexianLands);
const selectedLand = getRandomCard(lands);
// Fetch cards by rarity
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
// Decide the rare or mythic
const rareOrMythic = Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares);
let boosterPack = [selectedLand];
addCardsToPack(commons, 10, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
boosterPack.push(rareOrMythic);
// 33% chance to replace a common with a random card
if (Math.random() < 0.33) {
boosterPack.splice(2, 1); // Remove one common
boosterPack.push(getRandomCard(generalCardPool)); // Add random card to the end
}
// Display Pack
console.log('Generated ONE Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateONESetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const panoramaLands = await fetchONEPanoramaLands();
const phyrexianLands = await fetchONEPhyrexianLands();
const generalCardPool = await fetchONEGeneralCardPool();
const showcase = await fetchONEShowcase(); // Assuming this function fetches showcase commons and uncommons
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a random land
const lands = panoramaLands.concat(phyrexianLands);
const selectedLand = getRandomCard(lands);
// Fetch cards by rarity
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
const showcaseCommonUncommon = showcase.filter(card => ['common', 'uncommon'].includes(card.rarity));
// Decide the rare or mythic
const rareOrMythic = Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares);
let boosterPack = [selectedLand];
addCardsToPack(commons, 3, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
addCardsToPack(generalCardPool, 3, boosterPack); // 3 wildcards of any rarity
boosterPack.push(rareOrMythic);
boosterPack.push(getRandomCard(showcaseCommonUncommon));
// 1% chance to replace a common with a borderless planeswalker
if (Math.random() < 0.01) {
const borderlessPlaneswalkers = await fetchONEBorderlessPlaneswalkers(); // Assuming this function fetches the borderless planeswalkers
boosterPack.splice(1, 1); // Remove one common
boosterPack.push(getRandomCard(borderlessPlaneswalkers)); // Add a borderless planeswalker to the end
}
// Display Pack
console.log('Generated ONE Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateONECollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Initialize the pack
// Fetch functions
const panoramaLands = await fetchONEPanoramaLands();
const phyrexianLands = await fetchONEPhyrexianLands();
const generalCardPool = await fetchONEGeneralCardPool();
const extendedArtCards = await fetchONEExtendedArtCards();
const ONCCommanderExtended = await fetchONCCommanderExtended();
const showcase = await fetchONEShowcase();
const compleatFoils = await fetchONECompleatFoils();
const borderlessPlaneswalkers = await fetchONEBorderlessPlaneswalkers();
const alternateArtBorderless = await fetchONEAlternateArtBorderless();
// Fetch the Elesh Norn card
const eleshNornCard = await fetchONEEleshNorn(); // Returns a single card object
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Helper function to add cards
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a random land
const lands = panoramaLands.concat(phyrexianLands);
const selectedLand = getRandomCard(lands);
// Fetch cards by rarity
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
let collectorBoosterPack = [selectedLand];
addCardsToPack(commons, 4, collectorBoosterPack);
addCardsToPack(uncommons, 2, collectorBoosterPack);
// Add one rare or mythic
collectorBoosterPack.push(Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares));
// Add extended art cards
collectorBoosterPack.push(getRandomCard(extendedArtCards));
collectorBoosterPack.push(Math.random() < 0.5 ? getRandomCard(extendedArtCards) : getRandomCard(ONCCommanderExtended));
// Add two showcase cards
addCardsToPack(showcase.filter(card => ['common', 'uncommon'].includes(card.rarity)), 2, collectorBoosterPack);
// Add one Compleat Foil card
collectorBoosterPack.push(getRandomCard(compleatFoils));
// Add a rare or mythic with specific odds for the second last card
let rand = Math.random();
if (rand < 0.16) {
collectorBoosterPack.push(getRandomCard(alternateArtBorderless.filter(card => card.rarity === 'rare')));
} else if (rand < 0.41) {
collectorBoosterPack.push(getRandomCard(borderlessPlaneswalkers));
} else if (rand < 0.43) { // 2% chance for Elesh Norn
collectorBoosterPack.push(eleshNornCard);
} else {
collectorBoosterPack.push(getRandomCard(showcase.filter(card => ['rare', 'mythic'].includes(card.rarity))));
}
// Add a rare or mythic with extended art or specific odds for the last card
rand = Math.random();
if (rand < 0.49) {
collectorBoosterPack.push(Math.random() < 0.5 ? getRandomCard(extendedArtCards) : getRandomCard(ONCCommanderExtended));
} else {
rand = Math.random();
if (rand < 0.16) {
collectorBoosterPack.push(getRandomCard(alternateArtBorderless.filter(card => card.rarity === 'rare')));
} else if (rand < 0.41) {
collectorBoosterPack.push(getRandomCard(borderlessPlaneswalkers));
} else if (rand < 0.43) { // 2% chance for Elesh Norn
collectorBoosterPack.push(eleshNornCard);
} else {
collectorBoosterPack.push(getRandomCard(showcase.filter(card => ['rare', 'mythic'].includes(card.rarity))));
}
}
// Display Pack
console.log('Generated ONE Collector Booster:', collectorBoosterPack);
displayPack(collectorBoosterPack);
return collectorBoosterPack;
},
generateBRODraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const BROGeneralCardPool = await fetchBROGeneralCardPool();
const basicLands = await fetchBROBasicLands();
const fullArtLands = await fetchBROFullArtLands();
const BRRRetroFrameArtifacts = await fetchBRRRetroFrameArtifacts();
const BRRRetroSchematicArtifacts = await fetchBRRRetroSchematicArtifacts();
const BROAlternateArtBorderless = await fetchBROAlternateArtBorderless();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// 25% chance to get a full art land
const selectedLand = Math.random() < 0.25 ? getRandomCard(fullArtLands) : getRandomCard(basicLands);
const commons = BROGeneralCardPool.filter(card => card.rarity === 'common');
const uncommons = BROGeneralCardPool.filter(card => card.rarity === 'uncommon');
const rares = BROGeneralCardPool.filter(card => card.rarity === 'rare');
const mythics = BROGeneralCardPool.filter(card => card.rarity === 'mythic');
const rareOrMythic = Math.random() < 0.03 ? getRandomCard(BROAlternateArtBorderless) : (Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares));
let boosterPack = [selectedLand];
addCardsToPack(commons, 9, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
boosterPack.push(rareOrMythic);
// Determine the last card to be a retro artifact or schematic artifact
const lastCardChoice = Math.random() < 0.16 ? BRRRetroSchematicArtifacts : BRRRetroFrameArtifacts;
boosterPack.push(getRandomCard(lastCardChoice));
// 33% chance to replace a common with a random card
if (Math.random() < 0.33) {
boosterPack.splice(1, 1); // Remove one common
const replacementSet = [...BROGeneralCardPool, ...BRRRetroFrameArtifacts, ...BRRRetroSchematicArtifacts];
boosterPack.push(getRandomCard(replacementSet)); // Add random card to the end
}
console.log('Generated BRO Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateBROSetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetch card pools
const generalCardPool = await fetchBROGeneralCardPool();
const basicLands = await fetchBROBasicLands();
const fullArtLands = await fetchBROFullArtLands();
const BRRRetroFrameArtifacts = await fetchBRRRetroFrameArtifacts();
const BRRRetroSchematicArtifacts = await fetchBRRRetroSchematicArtifacts();
const transformers = await fetchBOTGeneralTransformers();
const BRCGeneralCards = await fetchBRCGeneralCards();
const alternateArtBorderless = await fetchBROAlternateArtBorderless();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
// Choose basic land (with a chance for full art)
const selectedLand = Math.random() < 0.27 ? getRandomCard(fullArtLands) : getRandomCard(basicLands);
// Wild card selection logic
const selectRegularWildCard = () => {
const allEligibleCards = generalCardPool.concat(transformers, BRRRetroFrameArtifacts, BRRRetroSchematicArtifacts, BRCGeneralCards);
return getRandomCard(allEligibleCards);
};
const selectSpecialWildCard = () => {
const specialCategories = generalCardPool.concat(transformers, BRRRetroFrameArtifacts, BRRRetroSchematicArtifacts, BRCGeneralCards, alternateArtBorderless);
return getRandomCard(specialCategories);
};
// Construct the booster pack
let boosterPack = [selectedLand];
// Add 3 commons from the generalCardPool
const commons = generalCardPool.filter(card => card.rarity === 'common');
for (let i = 0; i < 3; i++) {
boosterPack.push(getRandomCard(commons));
}
// Add 3 uncommons from the generalCardPool
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
for (let i = 0; i < 3; i++) {
boosterPack.push(getRandomCard(uncommons));
}
// Add 2 regular wild cards
for (let i = 0; i < 2; i++) {
boosterPack.push(selectRegularWildCard());
}
// Add 1 special wildcard
boosterPack.push(selectSpecialWildCard());
// Remaining pack logic
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
const rareOrMythic = Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares);
boosterPack.push(rareOrMythic);
// Retro or Schematic Artifact selection logic
const artifactRarityChance = Math.random();
let selectedArtifact;
if (artifactRarityChance < 0.07) {
selectedArtifact = Math.random() < (1/6) ? getRandomCard(BRRRetroSchematicArtifacts.filter(card => card.rarity === 'mythic')) : getRandomCard(BRRRetroFrameArtifacts.filter(card => card.rarity === 'mythic'));
} else if (artifactRarityChance < 0.34) {
selectedArtifact = Math.random() < (1/6) ? getRandomCard(BRRRetroSchematicArtifacts.filter(card => card.rarity === 'rare')) : getRandomCard(BRRRetroFrameArtifacts.filter(card => card.rarity === 'rare'));
} else {
selectedArtifact = Math.random() < (1/6) ? getRandomCard(BRRRetroSchematicArtifacts.filter(card => card.rarity === 'uncommon')) : getRandomCard(BRRRetroFrameArtifacts.filter(card => card.rarity === 'uncommon'));
}
boosterPack.push(selectedArtifact);
// Display Pack
console.log('Generated BRO Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateBROCollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView');
// Fetch card pools
const generalCardPool = await fetchBROGeneralCardPool();
const fullArtLands = await fetchBROFullArtLands();
const alternateArtBorderless = await fetchBROAlternateArtBorderless();
const extendedArt = await fetchBROExtendedArt();
const BRRRetroFrameArtifacts = await fetchBRRRetroFrameArtifacts();
const BRRRetroSchematicArtifacts = await fetchBRRRetroSchematicArtifacts();
const generalTransformers = await fetchBOTGeneralTransformers();
const shatteredGlassTransformers = await fetchBOTShatteredGlassTransformers();
const BRCExtendedArt = await fetchBRCExtendedArts();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const getRareOrMythic = (rares, mythics) => {
const isMythic = Math.random() < 1/8; // 1/8 chance for mythic, 7/8 for rare
if (isMythic) {
return getRandomCard(mythics);
} else {
return getRandomCard(rares);
}
};
const selectSchematicOrRetro = () => {
const combinedUncommonSchematicsAndRetro = BRRRetroFrameArtifacts.concat(BRRRetroSchematicArtifacts)
.filter(card => card.rarity === 'uncommon');
return getRandomCard(combinedUncommonSchematicsAndRetro);
};
const selectSpecialCard = () => {
const specialCategories = [
BRRRetroSchematicArtifacts,
BRRRetroFrameArtifacts,
alternateArtBorderless,
extendedArt,
BRCExtendedArt
];
const randomCategory = specialCategories[Math.floor(Math.random() * specialCategories.length)];
const rareOrMythicCards = randomCategory.filter(card => card.rarity === 'rare' || card.rarity === 'mythic');
return getRandomCard(rareOrMythicCards);
};
// Fetch cards by rarity from the general card pool
const commons = generalCardPool.filter(card => card.rarity === 'common');
const uncommons = generalCardPool.filter(card => card.rarity === 'uncommon');
const rares = generalCardPool.filter(card => card.rarity === 'rare');
const mythics = generalCardPool.filter(card => card.rarity === 'mythic');
// Construct the booster pack
let boosterPack = [getRandomCard(fullArtLands)]; // 1 Full Art Land
for (let i = 0; i < 4; i++) { // 4 commons
boosterPack.push(getRandomCard(commons));
}
for (let i = 0; i < 2; i++) { // 2 uncommons
boosterPack.push(getRandomCard(uncommons));
}
// Add 1 rare or mythic from the general BRO card pool
boosterPack.push(getRareOrMythic(rares, mythics));
// Add 1 extended art commander rare or mythic
const extendedArtRares = BRCExtendedArt.filter(card => card.rarity === 'rare');
const extendedArtMythics = BRCExtendedArt.filter(card => card.rarity === 'mythic');
boosterPack.push(getRareOrMythic(extendedArtRares, extendedArtMythics));
// 1 X rare or mythic from the extended art or from the borderless category
const isExtendedArt = Math.random() < 0.5; // 50% chance for each category
const extendedArtRaresAndMythics = extendedArt.concat(alternateArtBorderless)
.filter(card => card.rarity === 'rare' || card.rarity === 'mythic');
boosterPack.push(getRandomCard(extendedArtRaresAndMythics));
// 1 X retro artifact from the retro artifacts category
boosterPack.push(getRandomCard(BRRRetroFrameArtifacts));
// 1 X Schematic Artifact from the schematic artifacts category
boosterPack.push(getRandomCard(BRRRetroSchematicArtifacts));
// Add an uncommon schematic or a retro artifact
boosterPack.push(selectSchematicOrRetro());
// Add 1 rare or mythic from the special categories
boosterPack.push(selectSpecialCard());
// Display Pack
console.log('Generated BRO Collectors Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateWOEDraftBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const WOEGeneralCardPool = await fetchWOEGeneralCardPool();
const WOTGeneralCardPool = await fetchWOTGeneralCardPool();
const basicLands = await fetchWOEBasicLands();
const fullArtLands = await fetchWOEFullArtLands();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a basic land or full art land
const selectedLand = Math.random() < 0.33 ? getRandomCard(fullArtLands) : getRandomCard(basicLands);
// Fetch cards by rarity
const commons = WOEGeneralCardPool.filter(card => card.rarity === 'common');
const uncommons = WOEGeneralCardPool.filter(card => card.rarity === 'uncommon');
const rares = WOEGeneralCardPool.filter(card => card.rarity === 'rare');
const mythics = WOEGeneralCardPool.filter(card => card.rarity === 'mythic');
// Fetch an enchanting tales card from WOT
const enchantingTales = getRandomCard(WOTGeneralCardPool); // Assuming every card in WOTGeneralCardPool is an enchanting tale.
// Decide the rare or mythic
const rareOrMythic = Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares);
let boosterPack = [selectedLand];
addCardsToPack(commons, 9, boosterPack); // 9 commons
addCardsToPack(uncommons, 3, boosterPack); // 3 uncommons
boosterPack.push(enchantingTales);
boosterPack.push(rareOrMythic);
// 33% chance to replace a common with a random card
if (Math.random() < 0.33) {
boosterPack.splice(2, 1); // Remove one common
boosterPack.push(getRandomCard(WOEGeneralCardPool)); // Add random card to the end
}
// Display Pack
console.log('Generated WOE Draft Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateWOESetBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Add this line wherever you reset or initialize the pack
const WOEGeneralCardPool = await fetchWOEGeneralCardPool();
const WOEAlternateArt = await fetchWOEAlternateArtBorderless();
const WOEShowcase = await fetchWOEShowcase();
const WOTGeneralCardPool = await fetchWOTGeneralCardPool();
const WOTAnimeCardPool = await fetchWOTAnime(); // Corrected function name
const basicLands = await fetchWOEBasicLands();
const fullArtLands = await fetchWOEFullArtLands();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a basic land or full art land
const selectedLand = Math.random() < 0.33 ? getRandomCard(fullArtLands) : getRandomCard(basicLands);
// Fetch cards by rarity
const commons = WOEGeneralCardPool.filter(card => card.rarity === 'common');
const uncommons = WOEGeneralCardPool.filter(card => card.rarity === 'uncommon');
const rares = WOEGeneralCardPool.filter(card => card.rarity === 'rare');
const mythics = WOEGeneralCardPool.filter(card => card.rarity === 'mythic');
// Decide the rare or mythic
const rareOrMythic = Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares);
let boosterPack = [selectedLand];
addCardsToPack(commons, 3, boosterPack);
addCardsToPack(uncommons, 3, boosterPack);
// 3 wildcards with the specified probabilities
for (let i = 0; i < 3; i++) {
const wildcardRoll = Math.random();
if (wildcardRoll < 0.005) { // 0.5% chance for WOT Anime
boosterPack.push(getRandomCard(WOTAnimeCardPool));
} else if (wildcardRoll < 0.01) { // 0.5% chance for WOT General
boosterPack.push(getRandomCard(WOTGeneralCardPool));
} else if (wildcardRoll < 0.06) { // 5% chance for Alternate Art or Showcase
const replaceChoice = Math.random() < 0.5 ? WOEAlternateArt : WOEShowcase;
boosterPack.push(getRandomCard(replaceChoice));
} else if (wildcardRoll < 0.09) { // 3% chance for mythic (0.06 + 0.03)
boosterPack.push(getRandomCard(mythics));
} else if (wildcardRoll < 0.15) { // 6% chance for rare (0.09 + 0.06)
boosterPack.push(getRandomCard(rares));
} else { // Remaining chance for common/uncommon
const commonOrUncommon = Math.random() < 0.8 ? commons : uncommons; // 80% common, 20% uncommon
boosterPack.push(getRandomCard(commonOrUncommon));
}
}
// Enchanting Tales slot (2.8% chance for Anime)
const enchantingRoll = Math.random();
const enchantingTalesCard = enchantingRoll < 0.028
? getRandomCard(WOTAnimeCardPool)
: getRandomCard(WOTGeneralCardPool);
boosterPack.push(enchantingTalesCard);
// Add the main set rare or mythic
boosterPack.push(rareOrMythic);
// Display Pack
console.log('Generated WOE Set Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
generateWOECollectorBooster: async function() {
const displayArea = document.getElementById('packDisplay');
displayArea.classList.add('columnView'); // Ensure the display
// Fetch all necessary card pools
const WOEGeneralCardPool = await fetchWOEGeneralCardPool();
const WOEExtendedArt = await fetchWOEExtendedArt();
const WOEAlternateArt = await fetchWOEAlternateArtBorderless();
const WOEShowcase = await fetchWOEShowcase();
const WOTGeneralCardPool = await fetchWOTGeneralCardPool();
const WOTAnime = await fetchWOTAnime();
const fullArtLands = await fetchWOEFullArtLands();
const allBasicLands = await fetchWOEAllBasicLands();
const getRandomCard = (cardSet) => {
const idx = Math.floor(Math.random() * cardSet.length);
return cardSet.splice(idx, 1)[0];
};
const addCardsToPack = (cardSet, count, pack) => {
for (let i = 0; i < count; i++) {
pack.push(getRandomCard(cardSet));
}
};
// Select a full art land
const selectedLand = getRandomCard(fullArtLands);
// Fetch cards by rarity
const commons = WOEGeneralCardPool.filter(card => card.rarity === 'common');
const uncommonsWOE = WOEGeneralCardPool.filter(card => card.rarity === 'uncommon');
const uncommonsWOT = WOTGeneralCardPool.filter(card => card.rarity === 'uncommon');
const rares = WOEGeneralCardPool.filter(card => card.rarity === 'rare');
const mythics = WOEGeneralCardPool.filter(card => card.rarity === 'mythic');
const enchantingTalesRares = WOTGeneralCardPool.filter(card => card.rarity === 'rare');
const enchantingTalesMythics = WOTGeneralCardPool.filter(card => card.rarity === 'mythic');
const animeRares = WOTAnime.filter(card => card.rarity === 'rare');
const animeMythics = WOTAnime.filter(card => card.rarity === 'mythic');
let boosterPack = [selectedLand];
addCardsToPack(commons, 4, boosterPack);
addCardsToPack(uncommonsWOE, 3, boosterPack);
addCardsToPack(uncommonsWOT, 2, boosterPack);
boosterPack.push(Math.random() < (1/8) ? getRandomCard(mythics) : getRandomCard(rares));
boosterPack.push(Math.random() < (1/8) ? getRandomCard(WOEExtendedArt) : getRandomCard(rares));
const altOrShowcase = Math.random() < 0.5 ? WOEAlternateArt : WOEShowcase;
boosterPack.push(Math.random() < (1/8) ? getRandomCard(altOrShowcase) : getRandomCard(rares));
// Selecting enchanting tales card
const enchantingRandom = Math.random();
if (enchantingRandom < 0.733) {
boosterPack.push(getRandomCard(enchantingTalesRares));
} else if (enchantingRandom < 0.833) {
boosterPack.push(getRandomCard(enchantingTalesMythics));
} else if (enchantingRandom < 0.9) {
boosterPack.push(getRandomCard(animeRares));
} else {
boosterPack.push(getRandomCard(animeMythics));
}
// Random rare or mythic from any WOT or WOE category
const allCategories = [...WOEGeneralCardPool, ...WOEExtendedArt, ...WOEAlternateArt, ...WOEShowcase, ...WOTGeneralCardPool, ...WOTAnime];
const allRaresMythics = allCategories.filter(card => card.rarity === 'rare' || card.rarity === 'mythic');
boosterPack.push(Math.random() < (1/8) ? getRandomCard(allRaresMythics.filter(card => card.rarity === 'mythic')) : getRandomCard(allRaresMythics.filter(card => card.rarity === 'rare')));
// Display Pack
console.log('Generated WOE Collectors Booster:', boosterPack);
displayPack(boosterPack);
return boosterPack;
},
// End of window.cardGenerators
};
// Utility functions
function getRandomCard(cardList) {
const index = Math.floor(Math.random() * cardList.length);
return cardList.splice(index, 1)[0];
}
function getRandomCards(cardList, count) {
const selectedCards = [];
for (let i = 0; i < count; i++) {
const index = Math.floor(Math.random() * cardList.length);
selectedCards.push(cardList.splice(index, 1)[0]);
}
return selectedCards;
}
// Section 7 Closing Functions
var displayedCards = [];
// Utility function to create price divs
function createPriceDiv(card) {
let priceDiv = document.createElement("div");
priceDiv.className = "card-info";
let priceUSD = document.createElement("div");
priceUSD.innerText = `USD: $${card.prices && card.prices.usd ? card.prices.usd : 'N/A'}`;
priceDiv.appendChild(priceUSD);
let priceUSDFoil = document.createElement("div");
if (card.prices && card.prices.usd_etched) {
priceUSDFoil.innerText = `USD Etched: $${card.prices.usd_etched}`;
} else {
priceUSDFoil.innerText = `USD Foil: $${(card.prices && card.prices.usd_foil) ? card.prices.usd_foil : 'N/A'}`;
}
priceDiv.appendChild(priceUSDFoil);
return priceDiv;
}
function isRoomCard(card) {
if (!card) return false;
// Check type_line for "Room"
if (card.type_line && card.type_line.toLowerCase().includes('room')) {
return true;
}
// Check card_faces for split or modal cards containing "Room"
if (card.card_faces) {
return card.card_faces.some(face =>
face.type_line && face.type_line.toLowerCase().includes('room')
);
}
return false;
}
async function displayPack(pack, isLastPack = true) {
return new Promise((resolve, reject) => {
if (!pack || pack.length === 0) {
return reject(new Error('Error generating pack: The pack is empty or invalid.'));
}
const displayArea = document.getElementById('packDisplay');
const selectedLayout = window.selectedLayout || 'packView';
// Initialize pack container
let packContainer;
if (selectedLayout === 'draftView' || selectedLayout === 'sealedView') {
packContainer = document.createElement('div');
packContainer.className = 'pack-container';
displayArea.appendChild(packContainer);
} else {
packContainer = displayArea;
displayArea.innerHTML = '';
}
let foilTotal = 0;
let nonFoilTotal = 0;
displayedCards = [];
try {
pack.forEach((card, index) => {
const cardContainerElement = document.createElement('div');
cardContainerElement.className = `card-container ${index === 0 ? 'active' : ''}`;
cardContainerElement.dataset.rarity = card.rarity;
cardContainerElement.dataset.color = card.color_identity ? card.color_identity[0] : 'colorless';
cardContainerElement.dataset.isRoom = isRoomCard(card); // Pass Room info as a dataset
let imageUrl;
// Handle different double-sided card layouts
if ((card.layout === 'transform' || card.layout === 'modal_dfc') && card.card_faces?.length > 0) {
imageUrl = card.card_faces[0].image_uris?.normal || null;
} else if (card.layout === 'reversible_card' && card.card_faces?.length > 0) {
imageUrl = card.card_faces[0].image_uris?.normal || null;
} else {
imageUrl = card.image_uris?.normal || null;
}
if (imageUrl) {
const cardImage = document.createElement('img');
cardImage.src = imageUrl;
cardImage.alt = card.name || 'Unknown Card';
cardImage.style.maxWidth =
selectedCardSize === 'Small'
? '200px'
: selectedCardSize === 'Normal'
? '250px'
: '300px';
console.log(`Card Name: ${card.name}`);
console.log(`Type Line: ${card.type_line}`);
console.log(`Is Room Card?`, isRoomCard(card));
// Handle image load error
cardImage.onerror = () => {
console.error(`Failed to load image for card: ${card.name} at URL: ${imageUrl}`);
cardImage.style.display = 'none';
};
cardContainerElement.appendChild(cardImage);
}
// Additional elements (price, affiliate links, etc.)
const priceDiv = createPriceDiv(card);
cardContainerElement.appendChild(priceDiv);
const affiliateLink = `https://tcgplayer.pxf.io/c/5066134/1780961/21018?u=https%3A%2F%2Fwww.tcgplayer.com%2Fsearch%2Fall%2Fproduct%3Fq%3D${encodeURIComponent(
card.name
)}`;
const buyLink = document.createElement('a');
buyLink.href = affiliateLink;
buyLink.target = '_blank';
buyLink.className = 'tcgplayer-affiliate-link';
buyLink.textContent = `Buy ${card.name} on TCG Player`;
buyLink.onclick = (event) => event.stopPropagation();
cardContainerElement.appendChild(buyLink);
nonFoilTotal += parseFloat(card.prices?.usd || 0);
foilTotal += parseFloat(card.prices?.usd_etched || card.prices?.usd_foil || 0);
packContainer.appendChild(cardContainerElement);
displayedCards.push(card.name);
});
pack.foilTotalValue = parseFloat(foilTotal.toFixed(2));
pack.nonFoilTotalValue = parseFloat(nonFoilTotal.toFixed(2));
currentCardIndex = 0;
if (selectedLayout === 'packView') {
const nextCardButton = document.getElementById('nextCardBtn');
const prevCardButton = document.getElementById('prevCardBtn');
if (nextCardButton && prevCardButton) {
nextCardButton.style.display = pack.length > 1 ? 'block' : 'none';
prevCardButton.style.display = 'none';
}
}
updateLayout(selectedLayout);
if (selectedLayout === 'draftView' || selectedLayout === 'sealedView') {
reorderCardsByRarityAndColor();
}
if (isLastPack) {
updateNavigationButtons();
resolve(pack);
} else {
resolve();
}
} catch (error) {
console.error('Error displaying pack:', error);
reject(new Error('Error generating pack: An unexpected error occurred while displaying the pack.'));
}
});
}
async function displayPacks(packs) {
const displayArea = document.getElementById('packDisplay');
displayArea.innerHTML = ''; // Clear previous content
packs.forEach((pack, index) => {
displayPack(pack, index === packs.length - 1); // Pass 'isLastPack' flag to indicate the last pack
});
}
// Filter and Sort JS for Draft and Sealed views
document.addEventListener("DOMContentLoaded", function () {
const viewSelection = document.getElementById("viewSelection"); // ID of the view selector
const filtersContainer = document.getElementById("draft-sealed-filters");
// Ensure both elements exist before attempting to modify them
if (viewSelection && filtersContainer) {
// Initially hide filters; only display for Draft and Sealed views
filtersContainer.style.display = "none";
// Toggle visibility of filters based on selected view
viewSelection.addEventListener("change", function () {
const selectedView = viewSelection.value;
filtersContainer.style.display = (selectedView === "sealed" || selectedView === "draft") ? "block" : "none";
});
} else {
console.warn("One or both elements ('viewSelection', 'draft-sealed-filters') were not found on the page.");
}
});
/**
* Applies the selected filters and sorting options.
* This function separates the filtering and sorting logic for clarity.
*/
function applyFilters() {
// Gather selected colors from checkboxes
const selectedColors = [];
["white", "blue", "black", "red", "green", "colorless"].forEach(color => {
const checkbox = document.getElementById(`${color}-filter`);
if (checkbox && checkbox.checked) {
selectedColors.push(checkbox.value);
}
});
// Get the selected sort option
const sortOption = document.getElementById("sort-type").value;
// Filter cards based on selected colors
const filteredCards = generatedPackCards.filter(card => {
const cardColors = card.colors || [];
if (selectedColors.length === 0) return true; // No filter, include all cards
if (cardColors.length === 0) return selectedColors.includes("colorless"); // Include colorless if selected
return cardColors.every(color => selectedColors.includes(color)); // Include cards with selected colors
});
// Sort filtered cards
const sortedCards = sortCards(sortOption, filteredCards, selectedColors);
// Display sorted cards
displayFilteredCards(sortedCards);
}
/**
* Filters cards based on selected colors.
*/
function filterCards(selectedColors, cards) {
console.log("Filtering Cards with Selected Colors:", selectedColors);
if (!Array.isArray(selectedColors) || !Array.isArray(cards)) {
console.error("Invalid inputs to filterCards");
return [];
}
return cards.filter(card => {
const cardColors = card.colors || [];
if (selectedColors.length === 0) return true; // No filter, include all cards
// Exclude colorless cards unless "colorless" is selected
if (cardColors.length === 0) {
return selectedColors.includes("colorless");
}
// Include cards where all colors are within the selected colors
return cardColors.every(color => selectedColors.includes(color));
});
}
/**
* Sorts cards based on the selected sort option.
* @param {string} sortOption - The selected sorting option (e.g., "color", "type", "manaCost", "rarity").
* @param {Array} cards - The cards to be sorted.
* @param {Array} selectedColors - The list of colors selected for filtering.
* @returns {Array} - The sorted array of cards.
*/
function sortCards(sortOption, cards, selectedColors) {
console.log("Sorting Cards with Option:", sortOption);
if (!Array.isArray(cards)) {
console.error("Invalid input to sortCards");
return [];
}
return cards.sort((a, b) => {
const colorsA = a.colors || [];
const colorsB = b.colors || [];
// Primary sorting: by color (maintain the color order)
if (sortOption === "color" || sortOption === "manaCost" || sortOption === "type") {
// Single-colored cards come first
if (colorsA.length !== colorsB.length) {
return colorsA.length - colorsB.length; // Fewer colors come first
}
// Single-colored cards: Sort by selectedColors order
if (colorsA.length === 1 && colorsB.length === 1) {
const colorIndexA = selectedColors.indexOf(colorsA[0]);
const colorIndexB = selectedColors.indexOf(colorsB[0]);
if (colorIndexA !== colorIndexB) {
return colorIndexA - colorIndexB;
}
}
// Multi-colored cards: Sort by the first matching color in selectedColors
const primaryColorA = colorsA.find(color => selectedColors.includes(color)) || "";
const primaryColorB = colorsB.find(color => selectedColors.includes(color)) || "";
const colorOrderA = selectedColors.indexOf(primaryColorA);
const colorOrderB = selectedColors.indexOf(primaryColorB);
if (colorOrderA !== colorOrderB) {
return colorOrderA - colorOrderB;
}
}
// Additional sorting for "manaCost" sortOption
if (sortOption === "manaCost") {
const manaA = a.cmc || 0;
const manaB = b.cmc || 0;
// Within the same color group, sort by mana cost
return manaA - manaB;
}
// Additional sorting for "type" sortOption
if (sortOption === "type") {
const typeA = (a.type_line || "").split("—")[0].trim(); // Extract primary type
const typeB = (b.type_line || "").split("—")[0].trim();
// Within the same color group, sort by type alphabetically
return typeA.localeCompare(typeB);
}
// Additional sorting for "rarity"
if (sortOption === "rarity") {
const rarityOrder = { "mythic": 1, "rare": 2, "uncommon": 3, "common": 4 };
const rarityA = rarityOrder[a.rarity || "common"];
const rarityB = rarityOrder[b.rarity || "common"];
return rarityA - rarityB; // Higher rarity first
}
return 0; // Default: no further sorting
});
}
/**
* Displays filtered and sorted cards in the designated area.
*/
function displayFilteredCards(cards) {
console.log("Displaying Cards:", cards);
const displayArea = document.getElementById("packDisplay");
if (!displayArea) {
console.error("Display area not found for filtered cards.");
return;
}
// Clear existing cards but retain layout styles
displayArea.innerHTML = '';
// Detect the selected layout and card size for consistent styling
const selectedLayout = window.selectedLayout || 'packView';
const maxWidth = selectedCardSize === 'Small' ? '200px' :
selectedCardSize === 'Normal' ? '250px' :
selectedCardSize === 'Large' ? '300px' : '200px';
// Render each card with appropriate settings
cards.forEach(card => {
console.log("Rendering Card:", card);
const cardContainerElement = document.createElement("div");
cardContainerElement.classList.add("card-container");
cardContainerElement.dataset.rarity = card.rarity || "common";
cardContainerElement.dataset.color = card.colors?.join(' ') || "colorless";
const cardImage = document.createElement("img");
cardImage.src = card.image_uris?.normal || '';
cardImage.alt = card.name || "Unknown Card";
cardImage.style.maxWidth = maxWidth;
if (selectedLayout === 'draftView' || selectedLayout === 'sealedView') {
cardImage.addEventListener('click', () => showPopupCard(cardImage.src));
}
cardContainerElement.appendChild(cardImage);
const priceDiv = createPriceDiv(card);
cardContainerElement.appendChild(priceDiv);
const affiliateLink = document.createElement('a');
affiliateLink.href = `https://tcgplayer.pxf.io/c/5066134/1780961/21018?u=https%3A%2F%2Fwww.tcgplayer.com%2Fsearch%2Fall%2Fproduct%3Fq%3D${encodeURIComponent(card.name.replace(/ /g, "+"))}`;
affiliateLink.target = '_blank';
affiliateLink.classList.add('tcgplayer-affiliate-link');
affiliateLink.textContent = `Buy ${card.name} on TCG Player`;
affiliateLink.onclick = (event) => event.stopPropagation();
cardContainerElement.appendChild(affiliateLink);
cardContainerElement.style.display = selectedLayout === 'gridView' ? 'inline-block' : 'block';
cardContainerElement.style.margin = '10px';
displayArea.appendChild(cardContainerElement);
});
console.log("Cards successfully rendered.");
}
function initializeCards(cards) {
allCards = cards; // Set global allCards array with cards from the packs
displayFilteredCards(allCards); // Show all cards initially
}
// Other Functions
// Function to update navigation buttons visibility based on the current card index
function updateNavigationButtons() {
const nextCardButton = document.getElementById('nextCardBtn');
const prevCardButton = document.getElementById('prevCardBtn');
const cardContainers = document.querySelectorAll('#packDisplay .card-container');
// Check the current layout
const currentLayout = document.getElementById('packDisplay').className;
if (currentLayout === 'lineView' || currentLayout === 'gridView' || currentLayout === 'draftView' || currentLayout === 'sealedView') {
// Hide navigation buttons for line, grid, draft, and sealed views
nextCardButton.style.display = 'none';
prevCardButton.style.display = 'none';
return;
}
// Show or hide the previous button
prevCardButton.style.display = currentCardIndex > 0 ? 'block' : 'none';
// Show or hide the next button
if (currentCardIndex < cardContainers.length - 1) {
nextCardButton.textContent = 'Next Card';
nextCardButton.style.display = 'block';
} else {
nextCardButton.textContent = 'End';
nextCardButton.style.display = 'block';
}
}
function resetDisplayArea() {
const displayArea = document.getElementById('packDisplay');
const cardContainer = displayArea.querySelector('.card-container'); // Select the single card container
if (cardContainer) {
cardContainer.innerHTML = ''; // Clear only the contents of the card container
}
displayArea.className = ''; // Remove all classes from the display area
}
function resetViewToPack() {
const displayArea = document.getElementById('packDisplay');
displayArea.className = ''; // Remove all classes
displayArea.classList.add('packView'); // Add the default view class
}
function initializeGeneratePackAndNavigationButtons() {
// Initialize Generate Pack button
const generatePackBtn = document.getElementById('generatePackBtn');
if (generatePackBtn) {
generatePackBtn.addEventListener('click', generatePack);
}
// Initialize Next Card button
const nextCardBtn = document.getElementById('nextCardBtn');
if (nextCardBtn) {
nextCardBtn.addEventListener('click', () => showNextCard('next'));
nextCardBtn.style.display = 'none';
}
// Initialize Previous Card button
const prevCardBtn = document.getElementById('prevCardBtn');
if (prevCardBtn) {
prevCardBtn.addEventListener('click', () => showNextCard('prev'));
prevCardBtn.style.display = 'none';
}
// Initialize Generate CSV button
const generateCsvBtn = document.getElementById('generateCsvBtn');
if (generateCsvBtn) {
generateCsvBtn.addEventListener('click', generateAndExportPackAsCsv);
} else {
console.error('Button with ID "generateCsvBtn" not found.');
}
// Add event listeners for layout buttons
const packLayoutBtn = document.getElementById('packLayout');
const lineLayoutBtn = document.getElementById('lineLayout');
const gridLayoutBtn = document.getElementById('gridLayout');
const draftLayoutBtn = document.getElementById('draftLayout');
const sealedLayoutBtn = document.getElementById('sealedLayout');
if (packLayoutBtn) {
packLayoutBtn.addEventListener('click', () => {
window.selectedLayout = 'packView';
updateLayout('packView');
});
}
if (lineLayoutBtn) {
lineLayoutBtn.addEventListener('click', () => {
window.selectedLayout = 'lineView';
updateLayout('lineView');
});
}
if (gridLayoutBtn) {
gridLayoutBtn.addEventListener('click', () => {
window.selectedLayout = 'gridView';
updateLayout('gridView');
});
}
if (draftLayoutBtn) {
draftLayoutBtn.addEventListener('click', () => {
window.selectedLayout = 'draftView';
updateLayout('draftView');
});
}
if (sealedLayoutBtn) {
sealedLayoutBtn.addEventListener('click', () => {
window.selectedLayout = 'sealedView';
updateLayout('sealedView');
});
}
}
// Initialize event listeners after DOM content is loaded
document.addEventListener('DOMContentLoaded', () => {
initializeGeneratePackAndNavigationButtons();
// Set default layout to pack view
window.selectedLayout = 'packView';
updateLayout('packView');
});
// Function to generate and export pack as CSV
async function generateAndExportPackAsCsv() {
try {
console.log("Starting pack generation and export process.");
const pack = await generatePack(); // Generate the pack using the existing function
console.log("Pack generated:", pack);
const displayedPack = await displayPack(pack); // Ensure the pack is fully displayed
console.log("Pack displayed:", displayedPack);
exportPackAsCsv(displayedPack); // Export the displayed pack as CSV
} catch (error) {
console.error("An error occurred during the pack generation and export process:", error);
}
}
// Function to export pack as CSV
function exportPackAsCsv(pack) {
let csvContent = "Board,Qty,Card Name,Pack" + String.fromCharCode(10); // Updated header row to include "Pack" column
pack.forEach(card => {
let packColumnValue = `1 ${card.name}`; // Format as "1 cardName"
csvContent += `main,1,"${card.name.replace(/"/g, '""')}","${packColumnValue.replace(/"/g, '""')}"` + String.fromCharCode(10);
});
// Create a Blob object for the CSV content
let blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
let url = URL.createObjectURL(blob);
// Create a link to download the Blob
let link = document.createElement("a");
link.style.display = 'none';
link.href = url;
link.download = "mtg_pack.csv";
// Append the link, trigger the download, and then remove the link
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
console.log('CSV file generated and download triggered.');
}
function endOfPackOptions(pack = []) {
const displayArea = document.getElementById('packDisplay');
// Check if the end-of-pack message has already been displayed to avoid duplication
if (displayArea.classList.contains('end-of-pack-displayed')) {
return;
}
resetDisplayArea(); // Clear the display area
// Use the current layout selected by the user, not hardcoded to lineView
const selectedLayout = window.selectedLayout || 'packView';
updateLayout(selectedLayout);
// Clear the affiliate links container
const affiliateLinksContainer = document.getElementById('affiliateLinksContainer');
affiliateLinksContainer.innerHTML = '';
// Retrieve selected set and booster type
const setSelectionElement = document.getElementById('setSelection');
const selectedOptionElement = setSelectionElement.options[setSelectionElement.selectedIndex];
const setCode = setSelectionElement.value;
const setName = selectedOptionElement.text;
const boosterTypeElement = document.getElementById('boosterTypeSelection');
const boosterType = boosterTypeElement ? boosterTypeElement.value : '';
const nextCardButton = document.getElementById('nextCardBtn');
const prevCardButton = document.getElementById('prevCardBtn');
// Hide navigation buttons if in Pack View after the last card is shown
if (selectedLayout === 'packView') {
nextCardButton.style.display = 'none';
prevCardButton.style.display = 'none';
}
// Mark the display area as showing the end of the pack
displayArea.classList.add('end-of-pack-displayed');
// Add affiliate links and actions
const encodedSetName = encodeURIComponent(setName.replace(/ /g, "+"));
// Amazon Affiliate Link
const amazonAffiliateLink = `https://www.amazon.com/s?k=${encodedSetName}+Magic+the+Gathering&linkCode=ll2&tag=mtgpacks1337-20&linkId=6d347a7186f750a21dd775ddd7440b4d&language=en_US&ref_=as_li_ss_tl`;
addLinkButtonWithImage(displayArea, amazonAffiliateLink, `Buy ${setName} on Amazon`, "https://mtg-packs.com/wp-content/uploads/2024/07/available_at_amazon_US_EN_logo_stacked_RGB_WHITE.png", 'amazon-button');
// TCGPlayer Affiliate Link
const tcgPlayerLink = `https://tcgplayer.pxf.io/c/5066134/1780961/21018?u=https%3A%2F%2Fwww.tcgplayer.com%2Fsearch%2Fall%2Fproduct%3Fq%3D${encodedSetName}`;
addLinkButtonWithImage(displayArea, tcgPlayerLink, `Buy ${setName} on TCG Player`, "https://mtg-packs.com/wp-content/uploads/2024/08/TCGplayer-Primary-RGB_300px.png", 'tcgplayer-button');
// Wizards of the Coast official page link
const wizardsLink = getWizardsLink(setCode);
addLinkButton(displayArea, wizardsLink, `Learn More about collecting ${setName}`);
// Add YouTube links for the set and booster type
addYouTubeLinks(displayArea, setCode, boosterType);
// Add export as CSV button
addActionButton(displayArea, 'exportCsvBtn', 'Export as CSV', exportAsCsv);
}
// Updated addLinkButtonWithImage function to be more generic
function addLinkButtonWithImage(container, url, text, imageUrl, buttonClass) {
const button = document.createElement('a');
button.href = url;
button.target = '_blank';
button.className = buttonClass;
const textNode = document.createTextNode(text);
button.appendChild(textNode);
const img = document.createElement('img');
img.src = imageUrl;
img.alt = text;
button.appendChild(img);
container.appendChild(button);
}
function getWizardsLink(setCode) {
const links = {
'FDN': 'https://magic.wizards.com/en/news/feature/collecting-foundations',
'DSK': 'https://magic.wizards.com/en/news/feature/collecting-duskmourn',
'BLB': 'https://magic.wizards.com/en/news/feature/collecting-bloomburrow',
'ACR': 'https://magic.wizards.com/en/news/feature/collecting-assassins-creed',
'OTJ': 'https://magic.wizards.com/en/news/feature/collecting-outlaws-of-thunder-junction',
'MH3': 'https://magic.wizards.com/en/news/feature/collecting-modern-horizons-3',
'PIP': 'https://magic.wizards.com/en/news/feature/collecting-magic-the-gathering-fallout',
'RVR': 'https://magic.wizards.com/en/news/feature/collecting-march-of-the-machine',
'MOM': 'https://magic.wizards.com/en/news/feature/collecting-ravnica-remastered',
'MKM': 'https://magic.wizards.com/en/news/feature/collecting-murders-at-karlov-manor',
'LCI': 'https://magic.wizards.com/en/news/feature/collecting-the-lost-caverns-of-ixalan',
'WHO': 'https://magic.wizards.com/en/news/feature/collecting-magic-the-gathering-doctor-who',
'CMM': 'https://magic.wizards.com/en/news/feature/collecting-commander-masters',
'ONE': 'https://magic.wizards.com/en/news/feature/collecting-phyrexia-all-will-be-one',
'WOE': 'https://magic.wizards.com/en/news/feature/collecting-wilds-of-eldraine',
'DMR': 'https://magic.wizards.com/en/news/feature/collecting-dominaria-remastered-and-product-overview',
'BRO': 'https://magic.wizards.com/en/news/feature/whats-inside-the-brothers-war-boosters',
'2X2': 'https://magic.wizards.com/en/news/feature/collecting-double-masters-2022-and-product-overview',
'CLB': 'https://magic.wizards.com/en/news/feature/collecting-commander-legends-battle-for-baldurs-gate',
'NEO': 'https://magic.wizards.com/en/news/feature/collecting-kamigawa-neon-dynasty-2022-01-27'
};
return links[setCode] || '#';
}
function addLinkButton(container, link, text) {
const button = document.createElement('a');
button.href = link;
button.target = '_blank';
button.textContent = text;
button.style = 'display: inline-flex; align-items: center; justify-content: center; margin: 10px; padding: 10px 15px; font-size: 1em; cursor: pointer; border: none; background-color: #555; color: #fff; border-radius: 5px; text-decoration: none;';
container.appendChild(button);
}
function addActionButton(container, id, text, action) {
const button = document.createElement('button');
button.id = id;
button.textContent = text;
button.addEventListener('click', action);
container.appendChild(button);
}
function displayGrid() {
const cardContainers = document.querySelectorAll('#packDisplay .card-container');
const maxWidth = selectedCardSize === 'Small' ? '175px' : selectedCardSize === 'Normal' ? '225px' : '275px';
cardContainers.forEach(container => {
// Reset styles and apply grid-specific styles
container.style.position = '';
container.style.left = '';
container.style.transform = '';
container.style.display = 'flex'; // Flexbox to center content
container.style.justifyContent = 'center'; // Center horizontally
container.style.alignItems = 'center'; // Center vertically
container.style.width = maxWidth; // Set the card size based on the user's selection
container.style.margin = '25px'; // Add more space between the cards
});
// Reset and apply grid view to the display area
const displayArea = document.getElementById('packDisplay');
displayArea.className = ''; // Remove all existing layout classes
displayArea.classList.add('gridView'); // Apply grid view class
// Clean up buttons that are not relevant in grid view
const displayGridBtn = document.getElementById('displayGridBtn');
if (displayGridBtn) displayGridBtn.remove(); // Remove the grid button (if present)
const generateAnotherBtn = document.getElementById('generateAnotherBtn');
if (generateAnotherBtn) generateAnotherBtn.remove(); // Remove 'generate another' button (if present)
// Hide next and previous card buttons (relevant for pack view but not grid view)
const nextCardButton = document.getElementById('nextCardBtn');
if (nextCardButton) {
nextCardButton.style.display = 'none'; // Hide 'next' button
}
const prevCardButton = document.getElementById('prevCardBtn');
if (prevCardButton) {
prevCardButton.style.display = 'none'; // Hide 'prev' button
}
}
function exportAsCsv() {
if (!displayedCards || displayedCards.length === 0) {
console.error('No cards available to export.');
return;
}
let csvContent = "Board,Qty,Card Name,Pack" + String.fromCharCode(10); // Updated header row to include "Pack" column
displayedCards.forEach(cardName => {
let packColumnValue = `1 ${cardName}`; // Format as "1 cardName"
csvContent += `main,1,"${cardName.replace(/"/g, '""')}","${packColumnValue.replace(/"/g, '""')}"` + String.fromCharCode(10);
});
// Create a Blob object for the CSV content
let blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
let url = URL.createObjectURL(blob);
// Create a link to download the Blob
let link = document.createElement("a");
link.style.display = 'none';
link.href = url;
link.download = "mtg_pack.csv";
// Append the link, trigger the download, and then remove the link
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
console.log('CSV file generated and download triggered.');
}
function addYouTubeLinks(displayArea, setCode, boosterType) {
const links = {
'OTJ': {
'play': 'https://www.youtube.com/shorts/JL1sMQ1MKXI',
'collector': 'https://www.youtube.com/shorts/dSYMYVQreh4'
},
'RVR': {
'collector': 'https://www.youtube.com/shorts/zA8fi0Uhd2w'
},
'WHO': {
'collector': 'https://www.youtube.com/shorts/fJp5rWA3D5I'
},
'PIP': {
'collector': 'https://www.youtube.com/shorts/FRsNOgnYXAo'
},
'MKM': {
'collector': 'https://www.youtube.com/shorts/qdHbJfdGMkk',
'play': 'https://www.youtube.com/shorts/e5SnLk068ro'
},
'ONE': {
'set': 'https://www.youtube.com/shorts/wLpUaxB49TY',
'draft': 'https://www.youtube.com/shorts/wAA7PWLm8K4'
},
'MH3': {
'play': 'https://www.youtube.com/shorts/Z82n8C9kUhg',
'collector': 'https://www.youtube.com/shorts/FkurowUcSmc'
},
'ACR': {
'collector': 'https://www.youtube.com/shorts/ibYSzolbh6c',
'beyond': 'https://www.youtube.com/shorts/evHRRqNJslY'
}
};
const youtubeLink = links[setCode] && links[setCode][boosterType];
if (youtubeLink) {
addLinkButton(displayArea, youtubeLink, `Watch ${setCode} ${capitalizeFirstLetter(boosterType)} Booster Opening`);
}
}
// Ensure the script is loaded
console.log('Script is loaded');
</script>
<script id="wp-block-template-skip-link-js-after">
( function() {
var skipLinkTarget = document.querySelector( 'main' ),
sibling,
skipLinkTargetID,
skipLink;
// Early exit if a skip-link target can't be located.
if ( ! skipLinkTarget ) {
return;
}
/*
* Get the site wrapper.
* The skip-link will be injected in the beginning of it.
*/
sibling = document.querySelector( '.wp-site-blocks' );
// Early exit if the root element was not found.
if ( ! sibling ) {
return;
}
// Get the skip-link target's ID, and generate one if it doesn't exist.
skipLinkTargetID = skipLinkTarget.id;
if ( ! skipLinkTargetID ) {
skipLinkTargetID = 'wp--skip-link--target';
skipLinkTarget.id = skipLinkTargetID;
}
// Create the skip link.
skipLink = document.createElement( 'a' );
skipLink.classList.add( 'skip-link', 'screen-reader-text' );
skipLink.href = '#' + skipLinkTargetID;
skipLink.innerHTML = 'Skip to content';
// Inject the skip link.
sibling.parentElement.insertBefore( skipLink, sibling );
}() );
</script>
<script id="wpackio_dpIntroToursmain_main_dpit_public_f3672a47_js_script-js-extra">
var dpIntroTourPublicConfig = {"siteUrl":"https:\/\/mtg-packs.com","nonces":{"wp_rest":"40cc485072"},"dpDebugEn":"","isMultiSite":"","isAdmin":"","zIndexBase":"16777200","i18n":{"aria-main":"Guided intro tour","step":"Step","end-a-tour-q":"Are you sure to end a tour?","aria-step-num":"tour step number"},"currentPostId":"6","text_styles":null,"tours":[{"tourName":"Help Button","createNew":false,"tourId":553,"loggedInVisitCnt":0,"visitsLsKeyVersion":1,"theme":"basic","triggers":[{"first_user_visit_only":false,"allow_future_visits_checkbox":true,"first_n_user_visit":1,"visit_count_mode":"server","once_per_session_only":false,"allow_just_for_logged_in_users":false,"disable_for_roles":[],"in_view_port_offset":"0px","lock_by_url_parameter":false,"global_start_at_all_pages":false,"selector":"#helpButton","on":"click","specific_key_pressed":""}],"steps":"[{\"element\":\"\",\"intro\":\"<p>Discover the excitement of Magic the Gathering with our online pack simulator.<\\\/p>\",\"position\":\"center\",\"highlight\":\"\",\"enable_interaction\":\"base64__eyJ2YWwiOiIwIiwiZXh0Ijp7Iml0ZXJhdGVfYWZ0ZXJfY2xpY2tfc3RvcF9wcm9wYWdhdGlvbiI6IjAiLCJpdGVyYXRlX2FmdGVyX2NsaWNrIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfY2xpY2tfZGVsYXlfbXMiOiI1MDAiLCJvcGVuX3RhcmdldF9saW5rX2NsaWNrc19pbl9uZXdfdGFiIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfaG92ZXIiOiIwIiwiaXRlcmF0ZV9hZnRlcl9ob3Zlcl9kZWxheV9tcyI6IjUwMCIsImhpZGVfbmV4dF9idG4iOiIwIiwiaGlkZV9vdmVybGF5IjoiMCJ9fQ==\",\"hidden_meta\":\"base64__eyJ2YWwiOiIiLCJleHQiOnsiYnVpbGRfd2l0aF93cF9lZGl0b3IiOiIxIn19\"},{\"element\":\"#setSelection\",\"intro\":\"<p>Begin by choosing your favorite MTG set from this dropdown menu.<\\\/p>\",\"position\":\"\",\"highlight\":\"\",\"enable_interaction\":\"base64__eyJ2YWwiOiIwIiwiZXh0Ijp7Iml0ZXJhdGVfYWZ0ZXJfY2xpY2tfc3RvcF9wcm9wYWdhdGlvbiI6IjAiLCJpdGVyYXRlX2FmdGVyX2NsaWNrIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfY2xpY2tfZGVsYXlfbXMiOiI1MDAiLCJvcGVuX3RhcmdldF9saW5rX2NsaWNrc19pbl9uZXdfdGFiIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfaG92ZXIiOiIwIiwiaXRlcmF0ZV9hZnRlcl9ob3Zlcl9kZWxheV9tcyI6IjUwMCIsImhpZGVfbmV4dF9idG4iOiIwIiwiaGlkZV9vdmVybGF5IjoiMCJ9fQ==\",\"hidden_meta\":\"base64__eyJ2YWwiOiIiLCJleHQiOnsiYnVpbGRfd2l0aF93cF9lZGl0b3IiOiIxIn19\"},{\"element\":\"#boosterTypeSelection\",\"intro\":\"<p>Next, select the type of pack you want to simulate - Draft, Set, Collector, or Play Booster.<\\\/p>\",\"position\":\"\",\"highlight\":\"\",\"enable_interaction\":\"base64__eyJ2YWwiOiIwIiwiZXh0Ijp7Iml0ZXJhdGVfYWZ0ZXJfY2xpY2tfc3RvcF9wcm9wYWdhdGlvbiI6IjAiLCJpdGVyYXRlX2FmdGVyX2NsaWNrIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfY2xpY2tfZGVsYXlfbXMiOiI1MDAiLCJvcGVuX3RhcmdldF9saW5rX2NsaWNrc19pbl9uZXdfdGFiIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfaG92ZXIiOiIwIiwiaXRlcmF0ZV9hZnRlcl9ob3Zlcl9kZWxheV9tcyI6IjUwMCIsImhpZGVfbmV4dF9idG4iOiIwIiwiaGlkZV9vdmVybGF5IjoiMCJ9fQ==\",\"hidden_meta\":\"base64__eyJ2YWwiOiIiLCJleHQiOnsiYnVpbGRfd2l0aF93cF9lZGl0b3IiOiIxIn19\"},{\"element\":\"#selectedLayoutLabel\",\"intro\":\"<p>Select a layout for the pack. The default view is a pack view where the cards are stacked on top of each other. Line view is a mobile friendly version where all of the cards are displayed at once. Lastly, the grid view nicely lines up all the cards in a square grid.<\\\/p>\",\"position\":\"\",\"highlight\":\"\",\"enable_interaction\":\"base64__eyJ2YWwiOiIwIiwiZXh0Ijp7Iml0ZXJhdGVfYWZ0ZXJfY2xpY2tfc3RvcF9wcm9wYWdhdGlvbiI6IjAiLCJpdGVyYXRlX2FmdGVyX2NsaWNrIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfY2xpY2tfZGVsYXlfbXMiOiI1MDAiLCJvcGVuX3RhcmdldF9saW5rX2NsaWNrc19pbl9uZXdfdGFiIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfaG92ZXIiOiIwIiwiaXRlcmF0ZV9hZnRlcl9ob3Zlcl9kZWxheV9tcyI6IjUwMCIsImhpZGVfbmV4dF9idG4iOiIwIiwiaGlkZV9vdmVybGF5IjoiMCJ9fQ==\",\"hidden_meta\":\"base64__eyJ2YWwiOiIiLCJleHQiOnsiYnVpbGRfd2l0aF93cF9lZGl0b3IiOiIxIn19\"},{\"element\":\"#smallSizeBtn\",\"intro\":\"<p>Select the size of the cards for a better viewing experience. Choose from Small, Normal, or Large.<\\\/p>\",\"position\":\"\",\"highlight\":\"\",\"enable_interaction\":\"base64__eyJ2YWwiOiIwIiwiZXh0Ijp7Iml0ZXJhdGVfYWZ0ZXJfY2xpY2tfc3RvcF9wcm9wYWdhdGlvbiI6IjAiLCJpdGVyYXRlX2FmdGVyX2NsaWNrIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfY2xpY2tfZGVsYXlfbXMiOiI1MDAiLCJvcGVuX3RhcmdldF9saW5rX2NsaWNrc19pbl9uZXdfdGFiIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfaG92ZXIiOiIwIiwiaXRlcmF0ZV9hZnRlcl9ob3Zlcl9kZWxheV9tcyI6IjUwMCIsImhpZGVfbmV4dF9idG4iOiIwIiwiaGlkZV9vdmVybGF5IjoiMCJ9fQ==\",\"hidden_meta\":\"base64__eyJ2YWwiOiIiLCJleHQiOnsiYnVpbGRfd2l0aF93cF9lZGl0b3IiOiIxIn19\"},{\"element\":\"#generatePackBtn\",\"intro\":\"<p>Finally, click the 'Generate Pack' button to see your random pack of cards. Click on the shown card to reveal the next card.<\\\/p>\",\"position\":\"\",\"highlight\":\"\",\"enable_interaction\":\"base64__eyJ2YWwiOiIwIiwiZXh0Ijp7Iml0ZXJhdGVfYWZ0ZXJfY2xpY2tfc3RvcF9wcm9wYWdhdGlvbiI6IjAiLCJpdGVyYXRlX2FmdGVyX2NsaWNrIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfY2xpY2tfZGVsYXlfbXMiOiI1MDAiLCJvcGVuX3RhcmdldF9saW5rX2NsaWNrc19pbl9uZXdfdGFiIjoiMCIsIml0ZXJhdGVfYWZ0ZXJfaG92ZXIiOiIwIiwiaXRlcmF0ZV9hZnRlcl9ob3Zlcl9kZWxheV9tcyI6IjUwMCIsImhpZGVfbmV4dF9idG4iOiIwIiwiaGlkZV9vdmVybGF5IjoiMCJ9fQ==\",\"hidden_meta\":\"base64__eyJ2YWwiOiIiLCJleHQiOnsiYnVpbGRfd2l0aF93cF9lZGl0b3IiOiIxIn19\"}]","labeling":{"button_arrows":"vector","nextLabel":"Next","prevLabel":"Back","button_cancel_ico":"none","skipLabel":"Cancel","doneLabel":"Done","skipForFutureVisitsLabel":"Skip for future visits"},"properties":{"exitOnOverlayClick":false,"disableStartAnimation":false,"bulletAnimSize":30,"bulletAnimBorderRadius":50,"scrollSpeed":30,"max_tooltip_width":0,"loading_delay":0,"skip_absent_ref_el":false,"hide_previous_step_button":false,"hide_skip_button":false,"disable_navigation_by_bullets":false,"show_bullet_navigation":true,"show_progress_bar":true,"show_step_numbers":true},"accentColor":"#1d6093","text_styles":{"btn_font":"inherit"},"tooltip_radius":"-1","button_radius":"-1","highlight_radius":"-1"}],"currentUserId":"0","currentUserRoles":[],"mobile_break_points":{"mobile":600},"stepDefinitions":{"element":[],"intro":[],"position":[],"highlight":[],"enable_interaction":{"ext":{"iterate_after_click_stop_propagation":{"def":"0"},"iterate_after_click":{"def":"0"},"iterate_after_click_delay_ms":{"def":500},"open_target_link_clicks_in_new_tab":{"def":"0"},"iterate_after_hover":{"def":"0"},"iterate_after_hover_delay_ms":{"def":500},"hide_next_btn":{"def":"0"},"hide_overlay":{"def":"0"}}},"hidden_meta":{"ext":{"build_with_wp_editor":{"def":"0"}}}},"queryParamsDefs":{"dp_qp_step":"dp-step"}};
</script>
<script type='text/javascript' src='https://mtg-packs.com/_static/??-eJydzk1uAyEMBeAL1aUzEJguqp7FGM+UdPjRYBT19iWKInXTRbK0nt9nXypQycJZVN37FnNToULMchSQ0o8xxiYqYczq6FliYiDviGk2r+f2cnmgH3jFvguEGgUwpJjB43Eba/d7JCC7zIZwfpj+Y6zauhmNe8rw2Bia/OwM1ryd1ml62hmvyBenO8dsnXUL/8NtpWxjq0Vh+I5y87A1lqbO9/iajvBabqMMqQQGHax5PwViZE/z4olQjyOf6WNyWk/WLsb9AqAWsQo='></script>
<script src="https://stats.wp.com/e-202449.js" id="jetpack-stats-js" data-wp-strategy="defer"></script>
<script id="jetpack-stats-js-after">
_stq = window._stq || [];
_stq.push([ "view", JSON.parse("{\"v\":\"ext\",\"blog\":\"222738067\",\"post\":\"6\",\"tz\":\"-5\",\"srv\":\"mtg-packs.com\",\"hp\":\"atomic\",\"ac\":\"2\",\"amp\":\"0\",\"j\":\"1:14.1-beta\"}") ]);
_stq.push([ "clickTrackerInit", "222738067", "6" ]);
</script>
<script id="site-reviews-js-before">
window.hasOwnProperty("GLSR")||(window.GLSR={Event:{on:()=>{}}});GLSR.action="glsr_public_action";GLSR.addons=[];GLSR.ajaxpagination=["#wpadminbar",".site-navigation-fixed"];GLSR.ajaxurl="https://mtg-packs.com/wp-admin/admin-ajax.php";GLSR.captcha=[];GLSR.nameprefix="site-reviews";GLSR.starsconfig={"clearable":false,tooltip:"Select a Rating"};GLSR.state={"popstate":false};GLSR.text={closemodal:"Close Modal"};GLSR.urlparameter="reviews-page";GLSR.validationconfig={field:"glsr-field",form:"glsr-form","field_error":"glsr-field-is-invalid","field_hidden":"glsr-hidden","field_message":"glsr-field-error","field_required":"glsr-required","field_valid":"glsr-field-is-valid","form_error":"glsr-form-is-invalid","form_message":"glsr-form-message","form_message_failed":"glsr-form-failed","form_message_success":"glsr-form-success","input_error":"glsr-is-invalid","input_valid":"glsr-is-valid"};GLSR.validationstrings={accepted:"This field must be accepted.",between:"This field value must be between %s and %s.",betweenlength:"This field must have between %s and %s characters.",email:"This field requires a valid e-mail address.",errors:"Please fix the submission errors.",max:"Maximum value for this field is %s.",maxfiles:"This field allows a maximum of %s files.",maxlength:"This field allows a maximum of %s characters.",min:"Minimum value for this field is %s.",minfiles:"This field requires a minimum of %s files.",minlength:"This field requires a minimum of %s characters.",number:"This field requires a number.",pattern:"Please match the requested format.",regex:"Please match the requested format.",required:"This field is required.",tel:"This field requires a valid telephone number.",url:"This field requires a valid website URL (make sure it starts with http or https).",unsupported:"The review could not be submitted because this browser is too old. Please try again with a modern browser."};GLSR.version="7.2.3";
</script>
<script src="https://mtg-packs.com/wp-content/plugins/site-reviews/assets/scripts/site-reviews.js?ver=7.2.3" id="site-reviews-js" defer data-wp-strategy="defer"></script>
<!-- Cookie Notice plugin v2.5.4 by Hu-manity.co https://hu-manity.co/ -->
<div id="cookie-notice" role="dialog" class="cookie-notice-hidden cookie-revoke-hidden cn-position-bottom" aria-label="Cookie Notice" style="background-color: rgba(50,50,58,1);"><div class="cookie-notice-container" style="color: #fff"><span id="cn-notice-text" class="cn-text-container">Our pack simulator is free to the public; however, we do utilize cookies to make your experience more enjoyable. If you would like to learn more, please review our privacy policy below.</span><span id="cn-notice-buttons" class="cn-buttons-container"><a href="#" id="cn-accept-cookie" data-cookie-set="accept" class="cn-set-cookie cn-button" aria-label="Sounds good!" style="background-color: #d17600">Sounds good!</a><a href="https://mtg-packs.com/disclaimer/" target="_blank" id="cn-more-info" class="cn-more-info cn-button" aria-label="Privacy policy" style="background-color: #d17600">Privacy policy</a></span><span id="cn-close-notice" data-cookie-set="accept" class="cn-close-icon" title="No thanks."></span></div>
</div>
<!-- / Cookie Notice plugin --></body>
</html>
<!--
generated in 0.504 seconds
518545 bytes batcached for 300 seconds
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment