首页 > 其他分享 >连续番茄时钟和长休息

连续番茄时钟和长休息

时间:2025-01-16 15:23:59浏览次数:1  
标签:appendChild style const inputContainer 番茄 createElement document 休息 时钟

  1. 去支持Tempermonkey的浏览器的Add-ons安装
  2. 代码
  3. https://pomodoro.pomodorotechnique.com/ 打开后刷新一次
// ==UserScript==
// @name         Automated Pomodoro with Long Break
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  Automated Pomodoro cycles with long breaks after user-defined intervals (e.g., every 4 pomodoros with 15 or 50 minutes break options)
// @author       Syl
// @match        https://pomodoro.pomodorotechnique.com/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let isRunning = false;
    let timeoutHandles = [];

    function findButtonByText(text) {
        const buttons = Array.from(document.querySelectorAll('button'));
        return buttons.find(button => button.textContent.trim() === text);
    }

    function simulateUserClick(element) {
        if (!element) return console.error("Element not found.");
        const mouseDownEvent = new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window });
        const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: window });
        element.dispatchEvent(mouseDownEvent);
        element.dispatchEvent(clickEvent);
    }

    function waitForButton(text, callback) {
        const interval = setInterval(() => {
            if (!isRunning) {
                clearInterval(interval);
                return;
            }
            const button = findButtonByText(text);
            if (button) {
                clearInterval(interval);
                callback(button);
            }
        }, 500);
    }

    function startPomodoroCycles(cycles, longBreakInterval, longBreakTime) {
        let currentCycle = 0;

        function runCycle() {
            if (!isRunning) return;
            if (currentCycle >= cycles) {
                console.log("All Pomodoro cycles completed!");
                endPomodoroProcess();
                return;
            }

            console.log(`Starting pomodoro cycle ${currentCycle + 1}`);

            waitForButton("Wind Up", (windUpButton) => {
                console.log("Clicking Wind Up button...");
                simulateUserClick(windUpButton);

                const workTimeout = setTimeout(() => {
                    if (!isRunning) return;

                    console.log(`Work session for cycle ${currentCycle + 1} completed.`);

                    if (longBreakInterval > 0 && (currentCycle + 1) % longBreakInterval === 0) {
                        console.log(`Long break required after cycle ${currentCycle + 1}.`);
                        waitForPageState("Take a break").then(() => {
                            const longBreakText = longBreakTime === 15 ? "15" : "30";
                            waitForButton(longBreakText, (longBreakButton) => {
                                simulateUserClick(longBreakButton);

                                const longBreakTimeout = setTimeout(() => {
                                    if (!isRunning) return;
                                    currentCycle++;
                                    runCycle();
                                }, longBreakTime * 60 * 1000);
                                timeoutHandles.push(longBreakTimeout);
                            });
                        });
                    } else {
                        currentCycle++;
                        runCycle();
                    }
                }, 30 * 1000 * 60);
                timeoutHandles.push(workTimeout);
            });
        }

        runCycle();
    }

    function endPomodoroProcess() {
        console.log("Pomodoro process ended.");
        isRunning = false;
    }

    function stopPomodoro() {
        console.log("Stopping Pomodoro...");
        isRunning = false;
        timeoutHandles.forEach(handle => clearTimeout(handle));
        timeoutHandles = [];
    }

    function waitForPageState(targetText, timeout = 30000) {
        return new Promise((resolve, reject) => {
            const interval = 500;
            let elapsedTime = 0;

            const checkState = setInterval(() => {
                elapsedTime += interval;
                if (elapsedTime > timeout) {
                    clearInterval(checkState);
                    console.error(`Timeout: Page did not reach the expected state with text "${targetText}".`);
                    resolve(null);
                    return;
                }

                const targetElement = Array.from(document.querySelectorAll('button, div, span'))
                    .find(el => el.textContent.trim() === targetText);

                if (targetElement) {
                    clearInterval(checkState);
                    resolve(targetElement);
                }
            }, interval);
        });
    }

    const inputContainer = document.createElement('div');
    inputContainer.style.position = 'fixed';
    inputContainer.style.top = '100px';
    inputContainer.style.right = '25px';
    inputContainer.style.backgroundColor = 'white';
    inputContainer.style.border = '2px solid grey';
    inputContainer.style.borderRadius = '10px'; // 添加圆角样式
    inputContainer.style.padding = '10px';
    inputContainer.style.zIndex = '1000';
    inputContainer.style.display = 'flex';
    inputContainer.style.flexDirection = 'column';
    inputContainer.style.gap = '10px';

    const cyclesRow = document.createElement('div');
    cyclesRow.style.display = 'flex';
    cyclesRow.style.alignItems = 'center';
    cyclesRow.style.justifyContent = 'space-between';

    const inputLabel1 = document.createElement('label');
    inputLabel1.textContent = 'Number of cycles: ';
    const inputBox1 = document.createElement('input');
    inputBox1.type = 'number';
    inputBox1.min = '1';
    inputBox1.value = '4';
    inputBox1.style.width = '60px';

    cyclesRow.appendChild(inputLabel1);
    cyclesRow.appendChild(inputBox1);

    const everyRow = document.createElement('div');
    everyRow.style.display = 'flex';
    everyRow.style.alignItems = 'center';
    everyRow.style.justifyContent = 'space-between';

    const inputLabel2 = document.createElement('label');
    inputLabel2.textContent = 'Long break after every: ';
    const inputBox2 = document.createElement('input');
    inputBox2.type = 'number';
    inputBox2.min = '0';
    inputBox2.value = '0';
    inputBox2.style.width = '60px';

    everyRow.appendChild(inputLabel2);
    everyRow.appendChild(inputBox2);

    const durationRow = document.createElement('div');
    durationRow.style.display = 'flex';
    durationRow.style.alignItems = 'center';
    durationRow.style.justifyContent = 'space-between';

    const inputLabel3 = document.createElement('label');
    inputLabel3.textContent = 'Long break duration: ';
    const selectBox = document.createElement('select');
    selectBox.style.width = '80px';
    const option15 = document.createElement('option');
    option15.value = '15';
    option15.textContent = '15 min';
    const option30 = document.createElement('option');
    option30.value = '30';
    option30.textContent = '30 min';

    selectBox.appendChild(option15);
    selectBox.appendChild(option30);


    durationRow.appendChild(inputLabel3);
    durationRow.appendChild(selectBox);

    const buttonRow = document.createElement('div');
    buttonRow.style.display = 'flex';
    buttonRow.style.justifyContent = 'space-between';

    const startButton = document.createElement('button');
    startButton.textContent = 'Start';
    const endButton = document.createElement('button');
    endButton.textContent = 'End';

    buttonRow.appendChild(startButton);
    buttonRow.appendChild(endButton);

    inputContainer.appendChild(cyclesRow);
    inputContainer.appendChild(everyRow);
    inputContainer.appendChild(durationRow);
    inputContainer.appendChild(buttonRow);
    document.body.appendChild(inputContainer);

    startButton.addEventListener('click', () => {
        const cycles = parseInt(inputBox1.value, 10);
        const longBreakInterval = parseInt(inputBox2.value, 10);
        const longBreakTime = parseInt(selectBox.value, 10);
        if (!isNaN(cycles) && !isNaN(longBreakInterval) && !isNaN(longBreakTime) && cycles > 0) {
            isRunning = true;
            startPomodoroCycles(cycles, longBreakInterval, longBreakTime);
        } else {
            alert('Please enter valid numbers for cycles and long break settings.');
        }
    });

    endButton.addEventListener('click', () => {
        stopPomodoro();
        alert("Pomodoro cycle stopped.");
    });
})();

