// ==UserScript== // @name FarmTimer // @namespace https://github.com/MyRequiem/comfortablePlayingInGW // @description Выводит таймер для фермы рядом с "Об игре | Форум". Звуковое оповещение когда пора полить/собрать. // @id comfortablePlayingInGW@MyRequiem // @updateURL https://raw.githubusercontent.com/MyRequiem/comfortablePlayingInGW/master/separatedScripts/FarmTimer/farmTimer.meta.js // @downloadURL https://raw.githubusercontent.com/MyRequiem/comfortablePlayingInGW/master/separatedScripts/FarmTimer/farmTimer.user.js // @include https://*gwars* // @grant none // @license MIT // @version 2.23-140522 // @author MyRequiem [https://www.gwars.io/info.php?id=2095458] // ==/UserScript== /*global unsafeWindow */ /*jslint browser: true, maxlen: 80, vars: true, regexp: true, nomen: true, plusplus: true */ /*eslint-env browser */ /*eslint no-useless-escape: 'warn', linebreak-style: ['error', 'unix'], quotes: ['error', 'single'], semi: ['error', 'always'], eqeqeq: 'error', curly: 'error' */ /*jscs:disable requireMultipleVarDecl, requireVarDeclFirst */ /*jscs:disable disallowKeywords, disallowDanglingUnderscores */ /*jscs:disable validateIndentation */ (function () { 'use strict'; // ============================ НАСТРОЙКИ ================================== // звук когда пора поливать/собирать (0 - без звука) var farmSound = 8, // повторять звук не чаще чем один раз в X секунд (0 - не повторять) soundInterval = 120; // ========================= КОНЕЦ НАСТРОЕК ================================ /** * @class General * @constructor */ var General = function () { /** * @property root * @type {Object} */ this.root = this.getRoot(); /** * @property doc * @type {Object} */ this.doc = this.root.document; /** * @property loc * @type {String} */ this.loc = this.root.location.href; /** * @property st * @type {Object} */ this.st = this.root.localStorage; /** * @property STNAME * @type {String} */ this.STNAME = 'farmTimer'; /** * @property myID * @type {String} */ this.myID = /(^|;) ?uid=([^;]*)(;|$)/.exec(this.doc.cookie)[2]; /** * @property DESIGN_VERSION * @type {RegExpExecArray} */ this.DESIGN_VERSION = /(^|;) ?version=([^;]*)(;|$)/. exec(this.doc.cookie); /** * @property domain * @type {String} */ this.domain = this.doc.domain; }; /** * @lends General.prototype */ General.prototype = { /** * @method getRoot * @return {Object} */ getRoot: function () { var rt = typeof unsafeWindow; return rt !== 'undefined' ? unsafeWindow : window; }, /** * @method setData * @param {Array} data */ setData: function (data) { this.st.setItem(this.STNAME, data.join('|')); }, /** * @method getData * @return {Array} */ getData: function () { var stData = this.st.getItem(this.STNAME); if (stData) { return stData.split('|'); } stData = ['', '', '', '']; this.setData(stData); return stData; } }; var general = new General(); /** * @class GetTopPanel * @constructor */ var GetTopPanel = function () { /** * @method init * @return {HTMLElement|null} */ this.init = function () { // ищем верхнюю панель "MyRequiem [603/603] ... 21:01, 3095 онлайн" var topPanel; if (general.DESIGN_VERSION[2] === 'v2') { // новый дизайн topPanel = general.doc.querySelector('td.gw-header-col2 ' + 'td[width="50%"][valign="middle"]'); if (topPanel) { topPanel.setAttribute('style', 'width: 70%;'); } } else { topPanel = general.doc. querySelector('td.txt[align="left"] nobr:first-child'); if (topPanel) { // noinspection JSUnresolvedFunction topPanel.parentNode.setAttribute('style', 'width: 70%;'); } } return topPanel; }; }; /** * @class PlaySound * @constructor */ var PlaySound = function () { /** * @method init * @param {int|String} sound */ this.init = function (sound) { if (sound && sound !== '0') { var audio = general.doc.querySelector('#cpingw_audio'); if (!audio) { audio = general.doc.createElement('audio'); audio.setAttribute('id', 'cpingw_audio'); var divAudio = general.doc.createElement('div'); divAudio.setAttribute('style', 'display: none;'); divAudio.appendChild(audio); general.doc.body.appendChild(divAudio); } audio.volume = 0.3; audio.src = 'https://raw.githubusercontent.com/MyRequiem/' + 'comfortablePlayingInGW/master/sounds/' + sound + '.ogg'; audio.play(); } }; }; /** * @class GetRandom * @constructor */ var GetRandom = function () { /** * @method init * @param {int} a * @param {int} b * @return {int} */ this.init = function (a, b) { return Math.round(a + (b - a) * Math.random()); }; }; /** * @class FarmTimer * @constructor */ var FarmTimer = function () { /** * @property farmLink * @type {HTMLLinkElement|null} */ this.farmLink = null; /** * @property checkInterval * @type {int} */ this.checkInterval = 0; /** * @method setRedLink * @param {String} str */ this.setRedLink = function (str) { var action = str === '2' ? 'Собрать' : 'Полить'; this.farmLink.setAttribute('style', 'color: #FF0000; ' + 'font-weight: bold; text-decoration: none;'); this.farmLink.innerHTML = '[' + action + ']'; }; /** * @method checkState */ this.checkState = function () { if (!/bold/.test(this.farmLink.getAttribute('style'))) { if (this.checkInterval) { general.root.clearInterval(this.checkInterval); } return; } var stData = general.getData(); if (!stData[0]) { this.farmLink.innerHTML = ''; return; } var timeNow = new Date().getTime(), time = +stData[0]; if (timeNow <= time) { this.farmLink.setAttribute('style', 'color: #0000FF; ' + 'text-decoration: none;'); stData[3] = ''; general.setData(stData); this.showTimer(+((time - timeNow) / 1000).toFixed(0)); } }; /** * @method setReminder */ this.setReminder = function () { var stData = general.getData(); if (!stData[0]) { this.farmLink.innerHTML = ''; return; } this.setRedLink(stData[1]); var _this = this; this.checkInterval = general.root.setInterval(function () { _this.checkState(); }, 2000); if (!farmSound) { return; } var timeNow = new Date().getTime(); if (timeNow < +stData[0]) { return; } var soundTime = +stData[2], intrvl = soundInterval * 1000, random = new GetRandom(); // пора проигрывать звук if (timeNow - soundTime >= intrvl) { // в настройках указано не повторять звук if (!intrvl) { // если звук еще не был проигран if (!stData[3]) { stData[3] = '1'; general.setData(stData); new PlaySound().init(farmSound); } return; } stData[2] = timeNow; general.setData(stData); general.root.setTimeout(function () { _this.setReminder(); }, intrvl + random.init(1000, 10000)); new PlaySound().init(farmSound); } else if (intrvl) { general.root.setTimeout(function () { _this.setReminder(); }, intrvl - (timeNow - soundTime) + random.init(1000, 10000)); } }; /** * @method showTimer * @param {int} sec */ this.showTimer = function (sec) { var min, s, h; if (!sec) { this.setReminder(); return; } s = sec; h = Math.floor(s / 3600); s -= h * 3600; min = Math.floor(s / 60); s -= min * 60; this.farmLink.innerHTML = '[' + (h < 10 ? '0' + h : h) + ':' + (min < 10 ? '0' + min : min) + ':' + (s < 10 ? '0' + s : s) + ']'; sec -= 1; if (sec > -1) { var _this = this; general.root.setTimeout(function () { _this.showTimer(sec); }, 1000); } else { general.root.setTimeout(this.setReminder, new GetRandom().init(1000, 3000)); } }; /** * @method runInit */ this.runInit = function () { var _this = this; return function () { general.root.setTimeout(function () { _this.init(); }, 700); }; }; /** * @method init */ this.init = function () { /** localStorage: * [0] - время полива/сбора * [1] - действие (Полить|Собрать) * [2] - время последнего проигрывания звука * [3] - звук проигран? */ var stData = general.getData(), timeNow = new Date().getTime(); // на ферме запоминаем данные, выходим if (/\/ferma\.php/.test(general.loc)) { // не на своей ферме if (/id=\d+/.test(general.loc) && /id=(\d+)/.exec(general.loc)[1] !== general.myID) { return; } var a = general.doc.querySelectorAll('*[onclick*="gotourl("],' + '*[onclick*="openurl("],*[onclick*="plantit("]'), l; for (l = 0; l < a.length; l++) { a[l].addEventListener('click', this.runInit(), false); } var actionStr = /Ближайшее действие:.*(собрать|полить).*\(.*\)/. exec(general.doc.querySelector('td[width="400"]' + '[valign="top"]').innerHTML); if (!actionStr) { stData[0] = ''; general.setData(stData); return; } var aStr = actionStr[0]; var action = /собрать/.test(aStr) ? '2' : '1'; if (/уже пора/.test(aStr)) { general.setData([timeNow, action, timeNow, '1']); return; } var timeLeft = +/через (\d+) мин/.exec(aStr)[1]; general.setData([timeNow + timeLeft * 60 * 1000, action, timeNow, '']); return; } var topPanel = new GetTopPanel().init(); if (!topPanel || !stData[0]) { return; } this.farmLink = general.doc.createElement('a'); this.farmLink.setAttribute('style', 'color: #0000FF; ' + 'text-decoration: none;'); this.farmLink.href = 'https://' + general.domain + '/ferma.php?id=' + general.myID; this.farmLink.setAttribute('target', '_blank'); topPanel.appendChild(general.doc.createTextNode(' | ')); topPanel.appendChild(this.farmLink); if (timeNow >= +stData[0]) { this.setRedLink(stData[1]); var _this = this; general.root.setTimeout(function () { _this.showTimer(0); }, new GetRandom().init(1000, 3000)); return; } this.showTimer(+((+stData[0] - timeNow) / 1000).toFixed(0)); }; }; new FarmTimer().init(); }());