mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-04 11:48:22 +02:00
Added docstring and more type hint tp Game, Gui and Track to make the code more understandable
This commit is contained in:
parent
ee8fea9c5f
commit
a6ec86c61d
3 changed files with 197 additions and 72 deletions
121
source/Game.py
121
source/Game.py
|
@ -1,4 +1,4 @@
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox, StringVar, BooleanVar, IntVar
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import shutil
|
import shutil
|
||||||
import glob
|
import glob
|
||||||
|
@ -40,8 +40,32 @@ class CantConvertTrack(Exception):
|
||||||
super().__init__("Can't convert track, check if download are enabled.")
|
super().__init__("Can't convert track, check if download are enabled.")
|
||||||
|
|
||||||
|
|
||||||
|
class NoGui:
|
||||||
|
"""
|
||||||
|
'fake' gui if no gui are used for compatibility.
|
||||||
|
"""
|
||||||
|
def progression(self, *args, **kwargs): print(args, kwargs)
|
||||||
|
def translate(self, *args, **kwargs): return ""
|
||||||
|
def log_error(self, *args, **kwargs): print(args, kwargs)
|
||||||
|
|
||||||
|
is_dev_version = False
|
||||||
|
|
||||||
|
stringvar_game_format = StringVar()
|
||||||
|
boolvar_disable_download = BooleanVar()
|
||||||
|
intvar_process_track = IntVar()
|
||||||
|
boolvar_dont_check_track_sha1 = BooleanVar()
|
||||||
|
boolvar_del_track_after_conv = BooleanVar()
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
def __init__(self, path: str = "", region_ID: str = "P", game_ID: str = "RMCP01", gui=None):
|
def __init__(self, path: str = "", region_ID: str = "P", game_ID: str = "RMCP01", gui=None):
|
||||||
|
"""
|
||||||
|
Class about the game code and its treatment.
|
||||||
|
:param path: path of the game file / directory
|
||||||
|
:param region_ID: game's region id (P for PAL, K for KOR, ...)
|
||||||
|
:param game_ID: game's id (RMCP01 for PAL, ...)
|
||||||
|
:param gui: gui class used by the program
|
||||||
|
"""
|
||||||
if not os.path.exists(path) and path: raise InvalidGamePath()
|
if not os.path.exists(path) and path: raise InvalidGamePath()
|
||||||
self.extension = None
|
self.extension = None
|
||||||
self.path = path
|
self.path = path
|
||||||
|
@ -49,17 +73,21 @@ class Game:
|
||||||
self.region = region_id_to_name[region_ID]
|
self.region = region_id_to_name[region_ID]
|
||||||
self.region_ID = region_ID
|
self.region_ID = region_ID
|
||||||
self.game_ID = game_ID
|
self.game_ID = game_ID
|
||||||
self.gui = gui
|
self.gui = gui if gui else NoGui
|
||||||
self.ctconfig = CT_Config(gui=gui)
|
self.ctconfig = CT_Config(gui=gui)
|
||||||
|
|
||||||
def set_path(self, path):
|
def set_path(self, path: str) -> None:
|
||||||
|
"""
|
||||||
|
Change game path
|
||||||
|
:param path: game's file
|
||||||
|
"""
|
||||||
self.extension = get_extension(path).upper()
|
self.extension = get_extension(path).upper()
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
def convert_to(self, format: str = "FST"):
|
def convert_to(self, format: str = "FST") -> None:
|
||||||
"""
|
"""
|
||||||
|
Convert game to an another format
|
||||||
:param format: game format (ISO, WBFS, ...)
|
:param format: game format (ISO, WBFS, ...)
|
||||||
:return: converted game path
|
|
||||||
"""
|
"""
|
||||||
if format in ["ISO", "WBFS", "CISO"]:
|
if format in ["ISO", "WBFS", "CISO"]:
|
||||||
path_game_format: str = os.path.realpath(self.path + "/../MKWFaraphel." + format.lower())
|
path_game_format: str = os.path.realpath(self.path + "/../MKWFaraphel." + format.lower())
|
||||||
|
@ -70,7 +98,10 @@ class Game:
|
||||||
self.gui.progress(statut=self.gui.translate("Changing game's ID"), add=1)
|
self.gui.progress(statut=self.gui.translate("Changing game's ID"), add=1)
|
||||||
wszst.edit(self.path, region_ID=self.region_ID, name=f"Mario Kart Wii Faraphel {self.ctconfig.version}")
|
wszst.edit(self.path, region_ID=self.region_ID, name=f"Mario Kart Wii Faraphel {self.ctconfig.version}")
|
||||||
|
|
||||||
def extract(self):
|
def extract(self) -> None:
|
||||||
|
"""
|
||||||
|
Extract game file in the same directory.
|
||||||
|
"""
|
||||||
if self.extension == "DOL":
|
if self.extension == "DOL":
|
||||||
self.path = os.path.realpath(self.path + "/../../") # main.dol is in PATH/sys/, so go back 2 dir upper
|
self.path = os.path.realpath(self.path + "/../../") # main.dol is in PATH/sys/, so go back 2 dir upper
|
||||||
|
|
||||||
|
@ -104,6 +135,9 @@ class Game:
|
||||||
|
|
||||||
@in_thread
|
@in_thread
|
||||||
def install_mod(self):
|
def install_mod(self):
|
||||||
|
"""
|
||||||
|
Patch the game to install the mod
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
with open("./fs.json") as f:
|
with open("./fs.json") as f:
|
||||||
fs = json.load(f)
|
fs = json.load(f)
|
||||||
|
@ -204,14 +238,22 @@ class Game:
|
||||||
finally:
|
finally:
|
||||||
self.gui.progress(show=False)
|
self.gui.progress(show=False)
|
||||||
|
|
||||||
def patch_autoadd(self, auto_add_dir: str = "./file/auto-add"):
|
def patch_autoadd(self, auto_add_dir: str = "./file/auto-add") -> None:
|
||||||
|
"""
|
||||||
|
Create the autoadd directory used to convert wbz track into szs
|
||||||
|
:param auto_add_dir: autoadd directory
|
||||||
|
"""
|
||||||
if os.path.exists(auto_add_dir): shutil.rmtree(auto_add_dir)
|
if os.path.exists(auto_add_dir): shutil.rmtree(auto_add_dir)
|
||||||
if not os.path.exists(self.path + "/tmp/"): os.makedirs(self.path + "/tmp/")
|
if not os.path.exists(self.path + "/tmp/"): os.makedirs(self.path + "/tmp/")
|
||||||
wszst.autoadd(self.path, get_nodir(self.path) + "/tmp/auto-add/")
|
wszst.autoadd(self.path, get_nodir(self.path) + "/tmp/auto-add/")
|
||||||
shutil.move(self.path + "/tmp/auto-add/", auto_add_dir)
|
shutil.move(self.path + "/tmp/auto-add/", auto_add_dir)
|
||||||
shutil.rmtree(self.path + "/tmp/")
|
shutil.rmtree(self.path + "/tmp/")
|
||||||
|
|
||||||
def patch_bmg(self, gamefile: str): # gamefile est le fichier .szs trouvé dans le /files/Scene/UI/ du jeu
|
def patch_bmg(self, gamefile: str) -> None:
|
||||||
|
"""
|
||||||
|
Patch bmg file (text file)
|
||||||
|
:param gamefile: an .szs file where file will be patched
|
||||||
|
"""
|
||||||
NINTENDO_CWF_REPLACE = "Wiimmfi"
|
NINTENDO_CWF_REPLACE = "Wiimmfi"
|
||||||
MAINMENU_REPLACE = f"MKWFaraphel {self.ctconfig.version}"
|
MAINMENU_REPLACE = f"MKWFaraphel {self.ctconfig.version}"
|
||||||
menu_replacement = {
|
menu_replacement = {
|
||||||
|
@ -297,6 +339,9 @@ class Game:
|
||||||
|
|
||||||
@in_thread
|
@in_thread
|
||||||
def patch_file(self):
|
def patch_file(self):
|
||||||
|
"""
|
||||||
|
Prepare all files to install the mod (track, bmg text, descriptive image, ...)
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
if not (os.path.exists("./file/Track-WU8/")): os.makedirs("./file/Track-WU8/")
|
if not (os.path.exists("./file/Track-WU8/")): os.makedirs("./file/Track-WU8/")
|
||||||
with open("./convert_file.json") as f:
|
with open("./convert_file.json") as f:
|
||||||
|
@ -329,13 +374,24 @@ class Game:
|
||||||
finally:
|
finally:
|
||||||
self.gui.progress(show=False)
|
self.gui.progress(show=False)
|
||||||
|
|
||||||
def patch_image(self, fc):
|
def patch_image(self, fc) -> None:
|
||||||
|
"""
|
||||||
|
Convert .png image into the format wrote in convert_file
|
||||||
|
:param fc:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
for i, file in enumerate(fc["img"]):
|
for i, file in enumerate(fc["img"]):
|
||||||
self.gui.progress(statut=self.gui.translate("Converting images") + f"\n({i + 1}/{len(fc['img'])}) {file}",
|
self.gui.progress(statut=self.gui.translate("Converting images") + f"\n({i + 1}/{len(fc['img'])}) {file}",
|
||||||
add=1)
|
add=1)
|
||||||
wszst.img_encode("./file/" + file, fc["img"][file])
|
wszst.img_encode("./file/" + file, fc["img"][file])
|
||||||
|
|
||||||
def patch_img_desc(self, img_desc_path: str = "./file/img_desc", dest_dir: str = "./file"):
|
def patch_img_desc(self, img_desc_path: str = "./file/img_desc", dest_dir: str = "./file") -> None:
|
||||||
|
"""
|
||||||
|
patch descriptive image used when the game boot
|
||||||
|
:param img_desc_path: directory where original part of the image are stored
|
||||||
|
:param dest_dir: directory where patched image will be saved
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
il = Image.open(img_desc_path + "/illustration.png")
|
il = Image.open(img_desc_path + "/illustration.png")
|
||||||
il_16_9 = il.resize((832, 456))
|
il_16_9 = il.resize((832, 456))
|
||||||
il_4_3 = il.resize((608, 456))
|
il_4_3 = il.resize((608, 456))
|
||||||
|
@ -355,12 +411,21 @@ class Game:
|
||||||
new_4_3.paste(img_lang_4_3, (0, 0), img_lang_4_3)
|
new_4_3.paste(img_lang_4_3, (0, 0), img_lang_4_3)
|
||||||
new_4_3.save(dest_dir + f"/strapA_608x456{get_filename(get_nodir(file_lang))}.png")
|
new_4_3.save(dest_dir + f"/strapA_608x456{get_filename(get_nodir(file_lang))}.png")
|
||||||
|
|
||||||
def patch_tracks(self):
|
def patch_tracks(self) -> int:
|
||||||
|
"""
|
||||||
|
Download track's wu8 file and convert them to szs
|
||||||
|
:return: 0 if no error occured
|
||||||
|
"""
|
||||||
max_process = self.gui.intvar_process_track.get()
|
max_process = self.gui.intvar_process_track.get()
|
||||||
thread_list = {}
|
thread_list = {}
|
||||||
error_count, error_max = 0, 3
|
error_count, error_max = 0, 3
|
||||||
|
|
||||||
def add_process(track):
|
def add_process(track) -> int:
|
||||||
|
"""
|
||||||
|
a "single thread" to download, check sha1 and convert a track
|
||||||
|
:param track: the track that will be patched
|
||||||
|
:return: 0 if no error occured
|
||||||
|
"""
|
||||||
nonlocal error_count, error_max, thread_list
|
nonlocal error_count, error_max, thread_list
|
||||||
|
|
||||||
for _track in [track.file_szs, track.file_wu8]:
|
for _track in [track.file_szs, track.file_wu8]:
|
||||||
|
@ -370,6 +435,8 @@ class Game:
|
||||||
|
|
||||||
if not self.gui.boolvar_disable_download.get():
|
if not self.gui.boolvar_disable_download.get():
|
||||||
while True:
|
while True:
|
||||||
|
download_returncode = 0
|
||||||
|
if not os.path.exists(track.file_wu8):
|
||||||
download_returncode = track.download_wu8(
|
download_returncode = track.download_wu8(
|
||||||
GITHUB_DEV_BRANCH if self.gui.is_dev_version else GITHUB_MASTER_BRANCH)
|
GITHUB_DEV_BRANCH if self.gui.is_dev_version else GITHUB_MASTER_BRANCH)
|
||||||
if download_returncode == -1: # can't download
|
if download_returncode == -1: # can't download
|
||||||
|
@ -383,8 +450,6 @@ class Game:
|
||||||
messagebox.showwarning(self.gui.translate("Warning"),
|
messagebox.showwarning(self.gui.translate("Warning"),
|
||||||
self.gui.translate("Can't download this track !",
|
self.gui.translate("Can't download this track !",
|
||||||
f" ({error_count} / {error_max})"))
|
f" ({error_count} / {error_max})"))
|
||||||
elif download_returncode == 2:
|
|
||||||
break # if download is disabled, do not check sha1
|
|
||||||
|
|
||||||
if track.sha1:
|
if track.sha1:
|
||||||
if not self.gui.boolvar_dont_check_track_sha1.get():
|
if not self.gui.boolvar_dont_check_track_sha1.get():
|
||||||
|
@ -399,7 +464,7 @@ class Game:
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if not (os.path.exists(track.file_szs)) or download_returncode == 3:
|
if not os.path.exists(track.file_szs) or download_returncode == 3:
|
||||||
# returncode 3 is track has been updated
|
# returncode 3 is track has been updated
|
||||||
if os.path.exists(track.file_wu8):
|
if os.path.exists(track.file_wu8):
|
||||||
track.convert_wu8_to_szs()
|
track.convert_wu8_to_szs()
|
||||||
|
@ -411,29 +476,17 @@ class Game:
|
||||||
os.remove(track.file_wu8)
|
os.remove(track.file_wu8)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def clean_process():
|
def clean_process() -> int:
|
||||||
|
"""
|
||||||
|
Check if a track conversion ended, and remove them from thread_list
|
||||||
|
:return: 0 if thread_list is empty, else 1
|
||||||
|
"""
|
||||||
nonlocal error_count, error_max, thread_list
|
nonlocal error_count, error_max, thread_list
|
||||||
|
|
||||||
for track_key, thread in thread_list.copy().items():
|
for track_key, thread in thread_list.copy().items():
|
||||||
if not thread.is_alive(): # if conversion ended
|
if not thread.is_alive(): # if conversion ended
|
||||||
thread_list.pop(track_key)
|
thread_list.pop(track_key)
|
||||||
"""stderr = thread.stderr.read()
|
if self.gui.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)
|
||||||
if b"wszst: ERROR" in stderr: # Error occured
|
|
||||||
os.remove(track.file_szs)
|
|
||||||
error_count += 1
|
|
||||||
if error_count > error_max: # Too much track wasn't correctly converted
|
|
||||||
messagebox.showerror(
|
|
||||||
self.gui.translate("Error"),
|
|
||||||
self.gui.translate("Too much track had a conversion issue."))
|
|
||||||
raise CantConvertTrack()
|
|
||||||
else: # if the error max hasn't been reach
|
|
||||||
messagebox.showwarning(
|
|
||||||
self.gui.translate("Warning"),
|
|
||||||
self.gui.translate("The track", " ", track.file_wu8,
|
|
||||||
"do not have been properly converted.",
|
|
||||||
f" ({error_count} / {error_max})"))
|
|
||||||
else:
|
|
||||||
if self.gui.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)"""
|
|
||||||
if not (any(thread_list.values())): return 1 # if there is no more process
|
if not (any(thread_list.values())): return 1 # if there is no more process
|
||||||
|
|
||||||
if len(thread_list): return 1
|
if len(thread_list): return 1
|
||||||
|
@ -441,7 +494,7 @@ class Game:
|
||||||
|
|
||||||
total_track = len(self.ctconfig.all_tracks)
|
total_track = len(self.ctconfig.all_tracks)
|
||||||
for i, track in enumerate(self.ctconfig.all_tracks):
|
for i, track in enumerate(self.ctconfig.all_tracks):
|
||||||
while True:
|
while error_count <= error_max:
|
||||||
if len(thread_list) < max_process:
|
if len(thread_list) < max_process:
|
||||||
track_name = track.get_track_name()
|
track_name = track.get_track_name()
|
||||||
thread_list[track_name] = Thread(target=add_process, args=[track])
|
thread_list[track_name] = Thread(target=add_process, args=[track])
|
||||||
|
|
|
@ -20,6 +20,9 @@ def restart():
|
||||||
|
|
||||||
class Gui:
|
class Gui:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Initialize program Gui
|
||||||
|
"""
|
||||||
self.root = Tk()
|
self.root = Tk()
|
||||||
|
|
||||||
self.option = Option()
|
self.option = Option()
|
||||||
|
@ -156,7 +159,10 @@ class Gui:
|
||||||
self.progressbar = ttk.Progressbar(self.root)
|
self.progressbar = ttk.Progressbar(self.root)
|
||||||
self.progresslabel = Label(self.root)
|
self.progresslabel = Label(self.root)
|
||||||
|
|
||||||
def check_update(self):
|
def check_update(self) -> None:
|
||||||
|
"""
|
||||||
|
Check if an update is available
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
gitversion = requests.get(VERSION_FILE_URL, allow_redirects=True).json()
|
gitversion = requests.get(VERSION_FILE_URL, allow_redirects=True).json()
|
||||||
with open("./version", "rb") as f:
|
with open("./version", "rb") as f:
|
||||||
|
@ -200,13 +206,26 @@ class Gui:
|
||||||
except:
|
except:
|
||||||
self.log_error()
|
self.log_error()
|
||||||
|
|
||||||
def log_error(self):
|
def log_error(self) -> None:
|
||||||
|
"""
|
||||||
|
When an error occur, will show it in a messagebox and write it in error.log
|
||||||
|
"""
|
||||||
error = traceback.format_exc()
|
error = traceback.format_exc()
|
||||||
with open("./error.log", "a") as f:
|
with open("./error.log", "a") as f:
|
||||||
f.write(f"---\n{error}\n")
|
f.write(f"---\n{error}\n")
|
||||||
messagebox.showerror(self.translate("Error"), self.translate("An error occured", " :", "\n", error, "\n\n"))
|
messagebox.showerror(self.translate("Error"), self.translate("An error occured", " :", "\n", error, "\n\n"))
|
||||||
|
|
||||||
def progress(self, show=None, indeter=None, step=None, statut=None, max=None, add=None):
|
def progress(self, show: bool = None, indeter: bool = None, step: int = None,
|
||||||
|
statut: str = None, max: int = None, add: int = None) -> None:
|
||||||
|
"""
|
||||||
|
configure the progress bar shown when doing a task
|
||||||
|
:param show: show or hide the progress bar
|
||||||
|
:param indeter: if indeter, the progress bar will do a infinite loop animation
|
||||||
|
:param step: set the progress of the bar
|
||||||
|
:param statut: text shown under the progress bar
|
||||||
|
:param max: set the maximum step
|
||||||
|
:param add: add to step of the progress bar
|
||||||
|
"""
|
||||||
if indeter is True:
|
if indeter is True:
|
||||||
self.progressbar.config(mode="indeterminate")
|
self.progressbar.config(mode="indeterminate")
|
||||||
self.progressbar.start(50)
|
self.progressbar.start(50)
|
||||||
|
@ -229,7 +248,11 @@ class Gui:
|
||||||
self.progressbar["value"] = 0
|
self.progressbar["value"] = 0
|
||||||
if add: self.progressbar.step(add)
|
if add: self.progressbar.step(add)
|
||||||
|
|
||||||
def state_button(self, enable=True):
|
def state_button(self, enable: bool = True) -> None:
|
||||||
|
"""
|
||||||
|
used to enable or disable button when doing task
|
||||||
|
:param enable: are the button enabled ?
|
||||||
|
"""
|
||||||
button = [
|
button = [
|
||||||
self.button_game_extract,
|
self.button_game_extract,
|
||||||
self.button_install_mod,
|
self.button_install_mod,
|
||||||
|
@ -242,17 +265,18 @@ class Gui:
|
||||||
else:
|
else:
|
||||||
widget.config(state=DISABLED)
|
widget.config(state=DISABLED)
|
||||||
|
|
||||||
def translate(self, *texts, lang=None):
|
def translate(self, *texts, lang: str = None) -> str:
|
||||||
if lang is None:
|
"""
|
||||||
lang = self.stringvar_language.get()
|
translate text into an another language in translation.json file
|
||||||
elif lang == "F":
|
:param texts: all text to convert
|
||||||
lang = "fr"
|
:param lang: force a destination language to convert track
|
||||||
elif lang == "G":
|
:return: translated text
|
||||||
lang = "ge"
|
"""
|
||||||
elif lang == "I":
|
if lang is None: lang = self.stringvar_language.get()
|
||||||
lang = "it"
|
elif lang == "F": lang = "fr"
|
||||||
elif lang == "S":
|
elif lang == "G": lang = "ge"
|
||||||
lang = "sp"
|
elif lang == "I": lang = "it"
|
||||||
|
elif lang == "S": lang = "sp"
|
||||||
|
|
||||||
if lang in translation_dict:
|
if lang in translation_dict:
|
||||||
_lang_trad = translation_dict[lang]
|
_lang_trad = translation_dict[lang]
|
||||||
|
|
|
@ -6,10 +6,31 @@ from . import wszst
|
||||||
|
|
||||||
|
|
||||||
class Track:
|
class Track:
|
||||||
def __init__(self, name: str = "_", file_wu8: str = None, file_szs: str = None, prefix: str = None, suffix: str = None,
|
def __init__(self, name: str = "_", prefix: str = None, suffix: str = None,
|
||||||
author="Nintendo", special="T11", music="T11", new=True, sha1: str = None, since_version: str = None,
|
author="Nintendo", special="T11", music="T11", new=True, sha1: str = None, since_version: str = None,
|
||||||
score: int = 0, warning: int = 0, note: str = "", track_wu8_dir: str = "./file/Track-WU8/",
|
score: int = 0, warning: int = 0, note: str = "", track_wu8_dir: str = "./file/Track-WU8/",
|
||||||
track_szs_dir: str = "./file/Track/", *args, **kwargs):
|
track_szs_dir: str = "./file/Track/", *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Track class
|
||||||
|
:param name: track name
|
||||||
|
:param file_wu8: path to its wu8 file
|
||||||
|
:param file_szs: path to its szs file
|
||||||
|
:param prefix: track prefix (often original console or game)
|
||||||
|
:param suffix: track suffix (often for variation like Boost or Night)
|
||||||
|
:param author: track creator
|
||||||
|
:param special: track special slot
|
||||||
|
:param music: track music slot
|
||||||
|
:param new: is the track original or from an older game
|
||||||
|
:param sha1: track sha1
|
||||||
|
:param since_version: since when version did the track got added to the mod
|
||||||
|
:param score: what it the score of the track
|
||||||
|
:param warning: what is the warn level of the track (0 = none, 1 = minor bug, 2 = major bug)
|
||||||
|
:param note: note about the track
|
||||||
|
:param track_wu8_dir: where is stored the track wu8
|
||||||
|
:param track_szs_dir: where is stored the track szs
|
||||||
|
:param args: /
|
||||||
|
:param kwargs: /
|
||||||
|
"""
|
||||||
|
|
||||||
self.name = name # Track name
|
self.name = name # Track name
|
||||||
self.prefix = prefix # Prefix, often used for game or original console like Wii U, DS, ...
|
self.prefix = prefix # Prefix, often used for game or original console like Wii U, DS, ...
|
||||||
|
@ -28,18 +49,35 @@ class Track:
|
||||||
self.file_wu8 = f"{track_wu8_dir}/{self.get_track_name()}.wu8"
|
self.file_wu8 = f"{track_wu8_dir}/{self.get_track_name()}.wu8"
|
||||||
self.file_szs = f"{track_szs_dir}/{self.get_track_name()}.szs"
|
self.file_szs = f"{track_szs_dir}/{self.get_track_name()}.szs"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
|
"""
|
||||||
|
track representation when printed
|
||||||
|
:return: track information
|
||||||
|
"""
|
||||||
return f"{self.get_track_name()} sha1={self.sha1} score={self.score}"
|
return f"{self.get_track_name()} sha1={self.sha1} score={self.score}"
|
||||||
|
|
||||||
def check_sha1(self):
|
def check_sha1(self) -> int:
|
||||||
|
"""
|
||||||
|
check if track wu8's sha1 is correct
|
||||||
|
:return: 0 if yes, -1 if no
|
||||||
|
"""
|
||||||
ws = wszst.sha1(self.file_wu8)
|
ws = wszst.sha1(self.file_wu8)
|
||||||
if wszst.sha1(self.file_wu8) == self.sha1: return 0
|
if wszst.sha1(self.file_wu8) == self.sha1: return 0
|
||||||
else: return -1
|
else: return -1
|
||||||
|
|
||||||
def convert_wu8_to_szs(self):
|
def convert_wu8_to_szs(self) -> str:
|
||||||
|
"""
|
||||||
|
convert track to szs
|
||||||
|
:return: path to szs track
|
||||||
|
"""
|
||||||
return wszst.normalize(src_file=self.file_wu8)
|
return wszst.normalize(src_file=self.file_wu8)
|
||||||
|
|
||||||
def download_wu8(self, github_content_root: str):
|
def download_wu8(self, github_content_root: str) -> int:
|
||||||
|
"""
|
||||||
|
download track wu8 from github
|
||||||
|
:param github_content_root: url to github project root
|
||||||
|
:return: 0 if correctly downloaded, 1 if no need to download, 3 if track size is incorrect, -1 if error
|
||||||
|
"""
|
||||||
returncode = 0
|
returncode = 0
|
||||||
|
|
||||||
dl = requests.get(github_content_root + self.file_wu8, allow_redirects=True, stream=True)
|
dl = requests.get(github_content_root + self.file_wu8, allow_redirects=True, stream=True)
|
||||||
|
@ -60,8 +98,9 @@ class Track:
|
||||||
print(f"error {dl.status_code} {self.file_wu8}")
|
print(f"error {dl.status_code} {self.file_wu8}")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def get_ctfile(self, race=False, *args, **kwargs):
|
def get_ctfile(self, race=False, *args, **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
|
get ctfile text to create CTFILE.txt and RCTFILE.txt
|
||||||
:param race: is it a text used for Race_*.szs ?
|
:param race: is it a text used for Race_*.szs ?
|
||||||
:return: ctfile definition for the track
|
:return: ctfile definition for the track
|
||||||
"""
|
"""
|
||||||
|
@ -84,8 +123,9 @@ class Track:
|
||||||
|
|
||||||
return ctfile_text
|
return ctfile_text
|
||||||
|
|
||||||
def get_track_formatted_name(self, highlight_version: str = None):
|
def get_track_formatted_name(self, highlight_version: str = None) -> str:
|
||||||
"""
|
"""
|
||||||
|
get the track name with score, color, ...
|
||||||
:param highlight_version: if a specific version need to be highlighted.
|
:param highlight_version: if a specific version need to be highlighted.
|
||||||
:return: the name of the track with colored prefix, suffix
|
:return: the name of the track with colored prefix, suffix
|
||||||
"""
|
"""
|
||||||
|
@ -112,14 +152,22 @@ class Track:
|
||||||
name = name.replace("_", " ")
|
name = name.replace("_", " ")
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def get_track_name(self):
|
def get_track_name(self) -> str:
|
||||||
|
"""
|
||||||
|
get the track name without score, color...
|
||||||
|
:return: track name
|
||||||
|
"""
|
||||||
prefix = (self.prefix + " ") if self.prefix else ""
|
prefix = (self.prefix + " ") if self.prefix else ""
|
||||||
suffix = (" (" + self.suffix + ")") if self.suffix else ""
|
suffix = (" (" + self.suffix + ")") if self.suffix else ""
|
||||||
|
|
||||||
name = (prefix + self.name + suffix)
|
name = (prefix + self.name + suffix)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def load_from_json(self, track_json: dict):
|
def load_from_json(self, track_json: dict) -> None:
|
||||||
|
"""
|
||||||
|
load the track from a dictionary
|
||||||
|
:param track_json: track's dictionnary
|
||||||
|
"""
|
||||||
for key, value in track_json.items(): # load all value in the json as class attribute
|
for key, value in track_json.items(): # load all value in the json as class attribute
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue