Consider this MVCE:
import os
from time import sleep
from typing import List, Optional
class Member:
def __init__(self, name: str):
self.name: str = name
class VoiceChannel:
def __init__(self, number: int):
self.number: int = number
self.members: List[Member] = []
self.visible = True
def is_empty(self) -> bool:
return len(self.members) == 0
def add_member(self, member: Member):
self.members.append(member)
def remove_member(self, member: Member):
self.members.remove(member)
class System:
def __init__(self):
self.channels: List[VoiceChannel] = []
for channel_number in range(1, 6):
if channel_number == 1:
self.channels.append(VoiceChannel(channel_number))
else:
_ = VoiceChannel(channel_number)
_.visible = False
self.channels.append(_)
def get_room(self, number: int) -> Optional[VoiceChannel]:
if number > 0:
return self.channels[number - 1]
def on_voice_state_update(
self,
member: Member,
before: Optional[VoiceChannel],
after: Optional[VoiceChannel]
):
def join():
pass
def leave():
pass
if after in self.channels:
join()
if before in self.channels:
leave()
def join(self, member: Member, channel_number):
self.channels[channel_number - 1].add_member(member)
self.update_screen()
self.on_voice_state_update(member, None, self.channels[channel_number])
self.update_screen()
def leave(self, member: Member):
on_leave_channel = None
for channel in self.channels:
if member in channel.members:
on_leave_channel = channel
channel.remove_member(member)
self.update_screen()
break
if on_leave_channel:
self.on_voice_state_update(member, on_leave_channel, None)
def move(self, member: Member, channel_number: int):
for current_channel in self.channels:
if member in current_channel.members:
current_channel.remove_member(member)
self.update_screen()
break
channel = self.get_room(channel_number)
channel.add_member(member)
self.update_screen()
def update_screen(self):
_ = os.system("cls")
print("\n> Debate Rooms")
for channel in self.channels:
if channel.visible:
print(f" Debate {channel.number}")
if not channel.is_empty():
for member in channel.members:
print(f" {member.name}")
else:
print(f" ")
sleep(1.5)
if __name__ == "__main__":
system = System()
# Initialize Members
john = Member("John")
jane = Member("Jane")
abby = Member("Abby")
jess = Member("Jess")
hope = Member("Hope")
kate = Member("Kate")
liam = Member("Liam")
noah = Member("Noah")
jack = Member("Jack")
luke = Member("Luke")
# Prime Members
system.join(john, 1) # Show Debate 2.
system.leave(john) # Hide Debate 2.
system.join(john, 1) # Show Debate 2.
system.join(jane, 1) # Keep Showing Debate 2.
system.leave(john) # Keep Showing Debate 2.
system.leave(jane) # Hide Debate 2.
system.join(john, 1) # Show Debate 2.
system.join(jane, 2) # Show Debate 3.
system.join(abby, 3) # Show Debate 4.
system.leave(john) # Hide Debate 4 since 1 is available.
system.move(jane, 1) # Keep Debate 4 hidden, and Debate 2 shown.
I'm trying to make these channels visible and invisible per this requirement:
How do I implement this using just the join()
and leave()
functions in on_voice_state_update()
? I have been trying for a while and can't seem to figure it out.
I would make a function that assesses your condition 1. and acts accordingly if it isn't met. This function could work on the current state instead of having to know which member was removed/added to a room:
def ensure_one_empty_room(self):
empty_visible_channels = \
[channel for channel in self.channels if channel.is_empty() and channel.visible]
if len(empty_visible_channels)==0:
first_empty_channel = next(channel for channel in self.channels if channel.is_empty())
if first_empty_channel:
first_empty_channel.visible=True
elif len(empty_visible_channels)>1:
for channel in empty_visible_channels[1:]:
channel.visible=False
The full System class would then become:
class System:
def __init__(self):
self.channels = [VoiceChannel(i) for i in range(1, 6)]
self.ensure_one_empty_room()
self.update_screen()
def get_room(self, number: int) -> Optional[VoiceChannel]:
if number > 0:
return self.channels[number - 1]
def ensure_one_empty_room(self):
empty_visible_channels = \
[channel for channel in self.channels if channel.is_empty() and channel.visible]
if len(empty_visible_channels)==0:
first_empty_channel = next(channel for channel in self.channels if channel.is_empty())
if first_empty_channel:
first_empty_channel.visible=True
elif len(empty_visible_channels)>1:
for channel in empty_visible_channels[1:]:
channel.visible=False
def on_member_change(self):
self.ensure_one_empty_room()
self.update_screen()
def joined_channels(self, member):
return (channel for channel in self.channels if (member in channel.members))
def join(self, member: Member, channel_number):
self.get_room(channel_number).add_member(member)
self.on_member_change()
def leave(self, member: Member):
for channel in self.joined_channels(member):
channel.remove_member(member)
self.on_member_change()
def move(self, member: Member, channel_number: int):
for channel in self.joined_channels(member):
channel.remove_member(member)
self.get_room(channel_number).add_member(member)
self.on_member_change()
def update_screen(self):
os.system("cls")
print("\n> Debate Rooms")
for channel in self.channels:
if channel.visible:
print(f" Debate {channel.number}")
if not channel.is_empty():
for member in channel.members:
print(f" {member.name}")
else:
print(f" ")
sleep(1.5)
note: