florr.io | Playtime counter

Shows how no life you are

As of 2023-05-02. See the latest version.

// ==UserScript==
// @name         florr.io | Playtime counter
// @version      1.1.4
// @description  Shows how no life you are
// @author       Furaken
// @match        https://florr.io/*
// @grant        unsafeWindow
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js
// @namespace https://github.com/Samer-Kizi
// ==/UserScript==

var totalServers = 17 - 1
var today = new Date().toString().substring(0,15)
var leech = [{"date":today,"value":0,map:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}],
    cvs = document.querySelector('canvas')
var newDoc = document.createElement('div')
newDoc.style = `
    right: 6px;
    bottom: -3px;
    color: white;
    text-shadow: rgb(0, 0, 0) 2px 0px 0px, rgb(0, 0, 0) 1.75517px 0.958851px 0px, rgb(0, 0, 0) 1.0806px 1.68294px 0px, rgb(0, 0, 0) 0.141474px 1.99499px 0px, rgb(0, 0, 0) -0.832294px 1.81859px 0px, rgb(0, 0, 0) -1.60229px 1.19694px 0px, rgb(0, 0, 0) -1.97998px 0.28224px 0px, rgb(0, 0, 0) -1.87291px -0.701566px 0px, rgb(0, 0, 0) -1.30729px -1.5136px 0px, rgb(0, 0, 0) -0.421592px -1.95506px 0px, rgb(0, 0, 0) 0.567324px -1.91785px 0px, rgb(0, 0, 0) 1.41734px -1.41108px 0px, rgb(0, 0, 0) 1.92034px -0.558831px 0px;
    position: absolute;
    z-index: 1;
    font-family: Ubuntu;
    line-height: 0px;
    text-align: right;
    pointer-events: none;
`
document.querySelector('body').appendChild(newDoc)

if (localStorage.getItem("florrTime") === null) localStorage.setItem('florrTime', JSON.stringify(leech))
if (JSON.parse(localStorage.getItem("florrTime"))[0].date != today) {
    let x = JSON.parse(localStorage.getItem('florrTime'))
    x.unshift({"date":today,"value":0,map:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]})
    localStorage.setItem('florrTime', JSON.stringify(x));
}
if (JSON.parse(localStorage.getItem("florrTime"))[0].map == undefined) {
    let x = JSON.parse(localStorage.getItem('florrTime'))
    x[0].map = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    localStorage.setItem('florrTime', JSON.stringify(x));
}
var url
const nativeWebSocket = unsafeWindow.WebSocket;
unsafeWindow.WebSocket = function(...args){
    const socket = new nativeWebSocket(...args);
    url = socket.url
    return socket;
};
var start = Date.now() - Number(JSON.parse(localStorage.getItem("florrTime"))[0].value) * 1000,
    time,
    allTime = 0,
    allTimeA,
    stop = false,
    servers = [],
    indexV,
    start2,
    urlA = [],
    delta2

function Time(seconds) {
    var hoursLeft = Math.floor(seconds / 3600);
    var min = Math.floor((seconds - hoursLeft * 3600) / 60);
    var secondsLeft = seconds - hoursLeft * 3600 - min * 60;
    secondsLeft = Math.round(secondsLeft * 100) / 100;
    var answer = hoursLeft< 10 ? "0" + hoursLeft : hoursLeft;
    answer += ":" + (min < 10 ? "0" + min : min);
    answer += ":" + (secondsLeft< 10 ? "0" + secondsLeft : secondsLeft);
    return answer
}
for (let i = 0; i <= totalServers; i++) {
    fetch("https://api.n.m28.io/endpoint/florrio-map-" + i + "-green/findEach/").then((response) => response.json()).then((data) => {
        servers[i] = `${data.servers["vultr-miami"].id} ${data.servers["vultr-frankfurt"].id} ${data.servers["vultr-tokyo"].id}`
    })
}
setInterval(function() {
    if (stop) {
        start = Date.now()
        stop = false
    } else {
        var delta = Date.now() - start,
            start2 = JSON.parse(localStorage.getItem('florrTime'))[0].value
        let x = JSON.parse(localStorage.getItem('florrTime'))
        x[0].value = Math.floor(delta / 1000)
        time = Time(Math.floor(Number(x[0].value)))
        x.forEach(k => {allTime += Number(k.value)})
        allTimeA = Time(Math.floor(Number(allTime)))
        localStorage.setItem('florrTime', JSON.stringify(x));
        newDoc.innerHTML = `<p style="font-size:12px">Since ${JSON.parse(localStorage.getItem('florrTime')).at(-1).date}:  ${allTimeA}</p><p style="font-size:20px">${time}</p>`
        allTime = 0
        delta2 = JSON.parse(localStorage.getItem('florrTime'))[0].value - start2
        var xyz = JSON.parse(localStorage.getItem("florrTime"))
        xyz[0].map[indexV] += delta2
        localStorage.setItem('florrTime', JSON.stringify(xyz));
        urlA.unshift(url)
        if (urlA.length > 2) urlA.splice(2)
        if (urlA.at(-1) != urlA[0]) {
            start2 = JSON.parse(localStorage.getItem('florrTime'))[0].value
            servers.forEach(function callback(x, index) {
                if (x.includes(url.slice(6, 9))) indexV = index
            });
        }
    }
}, 1000)

var chartCon = document.createElement('div')
chartCon.style = `
    width: 100%;
    height: 100%;
    position: absolute;
    z-index: 100;
    font-family: Ubuntu;
    top: 0;
    margin: 0;
    opacity: 0;
    pointer-events: none;
    transition: 0.4s ease-in-out;
`
chartCon.innerHTML = `
    <canvas id="chartCtx" style="background: rgba(255, 255, 255, 0.9);padding: 50px;font-family: Ubuntu;transition: 0.4s ease-in-out;position: absolute;z-index: 1;"></canvas>
    <canvas id="chartCtx2" style="background: rgba(255, 255, 255, 0.9);padding: 50px;font-family: Ubuntu;;transition: 0.4s ease-in-out;position: absolute;"></canvas>
`
document.querySelector('body').appendChild(chartCon)

Chart.defaults.font.family = 'Ubuntu';
Chart.defaults.font.size = 16;
var chart = new Chart(document.getElementById('chartCtx'), {
    type: 'line',
    data: {
        labels: null,
        datasets: null
    },
    options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
            title: {
                text: 'Playtime (Month)',
                display: true
            }
        },
        scales: {
            x: {
                title: {
                    display: true,
                    text: 'Date'
                }
            },
            y: {
                title: {
                    display: true,
                    text: 'Hours'
                }
            }
        },
    },
});

var chart2 = new Chart(document.getElementById('chartCtx2'), {
    type: 'doughnut',
    data: {
        labels: null,
        datasets: null
    },
    options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
            title: {
                text: 'Playtime (Hours)',
                display: true
            }
        },
    },
});

function updateData() {
    var data = [],
        labels = [],
        labels2 = [],
        mapData = [],
        allMap = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]],
        localStr = JSON.parse(localStorage.getItem("florrTime")),
        len = 30,
        pieMapData = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        colorRandomPie = []

    function be(date) {
        return date.slice(8, 10) + "/" + (new Date(Date.parse(date.slice(4, 7) + " 1, 2012")).getMonth() + 1) + "/" + date.slice(-4)
    }

    for (let i = 0; i <= totalServers; i++) {
        labels2.push('MAP'+i)
    }
    if (localStr.length < 30) len = localStr.length
    for (let i = 0; i < len; i++) {
        data.unshift(localStr[i].value / 3600)
        labels.unshift(be(localStr[i].date))
        mapData.unshift(localStr[i].map)
    }
    mapData.forEach(x => {
        for (let i = 0; i <= totalServers; i++) {
            if (x == undefined) x = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
            allMap[i].push(x[i] / 3600)
            pieMapData[i] += (x[i] / 3600)
        }
    })
    var colorPalette = [
        "#067A69",
        "#09BB9F",
        "#39F3BB",
        "#18A1CD",
        "#1D81A2",
        "#15607A",
        "#003f5c",
        "#2f4b7c",
        "#665191",
        "#a05195",
        "#d45087",
        "#f95d6a",
        "#ff7c43",
        "#ffa600",
        "#DE6D12",
        "#C27A24",
        "#A68736"
        ]
    var chartObj = [{ label: 'All', data: data, fill: true, borderColor: 1, borderWidth: 4, tension: 0.3 }],
        color
    for (let i = 0; i <= totalServers; i++) {
        chartObj.push({ "label": "MAP" + i, "data": allMap[i], "fill": true, "backgroundColor": colorPalette[i] + "1A", "borderColor": colorPalette[i], "borderWidth": 2.5, "tension": 0.3 })
        localStr[0].map[i] = localStr[0].map[i] / 3600
    }
    chart.data.datasets = chartObj
    chart.data.labels = labels
    chart.update()

    chart2.data.labels = labels2
    chart2.data.datasets = [
        {
            label: 'Latest 30 Days',
            data: pieMapData,
            backgroundColor: colorPalette,
            hoverOffset: 10
        },
        {
            label: 'Today',
            data: localStr[0].map,
            backgroundColor: colorPalette,
            hoverOffset: 10
        }
    ]
    chart2.update()
}
document.documentElement.addEventListener("keydown", function() {
    if (event.keyCode === 191 && event.ctrlKey && event.shiftKey) {
        if (confirm("Confirm reset all")) {
            stop = true;
            localStorage.setItem('florrTime', JSON.stringify(leech))
        }
    }
    else if (event.keyCode === 186) newDoc.style.display = newDoc.style.display === 'none' ? '' : 'none'
    else if (event.keyCode === 220) {
        if (chartCon.style.opacity == '0') {
            chartCon.style.opacity = '1'
            chartCon.style.pointerEvents = 'all'
            updateData()
        } else {
            chartCon.style.opacity = '0'
            chartCon.style.pointerEvents = 'none'
        }
    }
    else if (event.keyCode === 221) {
        var x = document.getElementById('chartCtx')
        x.style.zIndex = x.style.zIndex === '1' ? '-1' : '1'
    }
});