GSJ TOP

try to take over the world!

当前为 2025-04-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         GSJ TOP
// @namespace    http://tampermonkey.net/
// @version      7.1
// @description  try to take over the world!
// @author       DK, Shikokuchuo
// @include      https://*.the-west.*/game.php*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=the-west.pl
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
(function (fn) {
    setTimeout(function() {
        var script = document.createElement('script');
        script.setAttribute('type', 'application/javascript');
        script.textContent = '(' + fn + ')();';
        document.body.appendChild(script);
        document.body.removeChild(script);
    }, 5000); // 5000 ms = 5 sekund
})(function () {
  // Inicjalizacja głównego obiektu GSJTOP
GSJTOP = {
    version: '7.1',
    name: 'GSJ TOP',
    author: 'Shiko',
    minGame: '2.01',
    maxGame: Game.version.toString(),
    toLoad: 0,
    loaded: 0,
    xMax: 181,
    yMax: 79,
    blockMaxLength: 300,
    dataLoaded: false,
    silverJobBbColor: '#708090',
    goldJobBbColor: '#AB9930',
    refreshInterval: null,
     preferences: {
        showSilver: localStorage.getItem('GSJTOP_showSilver') !== 'false',
        showGold: localStorage.getItem('GSJTOP_showGold') !== 'false',
        enabled: localStorage.getItem('GSJTOP_enabled') !== 'false',
        hideLowIdJobs: localStorage.getItem('GSJTOP_hideLowIdJobs') === 'true',
        hideHighIdJobs: localStorage.getItem('GSJTOP_hideHighIdJobs') === 'true',
        showTooltips: localStorage.getItem('GSJTOP_showTooltips') !== 'false',
        hideFilters: localStorage.getItem('GSJTOP_hideFilters') === 'true',
        currentPage: 0,
        jobsPerPage: parseInt(localStorage.getItem('GSJTOP_jobsPerPage')) || 8,
        hiddenJobs: JSON.parse(localStorage.getItem('GSJTOP_hiddenJobs') || '{}')
    },
    hiddenImageOpacity: 0.35,
    shownImageOpacity: 1,
    bestJobTime: 0,
    position: {
      top: 0,
      right: 0
    },
    langs: {
      pl: {
        language: 'Polish (polski)',
        ApiGui: 'Ten skrypt automatycznie wyszukuje złote i srebrne prace na mapie.',
        title: 'Złote i srebrne prace',
        loading: 'Ładowanie... To zajmie moment',
        next: '→',
        prev: '←',
        enableScript: 'Włącz skrypt'
      }
    },
    updateLang: function () {
      var lg = GSJTOP.langs;
      GSJTOP.lang = lg[localStorage.getItem('scriptsLang')] ? localStorage.getItem('scriptsLang') : lg[Game.locale.substr(0, 2)] ? Game.locale.substr(0, 2) : 'en';
      GSJTOPlang = lg[GSJTOP.lang];
    }
  };
          GSJTOP.updateLang();

  // Funkcja tworząca przełączniki (checkboxy) w interfejsie
GSJTOP.createToggleCheckbox = function() {
    var container = $('<div/>', {
        id: 'gj-toggle',
        css: {
            position: 'static',
            display: 'inline-block',
            float: 'right',
            marginRight: '-30px',
            zIndex: 10002,
            backgroundColor: 'rgba(255, 255, 255, 0.0)',
            padding: '5px',
            borderRadius: '3px'
        }
    });

 // Główny checkbox włączający skrypt
  var checkbox = $('<input/>', {
        type: 'checkbox',
        id: 'gj-checkbox',
        checked: this.preferences.enabled
    });

// Checkbox do ukrywania filtrów - poprawiona inicjalizacja
var hideFiltersCheckbox = $('<input/>', {
    type: 'checkbox',
    id: 'gj-hide-filters',
 checked: !this.preferences.hideFilters,
    css: {
        marginLeft: '5px'
    }
});

checkbox.on('change', function() {
    GSJTOP.preferences.enabled = this.checked;
    localStorage.setItem('GSJTOP_enabled', this.checked.toString());
    if (this.checked) {
        GSJTOP.init();
    } else {
        GSJTOP.closeWindow();
    }
});

hideFiltersCheckbox.on('change', function() {
 GSJTOP.preferences.hideFilters = !this.checked;
    localStorage.setItem('GSJTOP_hideFilters', GSJTOP.preferences.hideFilters.toString());
    GSJTOP.refreshWindow();
 });

    container.append(checkbox, hideFiltersCheckbox);
    $('#ui_topbar').append(container);


};
// Funkcja pobierająca dane o pracy
GSJTOP.getJobData = function(job, isSilver) {
    try {
        var jobData = JobList.getJobById(job.jobId);
        if (!jobData) return null;

        var jobModelData = JobsModel.Jobs.find(j => j.id === parseInt(job.jobId));
        if (!jobModelData) return null;

        var xp = jobModelData.basis.short.experience;
        var money = jobModelData.basis.short.money;
        var motivation = Math.round(jobModelData.jobmotivation * 100);

        if (isSilver) {
            xp = Math.ceil(xp * 1.5);
            money = Math.ceil(money * 1.5);
        }
        else if (job.gold) {
            xp = Math.ceil(xp * 2);
            money = Math.ceil(money * 2);
        }

        return {
            experience: xp,
            money: money,
            motivation: motivation,
            distance: job.distance
        };
    } catch (e) {
        return {
            experience: 0,
            money: 0,
            motivation: 0,
            distance: job.distance
        };
    }
};
          // Funkcja zamykająca okno
  GSJTOP.closeWindow = function() {
    if (this.refreshInterval) {
        clearTimeout(this.refreshInterval);
        this.refreshInterval = null;
    }
    $('#goldJobs-bar').remove();
  };

  // Funkcja do zarządzania automatycznym odświeżaniem
  GSJTOP.startAutoRefresh = function() {
    if (this.refreshInterval) {
        clearTimeout(this.refreshInterval);
    }

    const getRandomDelay = () => Math.floor(Math.random() * (20000 - 7000 + 1) + 7000);

    const scheduleNextRefresh = () => {
        if (!this.preferences.enabled) return;

        this.refreshWindow();
        const nextDelay = getRandomDelay();
        this.refreshInterval = setTimeout(scheduleNextRefresh, nextDelay);
    };

    scheduleNextRefresh();
  };

  // Funkcja obliczająca odległość
  GSJTOP.calculateDistance = function (jobX, jobY) {
    if (!Character || !Character.position) return 0;

    var to = {
        x: parseInt(jobX),
        y: parseInt(jobY)
    };

    return GameMap.calcWayTime(Character.position, to);
  };

  GSJTOP.parseWholeMap = function (tiles, onLoad) {
    this.loaded = 0;
    var x, y;
    var arr = [];
    var currentBlock = 0;
    var currentBlockLength = 0;
    for (x in tiles) {
      for (y in tiles[x]) {
        if (isNaN(x) || isNaN(y)) {
          continue;
        }
        if (currentBlockLength === 0) {
          arr[currentBlock] = [];
        }
        arr[currentBlock].push([parseInt(x), parseInt(y)]);
        if (++currentBlockLength == this.blockMaxLength) {
          currentBlock++;
          currentBlockLength = 0;
        }
      }
    }
    var i, to = arr.length;
    this.toLoad = to;
    for (i = 0; i < to; i++) {
      GameMap.Data.Loader.load(arr[i], function () {
        GSJTOP.loaded++;
        if (GSJTOP.loaded == GSJTOP.toLoad) {
          onLoad();
        }
      });
    }
  };
    GSJTOP.createVisibilityWindow = function() {
    var hiddenJobs = JSON.parse(localStorage.getItem('GSJTOP_hiddenJobs') || '{}');
    var data = GSJTOP.getFilteredData(true, true);
    var goldJobs = data.filter(job => job.gold);
    var silverJobs = data.filter(job => job.silver);

 var visibilityPanel = $('<div/>', {
        id: 'job-visibility-window',
        css: {
            // Style ramki i tła dla głównego okna (pozostają bez zmian)
            'position': 'fixed',
            'top': '50%',
            'left': '50%',
            'transform': 'translate(-525px, -50%)',
            'background': 'linear-gradient(to bottom, #4d351b 0%, #2a1608 100%)',
            'padding': '15px', // Padding zewnętrzny dla ramki
            'border-radius': '5px',
            'border': '2px solid #1b0a00',
            'border-top-color': '#150800',
            'border-left-color': '#150800',
            'box-shadow': '0 4px 15px rgba(0, 0, 0, 0.7), inset 0 0 5px rgba(0,0,0,0.2)',
            'z-index': 10002,
            // Wysokość całego okna - może wymagać dostosowania
            'height': 'auto', // Zmieniamy na auto, aby dopasować do zawartości
            'min-height': '340px', // Minimalna wysokość, jeśli potrzeba
            'max-height': '80vh', // Maksymalna wysokość, np. 80% wysokości widoku
            'overflow': 'hidden', // Ukrywamy overflow głównego okna
            'min-width': '440px',
            'width': '490px'
        }
    });
            var title = $('<div/>', {
        text: 'Widoczność prac',
        css: {
            'font-weight': 'bold',
            'margin-bottom': '10px',
            'text-align': 'center',
            'padding-bottom': '5px',
            'border-bottom': '1px solid rgba(255, 255, 255, 0.2)', // Jaśniejsza linia na ciemnym tle
            'color': '#fdf7e5' // Jaśniejszy kolor tekstu tytułu
        }
    });


    var toggleButton = $('<button/>', {
        text: 'Odznacz wszystkie',
        css: {
            'margin-bottom': '10px',
            'padding': '5px 10px',
            'border-radius': '3px',
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'background-color': '#f0f0f0',
            'cursor': 'pointer',
            'width': '100%',
            'transition': 'opacity 0.3s ease'
        }
    }).on('click', function() {
        var button = $(this);
        var checkboxes = checkboxContainer.find('input[type="checkbox"]');
        var allChecked = checkboxes.length === checkboxes.filter(':checked').length;

        button.prop('disabled', true).css('opacity', '0.5');

        function processCheckboxes(startIndex) {
            var batchSize = 1;
            var endIndex = Math.min(startIndex + batchSize, checkboxes.length);

            for(var i = startIndex; i < endIndex; i++) {
                $(checkboxes[i]).prop('checked', !allChecked).trigger('change');
            }

            if(endIndex < checkboxes.length) {
                setTimeout(() => processCheckboxes(endIndex), 200);
            } else {
                setTimeout(() => {
                    button.prop('disabled', false).css('opacity', '1');
                    button.text(allChecked ? 'Zaznacz wszystkie' : 'Odznacz wszystkie');
                }, 300);
            }
        }

        processCheckboxes(0);
    });

 var checkboxContainer = $('<div/>', {
        id: 'gsjtop-visibility-container-' + Date.now(), // Unikalne ID dla selektorów CSS
        css: {
            // --- Dokładne style podane przez użytkownika ---
            'display': 'flex',
            'flex-direction': 'column',
            'gap': '5px',
            'margin-bottom': '10px',
            'max-height': '255px',
            'overflow-y': 'auto',
            'padding-right': '10px', // Tylko prawy padding
            'scrollbar-width': 'thin',
            'scrollbar-color': '#888 #f0f0f0',
            'width': '480px',
            // --- Dodane style wyglądu kontenera ---
            'background-color': '#ffffff', // Jasne tło
            'border-radius': '3px',       // Zaokrąglenie
            'border': '1px solid #b89b6d' // Ramka wewnętrzna

        }
    });


        var jobVisibilityContainer = $('<div/>', {
        css: {
            'display': 'flex',
            'flex-wrap': 'wrap',
            'gap': '5px',
            'justify-content': 'center',
            'margin-top': '-20px',
            'background-color': 'rgba(255, 255, 255, 0.7)',
            'padding': '5px',
            'border-radius': '3px',
            'position': 'relative',
            'z-index': '10001'
        }
    });

    function createJobWrapper(job, jobData) {
        var wrapper = $('<div/>', {
            css: {
                'display': 'grid',
                'grid-template-columns': '30px 220px 50px 50px 80px',
                'align-items': 'center',
                'gap': '10px',
                'padding': '5px',
                'border-bottom': '1px solid rgba(0,0,0,0.1)',
                'width': '430px'
            }
        });

        var checkbox = $('<input/>', {
            type: 'checkbox',
            id: 'job-visibility-' + job.jobId,
            checked: !hiddenJobs[job.jobId]
        }).on('change', function() {
            hiddenJobs[job.jobId] = !this.checked;
            localStorage.setItem('GSJTOP_hiddenJobs', JSON.stringify(hiddenJobs));
            GSJTOP.refreshWindow();
        });

        var label = $('<label/>', {
            for: 'job-visibility-' + job.jobId,
            text: job.shortname,
            css: {
                'font-size': '12px',
                'white-space': 'nowrap',
                'overflow': 'hidden',
                'text-overflow': 'ellipsis'
            }
        });

        var xpDiv = $('<div/>', {
            html: '<img src="images/window/job/bigicon_xp.png" style="width: 14px; height: 14px; vertical-align: middle;"> ' +
                  '<span style="margin-left: 2px;">' + jobData.experience + '</span>',
            css: {
                'white-space': 'nowrap',
                'text-align': 'left',
                'font-size': '11px'
            }
        });

        var moneyDiv = $('<div/>', {
            html: '<img src="images/window/job/bigicon_money.png" style="width: 14px; height: 14px; vertical-align: middle;"> ' +
                  '<span style="margin-left: 2px;">' + jobData.money + '</span>',
            css: {
                'white-space': 'nowrap',
                'text-align': 'left',
                'font-size': '11px'
            }
        });

        var timeDiv = $('<div/>', {
            text: GSJTOP.formatTime(job.distance),
            css: {
                'white-space': 'nowrap',
                'text-align': 'left',
                'font-size': '11px'
            }
        });

        wrapper.append(checkbox, label, xpDiv, moneyDiv, timeDiv);
        return wrapper;
    }
        function createSortButton(text, sortFn, jobsType) {
        return $('<button/>', {
            text: text,
            css: {
                'padding': '2px 5px',
                'border': '1px solid rgba(0, 0, 0, 0.2)',
                'border-radius': '3px',
                'background': '#f0f0f0',
                'cursor': 'pointer',
                'font-size': '11px',
                'min-width': '25px',
                'transition': 'background-color 0.3s ease'
            }
        }).on('click', function() {
            var $button = $(this);
            if($button.prop('disabled')) return;

            $button.prop('disabled', true);

            var isAscending = !$button.data('ascending');
            $button.data('ascending', isAscending);

            $button.siblings('button').removeData('ascending');
            $button.siblings('button').css('background', '#f0f0f0');
            $button.css('background', isAscending ? '#e0ffe0' : '#ffe0e0');

            var jobs = jobsType === 'goldJobs' ? goldJobs : silverJobs;

            setTimeout(() => {
                jobs.sort((a, b) => {
                    var valueA = sortFn(a);
                    var valueB = sortFn(b);
                    return isAscending ? valueA - valueB : valueB - valueA;
                });

                refreshJobList(jobs, jobsType);

                setTimeout(() => {
                    $button.prop('disabled', false);
                }, 200);
            }, 100);
        });
    }

  function refreshJobList(jobs, jobsType) {
        var container = checkboxContainer.find('.' + jobsType);
        container.empty();

        const translations = {};
        JobList.getSortedJobs().forEach(job => {
            translations[job.id] = job.name;
        });

        // Definiujemy kolor naprzemienny w zależności od typu pracy
        let alternatingColor;
        if (jobsType === 'silverJobs') {
            alternatingColor = '#D3D3D3'; // Jasny srebrny (LightGray)
        } else { // Zakładamy, że to 'goldJobs'
            alternatingColor = '#FAFAD2'; // Jasny złoty (LightGoldenrodYellow)
        }

        jobs.forEach(function(job, index) { // Dodajemy 'index' do pętli
            var jobData = GSJTOP.getJobData(job, jobsType === 'silverJobs');
            if (jobData) {
                // Ustawiamy kolor tła na podstawie indeksu i typu pracy
                var backgroundColor = index % 2 === 0 ? alternatingColor : '#ffffff'; // Kolor naprzemienny lub biały

                var wrapper = $('<div/>', {
                    css: {
                        'display': 'grid',
                        'grid-template-columns': '30px 180px 80px 80px 80px',
                        'align-items': 'center',
                        'gap': '5px',
                        'padding': '5px',
                        'border-bottom': '1px solid rgba(0,0,0,0.1)',
                        'width': '460px',
                        'background-color': backgroundColor // Ustawiamy odpowiedni kolor tła
                    }
                });

                var checkbox = $('<input/>', {
                    type: 'checkbox',
                    id: 'job-visibility-' + job.jobId,
                    checked: !hiddenJobs[job.jobId]
                }).on('change', function() {
                    hiddenJobs[job.jobId] = !this.checked;
                    localStorage.setItem('GSJTOP_hiddenJobs', JSON.stringify(hiddenJobs));
                    GSJTOP.refreshWindow();
                });

                var jobName = translations[job.jobId] || job.shortname;
                var label = $('<label/>', {
                    for: 'job-visibility-' + job.jobId,
                    text: jobName,
                    css: {
                        'font-size': '11px',
                        'white-space': 'nowrap',
                        'overflow': 'hidden',
                        'text-overflow': 'ellipsis'
                    }
                });

                var xpDiv = $('<div/>', {
                    html: '<img src="images/window/job/bigicon_xp.png" style="width: 14px; height: 14px; vertical-align: middle;"> ' +
                          '<span style="margin-left: 2px;">' + jobData.experience + '</span>',
                    css: {
                        'white-space': 'nowrap',
                        'text-align': 'left',
                        'font-size': '11px'
                    }
                });

                var moneyDiv = $('<div/>', {
                    html: '<img src="images/window/job/bigicon_money.png" style="width: 14px; height: 14px; vertical-align: middle;"> ' +
                          '<span style="margin-left: 2px;">' + jobData.money + '</span>',
                    css: {
                        'white-space': 'nowrap',
                        'text-align': 'left',
                        'font-size': '11px'
                    }
                });

                var timeDiv = $('<div/>', {
                    text: GSJTOP.formatTime(job.distance),
                    css: {
                        'white-space': 'nowrap',
                        'text-align': 'left',
                        'font-size': '11px'
                    }
                });

                wrapper.append(checkbox, label, xpDiv, moneyDiv, timeDiv);
                container.append(wrapper);
            }
        });
    }
        var silverHeader = $('<div/>', {
        css: {
            'display': 'flex',
            'justify-content': 'space-between',
            'align-items': 'center',
            'font-weight': 'bold',
            'margin': '0px 0 5px 0',
            'padding': '5px',
            'background-color': 'rgba(112, 128, 144, 0.1)',
            'border-radius': '3px',
            'grid-column': '1 / -1'
        }
    }).append(
        $('<span/>').text('Srebrne prace'),
        $('<div/>', {
            css: {
                'display': 'flex',
                'gap': '5px'
            }
        }).append(
            createSortButton('XP', job => GSJTOP.getJobData(job, true).experience, 'silverJobs'),
            createSortButton('$', job => GSJTOP.getJobData(job, true).money, 'silverJobs'),
            createSortButton('↔', job => job.distance, 'silverJobs')
        )
    );

    var goldHeader = $('<div/>', {
        css: {
            'display': 'flex',
            'justify-content': 'space-between',
            'align-items': 'center',
            'font-weight': 'bold',
            'margin': '10px 0 5px 0',
            'padding': '5px',
            'background-color': 'rgba(171, 153, 48, 0.1)',
            'border-radius': '3px',
            'grid-column': '1 / -1'
        }
    }).append(
        $('<span/>').text('Złote prace'),
        $('<div/>', {
            css: {
                'display': 'flex',
                'gap': '5px'
            }
        }).append(
            createSortButton('XP', job => GSJTOP.getJobData(job, false).experience, 'goldJobs'),
            createSortButton('$', job => GSJTOP.getJobData(job, false).money, 'goldJobs'),
            createSortButton('↔', job => job.distance, 'goldJobs')
        )
    );

    var silverContainer = $('<div/>', { class: 'silverJobs' });
    var goldContainer = $('<div/>', { class: 'goldJobs' });

    checkboxContainer.append(silverHeader, silverContainer, goldHeader, goldContainer);

    refreshJobList(silverJobs, 'silverJobs');
    refreshJobList(goldJobs, 'goldJobs');
        // Dla panelu widoczności pokazujemy wszystkie prace
    data.forEach(function(job) {
        var jobData = GSJTOP.getJobData(job, job.silver);
        if (jobData) {
            var checkbox = $('<input/>', {
                type: 'checkbox',
                id: 'job-visibility-' + job.jobId,
                checked: !job.hidden,
                css: {
                    'margin': '2px'
                }
            }).on('change', function() {
                var hiddenJobs = JSON.parse(localStorage.getItem('GSJTOP_hiddenJobs') || '{}');
                hiddenJobs[job.jobId] = !this.checked;
                localStorage.setItem('GSJTOP_hiddenJobs', JSON.stringify(hiddenJobs));
                GSJTOP.refreshWindow();
            });

            var label = $('<label/>', {
                for: 'job-visibility-' + job.jobId,
                text: job.shortname,
                css: {
                    'font-size': '11px',
                    'margin-right': '5px'
                }
            });

            jobVisibilityContainer.append($('<div/>').append(checkbox, label));
        }
    });


  visibilityPanel.append(title, toggleButton, checkboxContainer);
    $('body').append(visibilityPanel);
}
GSJTOP.getJobIcon = function (jobId, x, y, shortname, gold, jobData) {
    var t = gold ? 'gold' : 'silver';
    var tooltipHtml = this.preferences.showTooltips ?
        '<div class="job-info" style="' +
        'position: absolute; ' +
        'top: 65px; ' +
        'width: 63px; ' +
        'background: #FDF7E5; ' +
        'border: 1px solid #B89B6D; ' +
        'padding: 0; ' +
        'box-shadow: 2px 2px 3px rgba(0,0,0,0.2); ' +
        'z-index: 10003;">' +

        // XP z tooltipem - powiększone cyfry
        '<div style="display: flex; justify-content: space-between; align-items: center; height: 18px; padding: 0 3px; background: #F5ECD4;" title="DOŚWIADCZENIE">' +
        '<div style="width: 14px; height: 14px; background: url(\'https://westpl.innogamescdn.com/images/window/job/bigicon_xp.png\') no-repeat center; background-size: contain;"></div>' +
        '<div style="color: #5C4219; font-size: 13px; font-weight: bold; text-align: right; min-width: 35px;">' + jobData.experience + '</div>' +
        '</div>' +

        // Pieniądze z tooltipem - powiększone cyfry
        '<div style="display: flex; justify-content: space-between; align-items: center; height: 18px; padding: 0 3px;" title="DOLARY">' +
        '<div style="width: 14px; height: 14px; background: url(\'https://westpl.innogamescdn.com/images/window/job/bigicon_money.png\') no-repeat center; background-size: contain;"></div>' +
        '<div style="color: #5C4219; font-size: 13px; font-weight: bold; text-align: right; min-width: 35px;">' + jobData.money + '</div>' +
        '</div>' +

        // Motywacja z tooltipem - powiększone cyfry
        '<div style="display: flex; justify-content: space-between; align-items: center; height: 18px; padding: 0 3px; background: #F5ECD4;" title="MOTYWACJA W PRACY">' +
        '<div style="color: #5C4219; font-size: 13px; font-weight: bold; width: 100%; text-align: center;">' + jobData.motivation + '%</div>' +
        '</div>' +

        // Czas z tooltipem - powiększone cyfry
        '<div style="display: flex; justify-content: space-between; align-items: center; height: 18px; padding: 0 3px;" title="CZAS DOTARCIA">' +
        '<div style="color: #5C4219; font-size: 13px; font-weight: bold; width: 100%; text-align: center;">' + GSJTOP.formatTime(jobData.distance) + '</div>' +
        '</div>' +
        '</div>' : '';

    return '<div class="job-wrapper" style="position: relative; display: inline-flex; flex-direction: column; align-items: center; margin: -1px; width: 65px; height: 65px; z-index: 10000;">' +
           '<div class="job" style="position: relative; width: 65px; height: 65px;">' +
           '<img src="images/jobs/' + shortname + '.png" class="job_icon" style="width: 65px; height: 65px; position: relative; z-index: 10000;">' +
           '<div onclick="javascript:GameMap.JobHandler.openJob(' + jobId + ',{x:' + x + ',y:' + y + '})" ' +
           'class="featured ' + t + '" style="position: absolute; top: -5px; left: -5px; z-index: 10001; width: 75px; height: 75px; background-size: contain;"></div>' +
           this.getGotoIcon(x, y) +
           '</div>' +
           tooltipHtml +
           '</div>';
};
          GSJTOP.formatTime = function(seconds) {
    seconds = Math.round(seconds);
    var hours = Math.floor(seconds / 3600);
    var minutes = Math.floor((seconds % 3600) / 60);
    var secs = seconds % 60;

    return String(hours).padStart(2, '0') + ':' +
           String(minutes).padStart(2, '0') + ':' +
           String(secs).padStart(2, '0');
  };

  GSJTOP.getGotoIcon = function (x, y) {
    return '<div class="centermap" onclick="javascript:GameMap.center(' + x + ',' + y + ');" ' +
           'style="position: absolute; background-image: url(\'images/map/icons/instantwork.png\'); ' +
           'width: 25px; height: 25px; top: -2px; right: -2px; cursor: pointer; z-index: 10002; background-size: contain;"></div>';
  };

GSJTOP.createNavigationButtons = function() {
    var wrapperStyle = {
        'width': '30px',
        'height': '60px',
        'display': 'flex',
        'justify-content': 'center',
        'align-items': 'center',
        'cursor': 'pointer',
        'margin-top': '35px',
        'z-index': 10001
    };

    var buttonStyle = {
        'width': '25px',
        'height': '44px',
        'background-image': 'url(\'https://westit.innogamescdn.com/images/window/trader/arrows.png\')',
        'color': 'white',
        'padding': '0px',
        'display': 'block',
        'background-size': 'cover',
        'text-align': 'center'
    };

    var prevWrapper = $('<div/>', {
        css: Object.assign({}, wrapperStyle, {
            'margin-right': '0px',
            'position': 'relative',
            'top': '-15px'
        })
    });

    var nextWrapper = $('<div/>', {
        css: Object.assign({}, wrapperStyle, {
            'margin-left': '0px',
            'position': 'relative',
            'top': '-15px'
        })
    });

    var prevButton = $('<div/>', {
        css: Object.assign({}, buttonStyle, {
            'background-position': 'top left'
        })
    });

    var nextButton = $('<div/>', {
        css: Object.assign({}, buttonStyle, {
            'background-position': 'top right'
        })
    });

    // Pobierz tylko widoczne prace
    var visibleJobs = this.getFilteredData(this.preferences.showSilver, this.preferences.showGold)
        .filter(job => !job.hidden);
    var totalJobs = visibleJobs.length;
    var maxPages = Math.ceil(totalJobs / this.preferences.jobsPerPage);

    // Aktualizacja stylów przycisków w zależności od dostępności stron
    var updateButtonStyles = function() {
        if (GSJTOP.preferences.currentPage <= 0) {
            prevWrapper.css('opacity', '0.5').css('cursor', 'default');
        } else {
            prevWrapper.css('opacity', '1').css('cursor', 'pointer');
        }

        if (GSJTOP.preferences.currentPage >= maxPages - 1 || maxPages <= 1) {
            nextWrapper.css('opacity', '0.5').css('cursor', 'default');
        } else {
            nextWrapper.css('opacity', '1').css('cursor', 'pointer');
        }
    };

    updateButtonStyles();

    prevWrapper.append(prevButton).click(function() {
        if (GSJTOP.preferences.currentPage > 0) {
            GSJTOP.preferences.currentPage--;
            GSJTOP.refreshWindow();
        }
    });

    nextWrapper.append(nextButton).click(function() {
        // Pobierz aktualną liczbę widocznych prac
        var visibleJobs = GSJTOP.getFilteredData(GSJTOP.preferences.showSilver, GSJTOP.preferences.showGold)
            .filter(job => !job.hidden);
        var totalJobs = visibleJobs.length;
        var maxPages = Math.ceil(totalJobs / GSJTOP.preferences.jobsPerPage);

        if (GSJTOP.preferences.currentPage < maxPages - 1) {
            GSJTOP.preferences.currentPage++;
            GSJTOP.refreshWindow();
        }
    });

    return {
        prev: prevWrapper,
        next: nextWrapper
    };
};
 GSJTOP.createJobsContainer = function (showSilver, showGold) {
     var hideHighIdJobsFilter = $('<div/>', {
        title: this.preferences.hideHighIdJobs ? 'POKAŻ PRACE POWYŻEJ 150 POZIOMU' : 'UKRYJ PRACE POWYŻEJ 150 POZIOMU',
        css: {
            'width': '24px',
            'height': '24px',
            'cursor': 'pointer',
            'margin-right': '1px',
            'background-color': this.preferences.hideHighIdJobs ? '#cccccc' : '#FFD700',
            'border-radius': '3px',
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'transition': 'all 0.3s ease',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)'
        }
    }).on('mouseenter', function() {
        $(this).css({
            'transform': 'scale(1.1)',
            'box-shadow': '0 2px 5px rgba(0, 0, 0, 0.2)'
        });
    }).on('mouseleave', function() {
        $(this).css({
            'transform': 'scale(1)',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)'
        });
    }).click(function() {
        var isCurrentlyActive = $(this).css('background-color') === 'rgb(204, 204, 204)';
        GSJTOP.preferences.hideHighIdJobs = !isCurrentlyActive;
        localStorage.setItem('GSJTOP_hideHighIdJobs', GSJTOP.preferences.hideHighIdJobs);
        $(this).css({
            'background-color': isCurrentlyActive ? '#FFD700' : '#cccccc'
        }).attr('title', isCurrentlyActive ? 'UKRYJ PRACE POWYŻEJ 150 POZIOMU' : 'POKAŻ PRACE POWYŻEJ 150 POZIOMU');
        GSJTOP.preferences.currentPage = 0;
        GSJTOP.refreshWindow();
    });

    var lowIdJobsFilter = $('<div/>', {
        title: this.preferences.hideLowIdJobs ? 'POKAŻ PRACE PONIŻEJ 100 POZIOMU' : 'UKRYJ PRACE PONIŻEJ 100 POZIOMU',
        css: {
            'width': '24px',
            'height': '24px',
            'cursor': 'pointer',
            'margin-right': '1px',
            'background-color': this.preferences.hideLowIdJobs ? '#cccccc' : '#ff4444',
            'border-radius': '3px',
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'transition': 'all 0.3s ease',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)'
        }
    }).on('mouseenter', function() {
        $(this).css({
            'transform': 'scale(1.1)',
            'box-shadow': '0 2px 5px rgba(0, 0, 0, 0.2)'
        });
    }).on('mouseleave', function() {
        $(this).css({
            'transform': 'scale(1)',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)'
        });
    }).click(function() {
        var isCurrentlyActive = $(this).css('background-color') === 'rgb(204, 204, 204)';
        GSJTOP.preferences.hideLowIdJobs = !isCurrentlyActive;
        localStorage.setItem('GSJTOP_hideLowIdJobs', GSJTOP.preferences.hideLowIdJobs);
        $(this).css({
            'background-color': isCurrentlyActive ? '#ff4444' : '#cccccc'
        }).attr('title', isCurrentlyActive ? 'UKRYJ PRACE PONIŻEJ 131 POZIOMU' : 'POKAŻ PRACE PONIŻEJ 131 POZIOMU');
        GSJTOP.preferences.currentPage = 0;
        GSJTOP.refreshWindow();
    });

    var container = $('<div/>', {
        class: 'jobs-container',
        css: {
            'display': 'flex',
            'flex-direction': 'column',
            'justify-content': 'flex-start',
            'align-items': 'center',
            'gap': '10px',
            'height': '120px',
            'overflow': 'visible',
            'background': 'rgba(255, 255, 255, 0.0)',
            'padding': '0 15px',
            'position': 'relative',
            'width': 'auto',
            'z-index': 10000,
            'min-height': '120px'
        }
    });

var jobsWrapper = $('<div/>', {
        css: {
            'display': 'flex',
            'justify-content': 'center',
            'align-items': 'center',
            'gap': '10px',
            'width': 'auto',
            'margin-bottom': '5px',
            'margin-top': '25px',
            'min-height': '65px',
            'flex-wrap': 'nowrap',
            'position': 'relative'
        }
    });

var jobVisibilityContainer = $('<div/>', {
    css: {
        'display': 'flex',
        'flex-wrap': 'wrap',
        'gap': '5px',
        'justify-content': 'center',
        'margin-top': '-20px', // Zmienione z 5px na -20px
        'background-color': 'rgba(255, 255, 255, 0.7)',
        'padding': '5px',
        'border-radius': '3px',
        'position': 'relative', // Dodane
        'z-index': '10001' // Dodane
    }
});

 var filterContainer = $('<div/>', {
        id: 'gsjtop-filters-container',
        css: {
            // Przywrócone pozycjonowanie absolutne
            'position': 'absolute',
            
            'top': '85px',
           
            'left': '50%', // Przykład: wycentrowanie poziome
            'transform': 'translateX(-50%)', // Przykład: wycentrowanie poziome
            'width': 'fit-content', // Aby szerokość dopasowała się do zawartości przy centrowaniu

            // Zachowany warunkowy margines górny dla ruchu góra-dół
            'margin-top': this.preferences.showTooltips ? '87px' : '10px', // Nadal kontroluje przesunięcie pionowe

            // Style layoutu (bez zmian)
           'display': this.preferences.hideFilters ? 'none' : 'flex',
            'justify-content': 'center',
            'align-items': 'center',
            'gap': '8px',
            'margin-bottom': '10px', // Może nie być potrzebny przy absolute

            // Style ciemnej ramki (bez zmian)
            'background': 'linear-gradient(to bottom, #4d351b 0%, #2a1608 100%)',
            'padding': '5px 10px',
            'border-radius': '5px',
            'border': '2px solid #1b0a00',
            'border-top-color': '#150800',
            'border-left-color': '#150800',
            'box-shadow': '0 2px 5px rgba(0, 0, 0, 0.5), inset 0 0 3px rgba(0,0,0,0.2)',
            'z-index': 10001 // Dodaj z-index, aby był nad innymi elementami
        }
    });

    var jobsPerPageSelect = $('<select/>', {
        css: {
            'padding': '2px',
            'margin-left': '5px',
            'border-radius': '3px',
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'background-color': 'white',
            'cursor': 'pointer'
        }
    }).on('change', function() {
        GSJTOP.preferences.jobsPerPage = parseInt($(this).val());
        localStorage.setItem('GSJTOP_jobsPerPage', GSJTOP.preferences.jobsPerPage);
        GSJTOP.preferences.currentPage = 0;
        GSJTOP.refreshWindow();
    });

    [4, 6, 8, 10].forEach(function(num) {
        jobsPerPageSelect.append($('<option/>', {
            value: num,
            text: num + (num === 1 ? ' praca' : num < 5 ? ' prace' : ' prac'),
            selected: GSJTOP.preferences.jobsPerPage === num
        }));
    });

    var tooltipsButton = $('<div/>', {
        id: 'gj-tooltips',
        title: GSJTOP.preferences.showTooltips ? 'UKRYJ INFORMACJE' : 'POKAŻ INFORMACJE', // Dodany tooltip
        css: {
            'width': '24px',
            'height': '24px',
            'background-color': GSJTOP.preferences.showTooltips ? '#4CAF50' : '#cccccc',
            'border-radius': '3px',
            'cursor': 'pointer',
            'transition': 'all 0.3s ease',
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)',
            'margin-right': '1px'
        }
    }).click(function() {
        GSJTOP.preferences.showTooltips = !GSJTOP.preferences.showTooltips;
        localStorage.setItem('GSJTOP_showTooltips', GSJTOP.preferences.showTooltips);
        $(this).css('background-color', GSJTOP.preferences.showTooltips ? '#4CAF50' : '#cccccc')
               .attr('title', GSJTOP.preferences.showTooltips ? 'UKRYJ INFORMACJE' : 'POKAŻ INFORMACJE'); // Aktualizacja tooltipa po kliknięciu
        GSJTOP.refreshWindow();
    });

 var visibilityButton = $('<div/>', {
        id: 'gsjtop-visibility-toggle', // Dodajmy ID dla łatwiejszego odniesienia (opcjonalne)
        title: 'Pokaż/Ukryj Mapę i Widoczność Prac', // Zaktualizujmy tooltip
        css: {
            'width': '24px',
            'height': '24px',
          'background-color': '#4a90e2',
            'border-radius': '3px',
            'cursor': 'pointer',
            'transition': 'all 0.3s ease',
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)',
            'margin-right': '1px',
            'background-size': '16px',
            'background-position': 'center',
            'background-repeat': 'no-repeat'
        }
     }).on('click', function() {
        // --- EDYCJA 1: Logika przełączania widoczności ---
        var visibilityPanel = $('#job-visibility-window');
        var mapWindow = $('#custom-map-window');

        // Sprawdź, czy którekolwiek z okien jest aktualnie otwarte
        if (visibilityPanel.length > 0 || mapWindow.length > 0) {
            // Jeśli tak, zamknij oba
            visibilityPanel.remove();
            mapWindow.remove();
            // Opcjonalnie: zmień wygląd przycisku na "nieaktywny"
            $(this).css({
                'background-color': '#4a90e2', // Wróć do domyślnego koloru
            });
        } else {
            // Jeśli nie, otwórz oba
             GSJTOP.createVisibilityWindow(); // Najpierw okno widoczności
            try {
                GSJTOP.createCustomMapWindow(); // Potem mapa
            } catch(e) {
                console.error('Błąd podczas tworzenia okna mapy:', e);
            }
            // Opcjonalnie: zmień wygląd przycisku na "aktywny"
             $(this).css('background-color', '#cccccc'); // Ciemniejszy niebieski jako wskaźnik aktywności
        }
    });

           var centerJobsFilter = $('<div/>', {
        title: this.preferences.hideCenterJobs ? 'POKAŻ PRACE PONIŻEJ 100 POZIOMU' : 'UKRYJ PRACE PONIŻEJ 100 POZIOMU', // Zmieniony tooltip
        css: {
            'width': '24px',
            'height': '24px',
            'cursor': 'pointer',
            'margin-right': '1px',
            'background-color': this.preferences.hideCenterJobs ? '#cccccc' : '#ff4444',
            'border-radius': '3px',
            'border': '1px solid rgba(0, 0, 0, 0.2)',
            'transition': 'all 0.3s ease',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)'
        }
    }).on('mouseenter', function() {
        $(this).css({
            'transform': 'scale(1.1)',
            'box-shadow': '0 2px 5px rgba(0, 0, 0, 0.2)'
        });
    }).on('mouseleave', function() {
        $(this).css({
            'transform': 'scale(1)',
            'box-shadow': '0 1px 3px rgba(0, 0, 0, 0.1)'
        });
    }).click(function() {
        var isCurrentlyActive = $(this).css('background-color') === 'rgb(204, 204, 204)';
        GSJTOP.preferences.hideCenterJobs = !isCurrentlyActive;
        localStorage.setItem('GSJTOP_hideCenterJobs', GSJTOP.preferences.hideCenterJobs);
        $(this).css({
            'background-color': isCurrentlyActive ? '#ff4444' : '#cccccc'
        }).attr('title', isCurrentlyActive ? 'UKRYJ PRACE PONIŻEJ 100 POZIOMU' : 'POKAŻ PRACE PONIŻEJ 100 POZIOMU'); // Zmieniony tooltip
        GSJTOP.preferences.currentPage = 0;
        GSJTOP.refreshWindow();
    });

    var goldFilter = $('<img/>', {
        src: 'images/jobs/featured/goldjob.png',
        css: {
            'width': '24px',
            'height': '24px',
            'opacity': showGold ? this.shownImageOpacity : this.hiddenImageOpacity,
            'cursor': 'pointer',
            'border': showGold ? '1px solid rgba(171, 153, 48, 0.5)' : 'none',
            'border-radius': '3px'
        },
        click: function() {
            GSJTOP.onJobIconFilterClick('gold', $(this));
        }
    });

    var silverFilter = $('<img/>', {
        src: 'images/jobs/featured/silverjob.png',
        css: {
            'width': '24px',
            'height': '24px',
            'opacity': showSilver ? this.shownImageOpacity : this.hiddenImageOpacity,
            'cursor': 'pointer',
            'border': showSilver ? '1px solid rgba(112, 128, 144, 0.5)' : 'none',
            'border-radius': '3px'
        },
        click: function() {
            GSJTOP.onJobIconFilterClick('silver', $(this));
        }
    });

   filterContainer.append(
        tooltipsButton,
        lowIdJobsFilter,
        hideHighIdJobsFilter,
        visibilityButton,
        silverFilter,
        goldFilter,
        jobsPerPageSelect
    );
    // Pobieramy zapisane ustawienia widoczności prac
    var hiddenJobs = JSON.parse(localStorage.getItem('GSJTOP_hiddenJobs') || '{}');

  var data = this.getFilteredData(showSilver, showGold);
    var start = this.preferences.currentPage * this.preferences.jobsPerPage;

    // Filtrujemy ukryte prace tylko dla głównego wyświetlania, nie dla panelu widoczności
    var visibleJobs = data.filter(job => !job.hidden);
    var pageJobs = visibleJobs.slice(start, start + this.preferences.jobsPerPage);

    pageJobs.forEach(function(job) {
        var jobData = GSJTOP.getJobData(job, job.silver);
        if (jobData) {
            jobsWrapper.append(GSJTOP.getJobIcon(job.jobId, job.x, job.y, job.shortname, job.gold, jobData));
        }
    });

    // Dla panelu widoczności pokazujemy wszystkie prace
    data.forEach(function(job) {
        var jobData = GSJTOP.getJobData(job, job.silver);
        if (jobData) {
            var checkbox = $('<input/>', {
                type: 'checkbox',
                id: 'job-visibility-' + job.jobId,
                checked: !job.hidden,
                css: {
                    'margin': '2px'
                }
            }).on('change', function() {
                var hiddenJobs = JSON.parse(localStorage.getItem('GSJTOP_hiddenJobs') || '{}');
                hiddenJobs[job.jobId] = !this.checked;
                localStorage.setItem('GSJTOP_hiddenJobs', JSON.stringify(hiddenJobs));
                GSJTOP.refreshWindow();
            });

            var label = $('<label/>', {
                for: 'job-visibility-' + job.jobId,
                text: job.shortname,
                css: {
                    'font-size': '11px',
                    'margin-right': '5px'
                }
            });

            jobVisibilityContainer.append($('<div/>').append(checkbox, label));
        }
    });

    container.append(jobsWrapper, filterContainer);
    return container;
};

    GSJTOP.onJobIconFilterClick = function (type, element) {
    var hiddenImageOpacity = this.hiddenImageOpacity;
    var shownImageOpacity = this.shownImageOpacity;

    var isCurrentlyActive = ($(element).css('opacity') == shownImageOpacity);
    var otherFilterActive = (type === 'gold') ? this.preferences.showSilver : this.preferences.showGold;

    if (isCurrentlyActive && !otherFilterActive) {
        return;
    }

    if (type === 'gold') {
        this.preferences.showGold = !isCurrentlyActive;
        localStorage.setItem('GSJTOP_showGold', this.preferences.showGold);
        $(element).css({
            'opacity': isCurrentlyActive ? hiddenImageOpacity : shownImageOpacity,
            'border': isCurrentlyActive ? 'none' : '1px solid rgba(171, 153, 48, 0.5)'
        });
    } else {
        this.preferences.showSilver = !isCurrentlyActive;
        localStorage.setItem('GSJTOP_showSilver', this.preferences.showSilver);
        $(element).css({
            'opacity': isCurrentlyActive ? hiddenImageOpacity : shownImageOpacity,
            'border': isCurrentlyActive ? 'none' : '1px solid rgba(112, 128, 144, 0.5)'
        });
    }

    this.preferences.currentPage = 0;
    this.refreshWindow();
};
    GSJTOP.openWindow = function () {
    if (!this.preferences.enabled) return;

    $('#goldJobs-bar').remove();

    var bar = $('<div/>', {
        id: 'goldJobs-bar',
        css: {
            'position': 'fixed',
            'background': 'rgba(255, 255, 255, 0.0)',
            'border': 'none',
            'padding': '0px',
            'z-index': 10000,
            'display': 'flex',
            'flex-direction': 'row',
            'align-items': 'center',
            'justify-content': 'center',
            'width': '100%',
            'height': '130px',
            'left': '0',
            'right': '0',
            'top': '20px',
            'margin': '0 auto',
            'pointer-events': 'none'
        }
    });

    var contentWrapper = $('<div/>', {
        css: {
            'display': 'flex',
            'justify-content': 'center',
            'align-items': 'center',
            'width': 'auto',
            'margin': '0 auto',
            'pointer-events': 'auto',
            'position': 'relative'
        }
    });

var navigation = this.createNavigationButtons();
    var jobsContainer = this.createJobsContainer(this.preferences.showSilver, this.preferences.showGold);

    contentWrapper.append(navigation.prev, jobsContainer, navigation.next);
    bar.append(contentWrapper);
    $('#ui_topbar').append(bar);

    $(document).on('position_change', GSJTOP.refreshWindow);
};

GSJTOP.getAllTiles = function (callback) {
    Ajax.get('map', 'get_minimap', {}, function (r) {
        if (r.error) {
            return;
        }
        var result = [];
        var jobGroups = r.job_groups,
        i,
        j;
        for (i in jobGroups) {
            for (j in jobGroups[i]) {
                var coords = jobGroups[i][j];
                var xTile = Math.floor(coords[0] / GameMap.tileSize);
                var yTile = Math.floor(coords[1] / GameMap.tileSize);
                if (!result.hasOwnProperty(xTile)) {
                    result[xTile] = {};
                }
                result[xTile][yTile] = 1;
            }
        }
        GSJTOP.tilesWithJobs = result;
        callback();
    });
};
GSJTOP.getFilteredData = function (showSilver, showGold) {
    var jobs = GameMap.JobHandler.Featured;
    var k, jobId, job, j;
    var result = [];
    var hiddenJobs = JSON.parse(localStorage.getItem('GSJTOP_hiddenJobs') || '{}');

    try {
        for (k in jobs) {
            var jobPlace = jobs[k];
            for (jobId in jobPlace) {
                job = JobList.getJobById(jobId);
                if (!job) continue;

                j = jobPlace[jobId];
                if ((j.silver && !showSilver) || (j.gold && !showGold)) {
                    continue;
                }

                if (this.preferences.hideLowIdJobs && parseInt(jobId) < 131) {
                    continue;
                }

                // Dodajemy wszystkie prace do rezultatu, ale oznaczamy je jako ukryte
                var distance = 0;
                try {
                    distance = this.calculateDistance(j.x, j.y);
                } catch (e) {}

                var motivation = 0;
                try {
                    var jobData = JobsModel.Jobs.find(jb => jb.id === parseInt(jobId));
                    if (jobData) {
                        motivation = Math.round(jobData.jobmotivation * 100);
                    }
if (this.preferences.hideHighIdJobs && parseInt(jobId) > 160) {
                continue;
            }
                } catch (e) {}

                result.push({
                    jobId: jobId,
                    x: j.x,
                    y: j.y,
                    shortname: job.shortname,
                    gold: j.gold,
                    silver: j.silver,
                    distance: distance,
                    motivation: motivation,
                    hidden: hiddenJobs[jobId] // Dodajemy flagę hidden
                });
            }
        }

        // Sortowanie według odległości
        result.sort(function(a, b) {
            if (a.distance !== b.distance) {
                return a.distance - b.distance;
            }
            return parseInt(a.jobId) - parseInt(b.jobId);
        });
    } catch (e) {}

    return result;
};


