Lobby Filter Pro mit optionalen AVG-Rahmen, horizontal ausgerichtetes Menü und korrektem Preset/Reset/Save-Button inklusive Frame-Checkbox
// ==UserScript==
// @name Autodarts Lobby Filter Pro
// @namespace http://tampermonkey.net/
// @version 6.0
// @description Lobby Filter Pro mit optionalen AVG-Rahmen, horizontal ausgerichtetes Menü und korrektem Preset/Reset/Save-Button inklusive Frame-Checkbox
// @match https://play.autodarts.io/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
// @grant GM_addStyle
// @run-at document-idle
// ==/UserScript==
(function() {
"use strict";
const STORAGE_KEY = "autodartsPreset_v2";
let preset = {
gamemode: "501",
minavg: "50",
maxavg: "All",
sidomode: "SI-DO",
stableList: true,
hideEmpty: true,
hideNoAvg: true,
onlyPlus: false,
hideDuplicates: true,
highlightAVG: true // Frame-Checkbox speichern
};
let defaults = {
gamemode: "All",
minavg: "All",
maxavg: "All",
sidomode: "All",
stableList: true,
hideEmpty: false,
hideNoAvg: false,
onlyPlus: false,
hideDuplicates: false,
highlightAVG: false // Standard für Frame
};
let scriptInitialized = false;
let observer = null;
let initObserver = null;
function checkPage() {
if(/^\/lobbies\/?$/.test(location.pathname)) {
if(!scriptInitialized){ scriptInitialized=true; initScript(); }
} else {
scriptInitialized=false;
if(observer) observer.disconnect();
if(initObserver) initObserver.disconnect();
$(".tm_menu").remove();
}
}
const pushState = history.pushState;
history.pushState = function() { pushState.apply(history, arguments); setTimeout(checkPage,50); };
window.addEventListener("popstate", checkPage);
setTimeout(checkPage,200);
function initScript() {
let savedPreset = localStorage.getItem(STORAGE_KEY);
if(savedPreset) {
try { preset = JSON.parse(savedPreset); }
catch(e) { console.warn("Preset konnte nicht geladen werden"); }
}
GM_addStyle(`
.hide { display: none !important; }
#gamemode, #avgmenumin, #avgmenumax, #sidomenu {
width: 75px; padding:4px; box-sizing:border-box;
}
#avgmenumin, #avgmenumax { width: 55px; }
.tm_menu {
display: flex;
margin-top: 10px;
align-items: flex-start;
gap: 12px;
font-size: 13px;
}
.tm_menu > div {
display: flex;
flex-direction: column;
align-items: center;
}
.tm_menu > div input[type="checkbox"] {
margin-top: 8px;
}
#presetbtn { color:white; border:none; border-radius:4px; font-weight:600; padding:5px 10px; cursor:pointer; }
#presetbtn[data-mode="preset"] { background:#38a169; }
#presetbtn[data-mode="reset"] { background:#e53e3e; }
#presetbtn[data-mode="save"] { background:#3182ce; }
`);
let gamemode = "All", minavg="All", maxavg="All", sidomode="All";
let stableList=true, hideEmpty=true, hideNoAvg=true, onlyPlus=false, hideDuplicates=true;
let highlightAVG = true;
let knownCards=new WeakSet();
let seenLobbyKeys=new Map();
let presetChanged = false;
function applyFilter(card){
$(card).removeClass("hide");
if(hideDuplicates){
let key=[];
$(card).find(".chakra-stack").each(function(){ key.push($(this).text().replace(/\s+/g," ").trim()); });
key = key.join("|");
if(seenLobbyKeys.has(key)){
let oldCard=seenLobbyKeys.get(key);
if(oldCard && oldCard!==card){ $(oldCard).addClass("hide"); }
seenLobbyKeys.set(key,card);
} else { seenLobbyKeys.set(key,card); }
}
if(hideEmpty && !card.querySelector(".ad-ext-player-name")){ $(card).addClass("hide"); return; }
if(hideNoAvg && !card.querySelector(".chakra-badge")){ $(card).addClass("hide"); return; }
let html = card.innerHTML;
let avgText = $(card).find(".chakra-badge").eq(0).text();
let avg = parseInt(avgText);
if(onlyPlus && !html.includes("chakra-image css-l5at91")){ $(card).addClass("hide"); return; }
if(gamemode !== "All" && !html.includes(gamemode+"</span>")){ $(card).addClass("hide"); return; }
if(sidomode !== "All" && !html.includes(sidomode+"</span>")){ $(card).addClass("hide"); return; }
if(minavg !== "All" && avg < parseInt(minavg)){ $(card).addClass("hide"); return; }
if(maxavg !== "All" && avg > parseInt(maxavg)){ $(card).addClass("hide"); return; }
}
function applyHighlight(card){
const badge = card.querySelector(".chakra-badge");
if(!badge) return;
if(!highlightAVG){ badge.style.border=""; return; }
let avg = parseInt(badge.innerText);
if(avg >= 70){ badge.style.border="3px solid rgb(250,240,137)"; }
else if(avg===60 || avg===65){ badge.style.border="3px solid rgb(214,188,250)"; }
else if(avg===50 || avg===55){ badge.style.border="3px solid rgb(123,218,210)"; }
else if(avg===40 || avg===45){ badge.style.border="3px solid rgb(154,230,180)"; }
else{ badge.style.border="3px solid white"; }
}
function refilterAll(){
seenLobbyKeys.clear();
document.querySelectorAll(".chakra-card").forEach(card=>{ applyFilter(card); applyHighlight(card); });
}
function processLobby(card){
if(knownCards.has(card)) return;
knownCards.add(card);
if(stableList){ const parent=card.parentNode; if(parent && parent.lastElementChild!==card) parent.appendChild(card); }
applyFilter(card); applyHighlight(card);
}
observer = new MutationObserver(mutations=>{
mutations.forEach(m=>{
m.addedNodes.forEach(node=>{
if(node.nodeType!==1) return;
if(node.classList?.contains("chakra-card")) processLobby(node);
node.querySelectorAll?.(".chakra-card").forEach(processLobby);
});
});
refilterAll();
});
observer.observe(document.body,{childList:true,subtree:true});
function createMenu(){
if($("#gamemode").length) return;
if(!$(".chakra-heading").length) return;
const menuHTML = `
<div class="tm_menu">
<div title="Spiel auswählen"><label>Game</label><select id="gamemode">
<option>All</option><option>501</option><option>301</option><option>Cricket</option><option>Tactics</option>
<option>Bermuda</option><option>Shanghai</option><option>Gotcha</option><option>ATC</option>
<option>RTW</option><option>Random Checkout</option><option>CountUp</option><option>Bob's 27</option>
<option>Killer</option></select></div>
<div title="Minimaler Average"><label>Min Avg</label><select id="avgmenumin">
<option>All</option><option>25</option><option>30</option><option>35</option><option>40</option><option>45</option>
<option>50</option><option>55</option><option>60</option><option>65</option><option>70</option></select></div>
<div title="Maximaler Average"><label>Max Avg</label><select id="avgmenumax">
<option>All</option><option>30</option><option>35</option><option>40</option><option>45</option>
<option>50</option><option>55</option><option>60</option><option>65</option><option>70</option><option>75</option></select></div>
<div title="CheckIn/CheckOut"><label>Mode</label><select id="sidomenu">
<option>All</option><option>SI-SO</option><option>SI-DO</option><option>SI-MO</option>
<option>DI-SO</option><option>DI-DO</option><option>DI-MO</option>
<option>MI-SO</option><option>MI-DO</option><option>MI-MO</option></select></div>
<div title="Neue Lobbies immer ans Ende">Sort<input type="checkbox" id="stablelist" checked></div>
<div title="Blendet Lobbies ohne Spieler aus">Empty<input type="checkbox" id="hideempty" checked></div>
<div title="Blendet Spieler ohne AVG">No_AVG<input type="checkbox" id="hidenoavg" checked></div>
<div title="Nur Autodarts Plus">Plus<input type="checkbox" id="onlyplus"></div>
<div title="Blendet identische Lobbies aus">No_Dup<input type="checkbox" id="hideduplicates"></div>
<div title="Rahmen ein-/ausschalten">Frame<input type="checkbox" id="highlightavg" checked></div>
<div title="Preset speichern/laden"><button id="presetbtn" data-mode="preset">Preset</button></div>
</div>
`;
$(".chakra-heading").after(menuHTML);
$("#highlightavg").on("change", function() { highlightAVG = this.checked; presetChanged=true; $("#presetbtn").text("Save").attr("data-mode","save"); refilterAll(); });
$("#gamemode, #avgmenumin, #avgmenumax, #sidomenu, #stablelist, #hideempty, #hidenoavg, #onlyplus, #hideduplicates").on("change", function() {
presetChanged = true;
$("#presetbtn").text("Save").attr("data-mode","save");
if(this.id==="gamemode") gamemode=this.value;
if(this.id==="avgmenumin") minavg=this.value;
if(this.id==="avgmenumax") maxavg=this.value;
if(this.id==="sidomenu") sidomode=this.value;
if(this.id==="stablelist") stableList=this.checked;
if(this.id==="hideempty") hideEmpty=this.checked;
if(this.id==="hidenoavg") hideNoAvg=this.checked;
if(this.id==="onlyplus") onlyPlus=this.checked;
if(this.id==="hideduplicates") hideDuplicates=this.checked;
refilterAll();
});
$("#presetbtn").on("click", function(){
let mode = $(this).attr("data-mode");
if(mode==="preset"){ loadPreset(false); }
else if(mode==="save"){ savePreset(); }
else if(mode==="reset"){ resetFilters(); }
});
setTimeout(()=>{ loadPreset(false); },100);
}
function loadPreset(showSaveButton=true){
gamemode=preset.gamemode; minavg=preset.minavg; maxavg=preset.maxavg; sidomode=preset.sidomode;
stableList=preset.stableList; hideEmpty=preset.hideEmpty; hideNoAvg=preset.hideNoAvg;
onlyPlus=preset.onlyPlus; hideDuplicates=preset.hideDuplicates; highlightAVG=preset.highlightAVG;
$("#gamemode").val(gamemode); $("#avgmenumin").val(minavg); $("#avgmenumax").val(maxavg);
$("#sidomenu").val(sidomode);
$("#stablelist").prop("checked",stableList); $("#hideempty").prop("checked",hideEmpty);
$("#hidenoavg").prop("checked",hideNoAvg); $("#onlyplus").prop("checked",onlyPlus);
$("#hideduplicates").prop("checked",hideDuplicates); $("#highlightavg").prop("checked",highlightAVG);
refilterAll();
presetChanged = false;
if(showSaveButton){
$("#presetbtn").text("Save").attr("data-mode","save");
} else {
$("#presetbtn").text("Preset").attr("data-mode","preset");
}
}
function savePreset(){
preset = { gamemode, minavg, maxavg, sidomode, stableList, hideEmpty, hideNoAvg, onlyPlus, hideDuplicates, highlightAVG };
localStorage.setItem(STORAGE_KEY, JSON.stringify(preset));
$("#presetbtn").text("Saved!");
setTimeout(()=>{ $("#presetbtn").text("Reset").attr("data-mode","reset"); },1000);
presetChanged = false;
}
function resetFilters(){
gamemode=defaults.gamemode; minavg=defaults.minavg; maxavg=defaults.maxavg; sidomode=defaults.sidomode;
stableList=defaults.stableList; hideEmpty=defaults.hideEmpty; hideNoAvg=defaults.hideNoAvg; onlyPlus=defaults.onlyPlus; hideDuplicates=defaults.hideDuplicates; highlightAVG=defaults.highlightAVG;
$("#gamemode").val(gamemode); $("#avgmenumin").val(minavg); $("#avgmenumax").val(maxavg);
$("#sidomenu").val(sidomode);
$("#stablelist").prop("checked",stableList); $("#hideempty").prop("checked",hideEmpty);
$("#hidenoavg").prop("checked",hideNoAvg); $("#onlyplus").prop("checked",onlyPlus);
$("#hideduplicates").prop("checked",hideDuplicates); $("#highlightavg").prop("checked",highlightAVG);
refilterAll();
$("#presetbtn").text("Preset").attr("data-mode","preset");
}
initObserver = new MutationObserver(()=>{
createMenu();
document.querySelectorAll(".chakra-card").forEach(processLobby);
});
initObserver.observe(document.body, { childList:true, subtree:true });
}
})();