Greasy Fork

Klavia Race Logger

Logs Klavia Races

目前为 2025-04-13 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/532751/1570578/Klavia%20Race%20Logger.js

// ==UserScript==
// @name         Klavia Race Logger
// @version      2024-03-30
// @namespace    https://greasyfork.org/users/1331131-tensorflow-dvorak
// @description  Logs Klavia Races
// @match        *://*.ntcomps.com/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function () {
  const STORAGE_KEY = "klaviaRaceHistory";
  const seenRaceIDs = new Set();

  const estimatePoints = (wpm, accuracy) =>
    Math.round(Math.pow(wpm, 1) * Math.pow(accuracy, 2.5) * 0.000027);

  function loadRaceHistory() {
    try {
      return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
    } catch {
      return [];
    }
  }

  function saveRaceHistory(history) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(history));
  }

  function attachRaceLogger(ws) {
    ws.addEventListener("message", (event) => {
      let parsed;
      try {
        parsed = JSON.parse(event.data);
      } catch {
        return;
      }

      const identifier = parsed.identifier ? JSON.parse(parsed.identifier) : {};
      const msg = parsed.message;

      if (
        identifier.channel === "RaceChannel" &&
        msg?.message === "update_race_results" &&
        msg?.textCompleted === true &&
        msg?.raceId &&
        !seenRaceIDs.has(msg.raceId)
      ) {
        seenRaceIDs.add(msg.raceId);

        const raceData = {
          raceId: msg.raceId,
          points: estimatePoints(msg.wpm, parseFloat(msg.accuracy)),
          wpm: msg.wpm,
          accuracy: parseFloat(msg.accuracy),
          raceSeconds: msg.raceSeconds,
          textSeconds: msg.textSeconds,
          boostBonus: msg.boostBonus,
          timestamp: new Date().toISOString(),
        };

        const history = loadRaceHistory();
        history.unshift(raceData);
        saveRaceHistory(history);

        window.dispatchEvent(
          new CustomEvent("klavia:race-logged", { detail: raceData })
        );
      }
    });
  }

  const originalWS = window.WebSocket;
  window.WebSocket = new Proxy(originalWS, {
    construct(target, args) {
      const ws = new target(...args);
      attachRaceLogger(ws);
      return ws;
    },
  });

  console.log("✅ Klavia Race Logger is active");
})();