NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Shiki Elite Rating // @author Chortowod (https://openuserjs.org/users/Chortowod) // @description Рейтинг илитарности (больше старых тайтлов просмотрено = больше рейтинг) // @namespace http://shikimori.me/ // @version 1.2.0 // @match *://shikimori.org/* // @match *://shikimori.one/* // @match *://shikimori.me/* // @icon https://www.google.com/s2/favicons?domain=shikimori.me // @license MIT // @updateURL https://openuserjs.org/meta/Chortowod/Shiki_Elite_Rating.meta.js // @downloadURL https://openuserjs.org/install/Chortowod/Shiki_Elite_Rating.user.js // @require https://gist.githubusercontent.com/Chortowod/814b010c68fc97e5f900df47bf79059c/raw/chtw_settings.js?v1 // @copyright 2023, Chortowod (https://openuserjs.org/users/Chortowod) // ==/UserScript== let settings = new ChtwSettings('chtwEliteRating', '<a target="_blank" href="https://openuserjs.org/scripts/Chortowod/Shiki_Elite_Rating">Илитарность</a>'); let debug; function initSettings() { settings.createOption('isLeft', 'Расположить слева', false); settings.createOption('isDebug', 'Режим отладки', false); settings.createOption('top', 'Отступ сверху (в %)', 15, 'number'); debug = settings.getOption('isDebug'); } let style = ` .chtw-elite-rating-wrap:hover { width: 220px; } .chtw-elite-rating-wrap { display: flex; color: initial; overflow: hidden; width: 50px; height: 50px; position: absolute; padding: 5px; ${settings.getOption('isLeft') ? 'left' : 'right'}: 0; ${settings.getOption('isLeft') ? 'transform: scale(-1, 1);' : ''}; top: ${settings.getOption('top')}%; border-radius: 10px 0px 0px 10px; background: #000000ad; transition: 0.5s; align-items: center; z-index: 9; } .chtw-elite-rating-info { display: flex; height: 100%; width: 50px; min-width: 45px; font-size: 34px; align-items: center; justify-content: center; color: #ffbd70; } .chtw-elite-rating-data { min-width: 170px; color: #dbfdff; font-weight: bold; ${settings.getOption('isLeft') ? 'transform: scale(-1, 1);' : ''}; display: flex; flex-direction: column; align-items: center; } .chtwERTitle { cursor: help; } `; let skippedAnime = {'skipped_type': 'аниме', 'no_year': [], 'no_episodes': [], 'ongoing': []}; let skippedManga = {'skipped_type': 'манга', 'no_year': [], 'no_chapters': [], 'ongoing': []}; let siteURL = document.location.origin; function log (message) { debug&&console.log(message) } function getTitle(score) { switch (true) { case score < 0.5 : return 'Average Hype Fan'; case score < 1 : return 'Average Hype Enjoyer'; case score < 3 : return 'Улитка'; case score < 5 : return 'Илита-кохай'; case score < 10 : return 'Илитнячок'; case score < 15 : return 'Илита'; case score < 30 : return 'Илита-сенсей'; case score < 50 : return 'Батя'; case score < 100 : return 'Илитный сверхразум'; case score >= 100 : return 'Дед-хранитель'; default: return false; } } function createDiv(type = 'title') { if ($('#chtwEliteRating').length > 0) return; let ratingWrap = document.createElement('div'); ratingWrap.id = 'chtwEliteRating'; ratingWrap.classList.add('chtw-elite-rating-wrap'); let ratingInfo = document.createElement('div'); ratingInfo.classList.add('chtw-elite-rating-info'); ratingInfo.innerHTML = '🛈'; ratingWrap.append(ratingInfo); let ratingData = document.createElement('div'); ratingData.id = 'chtwEliteRatingData'; ratingData.classList.add('chtw-elite-rating-data'); if (type === 'profile') { let ratingAnime = document.createElement('div'); ratingAnime.innerHTML = '<span id="chtwERanimeTitle" class="chtwERTitle">Аниме: </span><span id="chtwERanime"><span style="cursor: pointer;">посчитать</span></span>'; ratingData.append(ratingAnime); let ratingManga = document.createElement('div'); ratingManga.innerHTML = '<span id="chtwERmangaTitle" class="chtwERTitle">Манга: </span><span id="chtwERmanga"><span style="cursor: pointer;">посчитать</span></span>'; ratingData.append(ratingManga); } if (type === 'title') { ratingData.innerHTML = '<span style="cursor: pointer;">Посчитать</span></span>'; } ratingWrap.append(ratingData); document.body.append(ratingWrap); if (type === 'profile') { $('#chtwERanime').on('click', function () { $(this).html('~загрузка'); calculateAll('anime', 0, 1); }); $('#chtwERmanga').on('click', function () { $(this).html('~загрузка'); calculateAll('manga', 0, 1); }); } if (type === 'title') { $('#chtwEliteRatingData').on('click', function () { $(this).html('~загрузка'); showTitleRating(); }); } settings.addStyle(style); } function showTitleRating() { let id = $('.b-db_entry .b-user_rate').data('target_id'); let type = location.href.includes("/animes/") ? 'animes' : 'mangas'; $.ajax({ url: siteURL+'/api/'+type+'/'+id, success: function(data) { if (data.length === 0) { document.getElementById('chtwEliteRatingData').innerHTML = 'Нет данных.'; } else { if (type === 'animes') { let titleEp = data.episodes || data.episodes_aired; let titleData = data.aired_on; let titleKind = data.kind; let titleStatus = data.status; if (!titleData) { document.getElementById('chtwEliteRatingData').innerHTML = 'Нет года.' } else if (!titleEp) { document.getElementById('chtwEliteRatingData').innerHTML = 'Нет эпизодов.' } else if (titleStatus === 'ongoing') { document.getElementById('chtwEliteRatingData').innerHTML = 'Онгоинг.' } else { document.getElementById('chtwEliteRatingData').innerHTML = 'Стоимость: ' + parseFloat(calculateOne(titleData.substring(0, 4), 'anime', titleEp, titleKind).toFixed(4)); } } else { let titleData = data.aired_on; let titleChap = data.chapters; let titleKind = data.kind; if (!titleData) { document.getElementById('chtwEliteRatingData').innerHTML = 'Нет года.' } else if (!titleChap) { document.getElementById('chtwEliteRatingData').innerHTML = 'Нет эпизодов.' } else { document.getElementById('chtwEliteRatingData').innerHTML = 'Стоимость: ' + parseFloat(calculateOne(titleData.substring(0, 4), 'anime', titleChap, titleKind).toFixed(4)); } } } }, error: function(XMLHttpRequest, textStatus, errorThrown) { log('Произошла ошибка при загрузке. Обновите страницу или посмотрите причину ошибки в консоли разработчика.'); log(XMLHttpRequest); log("Status: " + textStatus + " | Error: " + errorThrown); }, complete: function() { } }); } function calculateOne(year, type, episodes, kind = 'tv') { let currentYear = new Date().getFullYear(); if (year >= currentYear) return 0; if (year < 1970) year = 1970; if (episodes > 120) episodes = 120; let coef = (parseInt(year) > 1999) ? 2 : 3; let result; if (type === 'anime') { if (kind === 'movie') result = (Math.pow(currentYear - year, coef))/(Math.pow(currentYear - 2000, coef) * 200); else result = (Math.pow(currentYear - year, coef) * episodes)/(Math.pow(currentYear - 2000, coef) * 1200); } else { if (kind === 'light_novel' || kind === 'novel') result = (Math.pow(currentYear - year, coef) * episodes)/(Math.pow(currentYear - 2000, coef) * 2500); else result = (Math.pow(currentYear - year, coef) * episodes)/(Math.pow(currentYear - 2000, coef) * 5000); } log(episodes); log(Math.pow(currentYear - year, coef) * episodes); log(Math.pow(currentYear - 2000, coef) * 1200); log(result) return result; } function initialize() { if ($('.p-profiles.p-profiles-show').length !== 0) { createDiv('profile'); } else if (!location.href.includes("/animes/") && !location.href.includes("/mangas/") && !location.href.includes("/ranobe/")) return false; else if ($('.b-db_entry .b-user_rate').data('target_id')) { createDiv('title'); } } function calculateAll(type, result, page) { let id = $('.profile-head').data('user-id'); if (!id) return; $.ajax({ url: siteURL+'/api/users/'+id+'/'+type+'_rates?limit=5000&status=completed&page='+page, success: function(data) { if (data === null) { log((type === 'anime') ? skippedAnime : skippedManga); document.getElementById('chtwER'+type+'Title').title = getTitle(result); document.getElementById('chtwER'+type).innerHTML = result ? result.toFixed(3) : 'мало данных.'; } else if (data.length === 0) { document.getElementById('chtwER'+type).innerHTML = 'нет данных.'; } else { data.forEach(function (item) { if (type === 'anime') { let titleEp = item[type].episodes; let titleData = item[type].aired_on; let titleKind = item[type].kind; let titleStatus = item[type].status; let titleRewatches = (item.rewatches) ? item.rewatches + 1 : 1; if (!titleData) { skippedAnime.no_year.push(siteURL+'/animes/' + item[type].id) } else if (!titleEp) { skippedAnime.no_episodes.push(siteURL+'/animes/' + item[type].id) } else if (titleStatus === 'ongoing') { skippedAnime.ongoing.push(siteURL+'/animes/' + item[type].id) } else { result += calculateOne(titleData.substring(0, 4), type, titleEp, titleKind) * titleRewatches; } } else { let titleData = item[type].aired_on; let titleChap = item[type].chapters; let titleKind = item[type].kind; let titleStatus = item[type].status; let titleRewatches = (item.rewatches) ? item.rewatches + 1 : 1; if (!titleData) { skippedManga.no_year.push(siteURL+'/mangas/' + item[type].id) } else if (!titleChap) { skippedManga.no_chapters.push(siteURL+'/mangas/' + item[type].id) } else if (titleStatus === 'ongoing') { skippedManga.ongoing.push(siteURL+'/mangas/' + item[type].id) } else { result += calculateOne(titleData.substring(0, 4), type, titleChap, titleKind) * (titleRewatches > 5 ? 5 : titleRewatches); } } }); setTimeout(() => { calculateAll(type, result, page+1); }, 250); } }, error: function(XMLHttpRequest, textStatus, errorThrown) { if (XMLHttpRequest.responseJSON && XMLHttpRequest.responseJSON.message === 'You are not authorized to access this page.') { log('Пользователь закрыл доступ к своей статистике.'); document.getElementById('chtwER'+type).innerHTML = 'нет доступа.'; } else { log('Произошла ошибка при загрузке. Обновите страницу или посмотрите причину ошибки в консоли разработчика.'); document.getElementById('chtwER'+type).innerHTML = 'ошибка.'; log(XMLHttpRequest); log("Status: " + textStatus + " | Error: " + errorThrown); } }, complete: function() { } }); } function ready(fn) { document.addEventListener('page:load', fn); document.addEventListener('turbolinks:load', fn); if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") fn(); else document.addEventListener('DOMContentLoaded', fn); } ready(initSettings); ready(initialize);