From 7706721eb1a041260e5331e9c52b2626908822c2 Mon Sep 17 00:00:00 2001 From: yenru0 Date: Wed, 6 May 2026 00:57:45 +0900 Subject: [PATCH] refactoring stage 6 - enhance state command - enhance init --- run.py | 138 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 54 deletions(-) diff --git a/run.py b/run.py index 8b1c6a5..0655cf5 100755 --- a/run.py +++ b/run.py @@ -305,6 +305,15 @@ class StateManager: def reload(self) -> None: self._state = None + def set_completed(self, lang: Language, is_completed: bool) -> None: + state = self._load() + if lang.value not in state.get("space", {}): + raise ValueError(f"No space found for language: {lang}") + if not state["space"].get(lang.value): + raise ValueError(f"No space found for language: {lang}") + state["space"][lang.value]["is_completed"] = is_completed + self._state = state + class StorageManager: _instance: "StorageManager | None" = None @@ -376,6 +385,16 @@ class StorageManager: with open(file_path, "rb") as f: return f.read() + def remove_file(self, location: str, lang: Language, filename: str) -> None: + path = self.check_get_file(location, lang, filename) + if path is None: + raise FileNotFoundError( + f"File not found in storage: {location}/{filename}.{lang.value}" + ) + file_path = f"{path}/{filename}" + if os.path.isfile(file_path): + os.remove(file_path) + def mark_completed(self, location: str, lang: Language, filename: str) -> None: uncompleted_file = ( STORAGE_DIR / location / lang.value / f"{filename}.{lang.value}" @@ -629,6 +648,7 @@ def load(target: str, force: bool): f_dst.write(f_src.read()) StateManager().remove_space(lang) StateManager().add_space(lang, prob, loc, False) + StorageManager().remove_file(loc, lang, prob) click.secho( f"Loaded '{prob}.{lang.value}' from location '{loc}' to src-space.", fg="cyan", @@ -705,38 +725,65 @@ def export(from_: tuple[str, ...], all_: bool, force: bool): _export_sub_command(l) -@click.command(name="state") +@click.group(name="state") def state(): - try: - with open(STATE_PATH, "r", encoding="utf-8") as f_state: - state = yaml.safe_load(f_state) - except FileNotFoundError as e: - raise click.ClickException(e) - except yaml.YAMLError as e: - raise click.ClickException(e) + """State management commands""" + pass - if "space" not in state: - raise click.ClickException("state.yml is wrong") - elif not state["space"]: - click.secho("state.space has no member", fg="yellow", bold=True) - state["space"] = {} - active = sum(1 for v in state["space"].values() if v) - total = len(state["space"]) - click.secho(f"Space: {active}/{total} active", fg="cyan", bold=True) - click.echo() - - for k, v in state["space"].items(): - click.secho(f" {k}/", fg="yellow") - if not v: - click.echo(f" {click.style('—', fg='bright_black')} empty") - else: - status = ( +@state.command(name="show") +def state_show(): + """Show current space state""" + click.secho("Current Space State:", fg="cyan", bold=True) + for lang in Language.languages(): + space = ( + StateManager().get_space(lang) if StateManager().check_space(lang) else None + ) + if space: + status_symbol = ( click.style("✓", fg="green") - if v["is_completed"] + if space.get("is_completed") else click.style("○", fg="white") ) - click.echo(f" {status} {v['file']}.{k} @ {v['location']}") + click.echo( + f"{status_symbol} {lang.value}: {space['file']} (Location: {space['location']})" + ) + else: + click.echo(f"{click.style('○', fg='white')} {lang.value}: No file loaded") + + +@state.command(name="complete") +@click.argument("lang", type=str) +def state_complete(lang: str): + """Mark language space as completed""" + lang_obj = Language.convert_name(lang) + if lang_obj is Language.UNDEFINED: + raise click.ClickException(f"Unknown language: {lang}") + + state_manager = StateManager() + try: + state_manager.set_completed(lang_obj, True) + state_manager.save() + except ValueError as e: + raise click.ClickException(str(e)) + click.secho(f"Language '{lang}' marked as completed.", fg="green") + + +@state.command(name="uncomplete") +@click.argument("lang", type=str) +def state_uncomplete(lang: str): + """Mark language space as not completed""" + lang_obj = Language.convert_name(lang) + if lang_obj is Language.UNDEFINED: + raise click.ClickException(f"Unknown language: {lang}") + + state_manager = StateManager() + try: + state_manager.set_completed(lang_obj, False) + state_manager.save() + except ValueError as e: + raise click.ClickException(str(e)) + click.secho(f"Language '{lang}' marked as not completed.", fg="green") @click.command(name="init") @@ -746,36 +793,20 @@ def init(count: int): init testcases with initial count and state.yml and config.yml """ if count < 1: - raise click.UsageError("var count should be greater than 1.") + raise click.UsageError("count should be greater than 0") - if not os.path.exists("./" + TC_DIR): - os.mkdir(TC_DIR) + TC_DIR.mkdir(exist_ok=True) for i in range(1, count + 1): - default_in_path = "./" + TC_DIR + f"/{i}.in" - default_out_path = "./" + TC_DIR + f"/{i}.out" - if not os.path.exists(default_in_path): - with open(default_in_path, "w", encoding="utf-8") as _: - pass - if not os.path.exists(default_out_path): - with open(default_out_path, "w", encoding="utf-8") as _: - pass - - click.echo(f"1. Testcases was made with count {count} successfully!") - - if not os.path.isfile("./state.yml"): - click.echo("2-1. state.yml does not exist, creating...") - with open("state.yml", "w", encoding="utf-8") as f: - f.write("space:\n") - click.echo("2-1. state.yml is created successfully!") + (TC_DIR / f"{i}.in").touch() + (TC_DIR / f"{i}.out").touch() + click.secho(f"1. Testcases created with count {count}", fg="cyan") + click.secho("2. Checking state.yml...", fg="cyan") + if not STATE_PATH.is_file(): + click.secho("2. state.yml does not exist, creating...", fg="yellow") + STATE_PATH.write_text("space:\n", encoding="utf-8") + click.secho("2. state.yml created", fg="cyan") else: - click.echo("2-1. state.yml exists") - if not os.path.isfile("./config.yml"): - click.echo("2-2. config.yml does not exist, creating...") - with open("config.yml", "w", encoding="utf-8") as f: - f.write("space:\n") - click.echo("2-2. config.yml is created successfully!") - else: - click.echo("2-2. config.yml exists") + click.secho("2. state.yml exists", fg="green") @click.command(name="show") @@ -797,7 +828,6 @@ def show(filter: str | None, completed: bool, show_all: bool): """ Show all stored problems in storage directory. - \b FILTER format (optional): location e.g. zeta location/lang e.g. zeta/rs