GSJTOP.refreshWindow = function () {
    if (!GSJTOP.preferences.enabled) {
        $('#goldJobs-bar').remove();
        return;
    }

    Ajax.get('work', 'index', {}, function(response) {
        if (response.error) {
            return;
        }

        JobsModel.initJobs(response.jobs);

        // Pobierz aktualną liczbę widocznych prac
        var visibleJobs = GSJTOP.getFilteredData(GSJTOP.preferences.showSilver, GSJTOP.preferences.showGold)
            .filter(job => !job.hidden);
        var totalJobs = visibleJobs.length;
        var maxPages = Math.ceil(totalJobs / GSJTOP.preferences.jobsPerPage);

        // Aktualizuj przyciski nawigacji
        var updateButtonStyles = function() {
            var prevButton = $('#goldJobs-bar .jobs-container').prev();
            var nextButton = $('#goldJobs-bar .jobs-container').next();

            if (GSJTOP.preferences.currentPage <= 0) {
                prevButton.css('opacity', '0.5').css('cursor', 'default');
            } else {
                prevButton.css('opacity', '1').css('cursor', 'pointer');
            }

            if (GSJTOP.preferences.currentPage >= maxPages - 1 || maxPages <= 1) {
                nextButton.css('opacity', '0.5').css('cursor', 'default');
            } else {
                nextButton.css('opacity', '1').css('cursor', 'pointer');
            }
        };

        // Wymień kontener z pracami
        var newContainer = GSJTOP.createJobsContainer(GSJTOP.preferences.showSilver, GSJTOP.preferences.showGold);
        $('#goldJobs-bar .jobs-container').replaceWith(newContainer);

        // Aktualizuj style przycisków
        updateButtonStyles();
    });
};
GSJTOP.createCustomMapWindow = function() {
    // Sprawdź czy okno już istnieje
    if ($('#custom-map-window').length > 0) return;

    var self = this; // Zapisz referencję do GSJTOP

    // Okno główne (kontener z ramką w stylu TW)
   var mapWindow = $('<div/>', {
        id: 'custom-map-window',
        css: {
            'position': 'fixed',
            'top': '50%',
            'left': '50%', // Lewa krawędź okna mapy na środku
            // Tylko centrowanie w pionie, bez przesunięcia poziomego
            'transform': 'translateY(-50%)',
            'background': 'linear-gradient(to bottom, #4d351b 0%, #2a1608 100%)',
            'padding': '15px', // Padding bez zmian
            'border-radius': '5px',
            'border': '2px solid #1b0a00',
            'border-top-color': '#150800',
            'border-left-color': '#150800',
            'box-shadow': '0 4px 15px rgba(0, 0, 0, 0.7), inset 0 0 5px rgba(0,0,0,0.2)',
            'z-index': 10003,
            // Szerokość okna wynika z szerokości mapContent i paddingu
        }
    });


    // Kontener na samą mapę i znaczniki
    var mapContent = $('<div/>', {
        css: {
            'width': '770px',
            'height': '338px',
            'position': 'relative',
            'margin': '0 auto',
            'overflow': 'hidden',
            'background-color': 'white',
            'border': '1px solid #333' // Ciemna ramka mapy
        }
    });

    // Definicje hrabstw (kafelków mapy)
    var counties = [
        {id: 1, left: 0, top: 0, width: 110, height: 169},
        {id: 2, left: 110, top: 0, width: 110, height: 169},
        {id: 3, left: 220, top: 0, width: 110, height: 169},
        {id: 4, left: 330, top: 0, width: 110, height: 114},
        {id: 5, left: 440, top: 0, width: 110, height: 169},
        {id: 6, left: 550, top: 0, width: 110, height: 169},
        {id: 7, left: 660, top: 0, width: 110, height: 169},
        {id: 8, left: 0, top: 169, width: 110, height: 169},
        {id: 9, left: 110, top: 169, width: 110, height: 169},
        {id: 10, left: 220, top: 169, width: 110, height: 169},
        {id: 11, left: 330, top: 224, width: 110, height: 114},
        {id: 12, left: 440, top: 169, width: 110, height: 169},
        {id: 13, left: 550, top: 169, width: 110, height: 169},
        {id: 14, left: 660, top: 169, width: 110, height: 169},
        {id: 15, left: 330, top: 114, width: 110, height: 110}
    ];

    // Tworzenie kafelków mapy jako elementy <img>
    counties.forEach(function(county) {
        $('<img>', {
            src: 'https://westpl.innogamescdn.com/images/map/minimap/county_' + county.id + '.jpg',
            css: {
                'position': 'absolute',
                'left': county.left + 'px',
                'top': county.top + 'px',
                'width': county.width + 'px',
                'height': county.height + 'px',
                'border': '1px solid #000'
            }
        }).appendTo(mapContent);
    });

    // Pobierz dane o pracach
    var data = self.getFilteredData(self.preferences.showSilver, self.preferences.showGold);

    // Ustawienia mapy i markerów
    var maxX = 46592;
    var maxY = 20480;
    var mapWindowWidth = 770;
    var mapWindowHeight = 338;
    var markerSize = 24;
    var markerOffset = markerSize / 2;

    // Dodaj markery prac na mapie
    data.forEach(function(job) {
        if (!job.hidden) {
            var markerLeft = (job.x / maxX * mapWindowWidth) - markerOffset;
            var markerTop = (job.y / maxY * mapWindowHeight) - markerOffset;

            // Utwórz element markera (div)
            var marker = $('<div/>', {
                title: job.name, // Użyj przetłumaczonej nazwy pracy jako tooltip
                css: {
                    'position': 'absolute',
                    'left': markerLeft + 'px',
                    'top': markerTop + 'px',
                    'width': markerSize + 'px',
                    'height': markerSize + 'px',
                    'cursor': 'pointer',
                    'z-index': 10004,
                    'border-radius': '50%',
                }
            }).append($('<img/>', { // Dodaj ikonę pracy do markera
                src: 'https://westpl.innogamescdn.com/images/jobs/' + job.shortname + '.png',
                css: {
                    'width': '100%',
                    'height': '100%'
                }
            }));

            // Dodaj obramowanie/cień w zależności od typu pracy
            if (job.gold) {
                marker.css('box-shadow', '0 0 5px 2px gold');
            } else if (job.silver) {
                marker.css('box-shadow', '0 0 5px 2px silver');
            } else {
                 marker.css('box-shadow', '0 0 3px rgba(0,0,0,0.5)');
            }

            // Dodaj akcję kliknięcia
            marker.click(function() {
                if (typeof GameMap !== 'undefined' && GameMap.center) {
                    GameMap.center(job.x, job.y);
                }
                mapWindow.remove();
            });

            // Dodaj marker do kontenera mapy
            mapContent.append(marker);
        }
    });

  

    // Dodaj mapContent i closeButton do mapWindow
    mapWindow.append(mapContent);

    // Dodaj całe okno mapy do strony
    $('body').append(mapWindow);
};
    GSJTOP.init = function () {
    if (!GSJTOP.preferences.enabled) return;

    var onLoad = function () {
        Ajax.get('work', 'index', {}, function(response) {
            if (response.error) {
                return;
            }

            JobsModel.initJobs(response.jobs);
            GSJTOP.preferences.currentPage = 0;
            GSJTOP.openWindow();
            GSJTOP.dataLoaded = true;
            GSJTOP.startAutoRefresh();
        });
    };

    if (!GSJTOP.hasOwnProperty('tilesWithJobs')) {
        new UserMessage(GSJTOPlang.loading, UserMessage.TYPE_HINT).show();
        GSJTOP.getAllTiles(function () {
            GSJTOP.parseWholeMap(GSJTOP.tilesWithJobs, onLoad);
        });
    } else {
        onLoad();
    }
};
GSJTOP.gui = {};
GSJTOP.gui.init = function () {};

