shin KGS timer sounds

Plays a beeping noise every five minutes of your clock, as well as 1m left and every second when time is less than or equal to ten seconds

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        shin KGS timer sounds
// @namespace   Violentmonkey Scripts
// @match       https://shin.gokgs.com/*
// @description Plays a beeping noise every five minutes of your clock, as well as 1m left and every second when time is less than or equal to ten seconds
// @grant       none
// @version     1.0
// @license     CC-0
// @author      blechx
// @run-at      document-end
// @description 12/16/2024, 1:21:28 AM
// ==/UserScript==

var audio_context
var envelope
var freq = 420
var volume = 0.05
var decay = 0.1

function setup_context() {
	audio_context = new AudioContext()

	envelope = audio_context.createGain()
	envelope.gain.value = 0
	envelope.connect(audio_context.destination)

	var oscillator = audio_context.createOscillator()
	oscillator.type = "sine"
	oscillator.frequency.value = 420
	oscillator.connect(envelope)
	oscillator.start()
}

function play_click() {
	if (!audio_context) {
		setup_context();
	}

	var time = audio_context.currentTime

	envelope.gain.setValueAtTime(volume, time)
	envelope.gain.linearRampToValueAtTime(0.0, time + decay)

	console.log("play_click")
}

// global interval handle
var interval_handle

function setup_notifications() {
	// first username is always self user when logged in
	var target_div = document.querySelector(".UserName")

	if (!target_div) {
		console.log("No logged in user detected, trying again in a sec")

		window.setTimeout(setup_notifications, 1000)
		return
	}

	var target_name = target_div.innerText;

	console.log("setting up script for user", target_name)

	var last_checked_time = 0

	var countdown_divs = document.querySelectorAll(".GamePlayersInfo-color .TimeCountdown")

	console.log("countoown_divs", countdown_divs)

	var interval_ms = 50

	window.clearInterval(interval_handle)
	interval_handle = null;

	for (var countdown_div of countdown_divs) {
		var surrounding_div = countdown_div.closest(".GamePlayersInfo-color")
		var player_name = surrounding_div.querySelector('.UserName').innerText

		console.log("considering", player_name)

		if (player_name == target_name) {
			console.log("found player info", target_name)

			interval_handle = window.setInterval(function () {
				var time_string = countdown_div.innerText
				var min_sec = time_string.split(" ")[0].split(":")

				var minutes = Number(min_sec[0])
				var seconds = Number(min_sec[1])

				console.log(minutes, seconds)

				var total = minutes * 60 + seconds

				if (seconds != last_checked_time) {
					if ((minutes % 5) == 0 && seconds == 0)  { play_click() }
					if (minutes == 1       && seconds == 0)  { play_click() }
					if (minutes == 0       && seconds <= 10) { play_click() }

					last_checked_time = seconds
				}
			}, interval_ms)

			break
		}
	}

	if (!interval_handle) {
		console.log("could not find player clock, retrying")
		window.setTimeout(setup_notifications, 1000)
	}
}

setup_notifications()