public void MemberJoin(RoomMember member) { if (_members.Any(x => x.UserName == member.UserName)) { return; } _members.Add(member); OnRoomMembersChanged?.Invoke(this, member.UserName); _roomEvents.Add(new UserEvent(member.UserName, member.FriendlyName, UserEventType.JoinedRoom)); OnRoomNotification?.Invoke(this, new RoomNotification { Category = RoomNotificationCategory.Information, Message = $"{member.FriendlyName} joined room" }); ToggleDj(member, false); if (_currentTrack != null) { StartSongForMemberUgly(member); } _timeSinceEmpty = CustomFutureDateTimeOffset; }
public void MemberJoin(RoomMember member) { if (_members.Any(x => x.UserName == member.UserName)) { return; } _statisticsService.IncrementUserCount(); _members.Add(member); OnRoomMembersChanged?.Invoke(this, member.UserName); _roomEvents.Add(new UserEvent(member.UserName, member.FriendlyName, UserEventType.JoinedRoom)); OnRoomNotification?.Invoke(this, new RoomNotification { Category = RoomNotificationCategory.Information, Message = $"{member.FriendlyName} joined room" }); ToggleDj(member, false); if (_currentTrack != null) { StartSongForMemberUgly(member); } }
public void MemberLeave(RoomMember member) { var didRemove = _members.Remove(member); if (!didRemove) { return; } _roomEvents.Add(new UserEvent(member.UserName, member.FriendlyName, UserEventType.LeftRoom)); OnRoomNotification?.Invoke(this, new RoomNotification { Category = RoomNotificationCategory.Information, Message = $"{member.FriendlyName} left the room" }); OnRoomMembersChanged?.Invoke(this, member.UserName); UpdateReactionTotals(); // this was the last member to leave if (!_members.Any()) { _timeSinceEmpty = DateTimeOffset.Now; } }
public void ToggleDj(RoomMember member, bool isDj) { member.IsDj = isDj; member.DjOrderNumber = isDj ? _members.Where(x => x.IsDj).Max(y => y.DjOrderNumber) + 1 : -1; _roomEvents.Add(new UserEvent(member.UserName, member.FriendlyName, isDj ? UserEventType.BecameDj : UserEventType.BecameListener)); OnRoomMembersChanged?.Invoke(this, null); }
public void ToggleDj(RoomMember member, bool isDj) { member.IsDj = isDj; member.DjOrderNumber = isDj ? _members.Where(x => x.IsDj).Max(y => y.DjOrderNumber) + 1 : -1; _roomEvents.Add(new UserEvent(member.UserName, member.FriendlyName, isDj ? UserEventType.BecameDj : UserEventType.BecameListener)); OnRoomNotification?.Invoke(this, new RoomNotification { Category = RoomNotificationCategory.Information, Message = $"{member.FriendlyName} became a {(isDj ? "DJ" : "listener")}" }); OnRoomMembersChanged?.Invoke(this, null); }
public void MemberLeave(RoomMember member) { var didRemove = _members.Remove(member); if (!didRemove) { return; } _roomEvents.Add(new UserEvent(member.UserName, member.FriendlyName, UserEventType.LeftRoom)); OnRoomMembersChanged?.Invoke(this, member.UserName); // this was the last member to leave if (!_members.Any()) { _timeSinceEmpty = DateTimeOffset.Now; } }
public void MemberLeave(RoomMember member) { var didRemove = _members.Remove(member); if (!didRemove) { return; } _statisticsService.DecrementUserCount(); _roomEvents.Add(new UserEvent(member.UserName, member.FriendlyName, UserEventType.LeftRoom)); OnRoomNotification?.Invoke(this, new RoomNotification { Category = RoomNotificationCategory.Information, Message = $"{member.FriendlyName} left the room" }); OnRoomMembersChanged?.Invoke(this, member.UserName); UpdateReactionTotals(); }
public async Task <RoomState> TryPlayNext(bool force = false) { while (true) { // return if song is playing right now, except when we're skipping a song if (!force && DateTimeOffset.Now < _handledUntil) { // we don't change room state here return(new RoomState()); } _currentTrack = null; // try getting next player var nextPlayer = GetNextPlayer(); // if we don't find any we don't have a DJ - this will exit the recursion if we run out of DJs if (nextPlayer == null) { CurrentRoomState = new RoomState(); return(CurrentRoomState); } var song = await GetSongFromQueue(nextPlayer, nextPlayer.PlaylistId); // success if (song != null) { _currentDjNumber = nextPlayer.DjOrderNumber; // start songs for everyone foreach (var roomMember in _members) { await PlaySong(roomMember, song); } // set handled _handledUntil = DateTimeOffset.Now.AddMilliseconds(song.DurationMs); _currentTrack = song; // return state CurrentRoomState = new RoomState { IsPlayingSong = true, CurrentDjUsername = nextPlayer.UserName, CurrentDjName = nextPlayer.FriendlyName, CurrentSongArtist = string.Join(", ", song.Artists.Select(x => x.Name).ToArray()), CurrentSongTitle = song.Name, CurrentSongArtUrl = song?.Album.Images.FirstOrDefault()?.Url ?? "/images/missingart.jpg", SongStartedAtUnixTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(), SongFinishesAtUnixTimestamp = _handledUntil.ToUnixTimeMilliseconds() }; _roomEvents.Add(new SongPlayedEvent(nextPlayer.UserName, nextPlayer.FriendlyName, $"{CurrentRoomState.CurrentSongArtist} - {CurrentRoomState.CurrentSongTitle}", song.Id, song.Uri)); return(CurrentRoomState); } // remove user as DJ if song is null nextPlayer.IsDj = false; OnRoomMembersChanged?.Invoke(this, null); // then try again } }
public async Task <RoomState> TryPlayNext(bool force = false) { while (true) { // return if song is playing right now, except when we're skipping a song if (!force && DateTimeOffset.Now < _handledUntil) { // we don't change room state here return(new RoomState()); } _currentTrack = null; // try getting next player var nextPlayer = GetNextPlayer(); // if we don't find any we don't have a DJ - this will exit the recursion if we run out of DJs if (nextPlayer == null) { CurrentRoomState = new RoomState(); return(CurrentRoomState); } var song = await GetSongFromQueue(nextPlayer, nextPlayer.PlaylistId); // success if (song != null) { _currentDjNumber = nextPlayer.DjOrderNumber; // do the loop on a tmp list of members, so if someone joins mid-play we don't err out var tmpMembers = _members.ToList(); // start songs for everyone (OLD) //foreach (var roomMember in tmpMembers) //{ // await PlaySong(roomMember, song); //} // start songs for everyone (NEW) var sw = new Stopwatch(); sw.Start(); var playTasks = tmpMembers.Select(x => PlaySong(x, song)).ToList(); await Task.WhenAll(playTasks); sw.Stop(); _logger.Log(LogLevel.Information, "Took {TimedApiPlayForAll} to start songs for {MemberCount} room members", sw.Elapsed, tmpMembers.Count); // set handled _handledUntil = DateTimeOffset.Now.AddMilliseconds(song.DurationMs); _currentTrack = song; // return state CurrentRoomState = new RoomState { IsPlayingSong = true, CurrentDjUsername = nextPlayer.UserName, CurrentDjName = nextPlayer.FriendlyName, CurrentSongArtist = string.Join(", ", song.Artists.Select(x => x.Name).ToArray()), CurrentSongTitle = song.Name, CurrentSongArtUrl = song?.Album.Images.FirstOrDefault()?.Url ?? "/images/missingart.jpg", SongStartedAtUnixTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(), SongFinishesAtUnixTimestamp = _handledUntil.ToUnixTimeMilliseconds() }; _roomEvents.Add(new SongPlayedEvent(nextPlayer.UserName, nextPlayer.FriendlyName, $"{CurrentRoomState.CurrentSongArtist} - {CurrentRoomState.CurrentSongTitle}", song.Id, song.Uri)); return(CurrentRoomState); } // remove user as DJ if song is null nextPlayer.IsDj = false; OnRoomMembersChanged?.Invoke(this, null); // then try again } }
public async Task <RoomState> TryPlayNext(bool force = false) { while (true) { // return if song is playing right now, except when we're skipping a song if (!force && DateTimeOffset.Now < _handledUntil) { // we don't change room state here return(new RoomState()); } // award points based on the track if there are multiple users in the room if (_currentTrack != null && _members.Count > 1) { // 0 points base if song got skipped, 1 if not var score = CurrentRoomState.SongFinishesAtUnixTimestamp > DateTimeOffset.Now.ToUnixTimeMilliseconds() ? 0 : 1; // then 1 point for every reaction foreach (var roomMember in _members) { // could write something for this, but eh... if (roomMember.ReactionFlagsForCurrentTrack.HasFlag(Reaction.Heart)) { score += 1; } if (roomMember.ReactionFlagsForCurrentTrack.HasFlag(Reaction.Rock)) { score += 1; } if (roomMember.ReactionFlagsForCurrentTrack.HasFlag(Reaction.Flame)) { score += 1; } if (roomMember.ReactionFlagsForCurrentTrack.HasFlag(Reaction.Clap)) { score += 1; } } // update score if needed if (score > 0) { await _userScoreService.IncreaseScoreForUser(CurrentRoomState.CurrentDjUsername, score); // update values as we have new scores OnRoomMembersChanged?.Invoke(this, null); } } _currentTrack = null; // try getting next player var nextPlayer = GetNextPlayer(); // if we don't find any we don't have a DJ - this will exit the recursion if we run out of DJs if (nextPlayer == null) { CurrentRoomState = new RoomState(); return(CurrentRoomState); } var song = await GetSongFromQueue(nextPlayer, nextPlayer.PlaylistId); // success if (song != null) { _currentDjNumber = nextPlayer.DjOrderNumber; // do the loop on a tmp list of members, so if someone joins mid-play we don't err out var tmpMembers = _members.ToList(); // start songs for everyone (NEW) var sw = new Stopwatch(); sw.Start(); var playTasks = tmpMembers.Select(x => PlaySong(x, song)).ToList(); await Task.WhenAll(playTasks); sw.Stop(); _logger.Log(LogLevel.Information, "Took {TimedApiPlayForAll} to start songs for {MemberCount} room members", sw.Elapsed, tmpMembers.Count); // set handled _handledUntil = DateTimeOffset.Now.AddMilliseconds(song.DurationMs); _currentTrack = song; // clear reactions & update them foreach (var roomMember in tmpMembers) { roomMember.ReactionFlagsForCurrentTrack = Reaction.None; } UpdateReactionTotals(); var artistSum = string.Join(", ", song.Artists.Select(x => x.Name).ToArray()); // return state CurrentRoomState = new RoomState { IsPlayingSong = true, CurrentDjUsername = nextPlayer.UserName, CurrentDjName = nextPlayer.FriendlyName, CurrentSongArtist = artistSum.Length > 50 ? artistSum.Substring(0, 50) + "..." : artistSum, CurrentSongTitle = song.Name.Length > 50 ? song.Name.Substring(0, 50) + "..." : song.Name, CurrentSongArtUrl = song?.Album.Images.FirstOrDefault()?.Url ?? "/images/missingart.jpg", SongStartedAtUnixTimestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(), SongFinishesAtUnixTimestamp = _handledUntil.ToUnixTimeMilliseconds() }; _roomEvents.Add(new SongPlayedEvent(nextPlayer.UserName, nextPlayer.FriendlyName, $"{CurrentRoomState.CurrentSongArtist} - {CurrentRoomState.CurrentSongTitle}", song.Id, song.Uri)); // successfully played song, so change last song played _timeSinceLastSongPlayed = _handledUntil; return(CurrentRoomState); } // remove user as DJ if song is null nextPlayer.IsDj = false; OnRoomMembersChanged?.Invoke(this, null); // then try again } }