// Inicjalizacja przy załadowaniu dokumentu
$(document).ready(function () {
    try {
        GSJTOP.gui.init();
        GSJTOP.createToggleCheckbox();
        if (GSJTOP.preferences.enabled) {
            GSJTOP.init();
        }
    } catch (e) {
        // Usunięto log błędu
    }
});

}); // Zamknięcie głównej funkcji

// Skrypt usuwający element first-purchase
    function usuńFirstPurchase() {
        const element = document.querySelector('.first-purchase');
        if (element) {
            element.remove();
        } else {
            clearInterval(intervalId);
        }
    }
    const intervalId = setInterval(usuńFirstPurchase, 1000);

// Funkcja do stworzenia słownika tłumaczeń z API gry
function createJobTranslations() {
    const translations = {};
    JobList.getSortedJobs().forEach(job => {
        // Tworzymy klucz w formacie takim jak w oryginalnym ID (np. 'picking_mushrooms')
        const englishKey = job.id.toString();
        translations[englishKey] = job.name;
    });
    return translations;
}

// Używamy w skrypcie
const jobTranslations = createJobTranslations();

// Funkcja do zamiany nazw w interfejsie
document.querySelectorAll('#job-visibility-window label').forEach(label => {
    const jobId = label.getAttribute('for').split('-')[2]; // Pobieramy ID z atrybutu 'for'
    if (jobTranslations[jobId]) {
        label.textContent = jobTranslations[jobId];
    }
});


