Мониторинг неактивов на карте

  • Автор темы DeletedUser45987
  • Дата начала

DeletedUser45987

Гость
Обновленный скрипт на тест. вроде не должен перерисовывать. + добавил чекбокс чтоб в спид мирах сузить диапазон времени по которому скрипт красит игроков. регулируется это в самом начале скрипта var speedMul = 100 (означает уменьшить диапазон времени на 100 раз).
PS1: Отсчет пойдет сначала, не использует хранилище первого скрипта.
PS2: Работает на хроме, на остальных незнаю.
PS3: Возможно позже первый скрипт (который по прямой ссылке) заменю этим.
Код:
javascript:
var speedMul = 100;

var utils =
{
    ServerTimeAsMs: function()
    {
        var serverTime = $("#serverTime").text().split(":");
        var serverDate = $("#serverDate").text().split("/");
        return new Date(serverDate[2], serverDate[1] - 1, serverDate[0], serverTime[0], serverTime[1], serverTime[2]).getTime();
    },
    FormatMilliseconds: function(ms)
    {
        var format = function (value) { return ((value < 10) ? "0" : "") + value; };
        var sec = ms / 1000;
        var days = Math.floor(sec / 86400);
        var hours = Math.floor((sec % 86400) / 3600);
        var minutes = Math.floor(((sec % 86400) % 3600) / 60);
        var seconds = ((sec % 86400) % 3600) % 60;
        return format(days) + " дней " + format(hours) + ":" + format(minutes) + ":" + format(seconds) + " часов назад";
    },
    ElapsedFrom: function(ms)
    {
        return this.ServerTimeAsMs() - ms;
    }
};

var colors = function()
{
    var minutes =
    {
        in1Day: 24 * 60,
        in2Days: 24 * 60 * 2,
        in5Days: 24 * 60 * 5,
        in7Days: 24 * 60 * 7
    };

    this.Default = function()
    {
        return [0, 0, 0];
    };
    
    this.Activity = function(elapsed)
    {
        var rgb = [0, 0, 0];
        var per = 0;
        
        if(elapsed >= minutes.in7Days)
        {
            rgb[0] = 255;
        }
        else if(elapsed >= minutes.in2Days)
        {
            per = 255 / minutes.in5Days;
            rgb[0] = 255;
            rgb[1] = 255 - Math.floor(elapsed * per);
        }
        else
        {
            per = 200 / minutes.in2Days;
            rgb[0] = 55 + Math.floor(elapsed * per);
            rgb[1] = rgb[0];
        }
        
        return rgb;
    };
    this.Downgraded = function()
    {
        return [ 0, 255, 0 ];
    };
    this.GetColor = function(difference, ms)
    {
        if(difference < 0) return this.Downgraded();
        return this.Activity(ms);
    };
    return this;
}.call(this);

var Player = function(data)
{
    this.id = data.id;
    this.points = data.points;
    this.changedPoints = data.changedPoints ? data.changedPoints : 0;
    this.changedTimeMs = data.changedTimeMs ? data.changedTimeMs : utils.ServerTimeAsMs();

    this.UpdateIfChanged = function(data)
    {
        var parse = function(string) { return parseInt(string.replace(".", "")); };
        var difference = parse(data.points) - parse(this.points);
        if(difference != 0)
        {
            this.points = data.points;
            this.changedPoints = difference;
            this.changedTimeMs = utils.ServerTimeAsMs();
        }
    };
};

var Players = function(data)
{
    var self = this;
    Object.keys(data).forEach(function(id){
        data[id].id = id;
        self[id] = new Player(data[id]);
    });
};

var playersRepository = function()
{
    var storageName = "Activity_" + window.game_data.world;

    this.GetPlayers = function()
    {
        var string = localStorage[storageName];
        return new Players(string != undefined ? JSON.parse(string) : {});
    };

    this.SavePlayers = function(players)
    {
        string = JSON.stringify(players);
        localStorage[storageName] = string;
    };

    return this;
}.call(this);

var Polymorphism = function(methodName, context, newMethod)
{
    this.method = context[methodName];

    this.InvokeBase = function()
    {
        this.method.apply(context, arguments);
    };
    this.Override = function()
    {
        context[methodName] = newMethod;
    };
    this.Restore = function()
    {
        context[methodName] = this.method;
    };
};

