Created
December 5, 2024 18:49
-
-
Save joshbedo/6169cf6ddaf66f4be6cf8bd49db02903 to your computer and use it in GitHub Desktop.
magic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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 […]" /> | |
<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 […]" /> | |
<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&d=identicon&r=g","url":"https://secure.gravatar.com/avatar/45ef2dd70cd0eb831d4d5191e366a2e1?s=96&d=identicon&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 » Feed" href="https://mtg-packs.com/feed/" /> | |
<link rel="alternate" type="application/octet-stream" title="Magic the Gathering (MTG) Pack Simulator » 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&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&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&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&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&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&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&family=Open+Sans&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’s a draft booster pack or a collector’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 “Generate” 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’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’s War</option> | |
<option value="DMU">Dominaria United</option> | |
<option value="2X2">Double Masters 2022</option> | |
<option value="CLB">Commander Legends: Battle for Baldur’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’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’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="{"woo_active":"0"}" 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