refactoring stage 6
- enhance state command - enhance init
This commit is contained in:
138
run.py
138
run.py
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user