var mapExtension = function()
{
    var self = this;
    var isSpeed = false;
    var onDragEnd = new Polymorphism("onDragEnd", TWMap.mapHandler, function(e, a) {
        onDragEnd.InvokeBase(e, a);
        self.DrawActivity();
    });
    var displayForVillage = new Polymorphism("displayForVillage", TWMap.popup, function(village, x, y){
        displayForVillage.InvokeBase(village, x, y);

        var id = parseInt(village.owner);
        var fields = function()
        {
            x = x - game_data.village.x;
            y = y - game_data.village.y;
            return Math.round(Math.sqrt( (x * x) + (y * y)));
        }.call();

        if(id > 0)
        {
            var player = playersRepository.GetPlayers()[id];
            var lastGrowTime = utils.FormatMilliseconds(utils.ElapsedFrom(player.changedTimeMs));
            $('#info_owner_row').after(`
                <tr>
                    <td><b>Очки роста:</b></td>
                    <td style="color: green;">` + player.changedPoints +`</td>
                 </tr>
                 <tr>
                    <td><b>Последняя активность:</b></td>
                    <td style="color: green;">` + lastGrowTime + `</td>
                 </tr>
            `);
        }
        $("#info_points_row").after(`
            <tr>
                <td><b>Расстояние:</b></td>
                <td>` + fields + `</td>
            </tr>
        `);
    });

    this.DrawActivity = function()
    {
        var players = playersRepository.GetPlayers();
        var mapPlayers = TWMap.players;
        var playerColor = colors.Default();
        Object.keys(mapPlayers).forEach(function(id) {
            var player = players[id];
            if(player != undefined)
            {
                player.UpdateIfChanged(mapPlayers[id]);
                var minutes = utils.ElapsedFrom(player.changedTimeMs) / 60000;
                playerColor = colors.GetColor(player.changedPoints, isSpeed ? minutes * speedMul : minutes);
            }
            else players[id] = new Player(mapPlayers[id]);
            TWMap.playerColors[id] = playerColor;
        }, this);
        playersRepository.SavePlayers(players);
        TWMap.reload();
    };

    this.Enable = function()
    {
        onDragEnd.Override();
        displayForVillage.Override();
        self.DrawActivity();
    };
    this.Disable = function()
    {
        onDragEnd.Restore();
        displayForVillage.Restore();
    };

    var checkbox = `
        <tr>
            <td><input type="checkbox" name="is_speed_server"></td>
            <td>Спид сервер</td>
        </tr>
    `;
    $("#content_value").prepend(checkbox);
    $("input[name=is_speed_server]").on("click", function() { isSpeed = this.checked; self.DrawActivity(); } );

    return this;
}.call(this);

mapExtension.Enable();
 

JSmith

Новичок
Оценка реакций
2
Код:
javascript:
let canUpdateMinutes = 30;
let Polymorphism = function(methodName, context, newMethod) {
    this.method = context[methodName];

    this.invokeBase = function() { return this.method.apply(context, arguments);
    };
    this.override = function() { context[methodName] = newMethod; return this;
    };
    this.restore = function() { context[methodName] = this.method; return this;
    };
};

String.prototype.removeSubstring = function(string) { return this.replaceAll(string, ""); };
String.prototype.toInt = function() { let int = parseInt(this); return isNaN(int) ? 0 : int; };

