Greasy Fork is available in English.

florr.io | Playtime counter

Shows how no life you are

// ==UserScript==
// @name         florr.io | Playtime counter
// @namespace    Furaken
// @version      2.0.4
// @description  Shows how no life you are
// @author       Furaken / sk
// @match        https://florr.io/*
// @grant        unsafeWindow
// @grant        GM_addStyle
// @require      https://cdn.jsdelivr.net/npm/chart.js@4.3.3/dist/chart.umd.min.js
// @require      https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0
// ==/UserScript==

var getTodayDateLocalString = new Date().toString().substring(0,15),
    allAvailableServersNumber = 5,
    icons = {
        hamburger: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyBmaWxsPSIjZmZmZmZmIiB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHJva2U9IiNmZmZmZmYiPgoNPGcgaWQ9IlNWR1JlcG9fYmdDYXJyaWVyIiBzdHJva2Utd2lkdGg9IjAiLz4KDTxnIGlkPSJTVkdSZXBvX3RyYWNlckNhcnJpZXIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgoNPGcgaWQ9IlNWR1JlcG9faWNvbkNhcnJpZXIiPgoNPHBhdGggZD0iTTYuMDAxIDcuMTI4TDYgMTAuNDM4bDE5Ljk5OC0uMDA1TDI2IDcuMTI0ek02LjAwMSAyMS41NjZMNiAyNC44NzZsMTkuOTk4LS4wMDYuMDAyLTMuMzA4ek02LjAwMSAxNC4zNDFMNiAxNy42NWwxOS45OTgtLjAwNC4wMDItMy4zMDl6Ii8+Cg08L2c+Cg08L3N2Zz4=",
        brackets: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHJva2U9IiNmZmZmZmYiPgoNPGcgaWQ9IlNWR1JlcG9fYmdDYXJyaWVyIiBzdHJva2Utd2lkdGg9IjAiLz4KDTxnIGlkPSJTVkdSZXBvX3RyYWNlckNhcnJpZXIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgoNPGcgaWQ9IlNWR1JlcG9faWNvbkNhcnJpZXIiPiA8cGF0aCBkPSJNOSAyMUM3Ljg5NTQzIDIxIDcgMjAuMTA0NiA3IDE5VjE1LjMyNTVDNyAxNC44MzYzIDcgMTQuNTkxNyA2Ljk0NDc0IDE0LjM2MTVDNi44OTU3NSAxNC4xNTc1IDYuODE0OTQgMTMuOTYyNCA2LjcwNTI4IDEzLjc4MzRDNi41ODE2IDEzLjU4MTYgNi40MDg2MyAxMy40MDg2IDYuMDYyNzQgMTMuMDYyN0w1IDEyTDYuMDYyNzQgMTAuOTM3M0M2LjQwODY0IDEwLjU5MTQgNi41ODE2IDEwLjQxODQgNi43MDUyOCAxMC4yMTY2QzYuODE0OTQgMTAuMDM3NiA2Ljg5NTc1IDkuODQyNTQgNi45NDQ3NCA5LjYzODQ2QzcgOS40MDgyOSA3IDkuMTYzNyA3IDguNjc0NTJWNUM3IDMuODk1NDMgNy44OTU0MyAzIDkgM00xNSAyMUMxNi4xMDQ2IDIxIDE3IDIwLjEwNDYgMTcgMTlWMTUuMzI1NUMxNyAxNC44MzYzIDE3IDE0LjU5MTcgMTcuMDU1MyAxNC4zNjE1QzE3LjEwNDMgMTQuMTU3NSAxNy4xODUxIDEzLjk2MjQgMTcuMjk0NyAxMy43ODM0QzE3LjQxODQgMTMuNTgxNiAxNy41OTE0IDEzLjQwODYgMTcuOTM3MyAxMy4wNjI3TDE5IDEyTDE3LjkzNzMgMTAuOTM3M0MxNy41OTE0IDEwLjU5MTQgMTcuNDE4NCAxMC40MTg0IDE3LjI5NDcgMTAuMjE2NkMxNy4xODUxIDEwLjAzNzYgMTcuMTA0MyA5Ljg0MjU0IDE3LjA1NTMgOS42Mzg0NkMxNyA5LjQwODI5IDE3IDkuMTYzNyAxNyA4LjY3NDUyVjVDMTcgMy44OTU0MyAxNi4xMDQ2IDMgMTUgMyIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjIuNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+IDwvZz4KDTwvc3ZnPg==",
        palette: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHJva2U9IiNmZmZmZmYiPgoNPGcgaWQ9IlNWR1JlcG9fYmdDYXJyaWVyIiBzdHJva2Utd2lkdGg9IjAiLz4KDTxnIGlkPSJTVkdSZXBvX3RyYWNlckNhcnJpZXIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgoNPGcgaWQ9IlNWR1JlcG9faWNvbkNhcnJpZXIiPiA8cGF0aCBkPSJNMTUuNSA4LjVIMTUuNTFNMTAuNSA3LjVIMTAuNTFNNy41IDExLjVINy41MU0xMiAyMUM3LjAyOTQ0IDIxIDMgMTYuOTcwNiAzIDEyQzMgNy4wMjk0NCA3LjAyOTQ0IDMgMTIgM0MxNi45NzA2IDMgMjEgNy4wMjk0NCAyMSAxMkMyMSAxMy42NTY5IDE5LjY1NjkgMTUgMTggMTVIMTcuNEMxNy4wMjg0IDE1IDE2Ljg0MjYgMTUgMTYuNjg3MSAxNS4wMjQ2QzE1LjgzMTMgMTUuMTYwMiAxNS4xNjAyIDE1LjgzMTMgMTUuMDI0NiAxNi42ODcxQzE1IDE2Ljg0MjYgMTUgMTcuMDI4NCAxNSAxNy40VjE4QzE1IDE5LjY1NjkgMTMuNjU2OSAyMSAxMiAyMVpNMTYgOC41QzE2IDguNzc2MTQgMTUuNzc2MSA5IDE1LjUgOUMxNS4yMjM5IDkgMTUgOC43NzYxNCAxNSA4LjVDMTUgOC4yMjM4NiAxNS4yMjM5IDggMTUuNSA4QzE1Ljc3NjEgOCAxNiA4LjIyMzg2IDE2IDguNVpNMTEgNy41QzExIDcuNzc2MTQgMTAuNzc2MSA4IDEwLjUgOEMxMC4yMjM5IDggMTAgNy43NzYxNCAxMCA3LjVDMTAgNy4yMjM4NiAxMC4yMjM5IDcgMTAuNSA3QzEwLjc3NjEgNyAxMSA3LjIyMzg2IDExIDcuNVpNOCAxMS41QzggMTEuNzc2MSA3Ljc3NjE0IDEyIDcuNSAxMkM3LjIyMzg2IDEyIDcgMTEuNzc2MSA3IDExLjVDNyAxMS4yMjM5IDcuMjIzODYgMTEgNy41IDExQzcuNzc2MTQgMTEgOCAxMS4yMjM5IDggMTEuNVoiIHN0cm9rZT0iI2ZmZmZmZiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4gPC9nPgoNPC9zdmc+",
        reset: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDI0LjAwIDI0LjAwIiBmaWxsPSJub25lIiB0cmFuc2Zvcm09InJvdGF0ZSgwKSIgc3Ryb2tlPSIjMDAwMDAwIj4KCjxnIGlkPSJTVkdSZXBvX2JnQ2FycmllciIgc3Ryb2tlLXdpZHRoPSIwIi8+Cgo8ZyBpZD0iU1ZHUmVwb190cmFjZXJDYXJyaWVyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KCjxnIGlkPSJTVkdSZXBvX2ljb25DYXJyaWVyIj4gPHBhdGggZD0iTTIxIDNWOE0yMSA4SDE2TTIxIDhMMTggNS4yOTE2OEMxNi40MDc3IDMuODY2NTYgMTQuMzA1MSAzIDEyIDNDNy4wMjk0NCAzIDMgNy4wMjk0NCAzIDEyQzMgMTYuOTcwNiA3LjAyOTQ0IDIxIDEyIDIxQzE2LjI4MzIgMjEgMTkuODY3NSAxOC4wMDggMjAuNzc3IDE0IiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+IDwvZz4KCjwvc3ZnPg==",
        cross: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyBmaWxsPSIjZmZmZmZmIiB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAxNiAxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMC4wMDAxNiI+Cg08ZyBpZD0iU1ZHUmVwb19iZ0NhcnJpZXIiIHN0cm9rZS13aWR0aD0iMCIvPgoNPGcgaWQ9IlNWR1JlcG9fdHJhY2VyQ2FycmllciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cg08ZyBpZD0iU1ZHUmVwb19pY29uQ2FycmllciI+IDxwYXRoIGQ9Ik0wIDE0LjU0NUwxLjQ1NSAxNiA4IDkuNDU1IDE0LjU0NSAxNiAxNiAxNC41NDUgOS40NTUgOCAxNiAxLjQ1NSAxNC41NDUgMCA4IDYuNTQ1IDEuNDU1IDAgMCAxLjQ1NSA2LjU0NSA4eiIgZmlsbC1ydWxlPSJldmVub2RkIi8+IDwvZz4KDTwvc3ZnPg==",
        eyeOpen: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KDTxnIGlkPSJTVkdSZXBvX2JnQ2FycmllciIgc3Ryb2tlLXdpZHRoPSIwIi8+Cg08ZyBpZD0iU1ZHUmVwb190cmFjZXJDYXJyaWVyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KDTxnIGlkPSJTVkdSZXBvX2ljb25DYXJyaWVyIj4gPHBhdGggZD0iTTE1LjAwMDcgMTJDMTUuMDAwNyAxMy42NTY5IDEzLjY1NzYgMTUgMTIuMDAwNyAxNUMxMC4zNDM5IDE1IDkuMDAwNzMgMTMuNjU2OSA5LjAwMDczIDEyQzkuMDAwNzMgMTAuMzQzMSAxMC4zNDM5IDkgMTIuMDAwNyA5QzEzLjY1NzYgOSAxNS4wMDA3IDEwLjM0MzEgMTUuMDAwNyAxMloiIHN0cm9rZT0iI2ZmZmZmZiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4gPHBhdGggZD0iTTEyLjAwMTIgNUM3LjUyMzU0IDUgMy43MzMyNiA3Ljk0Mjg4IDIuNDU4OTggMTJDMy43MzMyNCAxNi4wNTcxIDcuNTIzNTQgMTkgMTIuMDAxMiAxOUMxNi40Nzg4IDE5IDIwLjI2OTEgMTYuMDU3MSAyMS41NDM0IDEyQzIwLjI2OTEgNy45NDI5MSAxNi40Nzg4IDUgMTIuMDAxMiA1WiIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPiA8L2c+Cg08L3N2Zz4=",
        eyeClose: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KDTxnIGlkPSJTVkdSZXBvX2JnQ2FycmllciIgc3Ryb2tlLXdpZHRoPSIwIi8+Cg08ZyBpZD0iU1ZHUmVwb190cmFjZXJDYXJyaWVyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KDTxnIGlkPSJTVkdSZXBvX2ljb25DYXJyaWVyIj4gPHBhdGggZD0iTTIuOTk5MDIgM0wyMC45OTkgMjFNOS44NDMzIDkuOTEzNjRDOS4zMjA2NiAxMC40NTM2IDguOTk5MDIgMTEuMTg5MiA4Ljk5OTAyIDEyQzguOTk5MDIgMTMuNjU2OSAxMC4zNDIyIDE1IDExLjk5OSAxNUMxMi44MjE1IDE1IDEzLjU2NjcgMTQuNjY5IDE0LjEwODYgMTQuMTMzTTYuNDk5MDIgNi42NDcxNUM0LjU5OTcyIDcuOTAwMzQgMy4xNTMwNSA5Ljc4Mzk0IDIuNDU3MDMgMTJDMy43MzEyOCAxNi4wNTcxIDcuNTIxNTkgMTkgMTEuOTk5MiAxOUMxMy45ODgxIDE5IDE1Ljg0MTQgMTguNDE5NCAxNy4zOTg4IDE3LjQxODRNMTAuOTk5IDUuMDQ5MzlDMTEuMzI4IDUuMDE2NzMgMTEuNjYxNyA1IDExLjk5OTIgNUMxNi40NzY5IDUgMjAuMjY3MiA3Ljk0MjkxIDIxLjU0MTQgMTJDMjEuMjYwNyAxMi44OTQgMjAuODU3NyAxMy43MzM4IDIwLjM1MjIgMTQuNSIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPiA8L2c+Cg08L3N2Zz4=",
        capture: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHJva2U9IiNmZmZmZmYiPgoNPGcgaWQ9IlNWR1JlcG9fYmdDYXJyaWVyIiBzdHJva2Utd2lkdGg9IjAiLz4KDTxnIGlkPSJTVkdSZXBvX3RyYWNlckNhcnJpZXIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgoNPGcgaWQ9IlNWR1JlcG9faWNvbkNhcnJpZXIiPiA8cGF0aCBkPSJNMTIgMTZDMTMuNjU2OSAxNiAxNSAxNC42NTY5IDE1IDEzQzE1IDExLjM0MzEgMTMuNjU2OSAxMCAxMiAxMEMxMC4zNDMxIDEwIDkgMTEuMzQzMSA5IDEzQzkgMTQuNjU2OSAxMC4zNDMxIDE2IDEyIDE2WiIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjIuNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+IDxwYXRoIGQ9Ik0zIDE2LjhWOS4yQzMgOC4wNzk5IDMgNy41MTk4NCAzLjIxNzk5IDcuMDkyMDJDMy40MDk3MyA2LjcxNTY5IDMuNzE1NjkgNi40MDk3MyA0LjA5MjAyIDYuMjE3OTlDNC41MTk4NCA2IDUuMDc5OSA2IDYuMiA2SDcuMjU0NjRDNy4zNzc1OCA2IDcuNDM5MDUgNiA3LjQ5NTc2IDUuOTkzNUM3Ljc5MTY2IDUuOTU5NjEgOC4wNTcwNSA1Ljc5NTU5IDguMjE5NjkgNS41NDYwOUM4LjI1MDg2IDUuNDk4MjcgOC4yNzgzNiA1LjQ0MzI4IDguMzMzMzMgNS4zMzMzM0M4LjQ0MzI5IDUuMTEzNDIgOC40OTgyNyA1LjAwMzQ2IDguNTYwNjIgNC45MDc4MkM4Ljg4NTkgNC40MDg4MiA5LjQxNjY4IDQuMDgwNzggMTAuMDA4NSA0LjAxMjk5QzEwLjEyMTkgNCAxMC4yNDQ4IDQgMTAuNDkwNyA0SDEzLjUwOTNDMTMuNzU1MiA0IDEzLjg3ODEgNCAxMy45OTE1IDQuMDEyOTlDMTQuNTgzMyA0LjA4MDc4IDE1LjExNDEgNC40MDg4MiAxNS40Mzk0IDQuOTA3ODJDMTUuNTAxNyA1LjAwMzQ1IDE1LjU1NjcgNS4xMTM0NSAxNS42NjY3IDUuMzMzMzNDMTUuNzIxNiA1LjQ0MzI5IDE1Ljc0OTEgNS40OTgyNyAxNS43ODAzIDUuNTQ2MDlDMTUuOTQzIDUuNzk1NTkgMTYuMjA4MyA1Ljk1OTYxIDE2LjUwNDIgNS45OTM1QzE2LjU2MSA2IDE2LjYyMjQgNiAxNi43NDU0IDZIMTcuOEMxOC45MjAxIDYgMTkuNDgwMiA2IDE5LjkwOCA2LjIxNzk5QzIwLjI4NDMgNi40MDk3MyAyMC41OTAzIDYuNzE1NjkgMjAuNzgyIDcuMDkyMDJDMjEgNy41MTk4NCAyMSA4LjA3OTkgMjEgOS4yVjE2LjhDMjEgMTcuOTIwMSAyMSAxOC40ODAyIDIwLjc4MiAxOC45MDhDMjAuNTkwMyAxOS4yODQzIDIwLjI4NDMgMTkuNTkwMyAxOS45MDggMTkuNzgyQzE5LjQ4MDIgMjAgMTguOTIwMSAyMCAxNy44IDIwSDYuMkM1LjA3OTkgMjAgNC41MTk4NCAyMCA0LjA5MjAyIDE5Ljc4MkMzLjcxNTY5IDE5LjU5MDMgMy40MDk3MyAxOS4yODQzIDMuMjE3OTkgMTguOTA4QzMgMTguNDgwMiAzIDE3LjkyMDEgMyAxNi44WiIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjIuNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+IDwvZz4KDTwvc3ZnPg==",
        chart: "data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCA1MC44IDUwLjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0iI2ZmZmZmZiIgc3Ryb2tlPSIjZmZmZmZmIj4KDTxnIGlkPSJTVkdSZXBvX2JnQ2FycmllciIgc3Ryb2tlLXdpZHRoPSIwIi8+Cg08ZyBpZD0iU1ZHUmVwb190cmFjZXJDYXJyaWVyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KDTxnIGlkPSJTVkdSZXBvX2ljb25DYXJyaWVyIj4gPGcgc3R5bGU9ImRpc3BsYXk6aW5saW5lIj4gPHBhdGggZD0iTTcuODU0IDMzLjU0NiAxNiAyMi44OTNsNy41MiAxNi4yOTMgNi4yNjctMjcuNTcyIDMuNzYgOC43NzMgNS42NC02Ljg5MyAzLjc2IDguMTQ2IiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojZmZmZmZmO3N0cm9rZS13aWR0aDo1LjA4O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZCIvPiA8L2c+IDwvZz4KDTwvc3ZnPg=="
    },
    availableRegions = ["NA", "EU", "AS"],
    defaultColors = {
        "Garden": "#1EA761",
        "Desert": "#E0D1AF",
        "Ocean": "#66869E",
        "Jungle": "#3AA049",
        "Ant Hell": "#8E603F",
        "Sewers": "#752F08",
        "Hel / PvP": "#8F3838"
    },
    allAvailableMaps = Object.keys(defaultColors),
    defaultBarColors = {
        NA: "#EF476F",
        EU: "#FFD166",
        AS: "#06D6A0"
    },
    timeObject = JSON.stringify([
        {
            date: getTodayDateLocalString,
            region: {
                NA: 0,
                EU: 0,
                AS: 0
            },
            map: {
                Garden: 0
            }
        }
    ]),
    previewIndex = 0

