SongGuess
    Preparing search index...

    Hierarchy (View Summary)

    • Game
      • PlayerPicksGame
    Index
    currentQuestionIndex: number = -1

    The index of the current question. 0 based.

    gamePhase: GamePhase = GamePhase.PAUSE_MUSIC

    The current game phase

    hasPickingPhase: boolean = true

    Whether the game has a picking phase.

    isRunning: boolean = false

    Whether the game currently is running

    nextQuestions: Map<string, PlayerPicksQuestion> = ...

    Map of the questions selected by players during picking phase. Key is player uuid.

    questions: PlayerPicksQuestion[] = []

    The list of questions for the current game.

    questionStartTime: number = -1

    The timestamp when the current question started.

    questionTick: number = 0

    The current question round tick (in seconds).

    room: ValidRoom
    roundCurrent: number = 0

    Current round number. 1 based.

    • Ends the current game without returning to lobby and transitions to the results state.

      Parameters

      • sendUpdate: boolean = true

        whether to send an update that the game ended to the players.

      Returns void

    • Constructs an audio control load message.

      Parameters

      • action: "load"

        must be "load" for a load message.

      • OptionalaudioURL: string

        an ["audioURL"] to a music file that the client should preload.

      Returns
          | { action: "load"; audioURL: string; type: "audio_control" }
          | {
              action:
                  | "play"
                  | "pause"
                  | "play_countdown_running"
                  | "play_countdown_end";
              type: "audio_control";
          }

      a JSON string of the constructed AudioControlMessage

      • { action: "load"; audioURL: string; type: "audio_control" }
        • action: "load"
          • "load": Downloads the music.
        • audioURL: string

          URL to load music from.

        • type: "audio_control"
      • {
            action:
                | "play"
                | "pause"
                | "play_countdown_running"
                | "play_countdown_end";
            type: "audio_control";
        }
        • action: "play" | "pause" | "play_countdown_running" | "play_countdown_end"
          • "play": Starts playback of the music.
          • "pause": Pauses playback of the music.
          • "play_countdown_running": Plays the countdown_running sound effect on a secondary audio player.
          • "play_countdown_end": Plays the countdown_end sound effect on a secondary audio player.
        • type: "audio_control"
    • Constructs an audio control message.

      Parameters

      • action: "play" | "pause" | "play_countdown_running" | "play_countdown_end"

        the ["action"] that should be performed.

      • OptionalaudioURL: undefined

        can only be provided for load action.

      Returns
          | { action: "load"; audioURL: string; type: "audio_control" }
          | {
              action:
                  | "play"
                  | "pause"
                  | "play_countdown_running"
                  | "play_countdown_end";
              type: "audio_control";
          }

      a JSON string of the constructed AudioControlMessage

      • { action: "load"; audioURL: string; type: "audio_control" }
        • action: "load"
          • "load": Downloads the music.
        • audioURL: string

          URL to load music from.

        • type: "audio_control"
      • {
            action:
                | "play"
                | "pause"
                | "play_countdown_running"
                | "play_countdown_end";
            type: "audio_control";
        }
        • action: "play" | "pause" | "play_countdown_running" | "play_countdown_end"
          • "play": Starts playback of the music.
          • "pause": Pauses playback of the music.
          • "play_countdown_running": Plays the countdown_running sound effect on a secondary audio player.
          • "play_countdown_end": Plays the countdown_end sound effect on a secondary audio player.
        • type: "audio_control"
    • Should return an array of all required ServerMessages so clients know about the current game state.

      Parameters

      • OptionalsendPrevious: boolean

        whether to include all messages for the question. Useful when client joins.

      • Optionalplayer: Player

      Returns (
          | { duration: number; offset: number; type: "progressbar_update" }
          | {
              advancedSongFiltering: boolean;
              audioStartPosition: number | null;
              distractionsPreferSameArtist: boolean;
              endWhenAnswered: boolean;
              gameMode: "multiple_choice" | "player_picks";
              multipleChoiceAnswersCount: number;
              playerPickTimeout: number;
              roundsCount: number;
              timePerQuestion: number;
              type: "room_config";
          }
          | {
              entry: LogEntry;
              level: "error"
              | "info"
              | "warn"
              | "debug";
              type: "add_log_message";
          }
          | { messages: LoggerStorage; type: "update_log_messages" }
          | {
              gamePhase: GamePhase;
              question?:
                  | {
                      answerOptions: string[];
                      correctAnswerIndex?: number;
                      questionType: "multiple_choice";
                      startPos: number;
                  }
                  | {
                      correctAnswer?: {
                          artist: string;
                          audioURL: string;
                          cover: string
                          | null;
                          hrefURL: string;
                          name: string;
                      };
                      pickerId: string;
                      questionCount: number;
                      questionCurrent: number;
                      questionType: "player_picks";
                      startPos: number;
                  };
              roundCurrent: number;
              type: "round_state";
          }
          | { action: "load"; audioURL: string; type: "audio_control" }
          | {
              action:
                  | "play"
                  | "pause"
                  | "play_countdown_running"
                  | "play_countdown_end";
              type: "audio_control";
          }
          | { countdown: number; type: "countdown" }
          | {
              songs: {
                  artist: string;
                  audioURL: string;
                  cover: string | null;
                  hrefURL: string;
                  name: string;
              }[];
              type: "update_played_songs";
          }
          | {
              filteredSongsCount: number;
              playlists?: {
                  cover: string
                  | null;
                  hrefURL: string;
                  name: string;
                  songs: {
                      artist: string;
                      audioURL: string;
                      cover: string | null;
                      hrefURL: string;
                      name: string;
                  }[];
                  subtitle?: string;
              }[];
              type: "update_playlists";
          }
          | {
              players: Record<
                  string,
                  {
                      answerData?: {
                          answer?: string;
                          answerIndex?: number;
                          answerSpeed: number;
                          answerTimestamp: number;
                          questionPoints: number;
                      };
                      color: string;
                      hasPicked?: boolean;
                      isHost: boolean;
                      isSpectator: boolean;
                      points: number;
                      username: string;
                      uuid: string;
                  },
              >;
              state: "lobby"
              | "results"
              | "ingame";
              type: "room_state";
              uuid: string;
          }
          | {
              error?: string;
              sourceMessage: | {
                  duration: number;
                  offset: number;
                  type: "progressbar_update";
              }
              | {
                  song: {
                      artist: string;
                      audioURL: string;
                      cover: string
                      | null;
                      hrefURL: string;
                      name: string;
                  };
                  startPos: number;
                  type: "player_pick_song";
              }
              | { answer?: string; answerIndex?: number; type: "select_answer" }
              | { type: "start_game" }
              | {
                  playlists: {
                      cover: string | null;
                      hrefURL: string;
                      name: string;
                      songs: {
                          artist: string;
                          audioURL: string;
                          cover: string | null;
                          hrefURL: string;
                          name: string;
                      }[];
                      subtitle?: string;
                  }[];
                  type: "add_playlists";
              }
              | { index: number
              | null; type: "remove_playlist" }
              | { type: "change_username"; username: string }
              | {
                  advancedSongFiltering: boolean;
                  audioStartPosition: number | null;
                  distractionsPreferSameArtist: boolean;
                  endWhenAnswered: boolean;
                  gameMode: "multiple_choice" | "player_picks";
                  multipleChoiceAnswersCount: number;
                  playerPickTimeout: number;
                  roundsCount: number;
                  timePerQuestion: number;
                  type: "room_config";
              }
              | { playerName: string; type: "transfer_host" }
              | { type: "return_to"; where: "lobby" | "results" }
              | {
                  entry: LogEntry;
                  level: "error" | "info" | "warn" | "debug";
                  type: "add_log_message";
              }
              | { messages: LoggerStorage; type: "update_log_messages" }
              | {
                  gamePhase: GamePhase;
                  question?:
                      | {
                          answerOptions: string[];
                          correctAnswerIndex?: number;
                          questionType: "multiple_choice";
                          startPos: number;
                      }
                      | {
                          correctAnswer?: {
                              artist: string;
                              audioURL: string;
                              cover: string
                              | null;
                              hrefURL: string;
                              name: string;
                          };
                          pickerId: string;
                          questionCount: number;
                          questionCurrent: number;
                          questionType: "player_picks";
                          startPos: number;
                      };
                  roundCurrent: number;
                  type: "round_state";
              }
              | { action: "load"; audioURL: string; type: "audio_control" }
              | {
                  action:
                      | "play"
                      | "pause"
                      | "play_countdown_running"
                      | "play_countdown_end";
                  type: "audio_control";
              }
              | { countdown: number; type: "countdown" }
              | {
                  songs: {
                      artist: string;
                      audioURL: string;
                      cover: string | null;
                      hrefURL: string;
                      name: string;
                  }[];
                  type: "update_played_songs";
              }
              | {
                  filteredSongsCount: number;
                  playlists?: {
                      cover: string
                      | null;
                      hrefURL: string;
                      name: string;
                      songs: {
                          artist: string;
                          audioURL: string;
                          cover: (...) | (...);
                          hrefURL: string;
                          name: string;
                      }[];
                      subtitle?: string;
                  }[];
                  type: "update_playlists";
              }
              | {
                  players: Record<
                      string,
                      {
                          answerData?: {
                              answer?: string;
                              answerIndex?: number;
                              answerSpeed: number;
                              answerTimestamp: number;
                              questionPoints: number;
                          };
                          color: string;
                          hasPicked?: boolean;
                          isHost: boolean;
                          isSpectator: boolean;
                          points: number;
                          username: string;
                          uuid: string;
                      },
                  >;
                  state: "lobby"
                  | "results"
                  | "ingame";
                  type: "room_state";
                  uuid: string;
              }
              | { type: "other" };
              type: "confirmation";
          }
          | { seq: number; type: "ping" }
          | { seq: number; type: "pong" }
      )[]

      • { duration: number; offset: number; type: "progressbar_update" }
        • duration: number

          The duration of the progressbar.

        • offset: number

          The number of seconds to offset the progress bar start point.

        • type: "progressbar_update"
      • {
            advancedSongFiltering: boolean;
            audioStartPosition: number | null;
            distractionsPreferSameArtist: boolean;
            endWhenAnswered: boolean;
            gameMode: "multiple_choice" | "player_picks";
            multipleChoiceAnswersCount: number;
            playerPickTimeout: number;
            roundsCount: number;
            timePerQuestion: number;
            type: "room_config";
        }
        • advancedSongFiltering: boolean

          Whether to perform advanced filtering tactics when generating the songs array. Currently just ignores parens when filtering for identical song names.

        • audioStartPosition: number | null

          The music start position for a game.

          Must be a float between

          • 0.0: start of audio

          and

          • 1.0: close to end of audio (audio duration minus max play time determined by config + round padding)

          Can be null to use random position (multiple choice) / let picker decide (player picks)

        • distractionsPreferSameArtist: boolean

          Whether to prefer distractions by the same artist.

        • endWhenAnswered: boolean

          Whether to directly end the round after all players answered.

        • gameMode: "multiple_choice" | "player_picks"

          The game mode being played.

          • multiple_choice: the server selects random songs from the provided playlist and provides a multiple choice question with distractions.
          • player_picks: a player from the room picks a song for other players to guess each round. other players have to guess the song title by typing.
        • multipleChoiceAnswersCount: number

          The amount of multiple choice answers to add.

        • playerPickTimeout: number

          The amount of time a player should have to pick a song.

        • roundsCount: number

          The amount of rounds to play.

        • timePerQuestion: number

          The time per question in each round.

        • type: "room_config"
      • {
            entry: LogEntry;
            level: "error" | "info" | "warn" | "debug";
            type: "add_log_message";
        }
        • entry: LogEntry

          The added log message.

        • level: "error" | "info" | "warn" | "debug"

          The log level of the added message.

        • type: "add_log_message"
      • { messages: LoggerStorage; type: "update_log_messages" }
      • {
            gamePhase: GamePhase;
            question?:
                | {
                    answerOptions: string[];
                    correctAnswerIndex?: number;
                    questionType: "multiple_choice";
                    startPos: number;
                }
                | {
                    correctAnswer?: {
                        artist: string;
                        audioURL: string;
                        cover: string
                        | null;
                        hrefURL: string;
                        name: string;
                    };
                    pickerId: string;
                    questionCount: number;
                    questionCurrent: number;
                    questionType: "player_picks";
                    startPos: number;
                };
            roundCurrent: number;
            type: "round_state";
        }
        • gamePhase: GamePhase

          The current game phase.

          GamePhase

        • Optionalquestion?:
              | {
                  answerOptions: string[];
                  correctAnswerIndex?: number;
                  questionType: "multiple_choice";
                  startPos: number;
              }
              | {
                  correctAnswer?: {
                      artist: string;
                      audioURL: string;
                      cover: string
                      | null;
                      hrefURL: string;
                      name: string;
                  };
                  pickerId: string;
                  questionCount: number;
                  questionCurrent: number;
                  questionType: "player_picks";
                  startPos: number;
              }
        • roundCurrent: number

          The round number.

        • type: "round_state"
      • { action: "load"; audioURL: string; type: "audio_control" }
        • action: "load"
          • "load": Downloads the music.
        • audioURL: string

          URL to load music from.

        • type: "audio_control"
      • {
            action:
                | "play"
                | "pause"
                | "play_countdown_running"
                | "play_countdown_end";
            type: "audio_control";
        }
        • action: "play" | "pause" | "play_countdown_running" | "play_countdown_end"
          • "play": Starts playback of the music.
          • "pause": Pauses playback of the music.
          • "play_countdown_running": Plays the countdown_running sound effect on a secondary audio player.
          • "play_countdown_end": Plays the countdown_end sound effect on a secondary audio player.
        • type: "audio_control"
      • { countdown: number; type: "countdown" }
        • countdown: number

          The current countdown number. 0 to hide.

        • type: "countdown"
      • {
            songs: {
                artist: string;
                audioURL: string;
                cover: string | null;
                hrefURL: string;
                name: string;
            }[];
            type: "update_played_songs";
        }
        • songs: {
              artist: string;
              audioURL: string;
              cover: string | null;
              hrefURL: string;
              name: string;
          }[]

          The songs that were played in this round.

        • type: "update_played_songs"
      • {
            filteredSongsCount: number;
            playlists?: {
                cover: string | null;
                hrefURL: string;
                name: string;
                songs: {
                    artist: string;
                    audioURL: string;
                    cover: string | null;
                    hrefURL: string;
                    name: string;
                }[];
                subtitle?: string;
            }[];
            type: "update_playlists";
        }
        • filteredSongsCount: number

          The count of filtered songs.

          filterSongs

        • Optionalplaylists?: {
              cover: string | null;
              hrefURL: string;
              name: string;
              songs: {
                  artist: string;
                  audioURL: string;
                  cover: string | null;
                  hrefURL: string;
                  name: string;
              }[];
              subtitle?: string;
          }[]

          Currently selected playlist(s)

        • type: "update_playlists"
      • {
            players: Record<
                string,
                {
                    answerData?: {
                        answer?: string;
                        answerIndex?: number;
                        answerSpeed: number;
                        answerTimestamp: number;
                        questionPoints: number;
                    };
                    color: string;
                    hasPicked?: boolean;
                    isHost: boolean;
                    isSpectator: boolean;
                    points: number;
                    username: string;
                    uuid: string;
                },
            >;
            state: "lobby"
            | "results"
            | "ingame";
            type: "room_state";
            uuid: string;
        }
        • players: Record<
              string,
              {
                  answerData?: {
                      answer?: string;
                      answerIndex?: number;
                      answerSpeed: number;
                      answerTimestamp: number;
                      questionPoints: number;
                  };
                  color: string;
                  hasPicked?: boolean;
                  isHost: boolean;
                  isSpectator: boolean;
                  points: number;
                  username: string;
                  uuid: string;
              },
          >

          A map of all active (online, non-spectating) players. Key is server generated uuid, NOT connection id.

        • state: "lobby" | "results" | "ingame"

          The current game state

        • type: "room_state"
        • uuid: string

          The player's unique identifier generated by the server. Not connection id!

      • {
            error?: string;
            sourceMessage:
                | { duration: number; offset: number; type: "progressbar_update" }
                | {
                    song: {
                        artist: string;
                        audioURL: string;
                        cover: string | null;
                        hrefURL: string;
                        name: string;
                    };
                    startPos: number;
                    type: "player_pick_song";
                }
                | { answer?: string; answerIndex?: number; type: "select_answer" }
                | { type: "start_game" }
                | {
                    playlists: {
                        cover: string | null;
                        hrefURL: string;
                        name: string;
                        songs: {
                            artist: string;
                            audioURL: string;
                            cover: string | null;
                            hrefURL: string;
                            name: string;
                        }[];
                        subtitle?: string;
                    }[];
                    type: "add_playlists";
                }
                | { index: number
                | null; type: "remove_playlist" }
                | { type: "change_username"; username: string }
                | {
                    advancedSongFiltering: boolean;
                    audioStartPosition: number | null;
                    distractionsPreferSameArtist: boolean;
                    endWhenAnswered: boolean;
                    gameMode: "multiple_choice" | "player_picks";
                    multipleChoiceAnswersCount: number;
                    playerPickTimeout: number;
                    roundsCount: number;
                    timePerQuestion: number;
                    type: "room_config";
                }
                | { playerName: string; type: "transfer_host" }
                | { type: "return_to"; where: "lobby" | "results" }
                | {
                    entry: LogEntry;
                    level: "error" | "info" | "warn" | "debug";
                    type: "add_log_message";
                }
                | { messages: LoggerStorage; type: "update_log_messages" }
                | {
                    gamePhase: GamePhase;
                    question?:
                        | {
                            answerOptions: string[];
                            correctAnswerIndex?: number;
                            questionType: "multiple_choice";
                            startPos: number;
                        }
                        | {
                            correctAnswer?: {
                                artist: string;
                                audioURL: string;
                                cover: string
                                | null;
                                hrefURL: string;
                                name: string;
                            };
                            pickerId: string;
                            questionCount: number;
                            questionCurrent: number;
                            questionType: "player_picks";
                            startPos: number;
                        };
                    roundCurrent: number;
                    type: "round_state";
                }
                | { action: "load"; audioURL: string; type: "audio_control" }
                | {
                    action:
                        | "play"
                        | "pause"
                        | "play_countdown_running"
                        | "play_countdown_end";
                    type: "audio_control";
                }
                | { countdown: number; type: "countdown" }
                | {
                    songs: {
                        artist: string;
                        audioURL: string;
                        cover: string | null;
                        hrefURL: string;
                        name: string;
                    }[];
                    type: "update_played_songs";
                }
                | {
                    filteredSongsCount: number;
                    playlists?: {
                        cover: string
                        | null;
                        hrefURL: string;
                        name: string;
                        songs: {
                            artist: string;
                            audioURL: string;
                            cover: (...) | (...);
                            hrefURL: string;
                            name: string;
                        }[];
                        subtitle?: string;
                    }[];
                    type: "update_playlists";
                }
                | {
                    players: Record<
                        string,
                        {
                            answerData?: {
                                answer?: string;
                                answerIndex?: number;
                                answerSpeed: number;
                                answerTimestamp: number;
                                questionPoints: number;
                            };
                            color: string;
                            hasPicked?: boolean;
                            isHost: boolean;
                            isSpectator: boolean;
                            points: number;
                            username: string;
                            uuid: string;
                        },
                    >;
                    state: "lobby"
                    | "results"
                    | "ingame";
                    type: "room_state";
                    uuid: string;
                }
                | { type: "other" };
            type: "confirmation";
        }
        • Optionalerror?: string

          Optional error message if the requested action could not be performed.

        • sourceMessage:
              | { duration: number; offset: number; type: "progressbar_update" }
              | {
                  song: {
                      artist: string;
                      audioURL: string;
                      cover: string | null;
                      hrefURL: string;
                      name: string;
                  };
                  startPos: number;
                  type: "player_pick_song";
              }
              | { answer?: string; answerIndex?: number; type: "select_answer" }
              | { type: "start_game" }
              | {
                  playlists: {
                      cover: string | null;
                      hrefURL: string;
                      name: string;
                      songs: {
                          artist: string;
                          audioURL: string;
                          cover: string | null;
                          hrefURL: string;
                          name: string;
                      }[];
                      subtitle?: string;
                  }[];
                  type: "add_playlists";
              }
              | { index: number
              | null; type: "remove_playlist" }
              | { type: "change_username"; username: string }
              | {
                  advancedSongFiltering: boolean;
                  audioStartPosition: number | null;
                  distractionsPreferSameArtist: boolean;
                  endWhenAnswered: boolean;
                  gameMode: "multiple_choice" | "player_picks";
                  multipleChoiceAnswersCount: number;
                  playerPickTimeout: number;
                  roundsCount: number;
                  timePerQuestion: number;
                  type: "room_config";
              }
              | { playerName: string; type: "transfer_host" }
              | { type: "return_to"; where: "lobby" | "results" }
              | {
                  entry: LogEntry;
                  level: "error" | "info" | "warn" | "debug";
                  type: "add_log_message";
              }
              | { messages: LoggerStorage; type: "update_log_messages" }
              | {
                  gamePhase: GamePhase;
                  question?:
                      | {
                          answerOptions: string[];
                          correctAnswerIndex?: number;
                          questionType: "multiple_choice";
                          startPos: number;
                      }
                      | {
                          correctAnswer?: {
                              artist: string;
                              audioURL: string;
                              cover: string
                              | null;
                              hrefURL: string;
                              name: string;
                          };
                          pickerId: string;
                          questionCount: number;
                          questionCurrent: number;
                          questionType: "player_picks";
                          startPos: number;
                      };
                  roundCurrent: number;
                  type: "round_state";
              }
              | { action: "load"; audioURL: string; type: "audio_control" }
              | {
                  action:
                      | "play"
                      | "pause"
                      | "play_countdown_running"
                      | "play_countdown_end";
                  type: "audio_control";
              }
              | { countdown: number; type: "countdown" }
              | {
                  songs: {
                      artist: string;
                      audioURL: string;
                      cover: string | null;
                      hrefURL: string;
                      name: string;
                  }[];
                  type: "update_played_songs";
              }
              | {
                  filteredSongsCount: number;
                  playlists?: {
                      cover: string
                      | null;
                      hrefURL: string;
                      name: string;
                      songs: {
                          artist: string;
                          audioURL: string;
                          cover: (...) | (...);
                          hrefURL: string;
                          name: string;
                      }[];
                      subtitle?: string;
                  }[];
                  type: "update_playlists";
              }
              | {
                  players: Record<
                      string,
                      {
                          answerData?: {
                              answer?: string;
                              answerIndex?: number;
                              answerSpeed: number;
                              answerTimestamp: number;
                              questionPoints: number;
                          };
                          color: string;
                          hasPicked?: boolean;
                          isHost: boolean;
                          isSpectator: boolean;
                          points: number;
                          username: string;
                          uuid: string;
                      },
                  >;
                  state: "lobby"
                  | "results"
                  | "ingame";
                  type: "room_state";
                  uuid: string;
              }
              | { type: "other" }

          The message that is being confirmed.

        • type: "confirmation"
      • { seq: number; type: "ping" }
        • seq: number

          The sequence number the pong should respond with

        • type: "ping"
      • { seq: number; type: "pong" }
        • seq: number

          The sequence number asked for in the ping packet.

        • type: "pong"
    • Constructs a played songs update message with the songs played in the game.

      Returns {
          songs: {
              artist: string;
              audioURL: string;
              cover: string | null;
              hrefURL: string;
              name: string;
          }[];
          type: "update_played_songs";
      }

      a JSON string of the constructed UpdatePlayedSongsMessage

      • songs: {
            artist: string;
            audioURL: string;
            cover: string | null;
            hrefURL: string;
            name: string;
        }[]

        The songs that were played in this round.

      • type: "update_played_songs"
    • Core scoring logic that calculates points based on string similarity.

      Parameters

      • correctAnswer: string

        The normalized ground-truth string.

      • playerAnswer: string

        The normalized player-submitted string.

      • avgWithTokenSetRatio: boolean

        true: average the levenshtein ratio with the token set ratio in the calculation. will also scale the similarity based on the length of the target string, being more forgiving with longer target strings. false: only use levenshtein.

      Returns number

      A score ranging from 0 to half of QUESTION_MAX_POINTS.

      A minimum similarity of QUESTION_ANSWER_MIN_SIMILARITY is required to score. Points are scaled linearly from that point until 100%.

    • Calculates points based on the similarity of the "base" song title, effectively ignoring any parenthetical metadata of the solution like "(feat. Artist)" or "[Live]". Gets more forgiving the longer the target string.

      Parameters

      • player: Player

        The player object containing the submitted answer data.

      Returns number

      A score between 0 and 50% of the maximum round points.

      this.getPointsByDistance

    • Calculates points based on the similarity of the full song title, including all parenthetical metadata and extra descriptors.

      Parameters

      • player: Player

        The player object containing the submitted answer data.

      Returns number

      A score between 0 and 50% of the maximum round points.

      this.getPointsByDistance

    • Generates a progress bar update message based on the current game phase.

      Returns { duration: number; offset: number; type: "progressbar_update" }

      ProgressbarUpdateMessage with duration, startAt, and elapsed time for the progress bar.

      • duration: number

        The duration of the progressbar.

      • offset: number

        The number of seconds to offset the progress bar start point.

      • type: "progressbar_update"
    • Handles incoming client messages

      Parameters

      • player: Player

        the player that sent the message

      • msg:
            | {
                song: {
                    artist: string;
                    audioURL: string;
                    cover: string
                    | null;
                    hrefURL: string;
                    name: string;
                };
                startPos: number;
                type: "player_pick_song";
            }
            | { answer?: string; answerIndex?: number; type: "select_answer" }
            | { type: "start_game" }
            | {
                playlists: {
                    cover: string | null;
                    hrefURL: string;
                    name: string;
                    songs: {
                        artist: string;
                        audioURL: string;
                        cover: string | null;
                        hrefURL: string;
                        name: string;
                    }[];
                    subtitle?: string;
                }[];
                type: "add_playlists";
            }
            | { index: number
            | null; type: "remove_playlist" }
            | { type: "change_username"; username: string }
            | {
                advancedSongFiltering: boolean;
                audioStartPosition: number | null;
                distractionsPreferSameArtist: boolean;
                endWhenAnswered: boolean;
                gameMode: "multiple_choice" | "player_picks";
                multipleChoiceAnswersCount: number;
                playerPickTimeout: number;
                roundsCount: number;
                timePerQuestion: number;
                type: "room_config";
            }
            | { playerName: string; type: "transfer_host" }
            | { type: "return_to"; where: "lobby" | "results" }
            | {
                error?: string;
                sourceMessage:
                    | { duration: number; offset: number; type: "progressbar_update" }
                    | {
                        song: {
                            artist: string;
                            audioURL: string;
                            cover: string | null;
                            hrefURL: string;
                            name: string;
                        };
                        startPos: number;
                        type: "player_pick_song";
                    }
                    | { answer?: string; answerIndex?: number; type: "select_answer" }
                    | { type: "start_game" }
                    | {
                        playlists: {
                            cover: string | null;
                            hrefURL: string;
                            name: string;
                            songs: {
                                artist: string;
                                audioURL: string;
                                cover: string | null;
                                hrefURL: string;
                                name: string;
                            }[];
                            subtitle?: string;
                        }[];
                        type: "add_playlists";
                    }
                    | { index: number
                    | null; type: "remove_playlist" }
                    | { type: "change_username"; username: string }
                    | {
                        advancedSongFiltering: boolean;
                        audioStartPosition: number | null;
                        distractionsPreferSameArtist: boolean;
                        endWhenAnswered: boolean;
                        gameMode: "multiple_choice" | "player_picks";
                        multipleChoiceAnswersCount: number;
                        playerPickTimeout: number;
                        roundsCount: number;
                        timePerQuestion: number;
                        type: "room_config";
                    }
                    | { playerName: string; type: "transfer_host" }
                    | { type: "return_to"; where: "lobby" | "results" }
                    | {
                        entry: LogEntry;
                        level: "error" | "info" | "warn" | "debug";
                        type: "add_log_message";
                    }
                    | { messages: LoggerStorage; type: "update_log_messages" }
                    | {
                        gamePhase: GamePhase;
                        question?:
                            | {
                                answerOptions: string[];
                                correctAnswerIndex?: number;
                                questionType: "multiple_choice";
                                startPos: number;
                            }
                            | {
                                correctAnswer?: {
                                    artist: string;
                                    audioURL: string;
                                    cover: string
                                    | null;
                                    hrefURL: string;
                                    name: string;
                                };
                                pickerId: string;
                                questionCount: number;
                                questionCurrent: number;
                                questionType: "player_picks";
                                startPos: number;
                            };
                        roundCurrent: number;
                        type: "round_state";
                    }
                    | { action: "load"; audioURL: string; type: "audio_control" }
                    | {
                        action:
                            | "play"
                            | "pause"
                            | "play_countdown_running"
                            | "play_countdown_end";
                        type: "audio_control";
                    }
                    | { countdown: number; type: "countdown" }
                    | {
                        songs: {
                            artist: string;
                            audioURL: string;
                            cover: string | null;
                            hrefURL: string;
                            name: string;
                        }[];
                        type: "update_played_songs";
                    }
                    | {
                        filteredSongsCount: number;
                        playlists?: {
                            cover: string
                            | null;
                            hrefURL: string;
                            name: string;
                            songs: {
                                artist: string;
                                audioURL: string;
                                cover: string | null;
                                hrefURL: string;
                                name: string;
                            }[];
                            subtitle?: string;
                        }[];
                        type: "update_playlists";
                    }
                    | {
                        players: Record<
                            string,
                            {
                                answerData?: {
                                    answer?: string;
                                    answerIndex?: number;
                                    answerSpeed: number;
                                    answerTimestamp: number;
                                    questionPoints: number;
                                };
                                color: string;
                                hasPicked?: boolean;
                                isHost: boolean;
                                isSpectator: boolean;
                                points: number;
                                username: string;
                                uuid: string;
                            },
                        >;
                        state: "lobby"
                        | "results"
                        | "ingame";
                        type: "room_state";
                        uuid: string;
                    }
                    | { type: "other" };
                type: "confirmation";
            }
            | { seq: number; type: "ping" }
            | { seq: number; type: "pong" }

        the sent message

        • {
              song: {
                  artist: string;
                  audioURL: string;
                  cover: string | null;
                  hrefURL: string;
                  name: string;
              };
              startPos: number;
              type: "player_pick_song";
          }
          • song: {
                artist: string;
                audioURL: string;
                cover: string | null;
                hrefURL: string;
                name: string;
            }

            The song the player picked in the choose step.

            • artist: string

              The name of the song artist.

            • audioURL: string

              A URL to the audio file of the song. Currently only audio previews from Apple Music, SoundCloud and YT are allowed.

            • cover: string | null

              Cover URL of the song.

            • hrefURL: string

              The URL users will be redirected to when clicking.

            • name: string

              The name of the song.

          • startPos: number

            The selected start pos for the song.

            RoomConfigMessageSchema.audioStartPosition

          • type: "player_pick_song"
        • { answer?: string; answerIndex?: number; type: "select_answer" }
          • Optionalanswer?: string

            Provided only for PlayerPicksGame. The string of the song name the player guessed.

          • OptionalanswerIndex?: number

            Provided only for MultipleChoiceGame. The index of the selected answer.

          • type: "select_answer"
        • { type: "start_game" }
        • {
              playlists: {
                  cover: string | null;
                  hrefURL: string;
                  name: string;
                  songs: {
                      artist: string;
                      audioURL: string;
                      cover: string | null;
                      hrefURL: string;
                      name: string;
                  }[];
                  subtitle?: string;
              }[];
              type: "add_playlists";
          }
          • playlists: {
                cover: string | null;
                hrefURL: string;
                name: string;
                songs: {
                    artist: string;
                    audioURL: string;
                    cover: string | null;
                    hrefURL: string;
                    name: string;
                }[];
                subtitle?: string;
            }[]

            The new playlist to add.

          • type: "add_playlists"
        • { index: number | null; type: "remove_playlist" }
          • index: number | null

            The playlist index to remove.

          • type: "remove_playlist"
        • { type: "change_username"; username: string }
          • type: "change_username"
          • username: string

            The new username.

        • {
              advancedSongFiltering: boolean;
              audioStartPosition: number | null;
              distractionsPreferSameArtist: boolean;
              endWhenAnswered: boolean;
              gameMode: "multiple_choice" | "player_picks";
              multipleChoiceAnswersCount: number;
              playerPickTimeout: number;
              roundsCount: number;
              timePerQuestion: number;
              type: "room_config";
          }
          • advancedSongFiltering: boolean

            Whether to perform advanced filtering tactics when generating the songs array. Currently just ignores parens when filtering for identical song names.

          • audioStartPosition: number | null

            The music start position for a game.

            Must be a float between

            • 0.0: start of audio

            and

            • 1.0: close to end of audio (audio duration minus max play time determined by config + round padding)

            Can be null to use random position (multiple choice) / let picker decide (player picks)

          • distractionsPreferSameArtist: boolean

            Whether to prefer distractions by the same artist.

          • endWhenAnswered: boolean

            Whether to directly end the round after all players answered.

          • gameMode: "multiple_choice" | "player_picks"

            The game mode being played.

            • multiple_choice: the server selects random songs from the provided playlist and provides a multiple choice question with distractions.
            • player_picks: a player from the room picks a song for other players to guess each round. other players have to guess the song title by typing.
          • multipleChoiceAnswersCount: number

            The amount of multiple choice answers to add.

          • playerPickTimeout: number

            The amount of time a player should have to pick a song.

          • roundsCount: number

            The amount of rounds to play.

          • timePerQuestion: number

            The time per question in each round.

          • type: "room_config"
        • { playerName: string; type: "transfer_host" }
          • playerName: string

            The name of the player that should get host.

          • type: "transfer_host"
        • { type: "return_to"; where: "lobby" | "results" }
          • type: "return_to"
          • where: "lobby" | "results"

            Where to send the player to.

        • {
              error?: string;
              sourceMessage:
                  | { duration: number; offset: number; type: "progressbar_update" }
                  | {
                      song: {
                          artist: string;
                          audioURL: string;
                          cover: string | null;
                          hrefURL: string;
                          name: string;
                      };
                      startPos: number;
                      type: "player_pick_song";
                  }
                  | { answer?: string; answerIndex?: number; type: "select_answer" }
                  | { type: "start_game" }
                  | {
                      playlists: {
                          cover: string | null;
                          hrefURL: string;
                          name: string;
                          songs: {
                              artist: string;
                              audioURL: string;
                              cover: string | null;
                              hrefURL: string;
                              name: string;
                          }[];
                          subtitle?: string;
                      }[];
                      type: "add_playlists";
                  }
                  | { index: number
                  | null; type: "remove_playlist" }
                  | { type: "change_username"; username: string }
                  | {
                      advancedSongFiltering: boolean;
                      audioStartPosition: number | null;
                      distractionsPreferSameArtist: boolean;
                      endWhenAnswered: boolean;
                      gameMode: "multiple_choice" | "player_picks";
                      multipleChoiceAnswersCount: number;
                      playerPickTimeout: number;
                      roundsCount: number;
                      timePerQuestion: number;
                      type: "room_config";
                  }
                  | { playerName: string; type: "transfer_host" }
                  | { type: "return_to"; where: "lobby" | "results" }
                  | {
                      entry: LogEntry;
                      level: "error" | "info" | "warn" | "debug";
                      type: "add_log_message";
                  }
                  | { messages: LoggerStorage; type: "update_log_messages" }
                  | {
                      gamePhase: GamePhase;
                      question?:
                          | {
                              answerOptions: string[];
                              correctAnswerIndex?: number;
                              questionType: "multiple_choice";
                              startPos: number;
                          }
                          | {
                              correctAnswer?: {
                                  artist: string;
                                  audioURL: string;
                                  cover: string
                                  | null;
                                  hrefURL: string;
                                  name: string;
                              };
                              pickerId: string;
                              questionCount: number;
                              questionCurrent: number;
                              questionType: "player_picks";
                              startPos: number;
                          };
                      roundCurrent: number;
                      type: "round_state";
                  }
                  | { action: "load"; audioURL: string; type: "audio_control" }
                  | {
                      action:
                          | "play"
                          | "pause"
                          | "play_countdown_running"
                          | "play_countdown_end";
                      type: "audio_control";
                  }
                  | { countdown: number; type: "countdown" }
                  | {
                      songs: {
                          artist: string;
                          audioURL: string;
                          cover: string | null;
                          hrefURL: string;
                          name: string;
                      }[];
                      type: "update_played_songs";
                  }
                  | {
                      filteredSongsCount: number;
                      playlists?: {
                          cover: string
                          | null;
                          hrefURL: string;
                          name: string;
                          songs: {
                              artist: string;
                              audioURL: string;
                              cover: string | null;
                              hrefURL: string;
                              name: string;
                          }[];
                          subtitle?: string;
                      }[];
                      type: "update_playlists";
                  }
                  | {
                      players: Record<
                          string,
                          {
                              answerData?: {
                                  answer?: string;
                                  answerIndex?: number;
                                  answerSpeed: number;
                                  answerTimestamp: number;
                                  questionPoints: number;
                              };
                              color: string;
                              hasPicked?: boolean;
                              isHost: boolean;
                              isSpectator: boolean;
                              points: number;
                              username: string;
                              uuid: string;
                          },
                      >;
                      state: "lobby"
                      | "results"
                      | "ingame";
                      type: "room_state";
                      uuid: string;
                  }
                  | { type: "other" };
              type: "confirmation";
          }
          • Optionalerror?: string

            Optional error message if the requested action could not be performed.

          • sourceMessage:
                | { duration: number; offset: number; type: "progressbar_update" }
                | {
                    song: {
                        artist: string;
                        audioURL: string;
                        cover: string | null;
                        hrefURL: string;
                        name: string;
                    };
                    startPos: number;
                    type: "player_pick_song";
                }
                | { answer?: string; answerIndex?: number; type: "select_answer" }
                | { type: "start_game" }
                | {
                    playlists: {
                        cover: string | null;
                        hrefURL: string;
                        name: string;
                        songs: {
                            artist: string;
                            audioURL: string;
                            cover: string | null;
                            hrefURL: string;
                            name: string;
                        }[];
                        subtitle?: string;
                    }[];
                    type: "add_playlists";
                }
                | { index: number
                | null; type: "remove_playlist" }
                | { type: "change_username"; username: string }
                | {
                    advancedSongFiltering: boolean;
                    audioStartPosition: number | null;
                    distractionsPreferSameArtist: boolean;
                    endWhenAnswered: boolean;
                    gameMode: "multiple_choice" | "player_picks";
                    multipleChoiceAnswersCount: number;
                    playerPickTimeout: number;
                    roundsCount: number;
                    timePerQuestion: number;
                    type: "room_config";
                }
                | { playerName: string; type: "transfer_host" }
                | { type: "return_to"; where: "lobby" | "results" }
                | {
                    entry: LogEntry;
                    level: "error" | "info" | "warn" | "debug";
                    type: "add_log_message";
                }
                | { messages: LoggerStorage; type: "update_log_messages" }
                | {
                    gamePhase: GamePhase;
                    question?:
                        | {
                            answerOptions: string[];
                            correctAnswerIndex?: number;
                            questionType: "multiple_choice";
                            startPos: number;
                        }
                        | {
                            correctAnswer?: {
                                artist: string;
                                audioURL: string;
                                cover: string
                                | null;
                                hrefURL: string;
                                name: string;
                            };
                            pickerId: string;
                            questionCount: number;
                            questionCurrent: number;
                            questionType: "player_picks";
                            startPos: number;
                        };
                    roundCurrent: number;
                    type: "round_state";
                }
                | { action: "load"; audioURL: string; type: "audio_control" }
                | {
                    action:
                        | "play"
                        | "pause"
                        | "play_countdown_running"
                        | "play_countdown_end";
                    type: "audio_control";
                }
                | { countdown: number; type: "countdown" }
                | {
                    songs: {
                        artist: string;
                        audioURL: string;
                        cover: string | null;
                        hrefURL: string;
                        name: string;
                    }[];
                    type: "update_played_songs";
                }
                | {
                    filteredSongsCount: number;
                    playlists?: {
                        cover: string
                        | null;
                        hrefURL: string;
                        name: string;
                        songs: {
                            artist: string;
                            audioURL: string;
                            cover: string | null;
                            hrefURL: string;
                            name: string;
                        }[];
                        subtitle?: string;
                    }[];
                    type: "update_playlists";
                }
                | {
                    players: Record<
                        string,
                        {
                            answerData?: {
                                answer?: string;
                                answerIndex?: number;
                                answerSpeed: number;
                                answerTimestamp: number;
                                questionPoints: number;
                            };
                            color: string;
                            hasPicked?: boolean;
                            isHost: boolean;
                            isSpectator: boolean;
                            points: number;
                            username: string;
                            uuid: string;
                        },
                    >;
                    state: "lobby"
                    | "results"
                    | "ingame";
                    type: "room_state";
                    uuid: string;
                }
                | { type: "other" }

            The message that is being confirmed.

          • type: "confirmation"
        • { seq: number; type: "ping" }
          • seq: number

            The sequence number the pong should respond with

          • type: "ping"
        • { seq: number; type: "pong" }
          • seq: number

            The sequence number asked for in the ping packet.

          • type: "pong"

      Returns boolean

      whether the message was handled by this listener.

    • Handles a player picking a song during the PICKING phase.

      Parameters

      • player: Player

        The player submitting the pick.

      • msg: {
            song: {
                artist: string;
                audioURL: string;
                cover: string | null;
                hrefURL: string;
                name: string;
            };
            startPos: number;
            type: "player_pick_song";
        }

        The message containing the chosen song and start position.

        • song: {
              artist: string;
              audioURL: string;
              cover: string | null;
              hrefURL: string;
              name: string;
          }

          The song the player picked in the choose step.

          • artist: string

            The name of the song artist.

          • audioURL: string

            A URL to the audio file of the song. Currently only audio previews from Apple Music, SoundCloud and YT are allowed.

          • cover: string | null

            Cover URL of the song.

          • hrefURL: string

            The URL users will be redirected to when clicking.

          • name: string

            The name of the song.

        • startPos: number

          The selected start pos for the song.

          RoomConfigMessageSchema.audioStartPosition

        • type: "player_pick_song"

      Returns Promise<void>

    • Save timestamp and answer, when user selects an answer.

      Parameters

      • player: Player

        the player that selected an answer.

      • msg: { answer?: string; answerIndex?: number; type: "select_answer" }
        • Optionalanswer?: string

          Provided only for PlayerPicksGame. The string of the song name the player guessed.

        • OptionalanswerIndex?: number

          Provided only for MultipleChoiceGame. The index of the selected answer.

        • type: "select_answer"

      Returns boolean