Autodarts Lobby Filter Pro

Lobby Filter Pro mit optionalen AVG-Rahmen, horizontal ausgerichtetes Menü und korrektem Preset/Reset/Save-Button inklusive Frame-Checkbox

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

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

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

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

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==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 });
}
})();