var localStorage = window.localStorage; var localStoragePrefix = "unalike-"; var refreshFrequency = 5000; var maxUpdateDelayTolerance = 30; var defaultLobbyContent = '

No lobbies are open.

'; var defaultMultiplayerContent = '

History is empty.

'; var lobbyTemplate = '

Template loading...

'; var lobbyTemplate = ''; var refreshRequest = new XMLHttpRequest(); var templateRequest = new XMLHttpRequest(); var multiplayerRequest = new XMLHttpRequest(); var currentLobbiesContent = "initial"; var currentMultiplayerContent = "initial"; var onlineButtonSet = "initial"; var opMode = false; var session_username = "Guest"; var session_username_irc = "Guest"; var session_user_id = -3; var randomCover = (Math.floor(Math.random() * 8)+1); if (localStorage.getItem(localStoragePrefix + "lobbyCover")) { randomCover = localStorage.getItem(localStoragePrefix + "lobbyCover"); } refreshTemplate(); refreshRequest.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var result = JSON.parse(this.responseText); updateUnalikeDisplay(result); } }; multiplayerRequest.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var result = JSON.parse(this.responseText); updateMultiplayer(result); } }; function updateButtonSet(onlineState, force=false, full=false, empty=false) { if (document.getElementById("management-buttons")) { element = document.getElementById("management-buttons"); if (onlineButtonSet !== onlineState || force) { onlineButtonSet = onlineState; if (onlineButtonSet) { var temp = buttonsIfOnline; if (opMode) { temp = opButtonsIfOnline; } if (full) { temp = temp.replaceAll("putDisabledHere", "disabled"); } if (empty) { temp = temp.replaceAll("putDisabled2Here", "disabled"); } element.innerHTML = temp; } else { element.innerHTML = buttonsIfOffline; } } } } function updateUnalikeDisplay(unalikeJson) { var thisUpdateInterval = 10; // in seconds var thisUpdateIntervalIfLobby = 1; var thisUpdateIntervalIfPlaying = 6; var currentTimestamp = Math.floor(Date.now() / 1000); if (unalikeJson.timestamp + maxUpdateDelayTolerance < currentTimestamp) { unalikeJson = {} } statusDisplay = document.getElementById("unalike-status"); lobbiesContainer = document.getElementById("unalike-lobbies-container"); var oldLobbiesContent = currentLobbiesContent; var newStatus = ""; if (isEmpty(unalikeJson)) { newStatus = '

Unalike: Offline

Unalike is not running.

'; updateButtonSet(false); if (lobbiesContainer.innerHTML.trim().replace(/\s/g, "") != defaultLobbyContent.trim().replace(/\s/g, "")) { lobbiesContainer.innerHTML = defaultLobbyContent; } if (currentLobbiesContent != JSON.stringify(unalikeJson)) { currentLobbiesContent = JSON.stringify(unalikeJson); } } else { newStatus = '

Unalike: Online

Unalike is up.

'; var full = false var empty = false if (unalikeJson.maxLobbies && !isEmpty(unalikeJson)) { full = !(Object.keys(unalikeJson.lobbies).length < unalikeJson.maxLobbies) } if (!isEmpty(unalikeJson) && isEmpty(unalikeJson.lobbies)) { updateButtonSet(true, false, full, true); } if (unalikeJson.roundsPlayed) { var plural = "s have"; if (unalikeJson.roundsPlayed == 1) { plural = " gas"; } newStatus += "

" + unalikeJson.roundsPlayed + " game" + plural + " been played since boot."; } if (unalikeJson.delay) { newStatus += "

Current delay: " + unalikeJson.delay + " seconds between commands. (~" + unalikeJson.delay*4 + " seconds to create a lobby.)"; } if (unalikeJson.shutdownTimer) { newStatus += "

If nothing happens, Unalike will shut down in " + unalikeJson.shutdownTimer + " seconds."; } if (unalikeJson.sessionAdmin) { newStatus += "