// Funkcja do tłumaczenia okna widoczności prac
function translateJobVisibilityWindow() {
    const translations = {};
    JobList.getSortedJobs().forEach(job => {
        translations[job.id] = job.name;
    });

    const labels = document.querySelectorAll('#job-visibility-window label');
    labels.forEach(label => {
        const jobId = label.getAttribute('for').split('-')[2];
        if (translations[jobId]) {
            label.textContent = translations[jobId];
        }
    });
}

// Obserwator do wykrywania okna widoczności
const jobVisibilityObserver = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
        if (mutation.addedNodes && mutation.addedNodes.length > 0) {
            mutation.addedNodes.forEach((node) => {
                if (node.id === 'job-visibility-window') {
                    setTimeout(translateJobVisibilityWindow, 100);
                }
            });
        }
    });
});

// Uruchomienie obserwatora
jobVisibilityObserver.observe(document.body, {
    childList: true,
    subtree: true
});

// Dodanie stylów dla paska przewijania w Chrome/Safari
$('<style>')
    .text(`
        #job-visibility-window div::-webkit-scrollbar {
            width: 8px;
        }
        #job-visibility-window div::-webkit-scrollbar-track {
            background: #f0f0f0;
        }
        #job-visibility-window div::-webkit-scrollbar-thumb {
            background: #888;
            border-radius: 4px;
        }
        #job-visibility-window div::-webkit-scrollbar-thumb:hover {
            background: #666;
        }
    `)
    .appendTo('head');

})();