var MI = {
    Utils: {
        getServerTime() {
            let serverTime = document.querySelector("#serverTime").textContent.split(":");
            let serverDate = document.querySelector("#serverDate").textContent.split("/");
            return new Date(serverDate[2], serverDate[1] - 1, serverDate[0], serverTime[0], serverTime[1], serverTime[2]).getTime();
        },
        formatMS(ms) {
            let format = function (value) { return ((value < 10) ? "0" : "") + value; };
            let sec = ms / 1000;
            let days = Math.floor(sec / 86400);
            let hours = Math.floor((sec % 86400) / 3600);
            let minutes = Math.floor(((sec % 86400) % 3600) / 60);
            let seconds = ((sec % 86400) % 3600) % 60;
            let daysString = " дней ";
            let hoursString = " часов назад";
            return format(days) + daysString + format(hours) + ":" + format(minutes) + ":" + format(seconds) + hoursString;
        },
        getFields(x, y) {
            x = x - game_data.village.x; y = y - game_data.village.y;
            return Math.round(Math.sqrt( (x * x) + (y * y)));
        },
        toInt(string) { let int = parseInt(string); return isNaN(int) ? 0 : int; }
    },
    Colors: {
        Minutes: {
            in1Day: 24 * 60,
            in2Days: 24 * 60 * 2,
            in5Days: 24 * 60 * 5,
            in7Days: 24 * 60 * 7
        },
        default() { return [ 0, 0, 0 ]; },
        accountColor() { return [ 255, 255, 255 ]; },
        downgradedColor() { return [ 0, 255, 0 ]; },
        getActivityColor(player) {
            let elapsedMins = Math.round(player.inactiveTime / 1000 / 60);
            let rgb = this.default();
            let per = 0;
            
            if(elapsedMins >= this.Minutes.in7Days) {
                rgb[0] = 255;
            }
            else if(elapsedMins >= this.Minutes.in2Days) {
                per = 255 / this.Minutes.in5Days;
                rgb[0] = 255;
                rgb[1] = 255 - Math.floor(elapsedMins * per);
            }
            else {
                per = 200 / this.Minutes.in2Days;
                rgb[0] = 55 + Math.floor(elapsedMins * per);
                rgb[1] = rgb[0];
            }
            return rgb;
        },
        getPlayerColor(player) {
            if(player.isDowngraded) return this.downgradedColor();
            else return this.getActivityColor(player);
        }
    },

    Repository: {
        name:  "__MI_Players",
        load() { return JSON.parse(localStorage[this.name] ?? "{}"); },
        save(data) { localStorage[this.name] = JSON.stringify(data); }
    },

    Handlers: {
        displayForVillage(village, x, y) {
            let fields = MI.Utils.getFields(x, y);
            let id = village.owner.toInt == undefined ? 0 : village.owner.toInt();
            let html = `
                <tr>
                    <td><b>Расстояние:</b></td>
                    <td>` + fields + `</td>
                </tr>`;
            if(id > 0) {
                let player = MI.Repository.load()[id];
                html = `
                <tr>
                    <td><b>Очки роста:</b></td>
                    <td style="color: green;">` + player.changedPoints +`</td>
                </tr>
                <tr>
                    <td><b>Последняя активность:</b></td>
                    <td style="color: green;">` + MI.Utils.formatMS(MI.Utils.getServerTime() - player.updatedTime) + `</td>
                </tr>` + html;
            }
            let element = document.querySelector("#info_points_row");
            if(element) element.outerHTML = element.outerHTML + html;
        }
    },

    Local: {
        serverTime: 0,
        every: canUpdateMinutes * 60 * 1000,
        playerFromSource(source) {
            return {
                points: source.points.removeSubstring(".").toInt(),
                changedPoints: 0,
                isDowngraded: false,
                updatedTime: this.serverTime,
                inactiveTime: 0
            };
        },
        playerWithChanges(player, source) {
            let points = source.points.removeSubstring(".").toInt();
            player.changedPoints = points - player.points;
            player.isDowngraded = player.changedPoints < 0;
            if(player.points != points) {
                player.points = points;
                player.updatedTime = this.serverTime;
            }
            player.inactiveTime = this.serverTime - player.updatedTime;
            return player;
        },
        updatePlayer(player, source) {
            if(!player) return this.playerFromSource(source);
            let elapsed = this.serverTime - player.updatedTime;
            return elapsed >= this.every ? this.playerWithChanges(player, source) : player;
        },

        updateMapPlayers() {
            this.serverTime = MI.Utils.getServerTime();

            let players = MI.Repository.load();
            Object.keys(TWMap.players).forEach(function(id) {
                players[id] = this.updatePlayer(players[id], TWMap.players[id]);
                TWMap.playerColors[id] = MI.Colors.getPlayerColor(players[id]);
            }.bind(this));
            TWMap.playerColors[game_data.player.id] = MI.Colors.accountColor();

            MI.Repository.save(players);
            TWMap.reload();
        }
    },

    initHandlers() {
        let displayForVillage = new Polymorphism("displayForVillage", TWMap.popup, function(village, x, y) {
            displayForVillage.invokeBase(village, x, y);
            this.Handlers.displayForVillage(village, x, y);
        }.bind(this)).override();
        let onDragEnd = new Polymorphism("onDragEnd", TWMap.mapHandler, function(e, a) {
            onDragEnd.invokeBase(e, a);
            this.Local.updateMapPlayers();
        }.bind(this)).override();
        
    },

    execute() {
        this.Local.updateMapPlayers();
        this.initHandlers();
    },
};

MI.execute();

Тестируйте. Вроде пофиксил работоспособность.
+ добавил задержку между обновлением сохраненных данных, чтоб не перерисовывал, т.к. игра сама может прислать разное количество очков для одного и того же игрока. задержка 30 мин.
 
Верх