~/problems / Simulation & OOP design / Object-oriented design and extensible simulations

Chat bot system refactor

medium 4 levels ~80 min OpenAI

Level 1 Refactor the legacy chat service

The starter file is a working but messy chat service: one send_message function, string slicing everywhere, and all state in module-level globals. It hosts three bots:

  • AwayBot: /away <text> sets the sender's away status (it prints nothing). Whenever a message mentions a user who is away, it posts AwayBot: <user> is away: <text>.
  • MeetBot: /meet <user> posts a link https://meet.example.com/room-<k> (k counts meetings from 1) and marks both people as away with in a meeting with <other>.
  • TacoBot: /givetaco <tacos> @<user> counts the 🌮 characters, adds them to the user's running total, and announces the gift and the new total.

Read the starter for the exact output strings and the order they appear in.

Refactor it into an extensible object-oriented design. Your module must provide:

  • BotService: an abstract base class (abc.ABC) with abstract methods should_activate(name, msg) -> bool and execute(name, msg) -> list[str]. Instantiating it directly must raise TypeError.
  • AwayBot(), MeetBot(), TacoBot(): each a BotService subclass that keeps its own state. You choose how MeetBot updates AwayBot's statuses for now.
  • ChatRoom() with register_bot(bot), send_message(name, msg) and a messages list. It appends "<name>: <msg>", then asks each bot in registration order whether it activates and appends whatever it returns. Adding a new bot must not require editing ChatRoom.
  • default_room(): a new ChatRoom with an AwayBot, a MeetBot and a TacoBot registered, in that order.

Requirements:

  • For well-formed input, default_room() must produce exactly the lines the legacy code produces. The tests replay hundreds of random conversations through both.
  • No global state. Two rooms are completely independent, and that includes the meeting counter.
  • Each bot works on its own. For example, TacoBot().execute("A", "/givetaco 🌮🌮 @b") returns the announcement.
room = default_room()
room.send_message("Bob", "/meet Alice")
room.send_message("Emily", "ping @Alice")
room.messages[-1]   # 'AwayBot: Alice is away: in a meeting with Bob'

Level 2 unlocks when level 1 passes.

Level 3 unlocks when level 2 passes.

Level 4 unlocks when level 3 passes.

Topic: Object-oriented design and extensible simulations. Classes that survive new requirements: games, payments, subscriptions, refactors.

0:00
Ctrl ' run · Ctrl ↵ submit
esc