标签:appendChild,style,const,inputContainer,番茄,createElement,document,休息,时钟
From: https://www.cnblogs.com/Xeonilian/p/18675012/upgrade-pomodoro

相关文章

  • 单比特跨时钟域电路设计
    CDC电路设计1-singlebit引言:​跨时钟域问题一直是IC设计的核心关注问题之一,笔者利用闲暇时间再次从整体层面更深层次reviewCDC设计。1.1同步时钟,异步时钟跨时钟域处理的主要对象是异步时钟,辨别何为同步时钟,异步时钟是至关重要的。如下图,clk0clk1是异步......
  • 江科大STM32入门——读写备份寄存器(BKP)&实时时钟(RTC)笔记整理
    wx:嵌入式工程师成长日记https://mp.weixin.qq.com/s/hDk7QaXP8yfYIj1gUhtMrw?token=1051786482&lang=zh_CNhttps://mp.weixin.qq.com/s/hDk7QaXP8yfYIj1gUhtMrw?token=1051786482&lang=zh_CNRTC是一个独立的定时器,BKP并不能完全掉电不丢失,其可以完成一些主电源掉电时,保存少......
  • STM32CUBEMX时钟树配置
    以下以stm32f103c8t6为例打开STM32CUBEMX,点击CLockConfiguration这就是我们的时钟数配置了;默认情况下是呈以下配置:一、了解一下为什么叫做时钟树?下图拥有两棵树,一棵树是树干比较小的叫做低速树,树干比较大的叫做高速树。而时钟的产生离不开晶振,所以时钟树的根一般都为晶......
  • 易基因:关于用于干预研究的衰老生物标志物的专家共识声明 含DNA甲基化/表观遗传时钟
    大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。衰老生物标志物在促进长寿的干预措施中是重要的结果指标。然而,对于哪些具体的生物标志物最适合用于人类干预研究,目前的共识有限。本研究旨在通过德尔菲法(DelphiMethod,该方法用于在经验证据有限或存在争议时提供专家......
  • DS1302时钟模块
    DS1302DS1302是一个低功耗、实时时钟(RTC)芯片单字节写1.发送数据前,需要将CE拉高,使能通信。需要注意的是,拉高CE时,需确保SCLK处于低电平2.需要先发送命令字节,再发送数据字节,发送时都是低位优先命令字节用于指定寄存器地址以及声明读/写操作,各位的含义如下数据字节为发送......
  • 基于AT89C51的数字时钟课程设计
    摘要:单片微型计算机简称单片机,又称为微控制器,是将CPU、RAM、ROM、定时/计数器、I/O接口电路集成到一块电路芯片上构成的微型计算机。本次设计的系统由单片机系统、数码管显示系统、键盘、蜂鸣器等组成,通过按键来控制单片机实现数字时钟的时、分、秒显示,12、24制转换,设定时间、闹......
  • HDMI不同分辨率下的时钟频率是多少?
    HDMI不同分辨率下的时钟频率是多少? 摘要:进行EMC整改的时候,为了快速找到相应频率点,我们需要熟记常用端口协议的EMI干扰频率,如下就针对HDMI的频率进行介绍。HDMI作为一种高清晰度多媒体接口,在现代电子设备中被广泛应用。其工作频率范围较宽,...  进行EMC......
  • sdc时钟约束与综合经验总结
    这次的SoC做了多时钟域处理,因此也比之前的约束起来会更复杂一些,把目前的一些小经验给总结一下。首先描述一下这次的时钟域处理情况,对AXI总线上做了400MHz的时钟约束,AHB是二分频到200MHz,APB再二分频到100MHz,这是三路同步时钟,400MHz的时钟由PLL直接产生给到内部,200MHz和100MHz时钟......
  • STM32_引脚初始化与时钟基础
    为什么每用一个GPIO引脚,都要初始化一次时钟?TM32微控制器采用了时钟门控(ClockGating)机制,这是现代微控制器的一种功耗管理策略。时钟门控机制的核心思想是,只有在外设需要运行时,才使能相应外设的时钟,而在不使用时关闭时钟,以减少功耗和节省电源。//初始化时钟RCC_APB2Pe......
  • 【江协STM32】6-1/2 TIM定时中断、定时器定时中断&定时器外部时钟
    1. TIM定时中断1.1TIM简介TIM(Timer)定时器定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断16位计数器(执行计数定时的一个寄存器,每来一个时钟,计数器加1)、预分频器(可以对计数器的时钟进行分频,使计数更灵活)、自动重装寄存器(计数的目标值,就是想要计多少个时钟申......