function sumValuesInObject(obj) {
    var sum = 0
    for (var el in obj) {
        if(obj.hasOwnProperty(el)) {
            sum += Number(obj[el])
        }
    }
    return sum
}
function timeFormatting(input) {
    input = Number(input)
    var days = Math.floor(input / (24 * 60 * 60))
    var hours = Math.floor((input - days * (24 * 60 * 60)) / (60 * 60))
    var mins = Math.floor((input - days * (24 * 60 * 60) - hours * (60 * 60)) / 60)
    var seconds = input - days * (24 * 60 * 60) - hours * (60 * 60) - mins * 60
    seconds = Math.round(seconds * 100) / 100
    var output = `${days}d ${hours < 10 ? "0" + hours : hours}:${mins < 10 ? "0" + mins : mins}:${seconds < 10 ? "0" + seconds : seconds}`
    return output
}

Date.prototype.addDays = function(days) {
    var date = new Date(this.valueOf())
    date.setDate(date.getDate() + days)
    return date;
}

function getDates(startDate, stopDate) {
    var dateArray = new Array()
    var dateArrayTemporary = new Array()
    var currentDate = startDate
    while (currentDate <= stopDate) {
        dateArray.push(new Date(currentDate).toString().slice(8, 10))
        dateArrayTemporary.push(new Date(currentDate).toString().slice(0, 15))
        currentDate = currentDate.addDays(1)
    }
    return {dateArray, dateArrayTemporary}
}

