Created
February 14, 2022 05:32
-
-
Save stravant/389b6c5810581c2c279b15909e0d0635 to your computer and use it in GitHub Desktop.
Fetch info from masterduelmeta.com to compute relative value of SRs / URs.
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
import requests | |
import json | |
import urllib.parse | |
import re | |
top_decks_url = "https://www.masterduelmeta.com/api/v1/top-decks?limit=0" | |
included_cards = { | |
"Lightning Storm": 1, | |
"Solemn Judgment": 1, | |
"Ash Blossom & Joyous Spring": 1, | |
"Reinforcement of the Army": 1, | |
"Raigeki": 1, | |
"Unexpected Dai": 3, | |
"Blue-Eyes White Dragon": 2, | |
"Five-Headed Dragon": 2, | |
"Junk Synchron": 3, | |
"Junk Warrior": 1, | |
"Colossal Fighter": 1, | |
"Rasterliger": 1, | |
"Decode Talker": 1, | |
"Link Spider": 1, | |
"LANphorhynchus": 1, | |
"Shiranui Shogunsaga": 3, | |
"Shiranui Style Swallow's Slash": 3, | |
"Shiranui Solitaire": 3, | |
"Shiranui Spectralsword": 3, | |
"Digital Bug Rhinosebus": 3, | |
"Gladiator Beast Gaiodiaz": 3, | |
"Gladiator Beast Andabata": 3, | |
"Gladiator Beast Tamer Editor": 3, | |
"Gem-Knight Aquamarine": 3, | |
"Gem-Knight Fusion": 3, | |
} | |
def fetch_top_decks(): | |
top_decks_result = requests.get(top_decks_url) | |
top_decks = top_decks_result.content.decode("utf-8") | |
with open("top_decks.json", "w", encoding="utf-8") as f: | |
f.write(top_decks) | |
return top_decks | |
def tally_card(card_js, count_per_card, max_per_card): | |
name = card_js["card"]["name"] | |
count = card_js["amount"] | |
if name in included_cards: | |
count = max(0, count - included_cards[name]) | |
if name in max_per_card: | |
max_per_card[name] = max(max_per_card[name], count) | |
else: | |
max_per_card[name] = count | |
if name in count_per_card: | |
count_per_card[name] += count | |
else: | |
count_per_card[name] = count | |
def tally_deck(deck_js, count_per_card, max_per_card, count_per_deck): | |
deck_type = deck_js["deckType"]["name"] | |
if deck_type in count_per_deck: | |
count_per_deck[deck_type] += 1 | |
else: | |
count_per_deck[deck_type] = 1 | |
for main_card in deck_js["main"]: | |
tally_card(main_card, count_per_card, max_per_card) | |
for extra_card in deck_js["extra"]: | |
tally_card(extra_card, count_per_card, max_per_card) | |
def transform_and_write_top_decks_json(js): | |
count_per_card = {} | |
count_per_deck = {} | |
max_per_card = {} | |
for deck_js in js: | |
tally_deck(deck_js, count_per_card, max_per_card, count_per_deck) | |
with open("top_decks_processed.json", "w", encoding="utf-8") as fout: | |
fout.write(json.dumps({ | |
"total": len(js), | |
"count_per_deck": count_per_deck, | |
"count_per_card": count_per_card, | |
"max_per_card": max_per_card, | |
})) | |
def process_top_decks(): | |
with open("top_decks.json", "r", encoding="utf-8") as f: | |
transform_and_write_top_decks_json(json.loads(f.read())) | |
def open_card_info(): | |
try: | |
with open("card_info.json", "r", encoding="utf-8") as f: | |
return json.loads(f.read()) | |
except FileNotFoundError: | |
return {} | |
def write_card_info(info): | |
with open("card_info.json", "w", encoding="utf-8") as f: | |
f.write(json.dumps(info)) | |
def open_deck_stats(): | |
with open("top_decks_processed.json", "r", encoding="utf-8") as f: | |
return json.loads(f.read()) | |
card_url = "https://www.masterduelmeta.com/cards/%s" | |
# <div class="rarity-image svelte-en6kzk"><img src="/img/assets/rarities/ur.png" | |
def update_card_info(): | |
card_info = open_card_info() | |
deck_stats = open_deck_stats() | |
count_per_card = deck_stats["count_per_card"] | |
written = 0 | |
for name in count_per_card: | |
if not name in card_info: | |
encoded_name = urllib.parse.quote(name) | |
encoded_name = encoded_name.replace("/", "%2f") | |
result = requests.get(card_url % encoded_name) | |
if result.status_code == 200: | |
match = re.search('<div class="rarity-image svelte-en6kzk"><img src="/img/assets/rarities/(\\w+).png', result.content.decode("utf-8")) | |
rarity = match.group(1).lower() if match else "n" | |
card_info[name] = rarity | |
print("Rarity of '%s' is %s" % (name, rarity)) | |
written += 1 | |
if written > 10: | |
write_card_info(card_info) | |
written = 0 | |
else: | |
print("Failed to get card '%s'" % name) | |
write_card_info(card_info) | |
def tally_results(): | |
card_info = open_card_info() | |
deck_stats = open_deck_stats() | |
deck_count = deck_stats["total"] | |
count_by_rarity = { | |
"n": 0, | |
"r": 0, | |
"sr": 0, | |
"ur": 0, | |
} | |
count_per_card = deck_stats["count_per_card"] | |
for card in count_per_card: | |
count_by_rarity[card_info[card]] += count_per_card[card] | |
for rarity in count_by_rarity: | |
count_by_rarity[rarity] /= deck_count | |
# | |
total_needed_by_rarity = { | |
"n": 0, | |
"r": 0, | |
"sr": 0, | |
"ur": 0, | |
} | |
max_per_card = deck_stats["max_per_card"] | |
for card in max_per_card: | |
total_needed_by_rarity[card_info[card]] += max_per_card[card] | |
# | |
print("UR per SR (single deck): %.1f" % (count_by_rarity["ur"] / count_by_rarity["sr"])) | |
print("UR per SR (every deck): %.1f" % (total_needed_by_rarity["ur"] / total_needed_by_rarity["sr"])) | |
def everything(): | |
fetch_top_decks() | |
process_top_decks() | |
update_card_info() | |
tally_results() | |
if __name__ == "__main__": | |
everything() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment