wr-history-graph

Show graph for Mario Kart WR History

// ==UserScript==
// @name            wr-history-graph
// @namespace       npm/vite-plugin-monkey
// @version         0.0.4
// @author          monkey
// @description:en  Show graph of Mario Kart WR History
// @description:ja  マリオカートのWR Historyのグラフを表示します
// @license         MIT
// @icon            https://vitejs.dev/logo.svg
// @match           https://mkwrs.com/*
// @require         https://cdnjs.cloudflare.com/ajax/libs/apexcharts/4.3.0/apexcharts.min.js
// @description Show graph for Mario Kart WR History
// ==/UserScript==

(function () {
  'use strict';

  var __defProp = Object.defineProperty;
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  const toMilliseconds = (time) => {
    const regex = /(?:([\d]+)')?([\d]+)"([\d]+)/;
    const match = time.match(regex);
    if (!match) {
      return null;
    }
    const minutes = match[1] ? parseInt(match[1], 10) : 0;
    const seconds = parseInt(match[2], 10);
    const milliseconds = match[3].length === 3 ? parseInt(match[3], 10) : parseInt(match[3], 10) * 10;
    return minutes * 6e4 + seconds * 1e3 + milliseconds;
  };
  const toDateTime = (date) => {
    const dateTime = new Date(date).getTime();
    if (isNaN(dateTime)) {
      return null;
    }
    return dateTime;
  };
  class History {
    constructor(seriesName) {
      __publicField(this, "config");
      __publicField(this, "getTableData", () => {
        var _a;
        const rowIndexes = this.config.rowIndexes;
        const h2Elements = document.querySelectorAll("h2");
        let targetH2 = null;
        for (const h2 of Array.from(h2Elements)) {
          const h2Text = ((_a = h2.textContent) == null ? undefined : _a.trim()) ?? "";
          if (h2Text.includes("History") && !h2Text.includes("Graph")) {
            targetH2 = h2;
            break;
          }
        }
        if (!targetH2) {
          return [];
        }
        let nextElem = targetH2.nextElementSibling;
        if (!nextElem || !(nextElem instanceof HTMLTableElement)) {
          return [];
        }
        const tableData = [];
        const rows = nextElem.querySelectorAll("tr");
        rows.forEach((tr) => {
          const cells = tr.querySelectorAll("td");
          const rowData = Array.from(cells).map((td, index) => {
            var _a2, _b;
            if (index !== rowIndexes[3]) {
              return ((_a2 = td.textContent) == null ? undefined : _a2.trim()) ?? "";
            }
            return ((_b = td.querySelector("img")) == null ? undefined : _b.src) ?? "";
          });
          if (rowData.length === 0) {
            return;
          }
          const dateTime = toDateTime(rowData[rowIndexes[0]]);
          if (dateTime === null) {
            return;
          }
          tableData.push([
            dateTime,
            toMilliseconds(rowData[rowIndexes[1]]),
            rowData[rowIndexes[2]],
            rowData[rowIndexes[3]],
            rowData[rowIndexes[4]]
          ]);
        });
        tableData.push([
          (/* @__PURE__ */ new Date()).getTime(),
          tableData.at(-1)[1],
          tableData.at(-1)[2],
          tableData.at(-1)[3],
          tableData.at(-1)[4]
        ]);
        return tableData;
      });
      __publicField(this, "insertChartDiv", () => {
        var _a;
        const mainElement = document.querySelector("#main");
        if (!mainElement) {
          return null;
        }
        const h2Elements = document.querySelectorAll("h2");
        let targetH2 = null;
        for (const h2 of Array.from(h2Elements)) {
          if ((((_a = h2.textContent) == null ? undefined : _a.trim()) ?? "").endsWith(":")) {
            targetH2 = h2;
            break;
          }
        }
        if (!targetH2) {
          return null;
        }
        const chartTitle = document.createElement("h2");
        chartTitle.textContent = "WR History Graph";
        mainElement.insertBefore(chartTitle, targetH2);
        const chartDiv = document.createElement("div");
        chartDiv.id = "chart";
        mainElement.insertBefore(chartDiv, targetH2);
        return chartDiv;
      });
      let rowIndexes;
      switch (seriesName) {
        case "mkwii":
          rowIndexes = [0, 1, 2, 4, 11];
          break;
        case "mk64":
          rowIndexes = [0, 1, 3, 4, 6];
          break;
        default:
          rowIndexes = [0, 1, 2, 3, 4];
          break;
      }
      this.config = {
        rowIndexes
      };
    }
  }
  let ApexChartsLocal;
  const millisecondsToString = (value) => {
    const milliseconds = value % 1e3;
    const seconds = Math.floor(value / 1e3 % 60);
    const minutes = Math.floor(value / 6e4 % 60);
    return `${minutes}'${String(seconds).padStart(2, "0")}"${String(
    milliseconds.toFixed(0)
  ).padStart(3, "0")}`;
  };
  const getHistory = () => {
    const url = window.location.href;
    const seriesName = url.split("/")[3];
    return new History(seriesName);
  };
  const drawChart = (data) => {
    const options = {
      chart: {
        type: "line",
        height: 400,
        width: "90%",
        zoom: {
          enabled: true,
          type: "x",
          autoScaleYaxis: true
        }
      },
      markers: {
        size: 5
      },
      stroke: {
        curve: "stepline"
      },
      series: [
        {
          name: "history",
          data: data.map((d) => ({
            x: d[0],
            y: d[1],
            player: d[2],
            nation: d[3],
            duration: d[4]
          }))
        }
      ],
      tooltip: {
        custom: function({ seriesIndex, dataPointIndex, w }) {
          const data2 = w.globals.initialSeries[seriesIndex].data[dataPointIndex];
          const date = new Date(data2.x).toLocaleDateString();
          const time = data2.y;
          const player = data2.player;
          const nation = data2.nation;
          const duration = data2.duration;
          return `
          <div style="padding:10px; top:1000px">
            <strong>Date:</strong> ${date}<br/>
            <strong>Time:</strong> ${millisecondsToString(time)}<br/>
            <strong>Player:</strong> ${player}<br/>
            <strong>Nation:</strong> <img src="${nation}"><br/>
            <strong>Duration:</strong> ${duration}
          </div>
        `;
        },
        followCursor: true
      },
      xaxis: {
        type: "datetime",
        tooltip: {
          enabled: false
        }
      },
      yaxis: {
        title: {
          text: "Time"
        },
        labels: {
          formatter: millisecondsToString
        }
      },
      grid: {
        xaxis: {
          lines: {
            show: true
          }
        }
      }
    };
    const chart = new ApexChartsLocal(document.querySelector("#chart"), options);
    chart.render();
  };
  const main = () => {
    const history = getHistory();
    const chartDiv = history.insertChartDiv();
    if (!chartDiv) {
      return;
    }
    const tableData = history.getTableData();
    drawChart(tableData);
  };
  {
    ApexChartsLocal = ApexCharts;
    main();
  }

})();
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

一年攒够 12 元

云驰互联

云驰互联