How do I make items disappear based on the size of it's members?
https://softwareengineering.stackexchange.com/questions/419197
-
18-03-2021 - |
Pergunta
Consider a list of items (take a list of voice channels) where each item has these attributes
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
:
- When a member joins a
VoiceChannel
it should make the first invisible and empty channel in the list visible. - If one empty
VoiceChannel
is already visible then don't make any new ones visible. - If more than one empty channel is visible then only make the first empty channel visible.
Notes
- All
VoiceChannel
items except the first are invisible in initial state. - A member can only join one
VoiceChannel
at a time. - A member needs to join at least one
VoiceChannel
before they can switch between voice channels. So it's not possible to switch from channel 1 to channel 2 without having first already joined channel 1.
What I have tried
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
Question
How do I go about writing psuedo code or a concrete algorithm to make this work with just on_join
and on_leave
events?
Solução
Stop asking things about their state and start telling them what you want. Also, don't use null if you can help it.
With that in mind here's a redesign:
System::on_join(member, after, emptyChannel)
On the event when a member joins a VoiceChannel the first time, after is the VoiceChannel they join.
System::on_switch(member, before, after, emptyChannel)
When a member switches voice channels, before and after are different VoiceChannels.
System::on_leave(member, before, after, emptyChannel)
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.
Both on_switch and on_leave can call leaveChannel(member, before, emptyChannel)
and tell the channel about the member leaving. The channel can update it's member list, update it's visibility, or file a tax return, whatever the channel wants to do.
Both on_switch and on_join can call joinChannel(member, after, emptyChannel)
and tell the channel about the member leaving. The channel can update it's member list, update it's visibility, or send the member spam email, whatever the channel wants to do.
This might seem weird but you can make the channels smart enough to handle this stuff on their own. All they need to know is that it's time to check if they should be visible, how many members they have, and if empty, if emptyChannel
is lower numbered or conversely if it just got filled. With that info they can figure out visibility themselves. You don't have to keep building lists.