NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name 노벨피아 연독률 측정 // @namespace http://tampermonkey.net/ // @version 1.5 // @description 작가들을 위한 연독율 측정기. // @author BK927 // @match https://novelpia.com/novel/* // @icon https://www.google.com/s2/favicons?domain=novelpia.com // @updateURL https://openuserjs.org/meta/BK927/노벨피아_연독률_측정.meta.js // @downloadURL https://github.com/BK927/Novelpia-Continuous-Reading-Rates-Scouter/raw/main/Novelpia-Continuous-Reading-Rates-Scouter.user.js // @grant none // @license MIT // ==/UserScript== window.addEventListener("load", (event) => { const displayBox = document.querySelector("body > div:nth-child(28) > div.mobile_hidden.s_inv > div > div > table > tbody > tr:nth-child(2) > td > div > div:nth-child(1)"); const addEventToPageBtn = function () { const pageBtn = document.querySelectorAll("#episode_list > div > nav > ul > li"); pageBtn.forEach((element) => element.addEventListener("click", (e) => { setTimeout(() => { clacStats(); addEventToPageBtn(); }, 500); }) ); }; addEventToPageBtn(); clacStats(); }); function clacStats() { const allEpisodes = document.querySelectorAll("#episode_list > table > tbody > tr"); const favorite = parseInt(document.querySelector("#like_text").innerText); const notification = parseInt(document.querySelector("#alarm_text").innerText); const epiStats = []; allEpisodes.forEach((element, index) => { const node = document.querySelector("#episode_list > table > tbody > tr:nth-child(" + (1 + index * 2).toString() + ") > td.font12 > div > font > span:nth-child(2)"); const epiStatElement = extractEpisodesStats(node); if (index > 0) { const formerView = epiStats[index - 1]["view"]; const numSign = formerView > epiStatElement["view"] ? "-" : "+"; const gapPercent = Math.round((Math.abs(formerView - epiStatElement["view"]) / formerView) * 100); node.innerHTML = node.innerHTML + '<span style="font-size:12px;color:#0000FF;"> ' + numSign + gapPercent.toString() + "%</span>"; } const commentRatio = Math.round((epiStatElement["thumup"] / epiStatElement["comment"]) * 100) / 100; node.innerHTML = node.innerHTML + '<span style="font-size:12px;color:#008000;"> 댓글/좋아요: ' + commentRatio.toString() + "</span>"; const thumupRatio = Math.round((epiStatElement["view"] / epiStatElement["thumup"]) * 100) / 100; node.innerHTML = node.innerHTML + '<span style="font-size:12px;color:#008000;"> 조회수/좋아요: ' + thumupRatio.toString() + "</span>"; const favoriteRatio = Math.round((epiStatElement["view"] / favorite) * 100); node.innerHTML = node.innerHTML + '<span style="font-size:12px;color:#FF0000;"> 조회수/선작: ' + favoriteRatio.toString() + "%</span>"; const notificationRatio = Math.round((notification / epiStatElement["view"]) * 100); node.innerHTML = node.innerHTML + '<span style="font-size:12px;color:#FF0000;"> 알림/조회수: ' + notificationRatio.toString() + "%</span>"; epiStats.push(epiStatElement); }); return epiStats; } function extractEpisodesStats(element) { const regexp = /[0-9,]+/g; const parsed = element.innerText.match(regexp).map((e) => parseInt(e.replace(",", ""))); const dict = {}; dict["length"] = parsed[0]; dict["view"] = parsed[1]; dict["comment"] = parsed[2]; dict["thumup"] = parsed[3]; return dict; }