function calcColor(min, max, val) {
    var minHue = 240, maxHue = 0
    var curPercent = (val - min) / (max - min)
    var colString = "hsl(" + ((curPercent * (maxHue - minHue)) + minHue) + ",100%,50%)"
    return colString
}

let cp6 = unsafeWindow.cp6
let url = "";
const nativeWebsocketFinder = unsafeWindow.WebSocket;
unsafeWindow.WebSocket = function (...args) {
    const wss = new nativeWebsocketFinder(...args);
    url = wss.url
    return wss;
};

var currentServers = [],
    currentCodes = [],
    currentServerName = ""

function getCp6Codes() {
    for (let i = 0; i <= allAvailableServersNumber; i++) {
        fetch(`https://api.n.m28.io/endpoint/florrio-map-${i}-green/findEach/`).then((response) => response.json()).then((data) => {
            currentServers[i] = `${data.servers["vultr-miami"].id} ${data.servers["vultr-frankfurt"].id} ${data.servers["vultr-tokyo"].id}`
        });
    }
}
getCp6Codes()

function findCurrentServer() {
    var AlternativeWSS = url.slice(6, url.indexOf("."))
    if (!currentServers.join(" ").includes(AlternativeWSS)) getCp6Codes()
    currentServers.forEach((item, index) => {
        if (item.includes(AlternativeWSS)) {
            currentCodes = item.split(" ")
            if (AlternativeWSS == currentCodes[0]) currentServerName = "NA"
            else if (AlternativeWSS == currentCodes[1]) currentServerName = "EU"
            else if (AlternativeWSS == currentCodes[2]) currentServerName = "AS"
        }
    })
}

if (!localStorage.getItem("playtimeCounter2")) localStorage.setItem("playtimeCounter2", timeObject)
var thisTimeObject = JSON.parse(localStorage.getItem("playtimeCounter2"))

var FurakenContainer = document.createElement('div')
FurakenContainer.style = `
    position: absolute;
    bottom: 10px;
    right: 10px;
    width: 100%;
`
document.querySelector('body').appendChild(FurakenContainer)

var playtimeCounterContainer = document.createElement('div')
playtimeCounterContainer.className = "options-button"
playtimeCounterContainer.style = `
    background-color: #BB5555;
    width: fit-content;
    height: auto;
    border-radius: 5px;
    border: 6px solid rgba(0, 0, 0, 0.3);
    padding: 5px;
    position: absolute;
    bottom: 0;
    right: 0;
    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;
    font-family: 'Ubuntu';
    cursor: pointer;
    transition: all 0.2s ease-in-out;
    text-align: center;
    box-shadow: 5px 5px rgba(0, 0, 0, 0.3);
    opacity: 0;
`
playtimeCounterContainer.innerHTML = `
    <div style="background-image: url(${icons.hamburger}); background-repeat: no-repeat; background-position: center; background-size: 35px; height: 30px; width: 30px;"></div>
`
playtimeCounterContainer.onclick = function() {
    playtimeCounterOptions.style.display = playtimeCounterOptions.style.display == "block" ? "none" : "block"
}
playtimeCounterContainer.onmouseover = function() {
    playtimeDataPreview.style.opacity = 1
    playtimeCounterContainer.style.opacity = 1
}
playtimeCounterContainer.onmouseout = function() {
    playtimeDataPreview.style.opacity = 0
    playtimeCounterContainer.style.opacity = 0
}
FurakenContainer.appendChild(playtimeCounterContainer)

