Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,12 @@ async def guess(self, ctx: commands.Context, word: str = "") -> None:
await ctx.send(f"🎉 {ctx.author.name} found the word '{word}'!")
elif result.already_cited:
if result.entry.score is not None:
pct = int(result.entry.score * 100)
pct = round(result.entry.score * 100)
await ctx.send(f"'{word}' has already been suggested ({pct}% similarity).")
else:
await ctx.send(f"'{word}' has already been suggested.")
elif result.entry.score is not None:
pct = int(result.entry.score * 100)
pct = round(result.entry.score * 100)
await ctx.send(f"'{word}': {pct}% similarity")
else:
await ctx.send(f"'{word}' is not in the vocabulary.")
Expand Down Expand Up @@ -273,7 +273,7 @@ async def hint(self, ctx: commands.Context) -> None:
return

parts = [
f"{i + 1}. {e.raw_word} ({int((e.score or 0.0) * 100)}%)"
f"{i + 1}. {e.raw_word} ({round((e.score or 0.0) * 100)}%)"
for i, e in enumerate(top)
]
await ctx.send("Top guesses: " + " | ".join(parts))
Expand All @@ -300,7 +300,7 @@ async def status(self, ctx: commands.Context) -> None:
top = self._game_state.top_guesses(1)
if top:
best = top[0]
pct = int((best.score or 0.0) * 100)
pct = round((best.score or 0.0) * 100)
await ctx.send(
f"Game in progress. {attempts} attempt(s). "
f"Best guess: '{best.raw_word}' ({pct}%)."
Expand Down
21 changes: 21 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,27 @@ async def test_guess_near_match_shows_similarity(self):
message = ctx.send.call_args[0][0]
assert "%" in message

async def test_guess_percentage_uses_rounding_not_truncation(self):
"""Chat must show the same rounded percentage as the overlay (Math.round)."""

class _RoundingScorer:
"""Returns 0.475 so that truncation gives 47% but rounding gives 48%."""

def score_guess(self, guess: str, target: str) -> float | None:
from game.word_utils import clean_word
if clean_word(guess) == clean_word(target):
return 1.0
return 0.475

bot = _make_bot(cooldown=0)
bot._game_state = GameState(scorer=_RoundingScorer())
bot._game_state.start_new_game("chat", Difficulty.EASY)
ctx = _make_ctx()
ctx.author.name = "alice"
await _guess_fn(bot, ctx, "chien")
message = ctx.send.call_args[0][0]
assert "48%" in message, f"Expected 48% (rounded), got: {message}"

async def test_guess_unknown_word_reports_vocabulary_miss(self):
bot = _make_bot(cooldown=0)
bot._game_state.start_new_game("chat", Difficulty.EASY)
Expand Down
Loading