NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Goals Manager // @namespace http://tampermonkey.net/ // @version 0.3 // @description script for collecting users' statistics | visit https://smartprogress.do/post/4024944 | (c) Blogger 2015 aka Maverick, 2020 // @author languageblog96@gmail.com // @match https://smartprogress.do/goal/* // @grant none // @require https://cdn.jsdelivr.net/npm/chart.js@2.8.0 // @license MIT // @updateURL https://openuserjs.org/install/Maverick/Goals_Manager.user.js // ==/UserScript== (function() { 'use strict'; window.onload = async () => { const PRINT_STATS = false // Whether or not to print the overall statistics in the console const LINK = 'https://smartprogress.do/post/4024944' // Link to my post const GOALS_ARR = { "323684" : "1 000 000 приседаний", "295640" : "1 000 000 отжиманий. Продолжение", "327035" : "1 000 000 отжиманий на брусьях", "266116" : "100 000 подтягиваний на перекладине", "114389" : "1 000 000 прочитанных страниц", "343508" : "Ешь слона по кусочкам - ежедневно читать по 10 минут! Командная. Присоединяйтесь!", "341025" : "2 сезон - 450 000 Книжных страниц. Читаем по 20 страниц в день [Командная цель]", "308260" : "50 000 минут занятий на пресс (командная)", "357460" : "'Съедим' 20 000 помодоро вместе (Продолжение) Присоединяйтесь!", "361568" : "100 000 минут на наведение чистоты и порядка (командная) - 2", "358598" : "100 000 минут на приготовление пищи (командная, групповая)", "368916" : "Дневник успеха.Сезон 2 [Командная цель]", "329170" : "50 000 минут ухода за собой (командная цель)", "331883" : "Групповая программа II сезон - 1 000 000 очков на LinguaLeo", "356969" : "Выучить 10000 иностранных слов (Командная, групповая)", "348638" : "2 Сезон - 100 000 000 Груповых Шагов - [Групповая]", } if (window.GOALS_DATA == null || window.USER == null) return const USER_ID = window.USER.id.toString() const GOAL_ID = window.GOALS_DATA[Object.keys(window.GOALS_DATA)[0]].id if (Object.keys(GOALS_ARR).includes(GOAL_ID)){ magicInput() showStats() } var json // Json data where all posts will be stored // Creates list of users and ranks them async function showStats(){ // BarChart var canvas = document.createElement('canvas') var ctx = canvas.getContext('2d'); let data = { labels: [], // Will be filled later datasets: [{ barPercentage: 0.5, barThickness: 6, maxBarThickness: 8, minBarLength: 2, data: [] // Will be filled later }] } let options = { legend: { display: false }, maintainAspectRatio: false, scales: { xAxes: [{ gridLines: { offsetGridLines: true } }] }, title: { display: true, text: 'Top 10' } } // Creating DOM elements var sort_div = document.getElementsByClassName("post-sort")[0] // Div on the right side var points_div = document.createElement('div') // Div with users var select_div = document.getElementsByClassName('_3tR2Mvw7Q0')[0].cloneNode(true) var select = select_div.getElementsByTagName('select')[0] var label = select_div.getElementsByTagName('label')[0] var span = select_div.getElementsByTagName('span')[0] var info = document.createElement('div') // Users' posts var about = document.createElement('div') // Link to my goal :) var blogger = document.createElement('span') // Configuring DOM canvas.style.maxHeight = '200px' points_div.classList.add('post-sort__wrap') span.innerHTML = 'loading...' info.classList.add('post-sort__wrap') info.style.paddingTop = '20px' info.style.maxHeight = '100px' info.style.overflowY = 'scroll' about.classList.add('post-sort__wrap') about.style.paddingTop = '20px' about.style.paddingBottom = '20px' about.innerHTML = '<hr>' label.innerHTML = 'Пользователи оставившие комментарий' blogger.classList.add('action') blogger.style.fontSize = '11px' blogger.style.float = 'right' blogger.innerHTML = 'Blogger 2015' blogger.onclick = () => {window.open(LINK)} blogger.title = 'Поддержите)' points_div.appendChild(select_div) sort_div.appendChild(points_div) sort_div.appendChild(info) sort_div.appendChild(canvas) sort_div.appendChild(about) about.appendChild(blogger) for(let i = select.options.length - 1 ; i >= 0 ; i--){ select.remove(i); } // Getting the last post's id let last_few_posts let response = await fetch('https://smartprogress.do/blog/getPosts?sorting=new_top&start_id=0&end_id=0&step_id=0&only_author=0&change_sorting=1&obj_id=' + GOAL_ID + '&obj_type=0') if (response.ok) { last_few_posts = await response.json(); } else { points_div.innerHTML = 'Error' return } const LAST_ID = last_few_posts.blog[0].id // Getting all posts for current goal response = await fetch('https://smartprogress.do/blog/getPosts?sorting=old_top&start_id=0&end_id=' + (LAST_ID+1000) + '&step_id=0&only_author=0&change_sorting=1&obj_id=' + GOAL_ID + '&obj_type=0') if (response.ok) { json = await response.json(); } else { points_div.innerHTML = 'Error' return } // Filtering unique users and sorting them let members_list = json.blog.filter((user, index, self) =>{ return index === self.findIndex((t) => { return t.user_id === user.user_id && t.username === user.username }) }) members_list.sort((el1, el2) => el1.username.localeCompare(el2.username)) // Adding users to select members_list.forEach((user, index) => { let el = document.createElement("option") el.textContent = user.username el.value = user.username el.id = user.user_id el.username = user.username select.appendChild(el) user.reps_arr = [] }) select.options[0].selected = true span.innerHTML = select.value // Collecting data for each user let temp for (let i = 0; i < json.blog.length; i++){ let user_id = json.blog[i].user_id let username = json.blog[i].username let user_index_in_member_list = members_list.findIndex(el => el.user_id == user_id) let current_result = 0 let next_post = i < json.blog.length - 1 ? json.blog[i+1].id : '#' let prev_post = i > 0 ? json.blog[i-1].id : '#' let current_post_id = json.blog[i].id let result = getResult(i) if ((result.last - result.first) == result.sum || (result.last - result.first) == result.product){ // if (i > 0 && temp.last == result.first){ if (result.sum < result.first || i < 30){ // e.g. someone writes 10 + 1000 = 1010 when it shoud be 1000 + 10 = 1010 current_result = result.last - result.first } } else{ // console.log(result.last - result.first + '<a href = "https://smartprogress.do/post/' + json.blog[i].id + '"></a>') } members_list[user_index_in_member_list].reps_arr.push({ 'result' : current_result, 'next_post' : next_post, 'prev_post' : prev_post, 'current_post_id' : current_post_id, 'msg' : json.blog[i].msg, }) temp = result } // Sorting users by total reps count members_list.sort((a, b) => { function getSum(arr){ let sum = 0 for (let i = 0; i < arr.length; i++) { sum += arr[i].result } return sum } let sum1 = getSum(a.reps_arr) let sum2 = getSum(b.reps_arr) return sum2 - sum1 }) for (let i = 0; i < 10 && i < members_list.length; i++){ data.labels.push(members_list[i].username) let sum = 0 for (let j = 0; j < members_list[i].reps_arr.length; j++) { sum += members_list[i].reps_arr[j].result } data.datasets[0].data.push(sum) } // Creates chart var myBarChart = new Chart(ctx, { type: 'horizontalBar', data: data, options: options }) if (PRINT_STATS == true){ let stats = '' for (let i = 0; i < members_list.length; i++){ let sum = 0 for (let j = 0; j < members_list[i].reps_arr.length; j++){ sum += members_list[i].reps_arr[j].result } stats += '<p><a href = "https://smartprogress.do/user/' + members_list[i].user_id + '">' + members_list[i].username + '</a> - ' + sum + '</p>' } console.log(stats) } // Displaying user's posts select.onchange = () => { info.innerHTML = '' span.innerHTML = select.value let user_id = select.options[select.selectedIndex].id let username = select.options[select.selectedIndex].username let user_index_in_member_list = members_list.findIndex(el => el.user_id == user_id) let sum = 0 for (let j = 0; j < members_list[user_index_in_member_list].reps_arr.length; j++){ let current_result = members_list[user_index_in_member_list].reps_arr[j].result let last = members_list[user_index_in_member_list].reps_arr[j].last let first = members_list[user_index_in_member_list].reps_arr[j].first sum += Number(current_result) let prev_post = members_list[user_index_in_member_list].reps_arr[j].prev_post let next_post = members_list[user_index_in_member_list].reps_arr[j].next_post let current_post_id = members_list[user_index_in_member_list].reps_arr[j].current_post_id let msg = members_list[user_index_in_member_list].reps_arr[j].msg info.innerHTML += '<a href = "/post/' + current_post_id + '">Запись # ' + (j+1) + '</a> (+' + current_result + ')</h3><br>' + // '<a href = "/post/' + prev_post + '"><</a> <a href = "/post/' + next_post + '">></a>' + msg + '<br>' } info.innerHTML += '<br>Всего: ' + sum } select.onchange() } // Creates input for adding new results async function magicInput(){ if (window.GOALS_DATA[GOAL_ID].team_users_list.includes(USER_ID)){ // Creating DOM elements var redactor = document.getElementsByClassName('redactor_editor')[0] //var form = document.getElementsByClassName('_3yHbNGC-vy')[0]//.getElementsByTagName('button')[0].parentNode var span = document.createElement('span') var input = document.createElement('input') var redactor_btn = document.getElementsByClassName('redactor_btn')[1] // Configuring DOM input.style.cssText = 'width: 100px;padding: 12px 20px;margin: 8px 0;display: inline-block;border: 1px solid #ccc;border-radius: 4px;box-sizing: border-box;' input.type = 'number' input.min = 0 input.value = 0 input.id = 'magic' span.classList.add('submit-helper--send') span.classList.add('submit-helper') var onchange = () => { if (input !== document.activeElement){ try{ let form = document.getElementsByClassName('_3yHbNGC-vy')[0].getElementsByTagName('button')[0].parentNode form.appendChild(input) form.appendChild(span) redactor_btn = document.getElementsByClassName('redactor_btn')[1] redactor = document.getElementsByClassName('redactor_editor')[0] } catch(err){} } } var timer = setInterval(onchange, 2000) let response = await fetch('https://smartprogress.do/blog/getPosts?sorting=new_top&start_id=0&end_id=0&step_id=0&only_author=0&change_sorting=1&obj_id=' + GOAL_ID + '&obj_type=0') if (response.ok) { json = await response.json(); } else { return } let last_result = getResult(0).last if (last_result != 0){ input.oninput = () => write_post (last_result, Number(input.value)) input.onmouseout = () => { redactor_btn.click() redactor_btn.click() } span.innerHTML = '' } else { span.innerHTML = 'Error' } function put_whitespaces(number){ let result = "" let str = number.toString() while (str.length > 0) { result = str.substring(str.length-3,str.length) + " " + result; str = str.substring(str.length-6, str.length-3); } return result } function write_post(last_result, value){ if (value > 0) { redactor.innerHTML = '<h3>​' + put_whitespaces(last_result) + ' + ' + put_whitespaces(value) + ' = ' + put_whitespaces(last_result + value) +'</h3>' } else { redactor.innerHTML = '' } } } } // Getting result function getResult(post_index){ function filter(str){ return str.includes("+") && str.includes("=")// && !str.toLowerCase().includes("л") && !str.toLowerCase().includes("с") } function getLastNumberInString(str){ return str.replace(/\s+/g,'').split(/\D+/g).filter(el => el.length >0).pop() } let index = json.blog.findIndex(el => el.id == post_index) let message = json.blog[post_index].msg let message_initial = message let user_id = json.blog[post_index].user_id try{ message = message.match(/<[^> ]+[^>]*>[^<]*/g).map(el => el.replace(/<\/?[^>]+(>|$)/g, "")).filter(filter) let max_result = Math.max.apply(null, message.map(el => getLastNumberInString(el))) message = message.filter(el => getLastNumberInString(el) == max_result) if (message.length == 1){ let msg = message[0] let arr = msg.replace(/\s+/g,'').split(/\D+/g).filter(el => el.length >0).map(Number) let last = Number(arr.pop()) let first = Number(arr.shift()) let sum = arr.reduce((a, b) => a + b, 0) let product = Number(arr.reduce((a, b) => a * b, 1)) return {"last" : last, "first" : first, "sum" : sum, "product" : product} // Returns values extracted from the message } else { return 0 // If something goes wrong the result will be set to 0 :( } } catch(err){ return 0 } } } })()