var playtimeDataPreview = document.createElement('div')
playtimeDataPreview.className = "options-button"
playtimeDataPreview.style = `
    background-color: #BB5555;
    width: auto;
    height: 20px;
    line-height: 18px;
    border-radius: 5px;
    border: 6px solid rgba(0, 0, 0, 0.3);
    padding: 5px 20px;
    position: absolute;
    bottom: 0;
    right: 0;
    margin-right: 60px;
    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;
    font-family: 'Ubuntu';
    cursor: pointer;
    transition: all 0.2s ease-in-out;
    text-align: center;
    box-shadow: 5px 5px rgba(0, 0, 0, 0.3);
    opacity: 0;
    pointer-events: all;
`
playtimeDataPreview.innerHTML = "Fetching datas..."
playtimeDataPreview.onclick = function() {
    previewIndex = (previewIndex + 1) % 3
}
FurakenContainer.appendChild(playtimeDataPreview)

var playtimeCounterOptions = document.createElement('div')
playtimeCounterOptions.style = `
    height: auto;
    width: 30px;
    right: 0px;
    bottom: 60px;
    position: absolute;
    display: none;
`
FurakenContainer.appendChild(playtimeCounterOptions)

/*
var playtimeCounterOptions_EditableBox = document.createElement('div')
playtimeCounterOptions_EditableBox.contentEditable = "true"
playtimeCounterOptions_EditableBox.style = `
    overflow-y: auto;
    width: 300px;
    height: 83%;
    border-radius: 5px;
    background-color: #C52A61;
    border: 6px solid rgba(0, 0, 0, 0.3);
    position: absolute;
    margin-inline: -340px;
    box-shadow: 5px 5px rgba(0, 0, 0, 0.3);
    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;
    font-family: 'Ubuntu';
    font-size: 12px;
    padding: 10px;
`
playtimeCounterOptions.appendChild(playtimeCounterOptions_EditableBox)

var playtimeCounterOptions_Customize = document.createElement('div')
playtimeCounterOptions_Customize.innerHTML = `
    <div class="label">
        Customize
    </div>
`
playtimeCounterOptions.appendChild(playtimeCounterOptions_Customize)

var playtimeCounterOptions_Brackets = document.createElement('div')
playtimeCounterOptions_Brackets.innerHTML = `
    <div class="label">
        Datas
    </div>
`
playtimeCounterOptions.appendChild(playtimeCounterOptions_Brackets)
*/
var playtimeCounterOptions_Reset_Confirm = document.createElement('div')
playtimeCounterOptions_Reset_Confirm.innerHTML = `Clear all datas?`
playtimeCounterOptions_Reset_Confirm.className = "options-button"
playtimeCounterOptions_Reset_Confirm.style = `
    background-color: rgb(187, 85, 85);
    width: 100px;
    height: 20px;
    border-radius: 5px;
    border: 3px solid rgba(0, 0, 0, 0.3);
    background-size: 20px;
    background-repeat: no-repeat;
    background-position: center center;
    cursor: pointer;
    box-shadow: rgba(0, 0, 0, 0.3) 5px 5px;
    transition: all 0.2s ease-in-out 0s;
    position: absolute;
    right: 34px;
    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;
    font-family: 'Ubuntu';
    font-size: 12px;
    text-align: center;
    line-height: 20px;
    padding: 2px 5px;
    display: none;
    z-index: 1;
`
playtimeCounterOptions_Reset_Confirm.onclick = function() {
    localStorage.setItem("playtimeCounter2", JSON.stringify([{
        date: getTodayDateLocalString,
        region: {
            NA: 0,
            EU: 0,
            AS: 0
        },
        map: {
            Garden: 0
        }
    }]))
}
playtimeCounterOptions.appendChild(playtimeCounterOptions_Reset_Confirm)

var playtimeCounterOptions_Reset = document.createElement('div')
playtimeCounterOptions_Reset.innerHTML = `
    <div class="label">
        Reset
    </div>
`
playtimeCounterOptions_Reset.onclick = function() {
    playtimeCounterOptions_Reset_Confirm.style.display = playtimeCounterOptions_Reset_Confirm.style.display == "block" ? "none" : "block"
    playtimeCounterOptions_Reset.style.backgroundImage = playtimeCounterOptions_Reset_Confirm.style.display == "block" ? `url(${icons.cross})` : `url(${icons.reset})`
}
playtimeCounterOptions.appendChild(playtimeCounterOptions_Reset)

var ifEyeClose = false
var playtimeCounterOptions_Eye = document.createElement('div')
playtimeCounterOptions_Eye.innerHTML = `
    <div class="label">
        Toggle
    </div>
`
playtimeCounterOptions_Eye.onclick = function() {
    if (ifEyeClose) {
        ifEyeClose = false
        playtimeCounterOptions_Eye.style.backgroundImage = `url(${icons.eyeOpen})`
        playtimeDataPreview.style.pointerEvents = "all"
        playtimeDataPreview.classList.add("alwaysShow")
        playtimeCounterContainer.classList.add("alwaysShow")
    } else {
        ifEyeClose = true
        playtimeCounterOptions_Eye.style.backgroundImage = `url(${icons.eyeClose})`
        playtimeDataPreview.style.pointerEvents = "none"
        playtimeDataPreview.classList.remove("alwaysShow")
        playtimeCounterContainer.classList.remove("alwaysShow")
    }
}
playtimeCounterOptions.appendChild(playtimeCounterOptions_Eye)

var playtimeCounterOptions_Capture = document.createElement('div')
playtimeCounterOptions_Capture.innerHTML = `
    <div class="label">
        Capture
    </div>
`
playtimeCounterOptions_Capture.onclick = function() {
    var graph = document.getElementById("lineGraph")
    var image = new Image()
    image.src = graph.toDataURL()
    var blank_ = window.open("")
    blank_.document.body.appendChild(image)
    blank_.document.body.style.margin = 0
}
playtimeCounterOptions.appendChild(playtimeCounterOptions_Capture)

var playtimeCounterOptions_Chart = document.createElement('div')
playtimeCounterOptions_Chart.innerHTML = `
    <div class="label">
        Chart
    </div>
`
playtimeCounterOptions_Chart.onclick = function() {
    playtimeChart.style.opacity == 1 ? 0 : updateChartData()
    playtimeChart.style.opacity = playtimeChart.style.opacity == 1 ? 0 : 1
    playtimeChart.style.pointerEvents = playtimeChart.style.pointerEvents == "all" ? "none" : "all"
}
playtimeCounterOptions.appendChild(playtimeCounterOptions_Chart);

[/*playtimeCounterOptions_Brackets, playtimeCounterOptions_Customize, */playtimeCounterOptions_Reset, playtimeCounterOptions_Eye, playtimeCounterOptions_Capture, playtimeCounterOptions_Chart].forEach(item => {
    item.className = "options-button label-con"
    item.style = `
        width: 20px;
        height: 20px;
        border-radius: 5px;
        border: 3px solid rgba(0, 0, 0, 0.3);
        margin-bottom: 2px;
        background-size: 20px;
        background-repeat: no-repeat;
        background-position: center;
        padding: 2px;
        cursor: pointer;
        box-shadow: 5px 5px rgba(0, 0, 0, 0.3);
        transition: all 0.2s ease-in-out;
    `
})

playtimeDataPreview.classList.add("alwaysShow")
playtimeCounterContainer.classList.add("alwaysShow")
/*
playtimeCounterOptions_Customize.style.backgroundImage = `url(${icons.palette})`
playtimeCounterOptions_Customize.style.backgroundColor = `#C52A61`
playtimeCounterOptions_Brackets.style.backgroundImage = `url(${icons.brackets})`
playtimeCounterOptions_Brackets.style.backgroundColor = `#FFD166`
*/
playtimeCounterOptions_Reset.style.backgroundImage = `url(${icons.reset})`
playtimeCounterOptions_Reset.style.backgroundColor = `#BB5555`
playtimeCounterOptions_Eye.style.backgroundImage = `url(${icons.eyeOpen})`
playtimeCounterOptions_Eye.style.backgroundColor = `#2ACACC`
playtimeCounterOptions_Capture.style.backgroundImage = `url(${icons.capture})`
playtimeCounterOptions_Capture.style.backgroundColor = `#E83473`
playtimeCounterOptions_Chart.style.backgroundImage = `url(${icons.chart})`
playtimeCounterOptions_Chart.style.backgroundColor = `#2BFFA3`

var playtimeChart = document.createElement('div')
playtimeChart.style = `
    width: 100%;
    height: 100%;
    position: absolute;
    z-index: 100;
    top: 0;
    margin: 0;
    opacity: 0;
    transform: scale(0.9);
    transition: 0.4s ease-in-out;
    pointer-events: none;
`
playtimeChart.innerHTML = `
    <canvas id="lineGraph" style="border-radius: 15px;transition: 0.4s ease-in-out;position: absolute;z-index: 1;"></canvas>
`
document.querySelector('body').appendChild(playtimeChart)

