diff --git a/BOT/botscript.py b/BOT/botscript.py index d4efadf..af63423 100644 --- a/BOT/botscript.py +++ b/BOT/botscript.py @@ -4242,7 +4242,7 @@ async def set_player_perm_error(interaction, error): # ═══════════════════════════════════════════════════════════════════════════ -# /tally-claim · /tally-transfer · /tally-wipe — live VC scoreline tracking +# /tally-claim · /tally-transfer · /tally-clear — live VC scoreline tracking # ═══════════════════════════════════════════════════════════════════════════ def _invoker_voice_channel(interaction: discord.Interaction): @@ -4339,13 +4339,13 @@ async def tally_transfer(interaction: discord.Interaction, username: str): @bot.tree.command( - name="tally-wipe", + name="tally-clear", description=command_locale( "Clear the active tally on your current voice channel", "commands.tally.description_wipe", ), ) -async def tally_wipe(interaction: discord.Interaction): +async def tally_clear(interaction: discord.Interaction): lang = await guild_lang(interaction.guild.id) if interaction.guild else "en" vc = _invoker_voice_channel(interaction) if vc is None: @@ -4362,82 +4362,6 @@ async def tally_wipe(interaction: discord.Interaction): ) -@bot.tree.command( - name="dev-tally", - description="[DEV] Manually attribute a win or loss to the tally in your voice channel", -) -@app_commands.describe( - result="Whether to record a win or a loss", - username="The player to attribute it to (use alone, not with squadron)", - squadron="The squadron to attribute it to (use alone, not with username)", -) -@app_commands.choices(result=[ - app_commands.Choice(name="Win", value="win"), - app_commands.Choice(name="Loss", value="loss"), -]) -@discord.app_commands.autocomplete(username=player_autocomplete, squadron=squadron_autocomplete) -async def dev_tally(interaction: discord.Interaction, result: app_commands.Choice[str], - username: str = "", squadron: str = ""): - await collect_command_stats(interaction) - if not await is_dev_team(interaction): - await interaction.response.send_message(t("en", "dev.restricted_dev_team"), ephemeral=True) - return - lang = await guild_lang(interaction.guild.id) if interaction.guild else "en" - vc = _invoker_voice_channel(interaction) - if vc is None: - await interaction.response.send_message(t(lang, "commands.tally.not_in_vc"), ephemeral=True) - return - username = username.strip() - squadron = squadron.strip() - if username and squadron: - await interaction.response.send_message( - "Use `username` or `squadron` separately — don't pass both.", ephemeral=True - ) - return - if not username and not squadron: - await interaction.response.send_message( - "Provide a `username` or a `squadron` to attribute the result to.", ephemeral=True - ) - return - if not interaction.guild_id: - await interaction.response.send_message(t(lang, "commands.tally.not_in_vc"), ephemeral=True) - return - active = tally.get(interaction.guild_id, vc.id) - if active is None: - await interaction.response.send_message( - t(lang, "commands.tally.no_active", channel=vc.name), ephemeral=True - ) - return - # Only attribute the result if the argument matches what this VC tracks — - # a player arg must match a player-mode tally's target; a squadron arg must - # match a squadron-mode tally's target (tag-insensitive). Mirrors how a real - # finished game only counts when the tracked entity actually played. - if username: - matches = active.mode == "player" and active.target.strip().lower() == username.lower() - else: - matches = active.mode == "squadron" and \ - tally.strip_tag(active.target).lower() == tally.strip_tag(squadron).lower() - if not matches: - await interaction.response.send_message( - f"This VC is tracking the {active.mode} **{active.display_target}** — " - f"**{username or squadron}** doesn't match it, so nothing was recorded.", - ephemeral=True, - ) - return - tly = tally.apply_manual_result(interaction.guild_id, vc.id, result.value) - if tly is None: - await interaction.response.send_message( - t(lang, "commands.tally.no_active", channel=vc.name), ephemeral=True - ) - return - await tally.push_status(tly) - await interaction.response.send_message( - f"Recorded a **{result.name}** for **{username or squadron}** in **{vc.name}** " - f"(`{tly.wins}W-{tly.losses}L`).", - ephemeral=True, - ) - - # ═══════════════════════════════════════════════════════════════════════════ # /view-player-games — Last 20 games for a player # ═══════════════════════════════════════════════════════════════════════════ diff --git a/BOT/locales/en.json b/BOT/locales/en.json index 4443f92..bcdd1ff 100644 --- a/BOT/locales/en.json +++ b/BOT/locales/en.json @@ -861,7 +861,7 @@ "not_in_vc": "You must be connected to a voice channel to use this.", "premium_required": "This is a premium feature. Use /unlock to enable it for this server.", "need_one_input": "Provide exactly one of `ign` or `squadron_short`.", - "already_active": "A tally is already active in **{channel}** tracking **{target}**. Use /tally-transfer or /tally-wipe first.", + "already_active": "A tally is already active in **{channel}** tracking **{target}**. Use /tally-transfer or /tally-clear first.", "claimed": "Now tracking **{target}** in **{channel}**. Status set to `0W-0L`.", "no_active": "There is no active tally in **{channel}**.", "transferred": "Tally in **{channel}** now tracking **{target}** (count carried over: `{base}`).", diff --git a/BOT/tally.py b/BOT/tally.py index 620376f..075711a 100644 --- a/BOT/tally.py +++ b/BOT/tally.py @@ -217,28 +217,6 @@ def wipe(guild_id: int, channel_id: int) -> bool: return True -def apply_manual_result(guild_id: int, channel_id: int, kind: str, - opponent: str = "DEV") -> Optional["Tally"]: - """Manually bump a VC's active tally by a win or loss (dev/testing). - - ``kind`` is "win" or "loss". Mirrors what a finished game would do but with - no real opponent, so ``last_opponent`` is set to a fixed label. Returns the - updated tally, or None if the VC has no active tally. - """ - tly = _REGISTRY.get((guild_id, channel_id)) - if tly is None: - return None - if kind == "win": - tly.wins += 1 - else: - tly.losses += 1 - tly.last_result_kind = kind - tly.last_opponent = opponent - tly.last_update_ts = time.time() - _save() - return tly - - # --------------------------------------------------------------------------- # Voice-status HTTP helper # --------------------------------------------------------------------------- diff --git a/BOT/tests/test_tally_logic.py b/BOT/tests/test_tally_logic.py index ee9d2df..e3e8c0a 100644 --- a/BOT/tests/test_tally_logic.py +++ b/BOT/tests/test_tally_logic.py @@ -133,25 +133,6 @@ def test_squadron_mode_matches_bare_name_despite_resolved_short(): assert team_index_for(t, _teams_resolved_mismatch()) == 0 -def test_apply_manual_result_win_and_loss(): - import tempfile - import BOT.tally as tal - with tempfile.TemporaryDirectory() as d: - tal.TALLY_PATH = Path(d) / "TALLY.json" - tal._REGISTRY.clear() - tal.claim(1, 2, "player", "bravo", "Bravo", user_id=7) - win = tal.apply_manual_result(1, 2, "win") - assert win is not None - assert (win.wins, win.losses) == (1, 0) - assert win.last_result_kind == "win" and win.last_opponent == "DEV" - loss = tal.apply_manual_result(1, 2, "loss") - assert loss is not None - assert (loss.wins, loss.losses) == (1, 1) - assert loss.last_result_kind == "loss" and loss.last_opponent == "DEV" - # No active tally in a different VC → None - assert tal.apply_manual_result(1, 999, "win") is None - - def _run(): fns = [v for k, v in sorted(globals().items()) if k.startswith("test_")] for fn in fns: