refactoring stage 6

- enhance state command
- enhance init
This commit is contained in:
2026-05-06 00:57:45 +09:00
parent df8fb68a1d
commit 7706721eb1

138
run.py
View File

@@ -305,6 +305,15 @@ class StateManager:
def reload(self) -> None: def reload(self) -> None:
self._state = 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: class StorageManager:
_instance: "StorageManager | None" = None _instance: "StorageManager | None" = None
@@ -376,6 +385,16 @@ class StorageManager:
with open(file_path, "rb") as f: with open(file_path, "rb") as f:
return f.read() 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: def mark_completed(self, location: str, lang: Language, filename: str) -> None:
uncompleted_file = ( uncompleted_file = (
STORAGE_DIR / location / lang.value / f"{filename}.{lang.value}" 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()) f_dst.write(f_src.read())
StateManager().remove_space(lang) StateManager().remove_space(lang)
StateManager().add_space(lang, prob, loc, False) StateManager().add_space(lang, prob, loc, False)
StorageManager().remove_file(loc, lang, prob)
click.secho( click.secho(
f"Loaded '{prob}.{lang.value}' from location '{loc}' to src-space.", f"Loaded '{prob}.{lang.value}' from location '{loc}' to src-space.",
fg="cyan", fg="cyan",
@@ -705,38 +725,65 @@ def export(from_: tuple[str, ...], all_: bool, force: bool):
_export_sub_command(l) _export_sub_command(l)
@click.command(name="state") @click.group(name="state")
def state(): def state():
try: """State management commands"""
with open(STATE_PATH, "r", encoding="utf-8") as f_state: pass
state = yaml.safe_load(f_state)
except FileNotFoundError as e:
raise click.ClickException(e)
except yaml.YAMLError as e:
raise click.ClickException(e)
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) @state.command(name="show")
total = len(state["space"]) def state_show():
click.secho(f"Space: {active}/{total} active", fg="cyan", bold=True) """Show current space state"""
click.echo() click.secho("Current Space State:", fg="cyan", bold=True)
for lang in Language.languages():
for k, v in state["space"].items(): space = (
click.secho(f" {k}/", fg="yellow") StateManager().get_space(lang) if StateManager().check_space(lang) else None
if not v: )
click.echo(f" {click.style('', fg='bright_black')} empty") if space:
else: status_symbol = (
status = (
click.style("", fg="green") click.style("", fg="green")
if v["is_completed"] if space.get("is_completed")
else click.style("", fg="white") 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") @click.command(name="init")
@@ -746,36 +793,20 @@ def init(count: int):
init testcases with initial count and state.yml and config.yml init testcases with initial count and state.yml and config.yml
""" """
if count < 1: 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): TC_DIR.mkdir(exist_ok=True)
os.mkdir(TC_DIR)
for i in range(1, count + 1): for i in range(1, count + 1):
default_in_path = "./" + TC_DIR + f"/{i}.in" (TC_DIR / f"{i}.in").touch()
default_out_path = "./" + TC_DIR + f"/{i}.out" (TC_DIR / f"{i}.out").touch()
if not os.path.exists(default_in_path): click.secho(f"1. Testcases created with count {count}", fg="cyan")
with open(default_in_path, "w", encoding="utf-8") as _: click.secho("2. Checking state.yml...", fg="cyan")
pass if not STATE_PATH.is_file():
if not os.path.exists(default_out_path): click.secho("2. state.yml does not exist, creating...", fg="yellow")
with open(default_out_path, "w", encoding="utf-8") as _: STATE_PATH.write_text("space:\n", encoding="utf-8")
pass click.secho("2. state.yml created", fg="cyan")
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!")
else: else:
click.echo("2-1. state.yml exists") click.secho("2. state.yml exists", fg="green")
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.command(name="show") @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. Show all stored problems in storage directory.
\b
FILTER format (optional): FILTER format (optional):
location e.g. zeta location e.g. zeta
location/lang e.g. zeta/rs location/lang e.g. zeta/rs