Clicking on the "points of failure" chart will open the editor to that location.
// ==UserScript==
// @name osu: clickable points of failure chart
// @description Clicking on the "points of failure" chart will open the editor to that location.
// @match https://osu.ppy.sh/*
//
// @author quat
// @namespace https://highlysuspect.agency/
// @version 1.1
// @license CC0
//
// @grant none
// ==/UserScript==
!function() {
window.addEventListener("click", e => {
//have we clicked on a chart?
let chartElem = document.querySelector(".beatmap-success-rate__chart");
if(!chartElem.contains(e.target)) return;
//how far along the chart did we click?
let chartRect = chartElem.getBoundingClientRect();
let percent = (e.clientX - chartRect.x) / (chartRect.width);
//(rounded to the middle of each bar of the chart)
let barCount = chartElem.querySelectorAll(".stacked-bar-chart__col").length;
percent = (0.5 + Math.round(percent * barCount)) / barCount;
//what mapset is this, and what diff are we looking at
let mapsetData = JSON.parse(document.getElementById("json-beatmapset").textContent);
let mapId = window.location.hash.split("/")[1];
let mapData = mapsetData.beatmaps.find(map => map.id = mapId);
//compute mm:ss:SSS format timestamp corresponding to click location
let totalSeconds = mapData.total_length * percent;
let minutes = Math.floor(totalSeconds / 60);
let seconds = Math.floor(totalSeconds) - minutes * 60;
let milliseconds = Math.floor(totalSeconds) - seconds;
//create and click link
let pad = (n, digits) => n.toLocaleString("en-US", { minimumIntegerDigits: digits, useGrouping: false});
let href = `osu://edit/${pad(minutes, 2)}:${pad(seconds, 2)}:${pad(milliseconds, 3)}`;
let a = document.createElement("a");
a.href = href;
a.click();
a.remove();
}, {
passive: true
});
//inject a stylesheet in a way where turbolinks won't eat it
window.addEventListener("turbolinks:load", e => {
let id = "clickable-failchart-injected-style";
let existingStyle = document.getElementById(id);
if(!existingStyle) {
let style = document.createElement("style");
style.id = "clickable-failchart-injected-style";
style.innerHTML = `
.beatmap-success-rate__chart:hover {
cursor: pointer;
}
.beatmap-success-rate__chart .stacked-bar-chart__col:hover {
background-color: hsl(var(--hsl-red-3));
}
`;
document.head.appendChild(style);
}
});
}();