Chart.defaults.font.family = 'Ubuntu';
Chart.defaults.font.size = 15;
Chart.defaults.font.weight = 600;
Chart.defaults.color = '#E7E7E7';
var lineGraph = new Chart(document.getElementById('lineGraph'), {
    data: {
        labels: [""],
        datasets: [{
            type: "line",
            data: [],
            label: ""
        }]
    },
    options: {
        // animation: false,
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
            customCanvasBackgroundColor: {
                color: "#2A2A2A",
            },
            legend: {
                labels: {
                    boxWidth: 15,
                    boxHeight: 15
                },
                position: "top"
            },
            datalabels: {
                formatter: (value, context) => {
                    if (context.dataset.label == "Total" && value != 0) return value.toFixed(2)
                    else if (context.dataset.label == "Average" && context.dataIndex == 0) return value.toFixed(2)
                    else return ""
                },
                color: "#E7E7E7",
                font: {
                    size: 12,
                    weight: 600
                },
                align: 'end'
            }
        },
        layout: {
            padding: 50
        },
        scales: {
            x: {
                title: {
                    display: true,
                    text: ["Date", `Last 30 days - ${new Date().toString().slice(4, 7)}`]
                },
                grid: {
                    color: "#E7E7E71A"
                }
            },
            y: {
                title: {
                    display: true,
                    text: "Hours"
                },
                grid: {
                    color: "#E7E7E71A"
                },
                min: 0,
                ticks: {
                    stepSize: 1
                }
            }
        },
    },
    plugins: [{
        id: 'customCanvasBackgroundColor',
        beforeDraw: (chart, args, options) => {
            const { ctx } = chart;
            ctx.save();
            ctx.globalCompositeOperation = 'destination-over';
            ctx.fillStyle = options.color || '#000000';
            ctx.fillRect(0, 0, chart.width, chart.height);
            ctx.restore();
        }
    }, ChartDataLabels]
});

function updateChartData() {
    var priorDate = new Date()
    priorDate.setDate(priorDate.getDate() - 29)
    priorDate = new Date(priorDate.toString().slice(0, 15))

    var today = new Date(new Date().toString().slice(0, 15))
    var temporaryTimeObjForChart = JSON.parse(localStorage.getItem("playtimeCounter2")),
        chartLabels = getDates(priorDate, today).dateArray,
        matchingDateArray = getDates(priorDate, today).dateArrayTemporary,
        chartDataSets = [],
        chartRegionDataSets = [],
        dataOfDataSets = [],
        totalPlaytimeData = [],
        averagePlaytimeData = []

    for (let index = 0; index < allAvailableMaps.length; index++) {
        chartDataSets[index] = {
            type: "line",
            label: allAvailableMaps[index] + "​",
            data: [],
            borderColor: defaultColors[allAvailableMaps[index]],
            borderWidth: 2.5,
            tension: 0.3
        }
        for (let i = 0; i < chartLabels.length; i++) {
            chartDataSets[index].data.push(0)
        }
    }

    for (let index = 0; index < availableRegions.length; index++) {
        chartRegionDataSets[index] = {
            type: "bar",
            label: availableRegions[index] + "​",
            data: [],
            fill: true,
            backgroundColor: defaultBarColors[availableRegions[index]],
        }
        for (let i = 0; i < chartLabels.length; i++) {
            chartRegionDataSets[index].data.push(0)
        }
    }

    temporaryTimeObjForChart.forEach((item, index) => {
        if (matchingDateArray.includes(item.date)) {
            for (const property in temporaryTimeObjForChart[index].map) {
                chartDataSets[allAvailableMaps.indexOf(property)].data[matchingDateArray.indexOf(item.date)] = temporaryTimeObjForChart[index].map[property] / 3600
                if (!totalPlaytimeData[matchingDateArray.indexOf(item.date)]) totalPlaytimeData[matchingDateArray.indexOf(item.date)] = 0
                totalPlaytimeData[matchingDateArray.indexOf(item.date)] += temporaryTimeObjForChart[index].map[property] / 3600
            }
            for (const property in temporaryTimeObjForChart[index].region) chartRegionDataSets[availableRegions.indexOf(property)].data[matchingDateArray.indexOf(item.date)] = temporaryTimeObjForChart[index].region[property] / 3600
        }
    })

    var thisIndex = 0,
        thisChartDataSetsLength = chartDataSets.length
    for (let i = 0; i < thisChartDataSetsLength; i++) {
        var isAllZero = chartDataSets[thisIndex].data.every(item => item == 0)
        if (isAllZero) {
            chartDataSets.splice(chartDataSets.indexOf(chartDataSets[thisIndex]), 1)
            thisIndex--
        }
        thisIndex++
    }

    totalPlaytimeData = Array.from(totalPlaytimeData, item => item || 0)
    var sumOfTotalPlaytimeData = totalPlaytimeData.reduce((accumulator, currentValue) => {
        return accumulator + currentValue
    }, 0)
    sumOfTotalPlaytimeData = sumOfTotalPlaytimeData / 30
    for (let i = 0; i < matchingDateArray.length; i++) averagePlaytimeData.push(sumOfTotalPlaytimeData)

    chartDataSets.unshift({
        type: "line",
        label: "Average",
        data: averagePlaytimeData,
        borderColor: "#2BFFA399",
        borderWidth: 3,
        pointRadius: 0
    })
    chartDataSets.unshift({
        type: "line",
        label: "Total",
        data: totalPlaytimeData,
        borderColor: "#E7E7E7",
        borderWidth: 3,
        tension: 0.3
    })
    chartDataSets = chartDataSets.concat(chartRegionDataSets)

    lineGraph.data.labels = chartLabels
    lineGraph.data.datasets = chartDataSets
    lineGraph.update()
}

