class_name ScoreHistory extends RefCounted ## Who got a point on which song of the current game, for the graph and the summary on ## the Winner popup. ## ## Songs are counted from 1 at the start of the game, which is the start of the playlist ## or the first song after the last Reset points. ## The players, in the order of [code]Settings.player_array[/code]. var players: Array[PlayerObject] = [] ## For each song of the game, in the order they were played, the ids of the players who ## got a point on it. var songs: Array[Array] = [] ## The current game, from [code]Playlist.game_start_song[/code] up to the last song that ## has played. Songs downloaded ahead but not played yet are left out, and so are points ## of players who are no longer in [param game_players]. static func from_playlist(game_players: Array[PlayerObject]) -> ScoreHistory: var song_scorers: Array[Array] = [] # Not just the song playing now: an older song may have been picked in the music list var last_song: int = mini(Playlist.currently_playing_song, Playlist.song_object_array.size() - 1) for song_no: int in Playlist.song_object_array.size(): if Playlist.song_object_array[song_no].has_played: last_song = maxi(last_song, song_no) for song_no: int in range(Playlist.game_start_song, last_song + 1): var song: SongObject = Playlist.song_object_array[song_no] if song.has_played || song_no == Playlist.currently_playing_song: song_scorers.append(song.players_given_point) return from_songs(game_players, song_scorers) ## A history of [param song_scorers], the ids of the players who scored on each song. static func from_songs(game_players: Array[PlayerObject], song_scorers: Array) -> ScoreHistory: var history: ScoreHistory = ScoreHistory.new() history.players = game_players.duplicate() var ids: Array[String] = [] for player: PlayerObject in game_players: ids.append(player.id) for scorers: Array in song_scorers: history.songs.append(scorers.filter(func(id: String) -> bool: return ids.has(id))) return history ## [param player_id]'s score before the first song and after each song. func scores_after_songs(player_id: String) -> Array[int]: var scores: Array[int] = [0] for scorers: Array in songs: scores.append(scores.back() + (1 if scorers.has(player_id) else 0)) return scores ## [param player_id]'s score after the last song. func final_score(player_id: String) -> int: return scores_after_songs(player_id).back() ## The player with the most songs in a row with a point, e.g. ## "Crono, 5 songs in a row (14–18)". The earliest streak wins a tie. func longest_streak_text() -> String: if songs.is_empty(): return "No songs played" var best_length: int = 0 var best_start: int = 0 var best_player: PlayerObject = null for player: PlayerObject in players: var length: int = 0 for song: int in songs.size(): length = length + 1 if songs[song].has(player.id) else 0 var start: int = song - length + 1 if length > best_length || (length == best_length && length > 0 \ && start < best_start): best_length = length best_start = start best_player = player if best_length < 2: return "Nobody scored twice in a row" return "%s, %d songs in a row (%d–%d)" % [best_player.player_name, best_length, best_start + 1, best_start + best_length] ## The most songs in a row where nobody scored, e.g. "Songs 6–10, nobody scored". func longest_standstill_text() -> String: if songs.is_empty(): return "No songs played" var best_length: int = 0 var best_start: int = 0 var length: int = 0 for song: int in songs.size(): length = length + 1 if songs[song].is_empty() else 0 if length > best_length: best_length = length best_start = song - length + 1 if best_length == 0: return "Someone scored on every song" if best_length == 1: return "Song %d, nobody scored" % (best_start + 1) return "Songs %d–%d, nobody scored" % [best_start + 1, best_start + best_length] ## The song most players scored on, e.g. "Song 11, Marle and Lucca", or ## "Song 11, 3 players" when more than two did. The earliest song wins a tie. func most_shared_text() -> String: if songs.is_empty(): return "No songs played" var best_song: int = -1 for song: int in songs.size(): if songs[song].size() >= 2 \ && (best_song < 0 || songs[song].size() > songs[best_song].size()): best_song = song if best_song < 0: return "No song had two scorers" var scorers: Array = songs[best_song] if scorers.size() > 2: return "Song %d, %d players" % [best_song + 1, scorers.size()] var names: PackedStringArray = [] for player: PlayerObject in players: if scorers.has(player.id): names.append(player.player_name) return "Song %d, %s" % [best_song + 1, " and ".join(names)]