From 842921397d934fe11fbbe2fd889d65942d29e451 Mon Sep 17 00:00:00 2001 From: Tom Szymanski Date: Wed, 17 Jul 2024 13:23:52 -0500 Subject: [PATCH 1/5] v3.25 init --- builder/Installer.iss | 4 ++-- release_notes.txt | 3 +++ src/overlay.py | 2 +- tests/test_app_update.py | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/builder/Installer.iss b/builder/Installer.iss index e2bc7e6..39d6147 100644 --- a/builder/Installer.iss +++ b/builder/Installer.iss @@ -1,7 +1,7 @@ ; -- MtgaDraft.iss -- [Setup] AppName=MTGA Draft Tool -AppVersion=3.24 +AppVersion=3.25 WizardStyle=modern DefaultDirName={sd}\MtgaDraftTool DefaultGroupName=MtgaDraftTool @@ -11,7 +11,7 @@ Compression=lzma2 UsePreviousAppDir=yes SolidCompression=yes OutputDir={app} -OutputBaseFilename=MTGA_Draft_Tool_V0324 +OutputBaseFilename=MTGA_Draft_Tool_V0325 InfoAfterFile=..\release_notes.txt [Files] Source: "..\dist\MTGA_Draft_Tool.exe"; DestDir: "{app}" diff --git a/release_notes.txt b/release_notes.txt index 2ff466a..c789e89 100644 --- a/release_notes.txt +++ b/release_notes.txt @@ -1,3 +1,6 @@ +===================== RELEASE NOTES 3.25 ===================== +* TBD + ===================== RELEASE NOTES 3.24 ===================== * FiYir released feature: Card Popup Archetype Stats #32: Add archetype stats to card popup window diff --git a/src/overlay.py b/src/overlay.py index cc4be55..86a20f1 100644 --- a/src/overlay.py +++ b/src/overlay.py @@ -40,7 +40,7 @@ except ImportError: pass -APPLICATION_VERSION = 3.24 +APPLICATION_VERSION = 3.25 HOTKEY_CTRL_G = '\x07' diff --git a/tests/test_app_update.py b/tests/test_app_update.py index a34757d..4e30e25 100644 --- a/tests/test_app_update.py +++ b/tests/test_app_update.py @@ -27,7 +27,7 @@ def invalid_input_url(): @pytest.fixture def valid_input_url_zip(): - return "https://github.com/unrealities/MTGA_Draft_17Lands/releases/download/MTGA_Draft_Tool_V0323/MTGA_Draft_Tool_V0323.zip" + return "https://github.com/unrealities/MTGA_Draft_17Lands/releases/download/MTGA_Draft_Tool_V0324/MTGA_Draft_Tool_V0324.zip" @pytest.fixture def output_filename(): From 6cd29333c82042a5f5f15356730d77aa09a744b9 Mon Sep 17 00:00:00 2001 From: FiYir <> Date: Fri, 19 Jul 2024 14:44:57 -0400 Subject: [PATCH 2/5] FEAT: Adding dataset pre-download check --- src/file_extractor.py | 12 +++++-- src/overlay.py | 80 +++++++++++++++++++++++++++++++++++++------ src/utils.py | 9 ++++- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/src/file_extractor.py b/src/file_extractor.py index 1af3cf4..46adc85 100644 --- a/src/file_extractor.py +++ b/src/file_extractor.py @@ -762,6 +762,8 @@ def _assemble_set(self, matching_only): def retrieve_17lands_color_ratings(self): '''Use 17Lands endpoint to collect the data from the color_ratings page''' + result = True + game_count = 0 try: if self.user_group == constants.LIMITED_USER_GROUP_ALL: user_group = "" @@ -771,11 +773,13 @@ def retrieve_17lands_color_ratings(self): url_data = urllib.request.urlopen(url, context=self.context).read() color_json_data = json.loads(url_data) - self._process_17lands_color_ratings(color_json_data) + game_count = self._process_17lands_color_ratings(color_json_data) except Exception as error: + result = False logger.error(url) logger.error(error) + return result, game_count def _process_17lands_data(self, colors, cards): '''Parse the 17Lands json data to extract the card ratings''' @@ -847,7 +851,7 @@ def _process_17lands_color_ratings(self, colors): "(RGW)": "RGW", "(GWU)": "GWU", } - + game_count = 0 try: self.combined_data["color_ratings"] = {} for color in colors: @@ -866,9 +870,13 @@ def _process_17lands_color_ratings(self, colors): if processed_colors not in self.combined_data["color_ratings"]: self.combined_data["color_ratings"][processed_colors] = winrate + elif color["is_summary"] and color["color_name"] == "All Decks": + game_count = color["games"] if color["games"] else 0 + self.combined_data["meta"]["game_count"] = game_count except Exception as error: logger.error(error) + return game_count def _process_scryfall_data(self, data): '''Parse json data from the Scryfall API to extract pertinent card data''' diff --git a/src/overlay.py b/src/overlay.py index cc4be55..cbb2381 100644 --- a/src/overlay.py +++ b/src/overlay.py @@ -2,7 +2,7 @@ import tkinter from tkinter.ttk import Progressbar, Treeview, Style, OptionMenu, Button, Checkbutton, Label, Separator, Entry from tkinter import filedialog, messagebox, font -from datetime import date +from datetime import date, datetime, UTC import urllib import sys import io @@ -419,6 +419,7 @@ def __init__(self, args): self.root.title(f"Version {APPLICATION_VERSION:2.2f}") self.configuration, _ = read_configuration() self.root.resizable(False, False) + self.last_download = 0 self.__set_os_configuration() @@ -464,7 +465,7 @@ def __init__(self, args): self.filemenu.add_command(label="Open", command=self.__open_draft_log) self.datamenu = tkinter.Menu(self.menubar, tearoff=0) self.datamenu.add_command( - label="Add Sets", command=self.__open_set_view_window) + label="Download Dataset", command=self.__open_set_view_window) self.cardmenu = tkinter.Menu(self.menubar, tearoff=0) self.cardmenu.add_command( @@ -1796,7 +1797,7 @@ def __open_set_view_window(self): return popup = tkinter.Toplevel() - popup.wm_title("Add Sets") + popup.wm_title("Download Dataset") popup.protocol("WM_DELETE_WINDOW", lambda window=popup: self.__close_set_view_window(window)) popup.resizable(width=False, height=True) @@ -1905,7 +1906,7 @@ def __open_set_view_window(self): list_box, sets, status_text, - constants.DATA_SET_VERSION_3), text="ADD SET") + constants.DATA_SET_VERSION_3), text="DOWNLOAD") event_separator = Separator(popup, orient='vertical') set_separator = Separator(popup, orient='vertical') @@ -2820,15 +2821,27 @@ def __open_about_window(self): logger.error(error) def __add_set(self, popup, draft_set, draft, start, end, user_group, button, progress, list_box, sets, status, version): - '''Initiates the set download process when the Add Set button is clicked''' + '''Initiates the set download process when the Download Dataset button is clicked''' result = True result_string = "" return_size = 0 + current_time = datetime.now().timestamp() while True: try: - message_box = tkinter.messagebox.askyesno( - title="Download", message=f"17Lands updates their card data once a day at 03:00 UTC.\n\nAre you sure that you want to download the {draft_set.get()} {draft.get()} dataset?") - if not message_box: + time_difference = current_time - self.last_download + if time_difference >= constants.DATASET_DOWNLOAD_RATE_LIMIT_SEC: + message_box = tkinter.messagebox.askyesno( + title="Download", + message=f"Are you sure that you want to download the {draft_set.get()} {draft.get()} dataset?" + ) + if not message_box: + break + else: + message_box = tkinter.messagebox.showinfo( + title="Download", + message="Rate limit reached.\n\n" + f"Please wait {int(constants.DATASET_DOWNLOAD_RATE_LIMIT_SEC - time_difference)} seconds before trying again." + ) break status.set("Starting Download Process") @@ -2848,8 +2861,55 @@ def __add_set(self, popup, draft_set, draft, start, end, user_group, button, pro break self.extractor.set_user_group(user_group.get()) self.extractor.set_version(version) + + set_codes = [v.seventeenlands[0] for v in sets.values()] + file_list, error_list = retrieve_local_set_list(set_codes) + + # Log all of errors generated by retrieve_local_set_list + for error_string in error_list: + logger.error(error_string) + + self.last_download = current_time + status.set("Downloading Color Ratings") - self.extractor.retrieve_17lands_color_ratings() + result, game_count = self.extractor.retrieve_17lands_color_ratings() + + if result and file_list: + if game_count == 0: + message_box = tkinter.messagebox.askyesno( + title="Download", + message=f"17Lands doesn't have data for {draft_set.get()} {draft.get()} {start.get()} to {end.get()}.\n\n" + "Would you still like to continue with the download?" + ) + if not message_box: + status.set("Download Cancelled") + break + else: + notify = False + set_code = sets[draft_set.get()].seventeenlands[0] + for file in file_list: + if( + set_code == file[0] and + draft.get() == file[1] and + user_group.get() == file[2] and + start.get() == file[3] and + (end.get() == file[4] or end.get() > file[4]) and + game_count == file[6] + ): + notify = True + break + + if notify: + current_time_utc = datetime.now(UTC).strftime('%H:%M:%S') + message_box = tkinter.messagebox.askyesno( + title="Download", + message="Your dataset is already up-to-date.\n\n" + f"It's currently {current_time_utc} UTC, and 17Lands updates their card data once a day around 03:00:00 UTC.\n\n" + "Would you still like to continue with the download?" + ) + if not message_box: + status.set("Download Cancelled") + break result, result_string, temp_size = self.extractor.download_card_data( popup, progress, status, self.configuration.card_data.database_size) @@ -2862,7 +2922,6 @@ def __add_set(self, popup, draft_set, draft, start, end, user_group, button, pro result_string = "File Write Failure" break progress['value'] = 100 - button['state'] = 'normal' return_size = temp_size popup.update() status.set("Updating Set List") @@ -2886,6 +2945,7 @@ def __add_set(self, popup, draft_set, draft, start, end, user_group, button, pro message_box = tkinter.messagebox.showwarning( title="Error", message=message_string) else: + button['state'] = 'normal' self.configuration.card_data.database_size = return_size write_configuration(self.configuration) popup.update() diff --git a/src/utils.py b/src/utils.py index 4420591..7e17e7d 100644 --- a/src/utils.py +++ b/src/utils.py @@ -97,13 +97,20 @@ def retrieve_local_set_list(codes, names = None): else: start_date = json_data["meta"]["start_date"] end_date = json_data["meta"]["end_date"] + + if "game_count" in json_data["meta"]: + game_count = json_data["meta"]["game_count"] + else: + game_count = 0 + file_list.append(( set_name, event_type, user_group, start_date, end_date, - file_location + file_location, + game_count )) except Exception as error: error_list.append(error) From aa626311feaa72e5eee7ea03a6b3742c322ab009 Mon Sep 17 00:00:00 2001 From: FiYir <> Date: Fri, 19 Jul 2024 15:00:04 -0400 Subject: [PATCH 3/5] merge --- src/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/constants.py b/src/constants.py index 4eb382c..f07c4cc 100644 --- a/src/constants.py +++ b/src/constants.py @@ -263,6 +263,8 @@ SCRYFALL_REQUEST_BACKOFF_DELAY_SECONDS = 5 SCRYFALL_REQUEST_ATTEMPT_MAX = 5 +DATASET_DOWNLOAD_RATE_LIMIT_SEC = 60 + PLATFORM_ID_OSX = "darwin" PLATFORM_ID_WINDOWS = "win32" PLATFORM_ID_LINUX = "linux" From e24baf556d47adcf3b6477f31b26c6ef0eea34fe Mon Sep 17 00:00:00 2001 From: FiYir <> Date: Fri, 19 Jul 2024 15:08:54 -0400 Subject: [PATCH 4/5] TEST: Fixing utils test case --- README.md | 6 +++--- tests/test_utils.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8fae4e2..de9ba35 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Magic: The Gathering Arena draft tool that utilizes 17Lands data. - This step isn't necessary if the application is installed in the main directory of a drive (i.e., `C:/` or `D:/`) or the `Users//` directory - **Step 4:** In Arena, go to Adjust Options, Account, and then check the Detailed Logs (Plugin Support) check box. - **Step 5:** Double-click `MTGA_Draft_Tool.exe` to start the program. -- **Step 6:** Download the sets you plan to use (`Data->Add Sets`). +- **Step 6:** Download the sets you plan to use (`Data->Download Dataset`). Event datasets can be used for different events (e.g., the premier draft dataset can be used for a sealed event). - Quick draft players should consider using the premier draft dataset when quick draft initially becomes available. - **Step 7:** Configure the tool through the [Settings window](#settings). @@ -69,7 +69,7 @@ Magic: The Gathering Arena draft tool that utilizes 17Lands data. - **Bottles (Linux):** /home/{username}/.var/app/com.usebottles.bottles/data/bottles/bottles/MTG-Arena/drive_c/users/{username}/AppData/LocalLow/Wizards Of The Coast/MTGA/Player.log - **Lutris (Linux):** /home/{username}/Games/magic-the-gathering-arena/drive_c/users/{username}/AppData/LocalLow/Wizards Of The Coast/MTGA/Player.log - **Step 10:** (Mac Only) Set Arena to window mode. -- **Step 11:** Download the sets you plan to use (`Data->Add Sets`). +- **Step 11:** Download the sets you plan to use (`Data->Download Dataset`). - Event datasets can be used for different events (e.g., the premier draft dataset can be used for a sealed event). - Select `Arena Cube` and adjust the start date to download the data from the most recent Arena Cube event. - Quick draft players should consider using the premier draft dataset when quick draft initially becomes available. @@ -127,7 +127,7 @@ Magic: The Gathering Arena draft tool that utilizes 17Lands data. ![Settings_Colors](https://github.com/unrealities/MTGA_Draft_17Lands/blob/main/assets/96687942/90c6b3df-0ade-4f32-a1be-b2ef40cedc32.png) - **Read Draft Logs:** Read the log file from a draft by selecting `File->Open`. Select a file that has the following naming scheme `DraftLog___.log` file to read the file. -- **Download Set Data:** Open the Add Sets window by selecting `Data->Add Sets`. Enter the set information and click the ADD SET button to begin downloading the set data. +- **Download Set Data:** Open the Download Dataset window by selecting `Data->Download Dataset`. Enter the set information and click the ADD SET button to begin downloading the set data. - The download can take several minutes. - 17Lands will timeout the request if too many requests are made within a short period. - **List Taken Cards:** Get to the Taken Cards window by selecting `Cards->Taken Cards`. diff --git a/tests/test_utils.py b/tests/test_utils.py index 7906101..66a6c9f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -24,10 +24,10 @@ "OTJ_FakeDraft_All_Data.json", ] MOCKED_DATASETS_LIST_VALID = [ - ("MH3", "PremierDraft", "All", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "MH3_PremierDraft_All_Data.json")), - ("MH3", "PremierDraft", "Top", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "MH3_PremierDraft_Top_Data.json")), - ("OTJ", "TradDraft", "Middle", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "OTJ_TradDraft_Middle_Data.json")), - ("OTJ", "QuickDraft", "Bottom", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "OTJ_QuickDraft_Bottom_Data.json")) + ("MH3", "PremierDraft", "All", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "MH3_PremierDraft_All_Data.json"), 0), + ("MH3", "PremierDraft", "Top", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "MH3_PremierDraft_Top_Data.json"), 0), + ("OTJ", "TradDraft", "Middle", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "OTJ_TradDraft_Middle_Data.json"), 0), + ("OTJ", "QuickDraft", "Bottom", "2019-01-01", "2024-07-11", os.path.join(SETS_FOLDER, "OTJ_QuickDraft_Bottom_Data.json"), 0) ] MOCKED_DATASET_JSON = { "meta" : { From e1a720b89f8816dbcfaa602917ed5406c7b7bc6f Mon Sep 17 00:00:00 2001 From: Tom Szymanski Date: Sat, 20 Jul 2024 11:09:48 -0500 Subject: [PATCH 5/5] update release notes --- release_notes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release_notes.txt b/release_notes.txt index c789e89..e539c6c 100644 --- a/release_notes.txt +++ b/release_notes.txt @@ -1,5 +1,5 @@ ===================== RELEASE NOTES 3.25 ===================== -* TBD +* FiYir released feature: Dataset Pre-Download Check #38 ===================== RELEASE NOTES 3.24 ===================== * FiYir released feature: Card Popup Archetype Stats #32: Add archetype stats to card popup window