diff --git a/rooms/room.go b/rooms/room.go index 11d1d87..268b2f9 100644 --- a/rooms/room.go +++ b/rooms/room.go @@ -46,40 +46,100 @@ func (r *Room) RaiseHand(p PersonId, gesture HandGesture) Room { return *r } -// and how would i organize? -// i should have map[HandGesture]ParticipantId as mark. for 'from where to go clockwise if returning a level lover' -// now i want methods that for some person raise some hand, so i guess it adds what? to map[ParticipantId]HandGesture -// i suppose methods should be on a room, in a session i'd have ParticipantId to pass in, and would load room -// and i want all parts of room in same struct, because i'd want to subscribe to changes to all of them - -// i suppose raising a hand could be just in place adding PersonId->HandGesture, -// but releasing hand should have additional logic +// releasing the hand - removing the hand gesture currently being held by p PersonId +// if p is not current speaker: just removing the signal is ok +// when p is current speaker: +// - we should find next speaker +// - assign room.CurrentSpeaker to next speaker or to PersonId(0) to indicate that noone is speaking +// - if next speaker has gesture of higher priority - set Mark to current speaker for their gesture level func (r *Room) ReleaseHand(p PersonId) { // releasing a hand of a current speaker should result in selection of a new speaker log.Printf("about to release hand of %d in %s", p, r.Name) + // keeping hand in room until end of funcion in case we'll need it to determine next speaker + defer delete(r.ParticipantHands, p) - // first remove hand of the requested person - currentSpeakerGesture, currentSpeakerHandFound := r.ParticipantHands[p] - if !currentSpeakerHandFound { + handReleaseGesture, handReleaserFound := r.ParticipantHands[p] + if !handReleaserFound { return } - delete(r.ParticipantHands, p) - // if not a current speaker, no complicated logic required to release a hand if r.CurrentSpeaker != p { return } + // if a current speaker raises their hand + // - in addition to removing the hand, we need to find next speaker + nextSpeakerIndex, nextSpeakerFound, _ := r.NextSpeakerIndex() + + if !nextSpeakerFound { + log.Printf("there is not next speaker, that's ok") + r.CurrentSpeaker = PersonId(0) + } else { + // searching for the next speaker + currentSpeakerGesture := handReleaseGesture + nextSpeakerId := r.Paricipants[nextSpeakerIndex] + nextSpeakerGesture := r.ParticipantHands[nextSpeakerId] + log.Printf("found next speaker %+v", nextSpeakerId) + + if nextSpeakerGesture > currentSpeakerGesture { + // raising the level of the speaker, need to save mark + log.Printf("we do have nextSpeaker of priority %s higher than current %s", nextSpeakerGesture.String(), currentSpeakerGesture.String()) + r.Marks[currentSpeakerGesture] = p + } + + // also we need to remove marks from top to current speaker level + for _, gesture := range GesturesHighToLow { + if gesture < nextSpeakerGesture { + break + } + delete(r.Marks, gesture) + } + + r.CurrentSpeaker = nextSpeakerId + } +} + +// fully remove p PersonId from participants +func (r *Room) PersonToStandUpFromTable(p PersonId) { + personGesture, found := r.ParticipantHands[p] + if found { + r.ReleaseHand(p) + if r.Marks[personGesture] == p { + // the leaving person is marked + // TODO get better logic, maybe assign mark to a neighbor + delete(r.Marks, personGesture) + } + } + if slices.Contains(r.Paricipants, p) { + updated := slices.DeleteFunc(r.Paricipants, func(sittingPerson PersonId) bool { + return sittingPerson == p + }) + r.Paricipants = updated + } +} + +// find index of next speaker +// for the room with current speaker and their gesture present +// also returning index from which the person was counted: +// - if the gesture of next speaker is of same of higher priority +// should be counted from current speaker +// - if the gesture is of lover priority and there is no mark +// should be counted from current speaker +// - if the gesture is of lover priority and there is a mark for the gesture level +// should be counted from the mark +func (r *Room) NextSpeakerIndex() (nextSpeakerIndex int, found bool, countedFromIndex int) { // if a current speaker - after removing the hand, we need to find next speaker // from highest hand gesture to lowest, until one is found - gestures := [...]HandGesture{Meta, ClarifyingQ, Expand, ProbingQ, ChangeTopic} - var nextSpeakerId PersonId - var nextSpeakerFound bool + currentSpeakerGesture, currentSpeakerFound := r.ParticipantHands[r.CurrentSpeaker] + if !currentSpeakerFound { + log.Printf("> cur speaker gesture %s and found %t", currentSpeakerGesture.String(), currentSpeakerFound) + return -1, false, -1 + } gestureIteration: - for _, gesture := range gestures { + for _, gesture := range GesturesHighToLow { log.Printf("searching for gesture %s", gesture.String()) startIndex := r.gestureSearchStartIndex(gesture, currentSpeakerGesture) participantsCount := len(r.Paricipants) @@ -88,43 +148,18 @@ gestureIteration: checkPerson := r.Paricipants[checkIndex] checkGesture, isFound := r.ParticipantHands[checkPerson] if isFound && checkGesture == gesture { - nextSpeakerId, nextSpeakerFound = checkPerson, true + nextSpeakerIndex = slices.Index(r.Paricipants, checkPerson) + countedFromIndex = startIndex + found = true break gestureIteration } } } - if !nextSpeakerFound { + if !found { log.Printf("there is not next speaker, that's ok") } - nextSpeakerGesture := r.ParticipantHands[nextSpeakerId] - log.Printf("found next speaker %+v", nextSpeakerId) - - if nextSpeakerGesture > currentSpeakerGesture { - // raising the level of the speaker, need to save mark - log.Printf("we do have nextSpeaker of priority %s higher than current %s", nextSpeakerGesture.String(), currentSpeakerGesture.String()) - r.Marks[currentSpeakerGesture] = p - } - - // also we need to remove marks from top to current speaker level - for _, gesture := range gestures { - if gesture < nextSpeakerGesture { - break - } - delete(r.Marks, gesture) - } - - r.CurrentSpeaker = nextSpeakerId -} - -func (r *Room) PersonToStandUpFromTable(p PersonId) { - r.ReleaseHand(p) - if slices.Contains(r.Paricipants, p) { - updated := slices.DeleteFunc(r.Paricipants, func(sittingPerson PersonId) bool { - return sittingPerson == p - }) - r.Paricipants = updated - } + return } // find place to start - separate function @@ -189,6 +224,8 @@ const ( Meta ) +var GesturesHighToLow = [...]HandGesture{Meta, ClarifyingQ, Expand, ProbingQ, ChangeTopic} + func GestureFromInt(num int) (HandGesture, bool) { if num >= int(ChangeTopic) && num <= int(Meta) { return HandGesture(num), true