// Credit to: Florr.io 汉化
function getFlorrioCanvas() {
    if (typeof (OffscreenCanvasRenderingContext2D) == 'undefined') {
        return [CanvasRenderingContext2D]
    }
    return [OffscreenCanvasRenderingContext2D, CanvasRenderingContext2D];
}

for (const { prototype } of getFlorrioCanvas()) {
    if (prototype.getArcPrototype == undefined) {
        prototype.getFillTextPrototype = prototype.fillText;
    } else { break }
}

var lastMapName,
    thisStartTime = 0,
    lastRegion,
    thisStartTimeOfRegions = 0,
    lastOnScreenTime = Date.now(),
    og_text

for (const { prototype } of getFlorrioCanvas()) {
    prototype.fillText = function(text, x, y) {
        if (allAvailableMaps.includes(text) || /\b([0-9]|[1-9][0-9])\b Flowers?/.test(text)) {
            if (/\b([0-9]|[1-9][0-9])\b Flowers?/.test(text)) {
                og_text = text
                text = "Hel / PvP"
            } else og_text = text
            lastOnScreenTime = Date.now()
            thisTimeObject = JSON.parse(localStorage.getItem("playtimeCounter2"))
            if (!thisTimeObject[0].map[text]) thisTimeObject[0].map[text] = 0
            if (lastMapName != text) thisStartTime = Date.now() - thisTimeObject[0].map[text] * 1000
            if (lastRegion != currentServerName) thisStartTimeOfRegions = Date.now() - thisTimeObject[0].region[currentServerName] * 1000
            var thisDelta = Date.now() - thisStartTime
            var thisDeltaOfRegions = Date.now() - thisStartTimeOfRegions
            thisTimeObject[0].map[text] = Math.floor(thisDelta / 1000)
            thisTimeObject[0].region[currentServerName] = Math.floor(thisDeltaOfRegions / 1000)
            lastMapName = text
            lastRegion = currentServerName
            localStorage.setItem("playtimeCounter2", JSON.stringify(thisTimeObject))
            var totalPlaytime = 0,
                thisMapPlaytime = 0
            thisTimeObject.forEach(item => {
                totalPlaytime += sumValuesInObject(item.map)
                thisMapPlaytime += item.map[text] == null ? 0 : item.map[text]
            })
            var playtimeDatasArray = [
                `<td>Since ${thisTimeObject[thisTimeObject.length - 1].date}:</td><td>${timeFormatting(totalPlaytime)}</td>`,
                `<td>${text}:</td><td>${timeFormatting(thisMapPlaytime)}</td>`,
                `<td>Today:</td><td>${timeFormatting(sumValuesInObject(thisTimeObject[0].map)).slice(3)}</td>`
            ]
            playtimeDataPreview.innerHTML = `
                <table style="border-spacing: 15px 0; pointer-events: none;">
                    <tr>
                        ${playtimeDatasArray[previewIndex]}
                    </tr>
                </table>
            `
            text = og_text
        }
        return this.getFillTextPrototype(text, x, y);
    }
}

document.querySelector('canvas').onclick = function() {
    playtimeChart.style.display = "none"
}

var WSSArray = []
setInterval(() => {
    WSSArray.unshift(url)
    if (WSSArray.length > 2) WSSArray.splice(2)
    if (WSSArray[WSSArray.length - 1] != WSSArray[0]) findCurrentServer()

    getTodayDateLocalString = new Date().toString().substring(0,15)
    var temporaryTimeObj = JSON.parse(localStorage.getItem("playtimeCounter2"))
    temporaryTimeObj = temporaryTimeObj.filter((value, index, self) => index === self.findIndex((t) => (
        t.date == value.date
    )))
    localStorage.setItem("playtimeCounter2", JSON.stringify(temporaryTimeObj))

    if (Date.now() - lastOnScreenTime > 1000 && lastMapName != "Hel / PvP") {
        thisStartTime = Date.now() - thisTimeObject[0].map[lastMapName] * 1000
        thisStartTimeOfRegions = Date.now() - thisTimeObject[0].region[currentServerName] * 1000
    }

    if (temporaryTimeObj[0].date != getTodayDateLocalString) {
        thisStartTime = Date.now()
        thisStartTimeOfRegions = Date.now()
        temporaryTimeObj.unshift({
            date: getTodayDateLocalString,
            region: {
                NA: 0,
                EU: 0,
                AS: 0
            },
            map: {
                Garden: 0
            }
        })
        localStorage.setItem("playtimeCounter2", JSON.stringify(temporaryTimeObj))
    }
}, 1000)

GM_addStyle(`
    .alwaysShow {
        opacity: 1!important
    }
    .options-button:hover {
        filter: brightness(1.1)
    }
    .label {
        pointer-events: none;
        z-index: 1;
        width: fit-content;
        height: auto;
        line-height: 14px;
        padding: 5px 15px;
        background: rgba(0, 0, 0, 0.5);
        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;
        font-family: 'Ubuntu';
        color: white;
        position: absolute;
        right: 130%;
        margin-block: -1px;
        border-radius: 5px;
        font-size: 12px;
        transition: all 0.3s ease-in-out;
        opacity: 0;
    }
    .label-con:hover .label {
        opacity: 1;
    }
`)