您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Determines ideal goal value based on Created on and Due dates
当前为
- // ==UserScript==
- // @name Lattice Goals - Add Ideal
- // @namespace Violentmonkey Scripts
- // @match http://*.latticehq.com/goals/*
- // @match https://*.latticehq.com/goals/*
- // @grant none
- // @version 1.1
- // @author pedro-mass
- // @description Determines ideal goal value based on Created on and Due dates
- // @run-at document-idle
- // @require http://code.jquery.com/jquery-3.5.0.min.js
- // ==/UserScript==
- waitUntilTrue(shouldRun, run)
- function isPercentageBasedGoal() {
- // todo: make this actually check if there is a percentage based check?
- return true
- }
- function run() {
- console.log('Starting Lattice Goal Percentage calculations...')
- if (!isPercentageBasedGoal()) return
- const Dates = getDates()
- const GoalStats = getGoalStats()
- const percentageByDate = getRelativePercentage(
- Dates.start,
- Dates.end,
- Dates.current
- )
- const idealValue = Math.round(
- getRelativeValue(GoalStats.start, GoalStats.goal, percentageByDate)
- )
- const goalDirection = GoalStats.start <= GoalStats.end ? 1 : -1
- return insertIdeal(
- idealValue,
- GoalStats.unit,
- GoalStats.current,
- goalDirection
- )
- }
- function getRelativeValue(start, end, percentage) {
- const offset = start
- return (end - offset) * percentage + offset
- }
- function getDates() {
- const start = getDate(/^created\n\n/i)
- const end = getDate(/^due\n\n/i)
- const current = Date.now()
- return {
- start,
- end,
- current,
- }
- }
- function getGoalStats() {
- const unit = getValue(/^start: /i, 'span').replace(/\d+/, '')
- const getNumber = (regex) => Number(getValue(regex, 'span').replace(unit, ''))
- const start = getNumber(/^start: /i)
- const current = getNumber(/^current: /i)
- const goal = getNumber(/^goal: /i)
- return {
- start,
- goal,
- current,
- unit,
- }
- }
- function getProgressIndicator(ideal, current) {
- if (!current) return
- if (ideal <= current) {
- return '🎉'
- }
- return '😢'
- }
- function insertIdeal(ideal, unit, current, isAscendingGoal) {
- if (contains('span', /^ideally: /i).length > 0) {
- return
- }
- const progressIndicator = isAscendingGoal
- ? getProgressIndicator(ideal, current)
- : getProgressIndicator(current, ideal)
- const idealElem = `<span class="css-1mddpa2">Ideally: <span>${ideal}${unit}</span> <span>${progressIndicator}</span></span>`
- const goalsContainer = contains('div', /^start:/i)
- return $(goalsContainer).find('span').first().after(idealElem)
- }
- function shouldRun() {
- const pageCheck = contains('span', /^start: /i)
- return pageCheck != null && pageCheck.length > 0
- }
- function getRelativePercentage(startDate, endDate, currentDate) {
- const offset = startDate
- endDate = endDate - offset
- currentDate = currentDate - offset
- return currentDate / endDate
- }
- function getDate(regex, selector = 'div') {
- return new Date(getValue(regex, selector)).getTime()
- }
- function getValue(regex, selector) {
- return replaceString(getText(first(contains(selector, regex))), regex, '')
- }
- function replaceString(string, searchString, newString) {
- if (!string) {
- console.warn('Received bad params', { string, searchString, newString })
- return string
- }
- return string.replace(searchString, newString)
- }
- function contains(selector, text) {
- var elements = document.querySelectorAll(selector)
- return Array.prototype.filter.call(elements, function (element) {
- return RegExp(text).test(getText(element))
- })
- }
- function getText(element) {
- return element.innerText
- }
- function first(arr) {
- return arr[0]
- }
- function waitUntilTrue(checkFn, cb = (x) => x, timeout = 250) {
- const intervalId = setInterval(checkInterval, timeout)
- function checkInterval() {
- if (checkFn()) {
- clearInterval(intervalId)
- cb()
- }
- }
- }