" + unalikeJson.sessionAdmin + " was the first to interact with Unalike. Only he/she can shut it down on command."; } // dynamicJsonElement = document.getElementById("dynamic-json"); // dynamicJsonElement.innerHTML = JSON.stringify(unalikeJson); if (!isEmpty(unalikeJson.lobbies)) { if (unalikeJson.playing) { thisUpdateInterval = thisUpdateIntervalIfPlaying; } else { thisUpdateInterval = thisUpdateIntervalIfLobby; } var newLobbiesContent = ""; var songsInContent = []; var counter = 2; for (var lobby_id in unalikeJson.lobbies) { var lobby = unalikeJson.lobbies[lobby_id]; var playerList = []; if (!isEmpty(lobby.players)) { for (var player of lobby.players) { // playerList += "

  • " + player + "
  • "; if (session_username == player) { playerList.push('' + player + ''); } else { playerList.push('' + player + ''); } } // playerList = '

    Players:

    ' + // ''; playerList = '

    Players: ' + playerList.join(", ") + '

    '; } else { // playerList += "

    No one is in the lobby.

    "; } var title = 'Loading...
    ' + '
    ' + '
    ' + ''; if (lobby.beatmap && lobby.beatmap > 0) { var requestId = "songTitle" + counter++; var title = '
    ' + title + '
    '; songsInContent.push({ "requestId":requestId, "beatmapId":lobby.beatmap }); } else if (lobby.beatmap && lobby.beatmap == -2) { var title = 'Changing beatmap...
    ' + '
    ' + '
    ' + ''; } else { var title = 'No beatmap set.
    ' + '
    ' + '
    ' + ''; } var stateText = "Loading..."; var stateSymbol = "🔁"; var lobbyReady = true; if (lobby.playing) { stateSymbol = "▶️"; stateText = "Match in progress."; } else if (lobby.finished) { stateSymbol = "⏸"; stateText = "Finished. Waiting others..."; } else if (lobby.ready) { if (unalikeJson.playing) { stateSymbol = "🔁"; stateText = "Starting..."; } else { stateSymbol = "✅"; stateText = "Ready!"; } } else if (!isEmpty(lobby.players)) { stateSymbol = "❎"; stateText = "Not ready."; } else if (lobby.password) { stateSymbol = "🆙"; stateText = "Waiting for participants."; } else { stateSymbol = "🆕"; stateText = "Setting up lobby..."; lobbyReady = false; } if (lobbyReady) { if (lobby.desynced) { stateSymbol = "🔀 (Desynced)"; } else if (lobby.beatmapset > 0 && lobby.beatmapset != unalikeJson.current_mapset) { stateSymbol = "🆘 (Desynced)"; } } var state = stateSymbol + " " + stateText; var cover = "/Unalike/img/covers/c" + randomCover + ".jpg"; if (lobbyTemplate != '') { var tempLobbyText = lobbyTemplate .replaceAll("[[ SONG_INFO ]]", title) .replaceAll("[[ PLAYERS ]]", playerList) .replaceAll("[[ COVER_IMAGE ]]", cover) .replaceAll("[[ CHANNEL ]]", lobby.match) .replaceAll("[[ STATE ]]", state); if (!lobbyReady) { tempLobbyText = tempLobbyText.replaceAll("putDisabledHere", "disabled"); } newLobbiesContent += tempLobbyText; } } unalikeJson.timestamp = 0; if (currentLobbiesContent != JSON.stringify(unalikeJson) || lobbiesContainer.innerHTML.trim().replace(/\s/g, "") == "" || lobbiesContainer.innerHTML.trim().replace(/\s/g, "") == defaultLobbyContent.trim().replace(/\s/g, "") ) { lobbiesContainer.innerHTML = newLobbiesContent; currentLobbiesContent = JSON.stringify(unalikeJson); if (unalikeJson.maxLobbies) { full = !(Object.keys(unalikeJson.lobbies).length < unalikeJson.maxLobbies) } updateButtonSet(true, true, full); if (newLobbiesContent != "") { for (var songInContent of songsInContent) { refreshSongInfo(songInContent.requestId, songInContent.beatmapId); } } } } else { unalikeJson.timestamp = 0; if (currentLobbiesContent != JSON.stringify(unalikeJson)) { currentLobbiesContent = JSON.stringify(unalikeJson); updateButtonSet(true, true, false, true); } if (lobbiesContainer.innerHTML != defaultLobbyContent) { lobbiesContainer.innerHTML = defaultLobbyContent; } } } if (statusDisplay.innerHTML != newStatus) { statusDisplay.innerHTML = newStatus } if (currentLobbiesContent != oldLobbiesContent || currentLobbiesContent != oldLobbiesContent) { refreshMultiplayer(); } window.setTimeout(refreshData, thisUpdateInterval*1000) } function updateTemplate(templateReply) { lobbyTemplate = templateReply; refreshData(); } function updateSongInfo(elementId, beatmapId, beatmapJson) { if (document.getElementById(elementId)) { var content = ''; if (beatmapJson.url) { content += '
    '; } if (beatmapJson.beatmapset.title) { content += '' + beatmapJson.beatmapset.title + '
    '; } else { content += '
    '; } if (beatmapJson.beatmapset.artist) { content += '' + beatmapJson.beatmapset.artist + " // " + beatmapJson.beatmapset.creator + '
    '; } else { content += '
    '; } if (beatmapJson.version) { content += '' + beatmapJson.version + '
    '; } else { content += '
    '; } if (beatmapJson.difficulty_rating) { content += '' + beatmapJson.difficulty_rating.toFixed(2) + '★'; } else { content += ''; } if (beatmapJson.url) { content += '
    '; } var cover = beatmapJson.beatmapset.covers.cover; if (beatmapJson.beatmapset.covers["cover@2x"]) { cover = beatmapJson.beatmapset.covers["cover@2x"]; } element = document.getElementById(elementId); element.innerHTML = content if (beatmapJson.beatmapset.covers.cover) { element.parentElement.style.backgroundImage = "linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('" + cover + "')"; element.parentElement.style.backgroundSize = "cover"; } } } function updateMultiplayer(matchesJson) { if (currentMultiplayerContent != JSON.stringify(matchesJson)) { currentMultiplayerContent = JSON.stringify(matchesJson) var newContent = ""; if (isEmpty(matchesJson)) { newContent = defaultMultiplayerContent } else { var elementPrefix = "multiplayerMatch"; var counter = 1; for (var match of matchesJson) { var eId = elementPrefix + counter++; newContent += '
    '; } } if (document.getElementById("multiplayer-stats")) { document.getElementById("multiplayer-stats").innerHTML = newContent; var counter = 1; for (var match of matchesJson) { var eId = elementPrefix + counter++; refreshMatchInfo(eId, match); } } } } function updateMatchInfoContent(elementId, matchContent) { document.getElementById(elementId).innerHTML = matchContent; } function updateMatchInfo(elementId, matchJson) { for (var game of matchJson.games) { var newContent = "

    Game ID: " + game.game_id + "

    "; for (var score of game.scores) { newContent += "

    [#" + score.place + "] " + score.username + ": " + score.accuracy.toFixed(2) + "%

    "; } document.getElementById(elementId).innerHTML = newContent; break; } } function refreshData() { refreshRequest.open("GET", "./async/?", true); refreshRequest.send(); // console.log("Async request: ./async/?"); } function refreshMultiplayer() { multiplayerRequest.open("GET", "./async/match/?", true); multiplayerRequest.send(); } function refreshTemplate() { var localItemName = localStoragePrefix + "lobby-template"; templateRequest.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { localStorage.setItem(localItemName, this.responseText); updateTemplate(this.responseText); } }; if (localStorage.getItem(localItemName)) { updateTemplate(localStorage.getItem(localItemName)); } else { templateRequest.open("GET", "./async/lobby-template.html", true); templateRequest.send(); console.log("Async request: ./async/lobby-template.html"); } } function refreshSongInfo(elementId, beatmapId) { var songInfoRequest = new XMLHttpRequest(); var localItemName = localStoragePrefix + "beatmap-" + session_username + "-" + beatmapId; songInfoRequest.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var eId = elementId; var bId = beatmapId; var result = JSON.parse(this.responseText); localStorage.setItem(localItemName, this.responseText); updateSongInfo(eId, bId, result); } }; if (localStorage.getItem(localItemName)) { var localJson = JSON.parse(localStorage.getItem(localItemName)); updateSongInfo(elementId, beatmapId, localJson); } else { var playerName = session_username; songInfoRequest.open("GET", "./API/" + playerName + "/b/" + beatmapId, true); songInfoRequest.send(); console.log("Async request: ./API/" + playerName + "/b/" + beatmapId); } } function refreshMatchInfo(elementId, ualMatchId) { var matchInfoRequest = new XMLHttpRequest(); var localItemName = localStoragePrefix + "multiplayer-" + session_username + "-" + ualMatchId; matchInfoRequest.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var eId = elementId; // var result = JSON.parse(this.responseText); localStorage.setItem(localItemName, this.responseText); updateMatchInfoContent(eId, this.responseText); } }; if (localStorage.getItem(localItemName)) { updateMatchInfoContent(elementId, localStorage.getItem(localItemName)); } else { matchInfoRequest.open("GET", "./async/match/?render&select=" + ualMatchId, true); matchInfoRequest.send(); console.log("Async request: ./async/match/?render&select=" + ualMatchId); } }