iquestgod

AMQ-UI-Rearranger

Mar 8th, 2021
604
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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();
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×