design – How do I make items disappear based on the size of it’s members?

Consider a list of items (take a list of voice channels) where each item has these attributes

UML Diagram

System::vc: List of voice channels.

System::on_join(member, before, after): On the event when a member joins a VoiceChannel the first time, it’s before is Null and after is a VoiceChannel. When a member switches voice channels, before and after are different VoiceChannels.

System::on_leave(member, before, after): On the event when a member leaves all voice channels (ie: does not switch to another VoiceChannel), before will be a VoiceChannel and after will be Null.

System::get_room(no): Get a VoiceChannel from it’s number.

VoiceChannel::number: The number of the VoiceChannel (ie, index of System::vc + 1).

VoiceChannel::is_empty(): Returns True if there are no members in the channel, else False.

VoiceChannel::is_visible(): Returns True if the channel is currently visible, else False.

VoiceChannel::make_visible(): Makes a channel visible to all members. Returns True if successful and False if not.

VoiceChannel::make_invisible(): Makes a channel invisible to all members. Returns True if successful and False if not.


I’m trying to develop an algorithm to obtain this result when applied on System::vc:

  1. All VoiceChannel items except the first are invisible.
  2. When a member joins a VoiceChannel it should make the next one in the list visible.
  3. If one emptyVoiceChannel is already visible then don’t make any new ones visible.
  4. If more than one empty channel is visible while some are occupied, then make all empty visible channels except the next first one invisible.

Psuedocode

def on_join(member, before, after):
    vc_visible = ()
    for vc in self.vc:  # self is an instance of System
        if is_visible(vc):
            vc_visible.append(vc)
    
    last_vc_number = len(vc_visible) + 1
    if last_vc_number == 21:  # Total number of VoiceChannels + 1
        return
    
    self.vc_last = self.get_room(last_vc_number)
    for vc in self.vc:
        if is_visible(vc) and is_empty(vc) and vc.number != 1:
            self.vc_next_visible = vc
            return
        elif vc == self.vc_next_visible:
            await make_visible(self.vc_next_visible)
            return
        else:
            await make_visible(self.vc_last)
            return

async def on_leave(member, before, after):
    vc_visible = ()
    for vc in self.vc:  # self is an instance of System
        if is_visible(vc):
            vc_visible.append(vc)

    # Cycle through list from second last to front
    for vc in vc_visible(:len(vc_visible) * -1 :-1):
        if is_empty(vc) and is_empty(vc_visible(0)):
            await make_invisible(vc)
        elif is_empty(vc):
            if vc != self.vc_next_visible and vc.number != 2:
                await make_invisible(vc)

    for vc in self.vc:
        if is_visible(vc) and is_empty(vc) and vc.number != 1:
            self.vc_next_visible = vc
            return

How do I go about writing psuedo code or a concrete algorithm to make this work with just on_join and on_leave events?