Advertisement
iquestgod

AMQ-UI-Rearranger

Mar 8th, 2021
697
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JSON 14.71 KB | None | 0 0
  1. // ==UserScript==
  2. // @name         AMQ-UI-Rearranger
  3. // @namespace    https://github.com/blissfulyoshi
  4. // @version      0.4.0
  5. // @description  Create a Song Counter in AMQ
  6. // @match        https://animemusicquiz.com/
  7. // @grant        GM_xmlhttpRequest
  8. // @require      https://raw.githubusercontent.com/blissfulyoshi/AMQ-UI-Rearranger/master/AmqUtilityFunctions.js
  9. // @require      https://raw.githubusercontent.com/blissfulyoshi/AMQ-UI-Rearranger/master/SongCounter.js
  10. // @require      https://raw.githubusercontent.com/blissfulyoshi/AMQ-UI-Rearranger/master/SecondarySongInfo.js
  11. // ==/UserScript==
  12.  
  13. var debugMode = true;
  14.  
  15. var openingCounter = 0;
  16. var endingCounter = 0;
  17. var insertCounter = 0;
  18. var aikatsuCounter = 0;
  19. var starmyuCounter = 0;
  20. var priparaCounter = 0;
  21. var scorePercentageCounter = [0,0,0,0,0,0,0,0,0,0];
  22. var songData = [];
  23. var answerInformation = [];
  24. var fullAnimeList = [];
  25.  
  26. //separate array to track player scores only so I don't have to sort an array
  27. var playerScores = [];
  28.  
  29. function debugLog(text) {
  30.     if (debugMode) {
  31.         console.log(text)
  32.     }
  33. }
  34.  
  35. function ResetSongCounter() {
  36.     openingCounter = 0;
  37.     endingCounter = 0;
  38.     insertCounter = 0;
  39.     aikatsuCounter = 0;
  40.     starmyuCounter = 0;
  41.     priparaCounter = 0;
  42.     scorePercentageCounter = [0,0,0,0,0,0,0,0,0,0];
  43.     songData = [];
  44.     answerInformation = [];
  45.     updateSongCounter(openingCounter, endingCounter, insertCounter, priparaCounter, aikatsuCounter, starmyuCounter, scorePercentageCounter);
  46. }
  47.  
  48. //add the Song Counter
  49. function AddCorrectPlayersBox() {
  50.     var correctPlayersListing = "";
  51.     //`<h5><b>Correct</b></h5>
  52.     // <div id='correctPlayers'></div>`;
  53.  
  54.     var correctPlayersContainer = document.createElement('div');
  55.     correctPlayersContainer.id = 'correctPlayersContainer';
  56.     correctPlayersContainer.innerHTML = correctPlayersListing;
  57.     document.querySelector("#qpAnimeContainer .col-xs-3").appendChild(correctPlayersContainer);
  58. }
  59.  
  60. //check for song type
  61. function previousSongClear() {
  62.     clearSongCounterAfterPrevSong();
  63.     //document.querySelector('#correctPlayers').innerText = '';
  64. }
  65.  
  66. function updateUserCount() {
  67.     var correctCount = document.querySelectorAll('.qpAvatarAnswerText.rightAnswer').length;
  68.     var totalPlayers = document.querySelectorAll('#qpScoreBoardEntryContainer .qpStandingItem').length
  69.     var activePlayers = document.querySelectorAll('#qpScoreBoardEntryContainer .qpStandingItem:not(.disabled)').length
  70.     var totalCorrectAverage = correctCount / totalPlayers;
  71.     var totalPercentage = Math.round(totalCorrectAverage * 100);
  72.     var activeCorrectPercentage = Math.round(correctCount * 100 / activePlayers);
  73.     document.querySelector('#CurrentAvgScore').innerText = totalCorrectAverage.toFixed(2);
  74.     document.querySelector('#qpStandingCorrectCount').innerText = 'Active: ' + correctCount + ' / ' + activePlayers + ' ' + activeCorrectPercentage + '%';
  75.     let percentageTier = Math.floor(activeCorrectPercentage / 10);
  76.  
  77.     //To prevent bugs from 100% and above
  78.     if (percentageTier >= 10) {
  79.         percentageTier = 9
  80.     }
  81.     scorePercentageCounter[percentageTier]++;
  82. }
  83.  
  84. //counts the number of times Aikatsu is used an answer
  85. function answerTitleCounter(answer, title) {
  86.     return answer.toLowerCase().includes(title) ? 1 : 0
  87. }
  88.  
  89. function getNameFromAnimeList(playerAnswer) {
  90.     return fullAnimeList.findIndex((animeName) => animeName.toLowerCase() === playerAnswer.toLowerCase());
  91. }
  92.  
  93. function incrementAnswerList(answerList, animeArrayIndex) {
  94.     //if already defined, just increment
  95.     //else define it with the number 1
  96.     if (answerList[fullAnimeList[animeArrayIndex]]) {
  97.         answerList[fullAnimeList[animeArrayIndex]]++;
  98.     }
  99.     else {
  100.         answerList[fullAnimeList[animeArrayIndex]] = 1;
  101.     }
  102. }
  103.  
  104. function sortAnswerOccurence(answers) {
  105.     var answersArray = [];
  106.     for (var anime in answers) {
  107.         answersArray.push([anime, answers[anime]]);
  108.     }
  109.     answersArray.sort(function(a, b) {
  110.         return b[1] - a[1];
  111.     });
  112.     return answersArray;
  113. }
  114.  
  115. function updatePlayerAnswerArray(playerIndex, playerList, playerScore, onPlayerList, playerAnswer, rightAnswer) {
  116.     //if starting a new game, the player array needs to be restarted to accept clean information
  117.  
  118.     let firstSong = parseInt(document.querySelector('#qpCurrentSongCount').innerText) === 1;
  119.     let firstPlayerName = playerList[0].querySelector('.qpAvatarName').innerText;
  120.     let resetPlayerArray = firstSong || playerList.length !== answerInformation.length || (answerInformation[0].playerName !== firstPlayerName);
  121.     if (resetPlayerArray) {
  122.         let playerName = playerList[playerIndex].querySelector('.qpAvatarName').innerText;
  123.         answerInformation[playerIndex] = {
  124.             playerName: playerName,
  125.             playerScore: playerScore,
  126.             onPlayerList: [onPlayerList],
  127.             playerAnswer: [playerAnswer],
  128.             rightAnswer: [rightAnswer]
  129.         }
  130.     }
  131.     else {
  132.         answerInformation[playerIndex].playerScore = playerScore;
  133.         answerInformation[playerIndex].onPlayerList.push(onPlayerList);
  134.         answerInformation[playerIndex].playerAnswer.push(playerAnswer);
  135.         answerInformation[playerIndex].rightAnswer.push(rightAnswer);
  136.     }
  137. }
  138.  
  139. function updateSongCounters() {
  140.     let currentSongAikatsuCount = 0;
  141.     let currentSongStarmyuCount = 0;
  142.     let currentSongPriparaCount = 0;
  143.  
  144.     for (var i=0; i < answerInformation.length; i++) {
  145.         let playerAnswerList = answerInformation[i].playerAnswer
  146.         let playerAnswer = playerAnswerList[playerAnswerList.length - 1];
  147.  
  148.         //Silly extra code to do with player answers
  149.         currentSongAikatsuCount += answerTitleCounter(playerAnswer, "aikatsu");
  150.         currentSongStarmyuCount += answerTitleCounter(playerAnswer, "starmyu");
  151.         currentSongPriparaCount += answerTitleCounter(playerAnswer, "pripara") + answerTitleCounter(playerAnswer, "prism paradise");
  152.     }
  153.  
  154.     //Update the cumulative totals for fun numbers
  155.     aikatsuCounter += currentSongAikatsuCount;
  156.     starmyuCounter += currentSongStarmyuCount;
  157.     priparaCounter += currentSongPriparaCount;
  158.     document.querySelector("#CurrentAikatsuAnswerCount").innerText = currentSongAikatsuCount;
  159.     document.querySelector("#CurrentStarmyuAnswerCount").innerText = currentSongStarmyuCount;
  160.     document.querySelector("#CurrentPriparaAnswerCount").innerText = currentSongPriparaCount;
  161. }
  162.  
  163. function updateCorrectPlayers() {
  164.     let correctPlayers = [];
  165.  
  166.     for (var i=0; i < answerInformation.length; i++) {
  167.         let playerAnswerList = answerInformation[i].playerAnswer
  168.         let rightAnswer = answerInformation[i].rightAnswer[playerAnswerList.length - 1];
  169.  
  170.         if (rightAnswer) {
  171.             correctPlayers.push(answerInformation[i].playerName);
  172.         }
  173.     }
  174.  
  175.     //Print the users who got the song right
  176.     if (correctPlayers.length > 0 && songData.length) {
  177.         //document.querySelector("#correctPlayers").innerText = correctPlayers.join(' ');
  178.         if (correctPlayers.length <= 5) {
  179.             songData[songData.length-1].correctPlayers = correctPlayers;
  180.             console.log(correctPlayers);
  181.         }
  182.     }
  183. }
  184.  
  185. function GetAnswerInformation() {
  186.     var players = document.querySelectorAll('.qpAvatarContainerOuter');
  187.  
  188.     //check if the player array needs to be resetted for a new game
  189.     //playerName check is a pretty safe check if you're moving inbetween games, but definitely not the most robust
  190.     for (var i=0; i < players.length; i++) {
  191.         let playerScore = parseInt(players[i].querySelector('.qpAvatarScore').innerText);
  192.         let onPlayerList = !players[i].querySelector('.qpAvatarStatus').classList.contains('hide');
  193.         let playerAnswer = players[i].querySelector('.qpAvatarAnswerText').innerText;
  194.         let rightAnswer = players[i].querySelector('.qpAvatarAnswerText').classList.contains('rightAnswer');
  195.  
  196.         playerScores[i] = playerScore;
  197.         updatePlayerAnswerArray(i, players, playerScore, onPlayerList, playerAnswer, rightAnswer);
  198.     }
  199.  
  200.     //debugLog("recorded players (all players in the game should be here):" + JSON.stringify(players));
  201.     //debugLog("recorded answers (all answer information should be here):" + JSON.stringify(answerInformation));
  202.  
  203.     updateSongCounters();
  204.     updateCorrectPlayers();
  205. }
  206.  
  207. function PrintSongInformation() {
  208.     console.log(JSON.stringify(songData, null, 2));
  209. }
  210.  
  211. function PrintRanking() {
  212.     answerInformation.sort(function(a, b){return b.playerScore-a.playerScore});
  213.     let ranking = '';
  214.     for (var i = 0; i < answerInformation.length; i++) {
  215.         ranking += (i + 1) + ': ' + answerInformation[i].playerName + ' (' + answerInformation[i].playerScore + ')\n'
  216.     }
  217.     console.log(ranking);
  218. }
  219.  
  220. function EndRoundStuff() {
  221.     if(IfRoundIsOver()) {
  222.  
  223.         console.log("Aikatsu! Guess Count:" + aikatsuCounter);
  224.         console.log("STARMYU Guess Count:" + starmyuCounter);
  225.         console.log("Pripara Guess Count:" + priparaCounter);
  226.         console.log("Average Score:" + GetAverageScore());
  227.         for (var i = 0; i < scorePercentageCounter.length; i++) {
  228.             console.log(i + '0-' + (i + 1) + '0%:' + scorePercentageCounter[i]);
  229.         }
  230.         PrintRanking();
  231.         PrintSongInformation();
  232.     }
  233. }
  234.  
  235. const SongCounterCallback = function(mutationsList, observer) {
  236.     for(let mutation of mutationsList) {
  237.         if (mutation.type === 'attributes') {
  238.             if (document.querySelector('#qpAnimeNameHider').classList.contains('hide'))
  239.             {
  240.                 GetAnswerInformation();
  241.                 updateUserCount();
  242.                 updateSongCounter(openingCounter, endingCounter, insertCounter, priparaCounter, aikatsuCounter, starmyuCounter, scorePercentageCounter);
  243.                 EndRoundStuff();
  244.             }
  245.         }
  246.     }
  247. };
  248.  
  249. function updateSongData(result) {
  250.     var videoLink = (result.songInfo.urlMap.catbox && result.songInfo.urlMap.catbox['720']) ? result.songInfo.urlMap.catbox['720'] :
  251.                    (result.songInfo.urlMap.animethemes && result.songInfo.urlMap.animethemes['720']) ? result.songInfo.urlMap.animethemes['720'] :
  252.                    (result.songInfo.urlMap.openingsmoe && result.songInfo.urlMap.openingsmoe['720']) ? result.songInfo.urlMap.openingsmoe['720'] :
  253.                     (result.songInfo.urlMap.catbox && result.songInfo.urlMap.catbox['480']) ? result.songInfo.urlMap.catbox['480'] : ""
  254.     var activePlayers = document.querySelectorAll('#qpScoreBoardEntryContainer .qpStandingItem:not(.disabled)').length;
  255.     var songLink = result.songInfo.urlMap.catbox ? result.songInfo.urlMap.catbox["0"] : '';
  256.     var currentSongData = {
  257.         animeEng: result.songInfo.animeNames.english,
  258.         animeRomaji: result.songInfo.animeNames.romaji,
  259.         songName: result.songInfo.songName,
  260.         artist: result.songInfo.artist,
  261.         type: convertSongTypeToText(result.songInfo.type, result.songInfo.typeNumber),
  262.         correctCount: result.players.filter((player) => player.correct).length,
  263.         startTime: quizVideoController.moePlayers[quizVideoController.currentMoePlayerId].startPoint, //quizVideoController seems to be a global variable that AMQ populateds to
  264.         songDuration: quizVideoController.moePlayers[quizVideoController.currentMoePlayerId].$player.find("video")[0].duration,
  265.         songNumber: parseInt(document.querySelector('#qpCurrentSongCount').innerText),
  266.         activePlayerCount: activePlayers,
  267.         LinkVideo: videoLink,
  268.         LinkMp3: songLink
  269.     }
  270.     songData.push(currentSongData);
  271.  
  272.     //To avoid having songdata being lost because of various incidents, print it in the console after each guess
  273.     var totalPlayers = result.players.length;
  274.     console.log(currentSongData.animeEng + ': ' + currentSongData.artist + ' - ' + currentSongData.songName + ' (' + currentSongData.type + ') ' + currentSongData.correctCount + ' (' + Math.round(currentSongData.correctCount * 100/totalPlayers) + '%)');
  275. }
  276.  
  277. // Put Song data in textarea and copy to clipboard
  278. function CopySongData() {
  279.     document.querySelector('#songDataHolder').value = JSON.stringify(songData, null, 2);
  280.     document.querySelector('#songDataHolder').select();
  281.     document.execCommand('copy');
  282. }
  283.  
  284. function secondSongCounterCallback(result) {
  285.     copyToSecondarySongInfo(result);
  286.     updateSongData(result);
  287.     checkForSongType(result);
  288.     afkKicker.resetTimers();
  289. };
  290.  
  291. function MirrorTimerText() {
  292.     var timerText = document.querySelector('#qpHiderText').innerText;
  293.     document.querySelector('#qpAnimeNameHider').innerText = timerText
  294. }
  295.  
  296. // Mutation Observer for countdown timer dropping
  297. const CountodwnChangeCallback = function(mutationsList, observer) {
  298.     MirrorTimerText();
  299. };
  300.  
  301. // Things to run at the start of the game
  302. function StartGameCallback() {
  303.     // updateSongCounterLabels();
  304.     ResetSongCounter();
  305.     setTimeout(function(){ //Update dropdownlist autocomplete list. Beware, it doesn't work
  306.         quiz.answerInput.autoCompleteController.updateList();
  307.     }, 10000);
  308. };
  309.  
  310. function SetupMirrorTimer() {
  311.     var countdown = document.querySelector('#qpHiderText');
  312.     var countdownConfig = { characterData: true, childList: true};
  313.     var countdownObserver = new MutationObserver(CountodwnChangeCallback);
  314.     countdownObserver.observe(countdown, countdownConfig);
  315. }
  316.  
  317. // Observe when the answer is revealed
  318. function ObserveAnswerShowing() {
  319.     var countdown = document.querySelector('#qpAnimeNameHider');
  320.     var countdownConfig = { attributes: true};
  321.     var countdownObserver = new MutationObserver(SongCounterCallback);
  322.     countdownObserver.observe(countdown, countdownConfig);
  323. }
  324.  
  325. function getSongList() {
  326.     let retriveListListener = new Listener("get all song names", function (payload) {
  327.         if (payload.names && payload.names.length > 0) {
  328.             fullAnimeList = payload.names;
  329.         }
  330.     }).bindListener();
  331. }
  332.  
  333. function StartAmqScript() {
  334.     //check if script is already running to avoid running it twice
  335.     if (!document.querySelector('#SongCounter')) {
  336.         console.log("HAI");
  337.         getSongList();
  338.         AddSongCounter();
  339.         //AddCorrectPlayersBox
  340.         ObserveAnswerShowing();
  341.         SetupMirrorTimer();
  342.         AddSecondarySongInfo();
  343.  
  344.         new Listener('Game Starting', function () {
  345.             StartGameCallback();
  346.         }).bindListener();
  347.  
  348.         new Listener("answer results", function (result) {
  349.             secondSongCounterCallback(result);
  350.         }).bindListener();
  351.  
  352.         new Listener("play next song", function (data) {
  353.             previousSongClear();
  354.         }).bindListener();
  355.     }
  356. }
  357.  
  358. new Listener('Host Game', function () {
  359.     StartAmqScript();
  360. }).bindListener();
  361.  
  362. new Listener('Join Game', function () {
  363.     StartAmqScript();
  364. }).bindListener();
  365.  
  366. new Listener('Spectate Game', function () {
  367.     StartAmqScript();
  368. }).bindListener();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement