AWBW Income Grapher - Beta 5.2

Preview Income and Tank Order on any given map.

// ==UserScript==
// @name         AWBW Income Grapher - Beta 5.2
// @namespace    awbw
// @match        https://awbw.amarriner.com/prevmaps.php*
// @match        https://awbw.amarriner.com/editmap.php*
// @icon         https://awbw.amarriner.com/terrain/ani/neutralcity.gif
// @version      0.5.2
// @description  Preview Income and Tank Order on any given map.
// @author       Vesper, Steve (Code)
// @license      MIT
// @grant        none
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js
// @require      https://unpkg.com/chartjs-plugin-annotation@latest/dist/chartjs-plugin-annotation.min.js
// @run-at       document-end
// @inject-into  page
// ==/UserScript==
debugger;

var BaseInfo = {};

function loadScript(e) {
    return new Promise(((t, n) => {
        let i = document.createElement("script");
        document.head.append(i), i.onload = () => {
            t()
        }, i.onerror = () => {
            n()
        }, i.src = e
    }))
}
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
window.sleep = sleep;
function loadImage(e) {
    return new Promise(((t, n) => {
        const i = new Image;
        i.onload = () => {
            t(i)
        }, i.onerror = e => {
            n(e)
        }, i.src = e
    }))
}
function indexToCoords(e, t) {
    return {
        x: (e = parseInt(e)) % t,
        y: e / t | 0
    }
}
function brightenColor(r, g, b, factor) {
    // Ensure the factor is between 0 and 1
    factor = Math.min(Math.max(factor, 0), 1);

    // Increase each RGB component by the factor
    r = Math.min(Math.round(r + (255 - r) * factor), 255);
    g = Math.min(Math.round(g + (255 - g) * factor), 255);
    b = Math.min(Math.round(b + (255 - b) * factor), 255);

    return `rgb(${r}, ${g}, ${b})`;
}
window.brightenColor = brightenColor;
BaseInfo.countries = {
    os: {
        id: 1,
        name: "Orange Star",
        color: "181, 39, 68"
    },
    bm: {
        id: 2,
        name: "Blue Moon",
        color: "70,110,254"
    },
    ge: {
        id: 3,
        name: "Green Earth",
        color: "61, 194, 45"
    },
    yc: {
        id: 4,
        name: "Yellow Comet",
        color: "201, 189, 2"
    },
    bh: {
        id: 5,
        name: "Black Hole",
        color: "116, 89, 138"
    },
    rf: {
        id: 6,
        name: "Red Fire",
        color: "146, 50, 67"
    },
    gs: {
        id: 7,
        name: "Grey Sky",
        color: "114, 114, 114"
    },
    bd: {
        id: 8,
        name: "Brown Desert",
        color: "152, 83, 51"
    },
    ab: {
        id: 9,
        name: "Amber Blaze",
        color: "252, 163, 57"
    },
    js: {
        id: 10,
        name: "Jade Sun",
        color: "166, 182, 153"
    },
    ci: {
        id: 16,
        name: "Cobalt Ice",
        color: "11, 32, 112"
    },
    pc: {
        id: 17,
        name: "Pink Cosmos",
        color: "255, 102, 204"
    },
    tg: {
        id: 19,
        name: "Teal Galaxy",
        color: "60, 205, 193"
    },
    pl: {
        id: 20,
        name: "Purple Lightning",
        color: "111, 26, 155"
    },
    ar: {
        id: 21,
        name: "Acid Rain",
        color: "97, 124, 14"
    },
    wn: {
        id: 22,
        name: "White Nova",
        color: "205, 155, 154"
    },
    aa: {
        id: 23,
        name: "Azure Asteroid",
        color: "130, 220, 232"
    },
    ne: {
        id: 24,
        name: "Noir Eclipse",
        color: "3, 3, 3"
    },
    sc: {
        id: 25,
        name: "Silver Claw",
        color: "137, 168, 188"
    }
}
BaseInfo.terrain = {
    1: {
        name: "Plain",
        defense: 1,
        country: "",
        build_type: null
    },
    2: {
        name: "Mountain",
        defense: 4,
        country: "",
        build_type: ""
    },
    3: {
        name: "Wood",
        defense: 2,
        country: "",
        build_type: null
    },
    4: {
        name: "HRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    5: {
        name: "VRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    6: {
        name: "CRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    7: {
        name: "ESRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    8: {
        name: "SWRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    9: {
        name: "WNRiver",
        defense: 0,
        country: "",
        build_type: ""
    },
    10: {
        name: "NERiver",
        defense: 0,
        country: "",
        build_type: null
    },
    11: {
        name: "ESWRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    12: {
        name: "SWNRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    13: {
        name: "WNERiver",
        defense: 0,
        country: "",
        build_type: null
    },
    14: {
        name: "NESRiver",
        defense: 0,
        country: "",
        build_type: null
    },
    15: {
        name: "HRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    16: {
        name: "VRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    17: {
        name: "CRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    18: {
        name: "ESRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    19: {
        name: "SWRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    20: {
        name: "WNRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    21: {
        name: "NERoad",
        defense: 0,
        country: "",
        build_type: null
    },
    22: {
        name: "ESWRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    23: {
        name: "SWNRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    24: {
        name: "WNERoad",
        defense: 0,
        country: "",
        build_type: null
    },
    25: {
        name: "NESRoad",
        defense: 0,
        country: "",
        build_type: null
    },
    26: {
        name: "HBridge",
        defense: 0,
        country: "",
        build_type: null
    },
    27: {
        name: "VBridge",
        defense: 0,
        country: "",
        build_type: null
    },
    28: {
        name: "Sea",
        defense: 0,
        country: "",
        build_type: null
    },
    29: {
        name: "HShoal",
        defense: 0,
        country: "",
        build_type: null
    },
    30: {
        name: "HShoalN",
        defense: 0,
        country: "",
        build_type: null
    },
    31: {
        name: "VShoal",
        defense: 0,
        country: "",
        build_type: null
    },
    32: {
        name: "VShoalE",
        defense: 0,
        country: "",
        build_type: null
    },
    33: {
        name: "Reef",
        defense: 1,
        country: "",
        build_type: null
    },
    34: {
        name: "Neutral City",
        defense: 3,
        country: "",
        build_type: null
    },
    35: {
        name: "Neutral Base",
        defense: 3,
        country: "",
        build_type: ""
    },
    36: {
        name: "Neutral Airport",
        defense: 3,
        country: "",
        build_type: null
    },
    37: {
        name: "Neutral Port",
        defense: 3,
        country: "",
        build_type: null
    },
    38: {
        name: "Orange Star City",
        defense: 3,
        country: "os",
        build_type: null
    },
    39: {
        name: "Orange Star Base",
        defense: 3,
        country: "os",
        build_type: "L"
    },
    40: {
        name: "Orange Star Airport",
        defense: 3,
        country: "os",
        build_type: "A"
    },
    41: {
        name: "Orange Star Port",
        defense: 3,
        country: "os",
        build_type: "S"
    },
    42: {
        name: "Orange Star HQ",
        defense: 4,
        country: "os",
        build_type: null
    },
    43: {
        name: "Blue Moon City",
        defense: 3,
        country: "bm",
        build_type: null
    },
    44: {
        name: "Blue Moon Base",
        defense: 3,
        country: "bm",
        build_type: "L"
    },
    45: {
        name: "Blue Moon Airport",
        defense: 3,
        country: "bm",
        build_type: "A"
    },
    46: {
        name: "Blue Moon Port",
        defense: 3,
        country: "bm",
        build_type: "S"
    },
    47: {
        name: "Blue Moon HQ",
        defense: 4,
        country: "bm",
        build_type: null
    },
    48: {
        name: "Green Earth City",
        defense: 3,
        country: "ge",
        build_type: null
    },
    49: {
        name: "Green Earth Base",
        defense: 3,
        country: "ge",
        build_type: "L"
    },
    50: {
        name: "Green Earth Airport",
        defense: 3,
        country: "ge",
        build_type: "A"
    },
    51: {
        name: "Green Earth Port",
        defense: 3,
        country: "ge",
        build_type: "S"
    },
    52: {
        name: "Green Earth HQ",
        defense: 4,
        country: "ge",
        build_type: null
    },
    53: {
        name: "Yellow Comet City",
        defense: 3,
        country: "yc",
        build_type: null
    },
    54: {
        name: "Yellow Comet Base",
        defense: 3,
        country: "yc",
        build_type: "L"
    },
    55: {
        name: "Yellow Comet Airport",
        defense: 3,
        country: "yc",
        build_type: "A"
    },
    56: {
        name: "Yellow Comet Port",
        defense: 3,
        country: "yc",
        build_type: "S"
    },
    57: {
        name: "Yellow Comet HQ",
        defense: 4,
        country: "yc",
        build_type: null
    },
    81: {
        name: "Red Fire City",
        defense: 3,
        country: "rf",
        build_type: null
    },
    82: {
        name: "Red Fire Base",
        defense: 3,
        country: "rf",
        build_type: "L"
    },
    83: {
        name: "Red Fire Airport",
        defense: 3,
        country: "rf",
        build_type: "A"
    },
    84: {
        name: "Red Fire Port",
        defense: 3,
        country: "rf",
        build_type: "S"
    },
    85: {
        name: "Red Fire HQ",
        defense: 4,
        country: "rf",
        build_type: null
    },
    86: {
        name: "Grey Sky City",
        defense: 3,
        country: "gs",
        build_type: null
    },
    87: {
        name: "Grey Sky Base",
        defense: 3,
        country: "gs",
        build_type: "L"
    },
    88: {
        name: "Grey Sky Airport",
        defense: 3,
        country: "gs",
        build_type: "A"
    },
    89: {
        name: "Grey Sky Port",
        defense: 3,
        country: "gs",
        build_type: "S"
    },
    90: {
        name: "Grey Sky HQ",
        defense: 4,
        country: "gs",
        build_type: null
    },
    91: {
        name: "Black Hole City",
        defense: 3,
        country: "bh",
        build_type: null
    },
    92: {
        name: "Black Hole Base",
        defense: 3,
        country: "bh",
        build_type: "L"
    },
    93: {
        name: "Black Hole Airport",
        defense: 3,
        country: "bh",
        build_type: "A"
    },
    94: {
        name: "Black Hole Port",
        defense: 3,
        country: "bh",
        build_type: "S"
    },
    95: {
        name: "Black Hole HQ",
        defense: 4,
        country: "bh",
        build_type: ""
    },
    96: {
        name: "Brown Desert City",
        defense: 3,
        country: "bd",
        build_type: null
    },
    97: {
        name: "Brown Desert Base",
        defense: 3,
        country: "bd",
        build_type: "L"
    },
    98: {
        name: "Brown Desert Airport",
        defense: 3,
        country: "bd",
        build_type: "A"
    },
    99: {
        name: "Brown Desert Port",
        defense: 3,
        country: "bd",
        build_type: "S"
    },
    100: {
        name: "Brown Desert HQ",
        defense: 4,
        country: "bd",
        build_type: null
    },
    101: {
        name: "VPipe",
        defense: 0,
        country: "",
        build_type: ""
    },
    102: {
        name: "HPipe",
        defense: 0,
        country: "",
        build_type: ""
    },
    103: {
        name: "NEPipe",
        defense: 0,
        country: "",
        build_type: ""
    },
    104: {
        name: "ESPipe",
        defense: 0,
        country: "",
        build_type: ""
    },
    105: {
        name: "SWPipe",
        defense: 0,
        country: "",
        build_type: ""
    },
    106: {
        name: "WNPipe",
        defense: 0,
        country: "",
        build_type: ""
    },
    107: {
        name: "NPipe End",
        defense: 0,
        country: "",
        build_type: ""
    },
    108: {
        name: "EPipe End",
        defense: 0,
        country: "",
        build_type: ""
    },
    109: {
        name: "SPipe End",
        defense: 0,
        country: "",
        build_type: ""
    },
    110: {
        name: "WPipe End",
        defense: 0,
        country: "",
        build_type: ""
    },
    111: {
        name: "Missile Silo",
        defense: 3,
        country: "",
        build_type: ""
    },
    112: {
        name: "Missile Silo Empty",
        defense: 3,
        country: "",
        build_type: ""
    },
    113: {
        name: "HPipe Seam",
        defense: 0,
        country: "",
        build_type: ""
    },
    114: {
        name: "VPipe Seam",
        defense: 0,
        country: "",
        build_type: ""
    },
    115: {
        name: "HPipe Rubble",
        defense: 1,
        country: "",
        build_type: ""
    },
    116: {
        name: "VPipe Rubble",
        defense: 1,
        country: "",
        build_type: ""
    },
    117: {
        name: "Amber Blaze Airport",
        defense: 3,
        country: "ab",
        build_type: "A"
    },
    118: {
        name: "Amber Blaze Base",
        defense: 3,
        country: "ab",
        build_type: "L"
    },
    119: {
        name: "Amber Blaze City",
        defense: 3,
        country: "ab",
        build_type: ""
    },
    120: {
        name: "Amber Blaze HQ",
        defense: 4,
        country: "ab",
        build_type: ""
    },
    121: {
        name: "Amber Blaze Port",
        defense: 3,
        country: "ab",
        build_type: "S"
    },
    122: {
        name: "Jade Sun Airport",
        defense: 3,
        country: "js",
        build_type: "A"
    },
    123: {
        name: "Jade Sun Base",
        defense: 3,
        country: "js",
        build_type: "L"
    },
    124: {
        name: "Jade Sun City",
        defense: 3,
        country: "js",
        build_type: ""
    },
    125: {
        name: "Jade Sun HQ",
        defense: 4,
        country: "js",
        build_type: ""
    },
    126: {
        name: "Jade Sun Port",
        defense: 3,
        country: "js",
        build_type: "S"
    },
    127: {
        name: "Amber Blaze Com Tower",
        defense: 3,
        country: "ab",
        build_type: ""
    },
    128: {
        name: "Black Hole Com Tower",
        defense: 3,
        country: "bh",
        build_type: ""
    },
    129: {
        name: "Blue Moon Com Tower",
        defense: 3,
        country: "bm",
        build_type: ""
    },
    130: {
        name: "Brown Desert Com Tower",
        defense: 3,
        country: "bd",
        build_type: ""
    },
    131: {
        name: "Green Earth Com Tower",
        defense: 3,
        country: "ge",
        build_type: ""
    },
    132: {
        name: "Jade Sun Com Tower",
        defense: 3,
        country: "js",
        build_type: ""
    },
    133: {
        name: "Neutral Com Tower",
        defense: 3,
        country: "",
        build_type: ""
    },
    134: {
        name: "Orange Star Com Tower",
        defense: 3,
        country: "os",
        build_type: ""
    },
    135: {
        name: "Red Fire Com Tower",
        defense: 3,
        country: "rf",
        build_type: ""
    },
    136: {
        name: "Yellow Comet Com Tower",
        defense: 3,
        country: "yc",
        build_type: ""
    },
    137: {
        name: "Grey Sky Com Tower",
        defense: 3,
        country: "gs",
        build_type: ""
    },
    138: {
        name: "Amber Blaze Lab",
        defense: 3,
        country: "ab",
        build_type: ""
    },
    139: {
        name: "Black Hole Lab",
        defense: 3,
        country: "bh",
        build_type: ""
    },
    140: {
        name: "Blue Moon Lab",
        defense: 3,
        country: "bm",
        build_type: ""
    },
    141: {
        name: "Brown Desert Lab",
        defense: 3,
        country: "bd",
        build_type: ""
    },
    142: {
        name: "Green Earth Lab",
        defense: 3,
        country: "ge",
        build_type: ""
    },
    143: {
        name: "Grey Sky Lab",
        defense: 3,
        country: "gs",
        build_type: ""
    },
    144: {
        name: "Jade Sun Lab",
        defense: 3,
        country: "js",
        build_type: ""
    },
    145: {
        name: "Neutral Lab",
        defense: 3,
        country: "",
        build_type: ""
    },
    146: {
        name: "Orange Star Lab",
        defense: 3,
        country: "os",
        build_type: ""
    },
    147: {
        name: "Red Fire Lab",
        defense: 3,
        country: "rf",
        build_type: ""
    },
    148: {
        name: "Yellow Comet Lab",
        defense: 3,
        country: "yc",
        build_type: ""
    },
    149: {
        name: "Cobalt Ice Airport",
        defense: 3,
        country: "ci",
        build_type: "A"
    },
    150: {
        name: "Cobalt Ice Base",
        defense: 3,
        country: "ci",
        build_type: "L"
    },
    151: {
        name: "Cobalt Ice City",
        defense: 3,
        country: "ci",
        build_type: ""
    },
    152: {
        name: "Cobalt Ice Com Tower",
        defense: 3,
        country: "ci",
        build_type: ""
    },
    153: {
        name: "Cobalt Ice HQ",
        defense: 4,
        country: "ci",
        build_type: ""
    },
    154: {
        name: "Cobalt Ice Lab",
        defense: 3,
        country: "ci",
        build_type: ""
    },
    155: {
        name: "Cobalt Ice Port",
        defense: 3,
        country: "ci",
        build_type: "S"
    },
    156: {
        name: "Pink Cosmos Airport",
        defense: 3,
        country: "pc",
        build_type: "A"
    },
    157: {
        name: "Pink Cosmos Base",
        defense: 3,
        country: "pc",
        build_type: "L"
    },
    158: {
        name: "Pink Cosmos City",
        defense: 3,
        country: "pc",
        build_type: ""
    },
    159: {
        name: "Pink Cosmos Com Tower",
        defense: 3,
        country: "pc",
        build_type: ""
    },
    160: {
        name: "Pink Cosmos HQ",
        defense: 4,
        country: "pc",
        build_type: ""
    },
    161: {
        name: "Pink Cosmos Lab",
        defense: 3,
        country: "pc",
        build_type: ""
    },
    162: {
        name: "Pink Cosmos Port",
        defense: 3,
        country: "pc",
        build_type: "S"
    },
    163: {
        name: "Teal Galaxy Airport",
        defense: 3,
        country: "tg",
        build_type: "A"
    },
    164: {
        name: "Teal Galaxy Base",
        defense: 3,
        country: "tg",
        build_type: "L"
    },
    165: {
        name: "Teal Galaxy City",
        defense: 3,
        country: "tg",
        build_type: ""
    },
    166: {
        name: "Teal Galaxy Com Tower",
        defense: 3,
        country: "tg",
        build_type: ""
    },
    167: {
        name: "Teal Galaxy HQ",
        defense: 4,
        country: "tg",
        build_type: ""
    },
    168: {
        name: "Teal Galaxy Lab",
        defense: 3,
        country: "tg",
        build_type: ""
    },
    169: {
        name: "Teal Galaxy Port",
        defense: 3,
        country: "tg",
        build_type: "S"
    },
    170: {
        name: "Purple Lightning Airport",
        defense: 3,
        country: "pl",
        build_type: "A"
    },
    171: {
        name: "Purple Lightning Base",
        defense: 3,
        country: "pl",
        build_type: "L"
    },
    172: {
        name: "Purple Lightning City",
        defense: 3,
        country: "pl",
        build_type: ""
    },
    173: {
        name: "Purple Lightning Com Tower",
        defense: 3,
        country: "pl",
        build_type: ""
    },
    174: {
        name: "Purple Lightning HQ",
        defense: 4,
        country: "pl",
        build_type: ""
    },
    175: {
        name: "Purple Lightning Lab",
        defense: 3,
        country: "pl",
        build_type: ""
    },
    176: {
        name: "Purple Lightning Port",
        defense: 3,
        country: "pl",
        build_type: "S"
    },
    181: {
        name: "Acid Rain Airport",
        defense: 3,
        country: "ar",
        build_type: "A"
    },
    182: {
        name: "Acid Rain Base",
        defense: 3,
        country: "ar",
        build_type: "L"
    },
    183: {
        name: "Acid Rain City",
        defense: 3,
        country: "ar",
        build_type: ""
    },
    184: {
        name: "Acid Rain Com Tower",
        defense: 3,
        country: "ar",
        build_type: ""
    },
    185: {
        name: "Acid Rain HQ",
        defense: 4,
        country: "ar",
        build_type: ""
    },
    186: {
        name: "Acid Rain Lab",
        defense: 3,
        country: "ar",
        build_type: ""
    },
    187: {
        name: "Acid Rain Port",
        defense: 3,
        country: "ar",
        build_type: "S"
    },
    188: {
        name: "White Nova Airport",
        defense: 3,
        country: "wn",
        build_type: "A"
    },
    189: {
        name: "White Nova Base",
        defense: 3,
        country: "wn",
        build_type: "L"
    },
    190: {
        name: "White Nova City",
        defense: 3,
        country: "wn",
        build_type: ""
    },
    191: {
        name: "White Nova Com Tower",
        defense: 3,
        country: "wn",
        build_type: ""
    },
    192: {
        name: "White Nova HQ",
        defense: 4,
        country: "wn",
        build_type: ""
    },
    193: {
        name: "White Nova Lab",
        defense: 3,
        country: "wn",
        build_type: ""
    },
    194: {
        name: "White Nova Port",
        defense: 3,
        country: "wn",
        build_type: "S"
    },
    195: {
        name: "Teleporter",
        defense: 0,
        country: "",
        build_type: ""
    },
    196: {
        name: "Azure Asteroid Airport",
        defense: 3,
        country: "aa",
        build_type: "A"
    },
    197: {
        name: "Azure Asteroid Base",
        defense: 3,
        country: "aa",
        build_type: "L"
    },
    198: {
        name: "Azure Asteroid City",
        defense: 3,
        country: "aa",
        build_type: ""
    },
    199: {
        name: "Azure Asteroid Com Tower",
        defense: 3,
        country: "aa",
        build_type: ""
    },
    200: {
        name: "Azure Asteroid HQ",
        defense: 4,
        country: "aa",
        build_type: ""
    },
    201: {
        name: "Azure Asteroid Lab",
        defense: 3,
        country: "aa",
        build_type: ""
    },
    202: {
        name: "Azure Asteroid Port",
        defense: 3,
        country: "aa",
        build_type: "S"
    },
    203: {
        name: "Noir Eclipse Airport",
        defense: 3,
        country: "ne",
        build_type: "A"
    },
    204: {
        name: "Noir Eclipse Base",
        defense: 3,
        country: "ne",
        build_type: "L"
    },
    205: {
        name: "Noir Eclipse City",
        defense: 3,
        country: "ne",
        build_type: ""
    },
    206: {
        name: "Noir Eclipse Com Tower",
        defense: 3,
        country: "ne",
        build_type: ""
    },
    207: {
        name: "Noir Eclipse HQ",
        defense: 4,
        country: "ne",
        build_type: ""
    },
    208: {
        name: "Noir Eclipse Lab",
        defense: 3,
        country: "ne",
        build_type: ""
    },
    209: {
        name: "Noir Eclipse Port",
        defense: 3,
        country: "ne",
        build_type: "S"
    },
    210: {
        name: "Silver Claw Airport",
        defense: 3,
        country: "sc",
        build_type: "A"
    },
    211: {
        name: "Silver Claw Base",
        defense: 3,
        country: "sc",
        build_type: "L"
    },
    212: {
        name: "Silver Claw City",
        defense: 3,
        country: "sc",
        build_type: ""
    },
    213: {
        name: "Silver Claw Com Tower",
        defense: 3,
        country: "sc",
        build_type: ""
    },
    214: {
        name: "Silver Claw HQ",
        defense: 4,
        country: "sc",
        build_type: ""
    },
    215: {
        name: "Silver Claw Lab",
        defense: 3,
        country: "sc",
        build_type: ""
    },
    216: {
        name: "Silver Claw Port",
        defense: 3,
        country: "sc",
        build_type: "S"
    }
}
BaseInfo.units = {
    1: {
        name: "Infantry",
        cost: 1e3,
        move_points: 3,
        move_type: "F",
        fuel: 99,
        fuel_per_turn: 0,
        ammo: 0,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    2: {
        name: "Mech",
        cost: 3e3,
        move_points: 2,
        move_type: "B",
        fuel: 70,
        fuel_per_turn: 0,
        ammo: 3,
        short_range: 0,
        long_range: 0,
        second_weapon: "Y"
    },
    3: {
        name: "Md.Tank",
        cost: 16e3,
        move_points: 5,
        move_type: "T",
        fuel: 50,
        fuel_per_turn: 0,
        ammo: 8,
        short_range: 0,
        long_range: 0,
        second_weapon: "Y"
    },
    4: {
        name: "Tank",
        cost: 7e3,
        move_points: 6,
        move_type: "T",
        fuel: 70,
        fuel_per_turn: 0,
        ammo: 9,
        short_range: 0,
        long_range: 0,
        second_weapon: "Y"
    },
    5: {
        name: "Recon",
        cost: 4e3,
        move_points: 8,
        move_type: "W",
        fuel: 80,
        fuel_per_turn: 0,
        ammo: 0,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    6: {
        name: "APC",
        cost: 5e3,
        move_points: 6,
        move_type: "T",
        fuel: 70,
        fuel_per_turn: 0,
        ammo: 0,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    7: {
        name: "Artillery",
        cost: 6e3,
        move_points: 5,
        move_type: "T",
        fuel: 50,
        fuel_per_turn: 0,
        ammo: 9,
        short_range: 2,
        long_range: 3,
        second_weapon: "N"
    },
    8: {
        name: "Rocket",
        cost: 15e3,
        move_points: 5,
        move_type: "W",
        fuel: 50,
        fuel_per_turn: 0,
        ammo: 6,
        short_range: 3,
        long_range: 5,
        second_weapon: "N"
    },
    9: {
        name: "Anti-Air",
        cost: 8e3,
        move_points: 6,
        move_type: "T",
        fuel: 60,
        fuel_per_turn: 0,
        ammo: 9,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    10: {
        name: "Missile",
        cost: 12e3,
        move_points: 4,
        move_type: "W",
        fuel: 50,
        fuel_per_turn: 0,
        ammo: 6,
        short_range: 3,
        long_range: 5,
        second_weapon: "N"
    },
    11: {
        name: "Fighter",
        cost: 2e4,
        move_points: 9,
        move_type: "A",
        fuel: 99,
        fuel_per_turn: 5,
        ammo: 9,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    12: {
        name: "Bomber",
        cost: 22e3,
        move_points: 7,
        move_type: "A",
        fuel: 99,
        fuel_per_turn: 5,
        ammo: 9,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    13: {
        name: "B-Copter",
        cost: 9e3,
        move_points: 6,
        move_type: "A",
        fuel: 99,
        fuel_per_turn: 2,
        ammo: 6,
        short_range: 0,
        long_range: 0,
        second_weapon: "Y"
    },
    14: {
        name: "T-Copter",
        cost: 5e3,
        move_points: 6,
        move_type: "A",
        fuel: 99,
        fuel_per_turn: 2,
        ammo: 0,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    15: {
        name: "Battleship",
        cost: 28e3,
        move_points: 5,
        move_type: "S",
        fuel: 99,
        fuel_per_turn: 1,
        ammo: 9,
        short_range: 2,
        long_range: 6,
        second_weapon: "N"
    },
    16: {
        name: "Cruiser",
        cost: 18e3,
        move_points: 6,
        move_type: "S",
        fuel: 99,
        fuel_per_turn: 1,
        ammo: 9,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    17: {
        name: "Lander",
        cost: 12e3,
        move_points: 6,
        move_type: "L",
        fuel: 99,
        fuel_per_turn: 1,
        ammo: 0,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    18: {
        name: "Sub",
        cost: 2e4,
        move_points: 5,
        move_type: "S",
        fuel: 60,
        fuel_per_turn: 1,
        ammo: 6,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    46: {
        name: "Neotank",
        cost: 22e3,
        move_points: 6,
        move_type: "T",
        fuel: 99,
        fuel_per_turn: 1,
        ammo: 9,
        short_range: 0,
        long_range: 0,
        second_weapon: "Y"
    },
    960900: {
        name: "Piperunner",
        cost: 2e4,
        move_points: 9,
        move_type: "P",
        fuel: 99,
        fuel_per_turn: 0,
        ammo: 9,
        short_range: 2,
        long_range: 5,
        second_weapon: "Y"
    },
    968731: {
        name: "Black Bomb",
        cost: 25e3,
        move_points: 9,
        move_type: "A",
        fuel: 45,
        fuel_per_turn: 5,
        ammo: 0,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    1141438: {
        name: "Mega Tank",
        cost: 28e3,
        move_points: 4,
        move_type: "T",
        fuel: 50,
        fuel_per_turn: 0,
        ammo: 3,
        short_range: 0,
        long_range: 0,
        second_weapon: "Y"
    },
    28: {
        name: "Black Boat",
        cost: 7500,
        move_points: 7,
        move_type: "L",
        fuel: 60,
        fuel_per_turn: 1,
        ammo: 0,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    30: {
        name: "Stealth",
        cost: 24e3,
        move_points: 6,
        move_type: "A",
        fuel: 60,
        fuel_per_turn: 5,
        ammo: 6,
        short_range: 0,
        long_range: 0,
        second_weapon: "N"
    },
    29: {
        name: "Carrier",
        cost: 3e4,
        move_points: 5,
        move_type: "S",
        fuel: 99,
        fuel_per_turn: 1,
        ammo: 9,
        short_range: 3,
        long_range: 8,
        second_weapon: "N"
    }
}
BaseInfo.moveCosts = {
    C: {
        F: {
            1: 1,
            2: 2,
            3: 1,
            4: 2,
            5: 2,
            6: 2,
            7: 2,
            8: 2,
            9: 2,
            10: 2,
            11: 2,
            12: 2,
            13: 2,
            14: 2,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        B: {
            1: 1,
            2: 1,
            3: 1,
            4: 1,
            5: 1,
            6: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            13: 1,
            14: 1,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        T: {
            1: 1,
            2: 0,
            3: 2,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        W: {
            1: 2,
            2: 0,
            3: 3,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 2,
            116: 2,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        A: {
            1: 1,
            2: 1,
            3: 1,
            4: 1,
            5: 1,
            6: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            13: 1,
            14: 1,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 1,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 1,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        S: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 1,
            29: 0,
            30: 0,
            31: 0,
            32: 0,
            33: 2,
            34: 0,
            35: 0,
            36: 0,
            37: 1,
            38: 0,
            39: 0,
            40: 0,
            41: 1,
            42: 0,
            43: 0,
            44: 0,
            45: 0,
            46: 1,
            47: 0,
            48: 0,
            49: 0,
            50: 0,
            51: 1,
            52: 0,
            53: 0,
            54: 0,
            55: 0,
            56: 1,
            57: 0,
            81: 0,
            86: 0,
            82: 0,
            87: 0,
            83: 0,
            88: 0,
            84: 1,
            89: 1,
            85: 0,
            90: 0,
            91: 0,
            92: 0,
            93: 0,
            94: 1,
            95: 0,
            96: 0,
            97: 0,
            98: 0,
            99: 1,
            100: 0,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 0,
            112: 0,
            113: 0,
            114: 0,
            115: 0,
            116: 0,
            117: 0,
            118: 0,
            119: 0,
            120: 0,
            121: 1,
            122: 0,
            123: 0,
            124: 0,
            125: 0,
            126: 1,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 0,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 1,
            156: 0,
            157: 0,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 1,
            163: 0,
            164: 0,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 1,
            170: 0,
            171: 0,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 1,
            "": 0,
            181: 0,
            182: 0,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 1,
            188: 0,
            189: 0,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 1,
            195: 0
        },
        L: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 1,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 2,
            34: 0,
            35: 0,
            36: 0,
            37: 1,
            38: 0,
            39: 0,
            40: 0,
            41: 1,
            42: 0,
            43: 0,
            44: 0,
            45: 0,
            46: 1,
            47: 0,
            48: 0,
            49: 0,
            50: 0,
            51: 1,
            52: 0,
            53: 0,
            54: 0,
            55: 0,
            56: 1,
            57: 0,
            81: 0,
            86: 0,
            82: 0,
            87: 0,
            83: 0,
            88: 0,
            84: 1,
            89: 1,
            85: 0,
            90: 0,
            91: 0,
            92: 0,
            93: 0,
            94: 1,
            95: 0,
            96: 0,
            97: 0,
            98: 0,
            99: 1,
            100: 0,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 0,
            112: 0,
            113: 0,
            114: 0,
            115: 0,
            116: 0,
            117: 0,
            118: 0,
            119: 0,
            120: 0,
            121: 1,
            122: 0,
            123: 0,
            124: 0,
            125: 0,
            126: 1,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 0,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 1,
            156: 0,
            157: 0,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 1,
            163: 0,
            164: 0,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 1,
            170: 0,
            171: 0,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 1,
            "": 0,
            181: 0,
            182: 0,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 1,
            188: 0,
            189: 0,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 1,
            195: 0
        },
        P: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 0,
            29: 0,
            30: 0,
            31: 0,
            32: 0,
            33: 0,
            34: 0,
            35: 1,
            36: 0,
            37: 0,
            38: 0,
            39: 1,
            40: 0,
            41: 0,
            42: 0,
            43: 0,
            44: 1,
            45: 0,
            46: 0,
            47: 0,
            48: 0,
            49: 1,
            50: 0,
            51: 0,
            52: 0,
            53: 0,
            54: 1,
            55: 0,
            56: 0,
            57: 0,
            85: 0,
            90: 0,
            84: 0,
            89: 0,
            83: 0,
            88: 0,
            82: 1,
            87: 1,
            81: 0,
            86: 0,
            91: 0,
            92: 1,
            93: 0,
            94: 0,
            95: 0,
            96: 0,
            97: 1,
            98: 0,
            99: 0,
            100: 0,
            101: 1,
            102: 1,
            103: 1,
            104: 1,
            105: 1,
            106: 1,
            107: 1,
            108: 1,
            109: 1,
            110: 1,
            111: 0,
            112: 0,
            113: 1,
            114: 1,
            115: 0,
            116: 0,
            117: 0,
            118: 1,
            119: 0,
            120: 0,
            121: 0,
            122: 0,
            123: 1,
            124: 0,
            125: 0,
            126: 0,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 1,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 0,
            156: 0,
            157: 1,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 0,
            163: 0,
            164: 1,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 0,
            170: 0,
            171: 1,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 0,
            "": 0,
            181: 0,
            182: 1,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 0,
            188: 0,
            189: 1,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 0,
            195: 0
        }
    },
    S: {
        F: {
            1: 2,
            2: 4,
            3: 2,
            4: 2,
            5: 2,
            6: 2,
            7: 2,
            8: 2,
            9: 2,
            10: 2,
            11: 2,
            12: 2,
            13: 2,
            14: 2,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 2,
            116: 2,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        B: {
            1: 1,
            2: 2,
            3: 1,
            4: 1,
            5: 1,
            6: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            13: 1,
            14: 1,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        T: {
            1: 2,
            2: 0,
            3: 2,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 2,
            116: 2,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        W: {
            1: 3,
            2: 0,
            3: 3,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 3,
            116: 3,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        A: {
            1: 2,
            2: 2,
            3: 2,
            4: 2,
            5: 2,
            6: 2,
            7: 2,
            8: 2,
            9: 2,
            10: 2,
            11: 2,
            12: 2,
            13: 2,
            14: 2,
            15: 2,
            16: 2,
            17: 2,
            18: 2,
            19: 2,
            20: 2,
            21: 2,
            22: 2,
            23: 2,
            24: 2,
            25: 2,
            26: 2,
            27: 2,
            28: 2,
            29: 2,
            30: 2,
            31: 2,
            32: 2,
            33: 2,
            34: 2,
            35: 2,
            36: 2,
            37: 2,
            38: 2,
            39: 2,
            40: 2,
            41: 2,
            42: 2,
            43: 2,
            44: 2,
            45: 2,
            46: 2,
            47: 2,
            48: 2,
            49: 2,
            50: 2,
            51: 2,
            52: 2,
            53: 2,
            54: 2,
            55: 2,
            56: 2,
            57: 2,
            81: 2,
            86: 2,
            82: 2,
            87: 2,
            83: 2,
            88: 2,
            84: 2,
            89: 2,
            85: 2,
            90: 2,
            91: 2,
            92: 2,
            93: 2,
            94: 2,
            95: 2,
            96: 2,
            97: 2,
            98: 2,
            99: 2,
            100: 2,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 2,
            112: 2,
            113: 0,
            114: 0,
            115: 2,
            116: 2,
            117: 2,
            118: 2,
            119: 2,
            120: 2,
            121: 2,
            122: 2,
            123: 2,
            124: 2,
            125: 2,
            126: 2,
            127: 2,
            128: 2,
            129: 2,
            130: 2,
            131: 2,
            132: 2,
            133: 2,
            134: 2,
            135: 2,
            136: 2,
            137: 2,
            138: 2,
            139: 2,
            140: 2,
            141: 2,
            142: 2,
            143: 2,
            144: 2,
            145: 2,
            146: 2,
            147: 2,
            148: 2,
            149: 2,
            150: 2,
            151: 2,
            152: 2,
            153: 2,
            154: 2,
            155: 2,
            156: 2,
            157: 2,
            158: 2,
            159: 2,
            160: 2,
            161: 2,
            162: 2,
            163: 2,
            164: 2,
            165: 2,
            166: 2,
            167: 2,
            168: 2,
            169: 2,
            170: 2,
            171: 2,
            172: 2,
            173: 2,
            174: 2,
            175: 2,
            176: 2,
            "": 2,
            181: 2,
            182: 2,
            183: 2,
            184: 2,
            185: 2,
            186: 2,
            187: 2,
            188: 2,
            189: 2,
            190: 2,
            191: 2,
            192: 2,
            193: 2,
            194: 2,
            195: 0
        },
        S: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 2,
            29: 0,
            30: 0,
            31: 0,
            32: 0,
            33: 2,
            34: 0,
            35: 0,
            36: 0,
            37: 2,
            38: 0,
            39: 0,
            40: 0,
            41: 2,
            42: 0,
            43: 0,
            44: 0,
            45: 0,
            46: 2,
            47: 0,
            48: 0,
            49: 0,
            50: 0,
            51: 2,
            52: 0,
            53: 0,
            54: 0,
            55: 0,
            56: 2,
            57: 0,
            81: 0,
            86: 0,
            82: 0,
            87: 0,
            83: 0,
            88: 0,
            84: 2,
            89: 2,
            85: 0,
            90: 0,
            91: 0,
            92: 0,
            93: 0,
            94: 2,
            95: 0,
            96: 0,
            97: 0,
            98: 0,
            99: 2,
            100: 0,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 0,
            112: 0,
            113: 0,
            114: 0,
            115: 0,
            116: 0,
            117: 0,
            118: 0,
            119: 0,
            120: 0,
            121: 2,
            122: 0,
            123: 0,
            124: 0,
            125: 0,
            126: 2,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 0,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 2,
            156: 0,
            157: 0,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 2,
            163: 0,
            164: 0,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 2,
            170: 0,
            171: 0,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 2,
            "": 0,
            181: 0,
            182: 0,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 2,
            188: 0,
            189: 0,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 2,
            195: 0
        },
        L: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 2,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 2,
            34: 0,
            35: 0,
            36: 0,
            37: 2,
            38: 0,
            39: 0,
            40: 0,
            41: 2,
            42: 0,
            43: 0,
            44: 0,
            45: 0,
            46: 2,
            47: 0,
            48: 0,
            49: 0,
            50: 0,
            51: 2,
            52: 0,
            53: 0,
            54: 0,
            55: 0,
            56: 2,
            57: 0,
            81: 0,
            86: 0,
            82: 0,
            87: 0,
            83: 0,
            88: 0,
            84: 2,
            89: 2,
            85: 0,
            90: 0,
            91: 0,
            92: 0,
            93: 0,
            94: 2,
            95: 0,
            96: 0,
            97: 0,
            98: 0,
            99: 2,
            100: 0,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 0,
            112: 0,
            113: 0,
            114: 0,
            115: 0,
            116: 0,
            117: 0,
            118: 0,
            119: 0,
            120: 0,
            121: 2,
            122: 0,
            123: 0,
            124: 0,
            125: 0,
            126: 2,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 0,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 2,
            156: 0,
            157: 0,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 2,
            163: 0,
            164: 0,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 2,
            170: 0,
            171: 0,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 2,
            "": 0,
            181: 0,
            182: 0,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 2,
            188: 0,
            189: 0,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 2,
            195: 0
        },
        P: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 0,
            29: 0,
            30: 0,
            31: 0,
            32: 0,
            33: 0,
            34: 0,
            35: 1,
            36: 0,
            37: 0,
            38: 0,
            39: 1,
            40: 0,
            41: 0,
            42: 0,
            43: 0,
            44: 1,
            45: 0,
            46: 0,
            47: 0,
            48: 0,
            49: 1,
            50: 0,
            51: 0,
            52: 0,
            53: 0,
            54: 1,
            55: 0,
            56: 0,
            57: 0,
            85: 0,
            90: 0,
            84: 0,
            89: 0,
            83: 0,
            88: 0,
            82: 1,
            87: 1,
            81: 0,
            86: 0,
            91: 0,
            92: 1,
            93: 0,
            94: 0,
            95: 0,
            96: 0,
            97: 1,
            98: 0,
            99: 0,
            100: 0,
            101: 1,
            102: 1,
            103: 1,
            104: 1,
            105: 1,
            106: 1,
            107: 1,
            108: 1,
            109: 1,
            110: 1,
            111: 0,
            112: 0,
            113: 1,
            114: 1,
            115: 0,
            116: 0,
            117: 0,
            118: 1,
            119: 0,
            120: 0,
            121: 0,
            122: 0,
            123: 1,
            124: 0,
            125: 0,
            126: 0,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 1,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 0,
            156: 0,
            157: 1,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 0,
            163: 0,
            164: 1,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 0,
            170: 0,
            171: 1,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 0,
            "": 0,
            181: 0,
            182: 1,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 0,
            188: 0,
            189: 1,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 0,
            195: 0
        }
    },
    R: {
        F: {
            1: 1,
            2: 2,
            3: 1,
            4: 2,
            5: 2,
            6: 2,
            7: 2,
            8: 2,
            9: 2,
            10: 2,
            11: 2,
            12: 2,
            13: 2,
            14: 2,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        B: {
            1: 1,
            2: 1,
            3: 1,
            4: 1,
            5: 1,
            6: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            13: 1,
            14: 1,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        T: {
            1: 2,
            2: 0,
            3: 3,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 2,
            116: 2,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        W: {
            1: 3,
            2: 0,
            3: 4,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 0,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 0,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 3,
            116: 3,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        A: {
            1: 1,
            2: 1,
            3: 1,
            4: 1,
            5: 1,
            6: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            13: 1,
            14: 1,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            21: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1,
            27: 1,
            28: 1,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 1,
            34: 1,
            35: 1,
            36: 1,
            37: 1,
            38: 1,
            39: 1,
            40: 1,
            41: 1,
            42: 1,
            43: 1,
            44: 1,
            45: 1,
            46: 1,
            47: 1,
            48: 1,
            49: 1,
            50: 1,
            51: 1,
            52: 1,
            53: 1,
            54: 1,
            55: 1,
            56: 1,
            57: 1,
            81: 1,
            86: 1,
            82: 1,
            87: 1,
            83: 1,
            88: 1,
            84: 1,
            89: 1,
            85: 1,
            90: 1,
            91: 1,
            92: 1,
            93: 1,
            94: 1,
            95: 1,
            96: 1,
            97: 1,
            98: 1,
            99: 1,
            100: 1,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 1,
            112: 1,
            113: 0,
            114: 0,
            115: 1,
            116: 1,
            117: 1,
            118: 1,
            119: 1,
            120: 1,
            121: 1,
            122: 1,
            123: 1,
            124: 1,
            125: 1,
            126: 1,
            127: 1,
            128: 1,
            129: 1,
            130: 1,
            131: 1,
            132: 1,
            133: 1,
            134: 1,
            135: 1,
            136: 1,
            137: 1,
            138: 1,
            139: 1,
            140: 1,
            141: 1,
            142: 1,
            143: 1,
            144: 1,
            145: 1,
            146: 1,
            147: 1,
            148: 1,
            149: 1,
            150: 1,
            151: 1,
            152: 1,
            153: 1,
            154: 1,
            155: 1,
            156: 1,
            157: 1,
            158: 1,
            159: 1,
            160: 1,
            161: 1,
            162: 1,
            163: 1,
            164: 1,
            165: 1,
            166: 1,
            167: 1,
            168: 1,
            169: 1,
            170: 1,
            171: 1,
            172: 1,
            173: 1,
            174: 1,
            175: 1,
            176: 1,
            "": 1,
            181: 1,
            182: 1,
            183: 1,
            184: 1,
            185: 1,
            186: 1,
            187: 1,
            188: 1,
            189: 1,
            190: 1,
            191: 1,
            192: 1,
            193: 1,
            194: 1,
            195: 0
        },
        S: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 1,
            29: 0,
            30: 0,
            31: 0,
            32: 0,
            33: 2,
            34: 0,
            35: 0,
            36: 0,
            37: 1,
            38: 0,
            39: 0,
            40: 0,
            41: 1,
            42: 0,
            43: 0,
            44: 0,
            45: 0,
            46: 1,
            47: 0,
            48: 0,
            49: 0,
            50: 0,
            51: 1,
            52: 0,
            53: 0,
            54: 0,
            55: 0,
            56: 1,
            57: 0,
            81: 0,
            86: 0,
            82: 0,
            87: 0,
            83: 0,
            88: 0,
            84: 1,
            89: 1,
            85: 0,
            90: 0,
            91: 0,
            92: 0,
            93: 0,
            94: 1,
            95: 0,
            96: 0,
            97: 0,
            98: 0,
            99: 1,
            100: 0,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 0,
            112: 0,
            113: 0,
            114: 0,
            115: 0,
            116: 0,
            117: 0,
            118: 0,
            119: 0,
            120: 0,
            121: 1,
            122: 0,
            123: 0,
            124: 0,
            125: 0,
            126: 1,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 0,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 1,
            156: 0,
            157: 0,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 1,
            163: 0,
            164: 0,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 1,
            170: 0,
            171: 0,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 1,
            "": 0,
            181: 0,
            182: 0,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 1,
            188: 0,
            189: 0,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 1,
            195: 0
        },
        L: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 1,
            29: 1,
            30: 1,
            31: 1,
            32: 1,
            33: 2,
            34: 0,
            35: 0,
            36: 0,
            37: 1,
            38: 0,
            39: 0,
            40: 0,
            41: 1,
            42: 0,
            43: 0,
            44: 0,
            45: 0,
            46: 1,
            47: 0,
            48: 0,
            49: 0,
            50: 0,
            51: 1,
            52: 0,
            53: 0,
            54: 0,
            55: 0,
            56: 1,
            57: 0,
            81: 0,
            86: 0,
            82: 0,
            87: 0,
            83: 0,
            88: 0,
            84: 1,
            89: 1,
            85: 0,
            90: 0,
            91: 0,
            92: 0,
            93: 0,
            94: 1,
            95: 0,
            96: 0,
            97: 0,
            98: 0,
            99: 1,
            100: 0,
            101: 0,
            102: 0,
            103: 0,
            104: 0,
            105: 0,
            106: 0,
            107: 0,
            108: 0,
            109: 0,
            110: 0,
            111: 0,
            112: 0,
            113: 0,
            114: 0,
            115: 0,
            116: 0,
            117: 0,
            118: 0,
            119: 0,
            120: 0,
            121: 1,
            122: 0,
            123: 0,
            124: 0,
            125: 0,
            126: 1,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 0,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 1,
            156: 0,
            157: 0,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 1,
            163: 0,
            164: 0,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 1,
            170: 0,
            171: 0,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 1,
            "": 0,
            181: 0,
            182: 0,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 1,
            188: 0,
            189: 0,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 1,
            195: 0
        },
        P: {
            1: 0,
            2: 0,
            3: 0,
            4: 0,
            5: 0,
            6: 0,
            7: 0,
            8: 0,
            9: 0,
            10: 0,
            11: 0,
            12: 0,
            13: 0,
            14: 0,
            15: 0,
            16: 0,
            17: 0,
            18: 0,
            19: 0,
            20: 0,
            21: 0,
            22: 0,
            23: 0,
            24: 0,
            25: 0,
            26: 0,
            27: 0,
            28: 0,
            29: 0,
            30: 0,
            31: 0,
            32: 0,
            33: 0,
            34: 0,
            35: 1,
            36: 0,
            37: 0,
            38: 0,
            39: 1,
            40: 0,
            41: 0,
            42: 0,
            43: 0,
            44: 1,
            45: 0,
            46: 0,
            47: 0,
            48: 0,
            49: 1,
            50: 0,
            51: 0,
            52: 0,
            53: 0,
            54: 1,
            55: 0,
            56: 0,
            57: 0,
            85: 0,
            90: 0,
            84: 0,
            89: 0,
            83: 0,
            88: 0,
            82: 1,
            87: 1,
            81: 0,
            86: 0,
            91: 0,
            92: 1,
            93: 0,
            94: 0,
            95: 0,
            96: 0,
            97: 1,
            98: 0,
            99: 0,
            100: 0,
            101: 1,
            102: 1,
            103: 1,
            104: 1,
            105: 1,
            106: 1,
            107: 1,
            108: 1,
            109: 1,
            110: 1,
            111: 0,
            112: 0,
            113: 1,
            114: 1,
            115: 0,
            116: 0,
            117: 0,
            118: 1,
            119: 0,
            120: 0,
            121: 0,
            122: 0,
            123: 1,
            124: 0,
            125: 0,
            126: 0,
            127: 0,
            128: 0,
            129: 0,
            130: 0,
            131: 0,
            132: 0,
            133: 0,
            134: 0,
            135: 0,
            136: 0,
            137: 0,
            138: 0,
            139: 0,
            140: 0,
            141: 0,
            142: 0,
            143: 0,
            144: 0,
            145: 0,
            146: 0,
            147: 0,
            148: 0,
            149: 0,
            150: 1,
            151: 0,
            152: 0,
            153: 0,
            154: 0,
            155: 0,
            156: 0,
            157: 1,
            158: 0,
            159: 0,
            160: 0,
            161: 0,
            162: 0,
            163: 0,
            164: 1,
            165: 0,
            166: 0,
            167: 0,
            168: 0,
            169: 0,
            170: 0,
            171: 1,
            172: 0,
            173: 0,
            174: 0,
            175: 0,
            176: 0,
            "": 0,
            181: 0,
            182: 1,
            183: 0,
            184: 0,
            185: 0,
            186: 0,
            187: 0,
            188: 0,
            189: 1,
            190: 0,
            191: 0,
            192: 0,
            193: 0,
            194: 0,
            195: 0
        }
    }
}
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
window.BaseInfo = BaseInfo;
Object.freeze(BaseInfo);

window.RequestID = 0;
class IncomeGrapher {
    width;
    height;
    terrain;
    bases = new Map();
    properties = new Map();
    //x + y * this.wdith
    //x: e,
    //y: t,
    //id: n,
    //country: i
    units;
    otherUnits;
    canvas;
    canvasRecon;
    ctx;
    ctxRecon;
    dirty;
    constructor(e = 0, t = 0) {
        this.canvas = document.createElement("canvas");
        this.canvasRecon = document.createElement("canvas");
        this.resize(e, t);
        this.dirty = !0;
    }
    resize(width, height) {
        this.width = width;
        this.height = height;

        // Ensure canvas exists
        if (!this.canvas) {
            this.canvas = document.createElement("canvas");
        }

        // Ensure canvas exists
        if (!this.canvasRecon) {
            this.canvasRecon = document.createElement("canvas");
        }

        this.canvas.width = 16 * this.width;
        this.canvas.height = 16 * this.height;
        this.canvasRecon.width = 16 * this.width;
        this.canvasRecon.height = 16 * this.height;

        this.ctx = this.canvas.getContext("2d");
        if (this.ctx) {
            this.ctx.textAlign = "center";
        } else {
            console.warn("Canvas context could not be initialized.");
        }

        this.terrain = new Array(width * height).fill(null); // Ensure it's filled
        this.bases = {};
        this.properties = new Array(width * height).fill(null);
        this.units = {};

        return this;
    }
    init(e) {
        this.canvas.style = "\n        pointer-events: none;\n        z-index: 200;\n        position: absolute;\n        top: 0;\n        left: 0;";
        e = e ?? document.getElementById("gamemap");
        if (e) {
            e.append(this.canvas);
        }
        this.ctx = this.canvas.getContext("2d");
        this.ctx.font = "12px monospace";
        this.ctx.textAlign = "center";

        this.canvasRecon.style = "\n        pointer-events: none;\n        z-index: 200;\n        position: absolute;\n        top: 0;\n        left: 0;";
        if (e) {
            e.append(this.canvasRecon);
        }

        this.ctxRecon = this.canvasRecon.getContext("2d");
        this.ctxRecon.font = "12px monospace";
        this.ctxRecon.textAlign = "center";
    }
    idToCountry(e) {
        return BaseInfo.terrain[e].country
    }
    isNeutral(e) {
        return e >= 34 && e <= 37
    }
    getTile(e, t) {
        return this.terrain[e + t * this.width]
    }
    setTile(e, t, n) {
        let i = e + t * this.width;
        return this.terrain[i] = n, this.dirty = !0, this
    }
    setUnit(e, t, n, i) {
        this.units[e + t * this.width] = {
            x: e,
            y: t,
            id: n,
            country: i
        }, this.dirty = !0
    }
    setUnits(e) {
        this.deleteAllUnits();
        for (let t = 0; t < e.length; t++) {
            let n = e[t].units_x,
                i = e[t].units_y,
                o = e[t].units_id,
                r = e[t].units_code;
            this.setUnit(n, i, o, r)
        }
    }
    deleteUnit(e, t) {
        this.units[e + t * this.width] && (delete this.units[e + t * this.width], this.dirty = !0)
    }
    deleteAllUnits() {
        this.units = {}, this.dirty = !0
    }
    setTerrain({
        terrainInfo: e,
        tiles: t
    } = {}) {
        if (this.dirty = !0, e) {
            for (let t in e) {
                t = parseInt(t);
                for (let n in e[t]) n = parseInt(n), this.terrain[t + n * this.width] = e[t][n].terrain_id
            }
            for (let e in buildingsInfo) {
                e = parseInt(e);
                for (let t in buildingsInfo[e]) t = parseInt(t), this.terrain[e + t * this.width] = buildingsInfo[e][t].terrain_id
            }
        } else {
            if (!t) throw new Error("give me some tiles bro");
            for (let e = 0; e < this.width; e++) {
                for (let n = 0; n < this.height; n++) {
                    const index = n + e * this.height; // Calculate index
                    let is_prop = t[index] == null;
                    if (is_prop) {
                        continue;
                    }
                    const i = t[index].terrain_id;
                    this.terrain[e + n * this.width] = i;
                }
            }
        }
        return this
    }
    getMoveCostGraph(e, j, t = "C") {
        let n = new Array(this.width * this.height);
        const i = BaseInfo.moveCosts[t][e];
        for (let t = 0; t < this.height; t++) {
            for (let o = 0; o < this.width; o++) {
                // Vesper: Added code for the ignore Pipe Seam Function.
                // Should return move cost value like it was broken if ignorePipes (j) is on.
                // Remove this for the Income Grapher
                let r = this.terrain[o + t * this.width],
                    a = i[r],
                    bp = i[115];
                let b = "S" === e || "L" === e;
                let s = 113 === r || 114 === r;
                void 0 === a && (a = b ? -1 : 1)
                if (0 === a && 195 !== r) {
                    a = -1;
                }
                if (j && s && !b) {
                    a = bp;
                }
                n[o + t * this.width] = a;
            }
        }
        return new WeightedDirectedGraph(n, this.width, this.height)
    }
    clear() {
        this.ctx.clearRect(0, 0, 16 * this.width, 16 * this.height);
        this.ctxRecon.clearRect(0, 0, 16 * this.width, 16 * this.height);
    }
    setFont() {
        return this.ctx.font = "10px monospace", this.ctx.textAlign = "center", this.ctx.strokeStyle = "black", this.ctx.lineWidth = 2, this.ctx.fillStyle = "white", this
    }
    drawText(e, t, n) {
        return this.ctx.strokeText(e, t, n), this.ctx.fillText(e, t, n), this
    }
    // By country, whoever's base is closer to a property is theirs.
    // Country: [] of Vector2i
    propertyMap = {};
    // Country: [] of IncomeDay
    incomeDays = {};
    countries = [];
    validCountries = [];
    // Country: [] of Unit
    predeployed = {};
    predeployedOther = {};
    block_properties = false;
    // County: [] of Property
    incomeFlips = {};
    tankOrderFound = false;
    income = 1000;
    contested = [];
    ftaInfo = {};
    // Country: ReconData
    reconData = {};
    tankDelay = 0;
    async recalculate() {
        window.RequestID = 0;

        let countries = [];
        this.bases = new Map();
        this.properties = new Map();
        this.propertyMap = {};
        this.incomeDays = {};
        this.tankOrder = [];
        this.extendedTankOrder = [];
        this.extendedTankOrderIndex = [];
        this.contested = [];
        this.ftaInfo = {
            "Day1": 0,
            "Day2": 0,
            "Day3": 0,
            "Neutrals": 0,
            "Flips": 0,
        };
        for (let pos in this.units) {
            let data = this.units[pos]
            if (data.id != 1) {
                continue;
            }
            let country = data.country;
            if (!countries.includes(country)) {
                countries.push(country)
                this.predeployed[country] = [];
            }
            this.predeployed[country].push(data);
        }
        this.predeployedOther = {};
        for (let pos in this.otherUnits) {
            let data = this.otherUnits[pos]
            if (data.id == 1) {
                continue;
            }
            let country = data.country;
            if (!countries.includes(country)) {
                countries.push(country);
            }
            if (this.predeployedOther[country] == undefined) {
                this.predeployedOther[country] = [];
            }
            this.predeployedOther[country].push(data);
        }
        let validCountries = [];
        for (let y = 0; y < this.height; y++) {
            for (let x = 0; x < this.width; x++) {
                let id = this.terrain[x + y * this.width];
                let data = BaseInfo.terrain[id]
                if (!validCountries.includes(data.country) && data.country != "" && (data.name.includes(" Lab") || data.name.includes(" HQ"))) {
                    validCountries.push(data.country);
                }
            }
        }
        for (let y = 0; y < this.height; y++) {
            for (let x = 0; x < this.width; x++) {
                let id = this.terrain[x + y * this.width];
                let data = BaseInfo.terrain[id]
                if (data.country == "" || data.name.includes(" Lab") || data.name.includes("Com Tower")) {
                    continue;
                }
                let country = data.country;
                if (!countries.includes(country) && validCountries.includes(country)) {
                    countries.push(country)
                }
            }
        }
        validCountries.sort(function(a, b){return BaseInfo.countries[a].id - BaseInfo.countries[b].id});
        this.countries = validCountries;
        this.validCountries = validCountries;
        for (let country of this.countries) {
            let firstDay = new IncomeDay();
            this.incomeDays[country] = [firstDay];
            this.propertyMap[country] = new Map();
        }
        this.assignProperties();
        for (let country of Object.keys(this.incomeDays)) {
            let firstDay = this.incomeDays[country][0];
            for (let pos of this.propertyMap[country].keys()) {
                let property = this.propertyMap[country].get(pos);
                if (property.type == "Base") {
                    this.bases.set(pos, property);
                    firstDay.startingBases.push(property)
                }
                if (property.type == "City" || property.type == "HQ") {
                    firstDay.properties.push(property)
                    firstDay.startingCities.push(property)
                }
                firstDay.startingPropertyCount += 1;
                firstDay.endingPropertyCount += 1;
            }
        }
        for (let country of Object.keys(this.incomeDays)) {
            let firstDay = this.incomeDays[country][0];
            firstDay.generatedFunds = 0;
            firstDay.generatedTaxedFunds = 0;
            this.countryData[country] = {}
            this.countryData[country][0] = {
                totalInf: this.predeployed[country] != undefined ? this.predeployed[country].length : 0,
                countryName: BaseInfo.countries[country].name
            }
        }
        this.setCityOwnership();
        this.calculateIncomeDays();
        this.countries = validCountries;

        this.reconData = {};
        for (let country of this.countries) {
            let recon = new ReconData();
            recon.country = country;
            this.reconData[country] = recon;

            for (let base of this.bases.values()) {
                if (base.owner != country) continue;
                recon.bases.push(base.where);
            }

            for (let property of this.properties.values()) {
                for (let base of property.reconDistances.keys()) {
                    let distance = property.reconDistances.get(base);
                    let hit = {
                        what: property,
                        cost: distance,
                        from: base.where,
                        base: base,
                    }
                    recon.allHits.push(hit);
                }
            }
        }

        for (let country of this.countries) {
            let recon = this.reconData[country];
            let index = 0;

            if (this.incomeDays[country] == undefined) continue;

            for (let day of this.incomeDays[country]) {
                let activeBases = 0;
                activeBases += day.startingBases.length
                for (let base of day.bases) {
                    if (base.captured != -1 && index > base.captured) activeBases += 1;
                    else if (base.captured == -1) activeBases += 1;
                }
                if (recon.earliestSkipRecon == 0) {
                    if (day.startingFunds >= 4000 && activeBases > 0) {
                        recon.earliestSkipRecon = index;
                    }
                }
                if (day.startingFunds >= 4000 && activeBases > 0) {
                    if (day.startingFunds - 4000 >= (activeBases - 1) * 1000) {
                        recon.earliestNormalRecon = index;
                    }
                }
                if (recon.earliestSkipRecon != 0 && recon.earliestNormalRecon != 0) break;
                index += 1;
            }
        }

        let ctx = this.ctx;
        for (let c of Object.keys(this.predeployed)) {
            let inf = await loadImage(`terrain/aw1/${c}infantry.gif`);
            for (let unit of this.predeployed[c]) {
                if (!this.countries.includes(unit.country)) continue;
                let where = new Vector2i();
                where.x = unit.startingPos ? unit.startingPos.x : unit.x;
                where.y = unit.startingPos ? unit.startingPos.y : unit.y;

                let ignore = false;

                for (let property of this.properties.values()) {
                    if (property.ghosted || property.taxDays > 0) {
                        if (property.where.x == where.x && property.where.y == where.y) {
                            ignore = true;
                            break;
                        }
                    }
                }

                if (ignore) continue;

                ctx.drawImage(inf, 16 * where.x, 16 * where.y);
                if (unit.health < 10) {
                    let damage = await loadImage(`terrain/ani/${unit.health}.gif`)
                    ctx.drawImage(damage, 16 * where.x + 8, 16 * where.y + 7);
                }
            }
        }
        for (let c of Object.keys(this.predeployedOther)) {
            let inf = await loadImage(`terrain/aw1/${c}infantry.gif`);
            for (let unit of this.predeployedOther[c]) {
                let n = BaseInfo.units[unit.id].name.toLowerCase().replace(" ", "");
                let image = await loadImage(`terrain/aw1/${c}${n}.gif`);
                ctx.drawImage(image, 16 * unit.x, 16 * unit.y);
                if (unit.health < 10) {
                    let damage = await loadImage(`terrain/ani/${unit.health}.gif`)
                    ctx.drawImage(damage, 16 * unit.x + 8, 16 * unit.y + 7);
                }
            }
        }
    }
    async assignProperties() {
        for (let y = 0; y < this.height; y++) {
            for (let x = 0; x < this.width; x++) {
                let id = this.terrain[x + y * this.width];
                let data = BaseInfo.terrain[id]
                if (data.defense < 3 || data.name.includes("Missile") || data.name.includes(" Lab") || data.name.includes("Com Tower") || data.name.includes("Mountain")) {
                    continue;
                }
                let country = data.country;
                let property = new Property();
                let pos = new Vector2i();
                pos.x = x;
                pos.y = y;
                property.owner = country;
                property.originalOwner = data.country;
                property.where = pos;
                if (data.name.includes("Base")) {
                    property.type = "Base";
                    this.bases.set(pos, property);
                    if (property.owner == "") {
                        this.properties.set(pos, property);
                        let id = this.terrain[pos.x + pos.y * this.width]
                        if (id == 35) {
                            property.neutralBase = true;
                        }
                    }
                } else if (data.name.includes("HQ")) {
                    property.type = "HQ";
                    this.properties.set(pos, property);
                } else {
                    property.type = "City"
                    this.properties.set(pos, property);
                }
                if (country != "") {
                    if (!(country in this.propertyMap)) this.propertyMap[country] = new Map();
                    this.propertyMap[country].set(pos, property);
                } else {
                    let id = this.terrain[pos.x + pos.y * this.width]
                    if (id == 35) {
                        property.asleep = true;
                    }
                }
            }
        }
    }
    async setCityOwnership() {
        // Base: [Country: cost]
        for (let unit of this.units) {
            //Ignore 1HP Units.
            if (unit.health == 1) continue;
            //Ignore Ghost Units.
            if (!this.countries.includes(unit.country)) continue;

            let graph = this.getMoveCostGraph(BaseInfo.units[unit.id].move_type, false);
            let pathing = new Dijkstra(graph, [unit], this.width, this.height).iterate(3 * 15);
            for (let base of this.bases.values()) {
                if (base.owner == unit.country) {
                    continue;
                }
                let s = base.where.x + base.where.y * this.width;
                let cost = pathing[s];
                if (!base.neutralBase) {
                    let p = new Dijkstra(graph, [unit], this.width, this.height).iterate(3);
                    cost = p[s];
                }
                this.properties.set(base.where, base)
                if (cost != -1 && cost != undefined) {
                    if (cost <= 3 && !base.neutralBase) {
                        base.owner = unit.country;
                        base.disabled = true;
                    }
                }
            }
        }
        for (let unit of this.units) {
            let baseOnTop = undefined;
            for (let base of this.bases.values()) {
                if (unit.x == base.where.x && unit.y == base.where.y) {
                    baseOnTop = base;
                    break;
                }
            }
            if (baseOnTop != undefined) {
                if (unit.health == 1 && unit.country != baseOnTop.owner && this.countries.includes(unit.country)) {
                    baseOnTop.taxDays = 1;
                    continue;
                } else if (!this.countries.includes(unit.country)) {
                    baseOnTop.ghosted = true;
                    baseOnTop.neutralBase = false;
                    continue;
                }
            }

            //Ignore 1HP units.
            if (unit.health == 1) continue;
            //Ignore Ghost Units.
            if (!this.countries.includes(unit.country)) continue;

            let graph = this.getMoveCostGraph(BaseInfo.units[unit.id].move_type, false);
            let pathing = new Dijkstra(graph, [unit], this.width, this.height).iterate(3 * 15);
            for (let base of this.bases.values()) {
                if (base.owner == unit.country) {
                    continue;
                }
                let s = base.where.x + base.where.y * this.width;
                let cost = pathing[s];
                if (!base.neutralBase) {
                    let p = new Dijkstra(graph, [unit], this.width, this.height).iterate(3);
                    cost = p[s];
                }
                this.properties.set(base.where, base)
                if (cost != -1 && cost != undefined) {
                    if (cost <= 3 && !base.neutralBase) {
                        base.owner = unit.country;
                        base.disabled = true;
                    }
                    if (base.neutralBase) {
                        if (base.unitDistances[unit.country] == undefined) {
                            base.unitDistances[unit.country] = cost;
                        }
                        if (base.unitDistances[unit.country] > cost) {
                            base.unitDistances[unit.country] = cost;
                        }
                    }
                }
                // Check with nearby bases so that the predeployed doesn't steal it.
                for (let b of this.bases.values()) {
                    if (b == base) continue;
                    if (b.disabled) continue;
                    if (b.ghosted) continue;
                    let fakeUnit = {
                        x: b.where.x,
                        y: b.where.y,
                        id: 1,
                        country: "os"
                    };
                    let pathing = new Dijkstra(graph, [fakeUnit], this.width, this.height).iterate(3 * 15);
                    let s = base.where.x + base.where.y * this.width;
                    let cost = pathing[s];
                    if (cost != -1 && cost != undefined) {
                        if (base.unitDistances[b.owner] != undefined && base.unitDistances[b.owner] > cost) {
                            base.unitDistances[b.owner] = cost;
                        } else if (base.unitDistances[b.owner] == undefined) {
                            base.unitDistances[b.owner] = cost;
                        }
                    }
                }
            }
        }
        for (let base of this.bases.values()) {
            if (!base.neutralBase) continue;
            if (base.owner != "") continue;
            let items = Object.keys(base.unitDistances).map(function(key) {
                return [key, base.unitDistances[key]];
            });
            // Sort the array based on the second element
            items.sort(function(first, second) {
                if (second == undefined) return -1;
                if (first == undefined) return 1;
                return first[1] - second[1];
            });
            if (items.length > 0) {
                let winner = items[0][0];
                base.owner = winner;
            }
        }
        let neutralBases = [];
        // First Pass For Bases.
        for (let pos of this.properties.keys()) {
            let property = this.properties.get(pos);
            if (!property.neutralBase) continue;
            let fakeUnit = {
                x: pos.x,
                y: pos.y,
                id: 1,
                country: "os"
            };
            let graph = this.getMoveCostGraph(BaseInfo.units[fakeUnit.id].move_type, false);
            let pathCosts = {};
            let baseCosts = {};
            for (let country of this.countries) {
                let costs = [];
                for (let base of this.bases.values()) {
                    if (base == property) continue;
                    if (base.owner != country) {
                        continue;
                    }

                    // Infantry Check
                    fakeUnit.x = base.where.x;
                    fakeUnit.y = base.where.y;
                    let pathing = new Dijkstra(graph, [fakeUnit], this.width, this.height).iterate(3 * 15);
                    let s = pos.x + pos.y * this.width;
                    let cost = pathing[s];
                    let lowestDistance = Math.abs(base.where.x - property.where.x) + Math.abs(base.where.y - property.where.y);
                    if (cost != -1 && cost != undefined) {
                        costs.push(cost);
                        property.distances.set(base, Math.ceil(cost / 3))
                    }
                }
                let unitDistance = property.unitDistances[country]
                if (unitDistance != undefined) {
                    costs.push(unitDistance);
                }
                costs.sort(function(a, b){return a - b});
                if (costs.length > 0) {
                    pathCosts[country] = costs[0];
                }
            }
            let items = Object.keys(pathCosts).map(function(key) {
                return [key, pathCosts[key]];
            });
            // Sort the array based on the second element
            items.sort(function(first, second) {
                if (second == undefined) return -1;
                if (first == undefined) return 1;
                return first[1] - second[1];
            });
            if (items.length > 0) {
                if (items.length >= 2 && items[0][1] == items[1][1]) {
                    property.owner = "";
                    property.contested = true;
                    this.contested.push(property);
                } else {
                    let winner = items[0][0];
                    property.owner = winner;
                    property.travelDays = Math.ceil(pathCosts[winner] / 3);
                    this.ftaInfo.Neutrals += 1;
                    neutralBases.push(property);
                }
            }
        }
        for (let pos of this.properties.keys()) {
            let property = this.properties.get(pos);
            if (property.neutralBase) continue;
            let fakeUnit = {
                x: pos.x,
                y: pos.y,
                id: 1,
                country: "os"
            };

            for (let unit of this.units) {
                if (unit.x == pos.x && unit.y == pos.y && !this.countries.includes(unit.country)) {
                    property.ghosted = true;
                } else if (unit.x == pos.x && unit.y == pos.y && unit.health == 1) {
                    property.taxDays = 1;
                }
            }

            let graph = this.getMoveCostGraph(BaseInfo.units[fakeUnit.id].move_type, false);
            let reconGraph = this.getMoveCostGraph(BaseInfo.units[5].move_type, false);

            let pathCosts = {};
            let baseCosts = {};
            for (let country of this.countries) {
                let costs = [];
                let all_bases = [];
                for (let b of this.bases.values()) all_bases.push(b);
                for (let b of neutralBases) all_bases.push(b);
                for (let base of all_bases) {
                    if (base.owner != country) {
                        continue;
                    }
                    fakeUnit.x = base.where.x;
                    fakeUnit.y = base.where.y;
                    let dij = new Dijkstra(graph, [fakeUnit], this.width, this.height);
                    let pathing = dij.iterate(3 * 15);
                    let s = pos.x + pos.y * this.width;
                    let cost = pathing[s];
                    if (cost != -1 && cost != undefined) {
                        costs.push(pathing[s]);
                        property.distances.set(base, Math.ceil(pathing[s] / 3))
                    }
                }
                costs.sort(function(a, b){return a - b});
                if (costs.length > 0) {
                    pathCosts[country] = costs[0];
                }
            }
            let items = Object.keys(pathCosts).map(function(key) {
                return [key, pathCosts[key]];
            });
            // Sort the array based on the second element
            items.sort(function(first, second) {
                return first[1] - second[1];
            });
            if (items.length > 0) {
                if (items.length >= 2 && items[0][1] == items[1][1]) {
                    property.owner = "";
                    property.contested = true;
                    this.contested.push(property);
                } else {
                    let winner = items[0][0];
                    property.travelDays = Math.ceil(pathCosts[winner] / 3);
                    property.owner = winner;
                    if (property.travelDays <= 3) {
                        if (property.travelDays == 1) this.ftaInfo.Day1 += 1;
                        else if (property.travelDays == 2) this.ftaInfo.Day2 += 1;
                        else if (property.travelDays == 3) this.ftaInfo.Day3 += 1;
                    }
                }
            }
        }
        let reconGraph = this.getMoveCostGraph(BaseInfo.units[5].move_type, false);
        for (let pos of this.properties.keys()) {
            let property = this.properties.get(pos);
            for (let country of this.countries) {
                if (property.owner == country) continue;

                let costs = [];
                let all_bases = [];
                for (let b of this.bases.values()) all_bases.push(b);
                for (let b of neutralBases) all_bases.push(b);
                for (let base of all_bases) {
                    if (base.owner != country) {
                        continue;
                    }

                    // Recon Check
                    let recon = {
                        x: base.where.x,
                        y: base.where.y,
                        id: 5,
                        country: "os"
                    };
                    // Check within 5 days
                    // The default reader will check for 2 days anyway.
                    let reconPathing = new Dijkstra(reconGraph, [recon], this.width, this.height).iterate(8 * 5);
                    let sR = pos.x + pos.y * this.width;
                    let costR = reconPathing[sR];
                    property.reconDistances.set(base, costR);
                }
            }
        }
    }
    // Country
      // Day:
        // startingFunds: int,
        // endingFunds: int,
        // startingIncome: int,
        // endingIncome: int
    countryData = {};
    // {
    // Country: os
    // Day: int
    // }
    tankOrder = [];
    // In Letters
    extendedTankOrder = [];
    extendedTankOrderIndex = [];
    // Country
    // {
    // Day: int
    // }
    flipQueue = {}
    // Country
    // {
    // Day: [] of Vector2i()
    // }
    whereFlips = {};
    async calculateIncomeDays() {
        let unitMap = [];
        for (let country of Object.keys(this.predeployed)) {
            for (let unit of this.predeployed[country]) {
                unitMap.push(structuredClone(unit));
            }
        }
        let unitMapOther = [];
        for (let country of Object.keys(this.predeployedOther)) {
            for (let unit of this.predeployedOther[country]) {
                unitMapOther.push(structuredClone(unit));
            }
        }
        let day = 0;
        for (let country of this.countries) {
            this.incomeFlips[country] = {};
            this.flipQueue[country] = {};
            this.whereFlips[country] = {};
        }
        while (Object.keys(this.tankOrder).length <= 2 * this.countries.length && day < 15) {
            day += 1;
            for (let country of this.countries) {
                if (this.whereFlips[country][day] == undefined) {
                    this.whereFlips[country][day] = [];
                }
                let d = this.incomeDays[country][day] ?? new IncomeDay();
                this.incomeDays[country][day] = d;

                let leftoverRequests = [];
                let pd = null;
                if (this.incomeDays[country][day - 1] != undefined) {
                    pd = this.incomeDays[country][day - 1];

                    for (let r of pd.leftoverRequests) leftoverRequests.push(r);

                    d.previousDay = pd;
                    d.capRequests = new Map(pd.capRequests);
                    d.bases = pd.bases.slice();
                    d.properties = pd.properties.slice();
                    d.startingBases = pd.startingBases.slice();
                    d.startingCities = pd.startingCities.slice();
                    d.recentBaseCaps = pd.recentBaseCaps.slice();
                    d.recentCityCaps = pd.recentCityCaps.slice();
                    d.recentUsedCityCaps = pd.recentUsedCityCaps.slice();
                    d.startingPropertyCount = pd.endingPropertyCount;
                    let withoutFlipped = [];
                    let flipped = [];
                    for (let prop of d.properties) {
                        if (prop.flipped) {
                            flipped.push(prop);
                        } else {
                            withoutFlipped.push(prop);
                        }
                    }
                    if (this.countries[0] == country) {
                        for (let prop of flipped) {
                            if (prop.originalOwner == country && prop.flipped && prop.captured + 1 == day) {
                                d.startingPropertyCount -= 1;
                            }
                        }
                        for (let base of d.startingBases) {
                            if (base.flipped && base.captured + 1 == day) d.startingPropertyCount -= 1;
                        }
                    }
                    if (this.countries[0] != country) {
                        for (let prop of flipped) {
                            if (prop.originalOwner == country && prop.flipped && prop.captured == day) {
                                d.startingPropertyCount -= 1;
                            }
                        }
                        for (let base of d.startingBases) {
                            if (base.flipped && base.captured == day) d.startingPropertyCount -= 1;
                        }
                    }
                    d.properties = withoutFlipped;
                    d.startingFunds = pd.endingFunds + d.getStartingIncome(this.income);
                    d.generatedFunds += d.getStartingIncome(this.income) + pd.generatedFunds;
                    d.generatedTaxedFunds += d.getStartingIncome(this.income) + pd.generatedTaxedFunds;
                    d.totalUnitValue += pd.totalUnitValue;
                    d.totalInf = pd.totalInf;
                    d.totalTanks = pd.totalTanks;
                    d.totalOtherDeployed = pd.totalOtherDeployed;
                }
                let all_requests = [];
                let infantryPositions = [];
                let infantryHealths = {};
                for (let pos of d.recentCityCaps) {
                    if (!d.recentUsedCityCaps.includes(pos)) {
                        infantryPositions.push(pos);
                    }
                }
                // true = Infantry, false = Base;
                let operatingBases = [];
                if (day == 1) {
                    for (let pos of this.propertyMap[country].keys()) {
                        let property = this.propertyMap[country].get(pos);
                        if (property.owner != country) {
                            continue;
                        }
                        if (property.type == "Base" && !d.startingBases.includes(property)) {
                            d.bases.push(property);
                            d.startingBases.push(property)
                        } else if (property.type != "Base" && !d.startingCities.includes(property)) {
                            d.properties.push(property);
                            d.startingCities.push(property);
                        }
                    }
                    d.startingPropertyCount = d.startingBases.length + d.startingCities.length;
                    d.startingFunds = d.startingPropertyCount * this.income;
                    for (let c of Object.keys(this.predeployedOther)) {
                        if (c != country) {
                            continue;
                        }
                        for (let unit of this.predeployedOther[c]) {
                            let value = BaseInfo.units[unit.id].cost;
                            let n = BaseInfo.units[unit.id].name.toLowerCase().replace(" ", "");
                            d.totalUnitValue += value;
                            if (d.totalOtherDeployed[n] == undefined) {
                                d.totalOtherDeployed[n] = 0;
                            }
                            d.totalOtherDeployed[n] += 1;
                        }
                    }
                    for (let c of Object.keys(this.predeployed)) {
                        if (c != country) {
                            continue;
                        }
                        for (let unit of this.predeployed[c]) {
                            let pos = new Vector2i();
                            pos.x = unit.x;
                            pos.y = unit.y;
                            infantryPositions.push(pos)
                            let value = 1e3 * (unit.health / 10);
                            d.totalUnitValue += value;
                        }
                    }
                    d.totalInf = this.predeployed[country] != undefined ? this.predeployed[country].length : 0;
                }
                // Unit Repairs
                if (d.startingFunds > 0) {
                    let allUnits = unitMap.slice();
                    for (let u of unitMapOther) allUnits.push(u);

                    allUnits.sort((a, b) => {
                        if (a.x === b.x) {
                            return a.y - b.y; // Sort by y if x values are equal
                        }
                        return a.x - b.x; // Sort by x first
                    });

                    for (let unit of allUnits) {
                        let health = unit.health;
                        if (unit.country != country) continue;
                        if (health == 10) continue;

                        let pos = new Vector2i();
                        pos.x = unit.x;
                        pos.y = unit.y;

                        let req = undefined;
                        if (unit.id == 1) {
                            for (let request of d.capRequests.values()) {
                                if (request.health < 10 && request.unit == unit) {
                                    req = request;
                                    break;
                                }
                            }

                            // Skip Me if I am moving yet I could have been healed.
                            if (req == undefined && day != 1) continue;
                            // It needs to have been captured the day before.
                            if (req != undefined && !req.isCaptured(day - 1)) continue;
                        }

                        let moveType = BaseInfo.units[unit.id].move_type;
                        let property = null;
                        let at = pos;
                        if (req != undefined) {
                            at = req.to;
                        }
                        for (let prop of this.properties.values()) {
                            if (prop.where.x == at.x && prop.where.y == at.y) {
                                property = prop;
                                break;
                            }
                        }
                        if (property == undefined) {
                            for (let base of this.bases.values()) {
                                let where = base.where;
                                if (where.x == pos.x && where.y == pos.y) {
                                    property = base;
                                    break
                                }
                            }
                            if (property == undefined) continue;
                        }

                        if (property.owner != country) continue;
                        if (property.type != "Base") {
                            if (property.captured == -1 && !d.startingCities.includes(property)) continue;
                            if (property.captured != -1 && property.captured > day) continue;
                        }

                        let terrainID = this.terrain[at.x + this.width * at.y];
                        if (terrainID == undefined) continue;

                        let terrainInfo = BaseInfo.terrain[terrainID];
                        if (moveType == "A" && !terrainInfo.name.includes("Airport")) continue;
                        else if ((moveType == "S" || moveType == "L") && !terrainInfo.name.includes("Port")) continue;
                        else if ((moveType != "A" && moveType != "S" && moveType != "L") &&
                                 !terrainInfo.name.includes("City") && !terrainInfo.name.includes("Base") && !terrainInfo.name.includes("HQ")) continue;

                        let unitData = BaseInfo.units[unit.id];
                        let cost = unitData.cost;
                        let costPerHealth = cost / 10;
                        let maxHeal = Math.min(2, 10 - health);
                        let totalCost = costPerHealth * maxHeal;

                        let newFunds = d.startingFunds - totalCost;
                        if (newFunds < 0) continue;

                        let repair = {
                            x: at.x,
                            y: at.y,
                            health: maxHeal,
                            newHealth: unit.health + maxHeal,
                            cost: totalCost,
                            who: country,
                            what: unitData.name,
                            sprite: unitData.name.toLowerCase().replace(" ", ""),
                        };
                        d.repairs.push(repair);
                        d.startingFunds -= totalCost;
                        d.generatedTaxedFunds -= totalCost;
                        d.totalUnitValue += totalCost;
                        unit.health += maxHeal;
                        if (unit.id == 1) unit.startingPos = at;
                    }
                }
                for (let pos of this.bases.keys()) {
                    let base = this.bases.get(pos);
                    if (base.owner != country || base.neutral || base.disabled || base.asleep || base.ghosted) {
                        continue;
                    }
                    operatingBases.push(base);
                }
                for (let base of d.bases) {
                    if (operatingBases.includes(base) || base.asleep || base.ghosted) {
                        continue;
                    }
                    operatingBases.push(base);
                }
                let redo = [];
                for (let infPos of infantryPositions) {
                    for (let pos of this.properties.keys()) {
                        let property = this.properties.get(pos);
                        if (d.capRequests.has(pos) || d.startingBases.includes(property) || d.startingCities.includes(property)) {
                            continue;
                        }
                        if (property.owner != country) {
                            continue;
                        }
                        let request = new CapRequest();
                        request.when = day;
                        request.from = infPos;
                        request.to = pos;
                        request.what = property;
                        let fakeUnit = {
                            x: infPos.x,
                            y: infPos.y,
                            id: 1,
                            country: country
                        };
                        let c = this.properties.get(infPos);
                        // if (property.where.x == 20 && property.where.y == 8) {
                        //     console.log("Walked to 20, 8!")
                        //     console.log(request)
                        //     console.log(structuredClone(c))
                        // }
                        if (c != undefined) {
                            if (c.next != null || c.chained || property.chained || c.fromRequests.length > 0) {
                                continue;
                            }
                        }
                        let unit = undefined;
                        let health = 10;
                        for (let u of unitMap) {
                            if (u.x == infPos.x && u.y == infPos.y) {
                                unit = u;
                                health = u.health;
                            }
                        }
                        if (health == 1) continue;
                        let graph = this.getMoveCostGraph(BaseInfo.units[fakeUnit.id].move_type, false);
                        let pathing = new Dijkstra(graph, [fakeUnit], this.width, this.height).iterate(3 * 15);
                        let s = pos.x + pos.y * this.width;
                        let cost = pathing[s];
                        if (cost != -1 && cost != undefined) {
                            request.travelDays = Math.ceil(cost / 3);
                            request.createInfantry = false;
                            request.neutralBase = property.neutralBase;
                            request.reason = "Infantry";
                            request.chained = true;
                            request.health = health;
                            request.unit = unit;
                            all_requests.push(request)
                        }
                    }
                }
                for (let base of operatingBases) {
                    for (let pos of this.properties.keys()) {
                        let property = this.properties.get(pos);
                        if (d.capRequests.has(pos) && property.owner == country && !(d.startingBases.includes(property) || d.startingCities.includes(property))) {
                            let r = d.capRequests.get(pos);
                            let myDist = property.distances.get(base) ?? -1;
                            if (myDist == -1) {
                                continue;
                            }
                            if (r.when + r.getDayCost() >= day + myDist + 1 + (r.what.taxDays > 0 ? 1 : 0)) {
                                d.capRequests.delete(pos);
                            }
                        } else {
                            if (d.startingBases.includes(property) || d.startingCities.includes(property)) {
                                continue;
                            }
                            if (property.owner != country) {
                                continue;
                            }
                        }
                        let request = new CapRequest();
                        request.when = day;
                        request.from = base.where;
                        request.to = pos;
                        request.what = property;
                        request.travelDays = property.distances.get(base) ?? -1;
                        if (d.recentBaseCaps.includes(base.where)) {
                            request.createInfantry = false;
                        }
                        if (day == 1 && infantryPositions.includes(base.where)) {
                            request.createInfantry = false;
                        }
                        request.neutralBase = property.neutralBase;
                        if (request.travelDays == -1) {
                            continue;
                        }
                        request.reason = "Base";
                        all_requests.push(request)
                    }
                }
                for (let request of leftoverRequests) all_requests.push(request);
                // Skip Requests that have a faster request from elsewhere
                for (let request of all_requests) {
                    if (request.travelDays == -1) {
                        continue;
                    }
                    // Compare the distances from each other base you own.
                    // If it is faster to build from the other base even if you skip a day, do a different cap instead.
                    if (request.neutralBase) {
                        let skipMe = false;
                        for (let base of request.what.distances.keys()) {
                            if (skipMe) {
                                continue;
                            }
                            if (base.country != request.what.country) {
                                continue;
                            }
                            let theirDistance = request.what.distances.get(base);
                            let requester = this.bases.get(request.from);
                            let myDistance = request.what.distances.get(requester);
                            if (theirDistance != -1 && theirDistance + 1 < myDistance) {
                                skipMe = true;
                            }
                        }
                        if (skipMe) {
                            request.priority = -1;
                            continue;
                        }
                    }
                }
                // Sort all requests
                all_requests.sort(function(a, b) {
                    if (a.getDayCost() == -1) return 1;
                    if (b.getDayCost() == -1) return -1;

                    if (a.what.disabled && !b.what.disabled) return -1;
                    if (b.what.disabled && !a.what.disabled) return 1;

                    // Prioritize `neutralBase`
                    if (a.neutralBase && !b.neutralBase) return -1;
                    if (!a.neutralBase && b.neutralBase) return 1;

                    // If both have `neutralBase` (either both `true` or both `false`), sort by `priority` (descending)
                    if (a.priority !== b.priority) {
                        return b.priority - a.priority;
                    }

                    if (a.getDayCost() - b.getDayCost() == 0) {
                        if (a.what.originalOwner != "" && a.what.originalOwner != country) return -1;
                        if (b.what.originalOwner != "" && b.what.originalOwner != country) return 1;
                        if (!a.createInfantry && b.createInfantry) return -1;
                        if (a.createInfantry && !b.createInfantry) return 1;
                    }

                    // If `priority` is the same, sort by `dayCost` (ascending)
                    return a.getDayCost() - b.getDayCost();
                });
                let doneBases = [];
                let doneInfs = [];
                // Add Chain Requests from every recentCityCap that has been done.
                let requests = new Map(d.capRequests);
                for (let to of requests.keys()) {
                    let request = requests.get(to);
                    if (request.isCaptured(day) || request.neutralBase) {
                        continue;
                    }
                    let prop = request.what;
                    for (let cityPos of d.recentCityCaps.slice()) {
                        let city = d.capRequests.get(cityPos).what;
                        if (city == undefined) continue;
                        let r = d.capRequests.get(cityPos);
                        if (r == undefined || city.chained || prop.chained || city.chain != undefined || city.next != undefined ||
                            d.recentUsedCityCaps.includes(cityPos) || d.recentUsedCityCaps.includes(prop.where)) {
                            continue;
                        }
                        if (!r.isCaptured(Math.max(request.when, day))) {
                            continue;
                        }
                        if (d.recentUsedCityCaps.includes(city.where)) {
                            continue;
                        }
                        let chainRequest = new CapRequest();
                        chainRequest.when = city.captured + 1;
                        chainRequest.from = cityPos;
                        chainRequest.to = to;
                        chainRequest.what = request.what;
                        let fakeUnit = {
                            x: cityPos.x,
                            y: cityPos.y,
                            id: 1,
                            country: country
                        };
                        let graph = this.getMoveCostGraph(BaseInfo.units[fakeUnit.id].move_type, false);
                        // Search 4 days deep.
                        let pathing = new Dijkstra(graph, [fakeUnit], this.width, this.height).iterate(3 * 4);
                        let s = to.x + to.y * this.width;
                        let cost = pathing[s];
                        if (cost != -1 && cost != undefined) {
                            chainRequest.travelDays = Math.ceil(cost / 3);
                            chainRequest.createInfantry = false;

                            // Mark city as used as soon as the request is valid
                            if (chainRequest.travelDays < request.travelDays &&
                                request.when + request.getDayCost() >= chainRequest.when + chainRequest.getDayCost()) {

                                // Mark the city as used to prevent it from being reused
                                city.chained = true;
                                if (city.type != "Base") d.recentUsedCityCaps.push(cityPos);

                                d.leftoverRequests.push(request);

                                // Update the chain request
                                d.capRequests.set(to, chainRequest);
                                chainRequest.chained = true;
                                chainRequest.reason = "Chain";
                                city.chain = chainRequest;
                                city.next = prop;
                                city.fromRequests = [chainRequest];
                                request.what.next = null;
                                request.what.chain = null;
                                prop.capturer = chainRequest;

                                // Remove the city from recentCityCaps
                                let index = d.recentCityCaps.indexOf(cityPos);
                                if (index !== -1) {
                                    d.recentCityCaps.splice(index, 1);
                                }

                                redo.push(request.from);
                                let allCapRequests = [];
                                for (let r of d.capRequests.values()) allCapRequests.push(r);
                                allCapRequests.reverse();
                                for (let r of allCapRequests) {
                                    if (r.adjusted) break;
                                    if (r.when == chainRequest.when - 1 && r.from == request.from && r.reason == "Base") {
                                        r.when -= 1;
                                        r.adjusted = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                //Second pass for the bases that got replaced when a faster request was found
                for (let request of all_requests) {
                    if (request.travelDays == -1) {
                        continue;
                    }
                    if (request.priority < 0 || doneBases.includes(request.from) || doneInfs.includes(request.from) || d.capRequests.has(request.to)) {
                        continue;
                    }
                    let c = this.properties.get(request.from);
                    if (c != undefined && c.type != "Base") {
                        c.next = this.properties.get(request.to);
                        if (request.reason == "Infantry") {
                            c.chained = true;
                        }
                        let index = d.recentCityCaps.indexOf(c.where);
                        if (index !== -1) {
                            d.recentCityCaps.splice(index, 1);
                        }
                        if (c.type == "City" && c.fromRequests.length > 0) continue;
                        c.fromRequests.push(request);
                    }
                    d.capRequests.set(request.to, request);
                    if (request.createInfantry) {
                        doneBases.push(request.from);
                    } else {
                        doneInfs.push(request.from);
                    }
                }
                let totalCaps = d.startingBases.length + d.startingCities.length;
                for (let base of d.startingBases) {
                    if (base.flipped) totalCaps -= 1;
                }
                for (let prop of d.startingCities) {
                    if (prop.flipped) totalCaps -= 1;
                }
                let recentBaseCaps = 0;
                // Income Flips and Update Caps
                for (let request of d.capRequests.values()) {
                    if (request.isCaptured(day)) {
                        if (!d.properties.includes(request.what) && request.what.type == "City") {
                            let from = request.from;
                            let recentlyHealed = unitMap.find(x => {
                                return x.startingPos != undefined && x.startingPos.x == from.x && x.startingPos.y == from.y && x.health < 10;
                            });
                            // If the unit was moving someone and finished capturing.
                            // Change the position so that repairs can be done!
                            if (recentlyHealed != undefined) {
                                recentlyHealed.x = request.to.x;
                                recentlyHealed.y = request.to.y;
                            }
                            d.properties.push(request.what);
                            d.recentCityCaps.push(request.to);
                            request.what.captured = day;
                            request.what.capturer = request;
                        } else if (!d.properties.includes(request.what) && request.what.type == "Base") {
                            let from = request.from;
                            let recentlyHealed = unitMap.find(x => {
                                return x.startingPos != undefined && x.startingPos.x == from.x && x.startingPos.y == from.y
                            });
                            // If the unit was moving someone and finished capturing.
                            // Change the position so that repairs can be done!
                            if (recentlyHealed != undefined) {
                                recentlyHealed.x = request.to.x;
                                recentlyHealed.y = request.to.y;
                            }
                            d.properties.push(request.what);
                            if (!request.what.flipped) {
                                request.what.captured = day;
                                request.what.capturer = request;
                            }
                        }
                        totalCaps += 1;
                        for (let c of Object.keys(this.incomeDays)) {
                            let checked = false;
                            let firstDay = this.incomeDays[c][0];
                            if (firstDay.startingCities.includes(request.what)) {
                                if (checked) {
                                    continue;
                                }
                                let d = this.countries[0] == c ? day + 1 : day;
                                if (this.incomeFlips[c][d] == undefined) {
                                    this.incomeFlips[c][d] = 0;
                                    this.flipQueue[c][d] = 0;
                                }
                                this.incomeFlips[c][d] += 1;
                                this.flipQueue[c][d] += 1;
                                if (!request.what.flipped) {
                                    if (this.whereFlips[request.what.originalOwner][d] == undefined) {
                                        this.whereFlips[request.what.originalOwner][d] = [];
                                    }
                                    this.whereFlips[request.what.originalOwner][d].push(request.to);
                                    this.ftaInfo.Flips += 1;
                                }
                                request.what.flipped = true
                                checked = true;
                            }
                            if (firstDay.startingBases.includes(request.what) && !request.what.flipped) {
                                if (checked) {
                                    continue;
                                }
                                let d = this.countries[0] != c ? day : day + 1;
                                if (this.incomeFlips[c][d] == undefined) {
                                    this.incomeFlips[c][d] = 0;
                                    this.flipQueue[c][d] = 0;
                                }
                                this.incomeFlips[c][d] += 1;
                                this.flipQueue[c][d] += 1;
                                checked = true;
                            }
                        }
                        if (!d.bases.includes(request.what) && (request.neutralBase || request.what.disabled || request.asleep)) {
                            d.bases.push(request.what)
                            recentBaseCaps += 1;
                            d.recentBaseCaps.push(request.to);
                            request.what.asleep = false;
                            if (request.what.disabled) {
                                if (!request.what.flipped && request.what.originalOwner != "") {
                                    let d = this.countries[0] != request.what.originalOwner ? day : day + 1;
                                    if (this.whereFlips[request.what.originalOwner][d] == undefined) {
                                        this.whereFlips[request.what.originalOwner][d] = [];
                                    }
                                    this.whereFlips[request.what.originalOwner][d].push(request.to);
                                }
                                request.what.flipped = true
                            }
                        }
                    }
                }
                d.endingPropertyCount = Math.max(d.endingPropertyCount, totalCaps);
                let funds = d.startingFunds;
                let infantryBases = (d.startingBases.length + d.bases.length) - recentBaseCaps;
                for (let base of d.startingBases) {
                    if (base.disabled || base.ghosted || base.asleep || (base.owner != country) || base.flipped) infantryBases -= 1;
                }
                let tankBases = 0;
                // Buy a tank if you have a spare base.
                let order = this.countries.indexOf(country);
                while (funds >= 7000 + (infantryBases - 1) * 1000 && infantryBases > 0 && day >= this.tankDelay) {
                    tankBases += 1;
                    infantryBases -= 1;
                    funds -= 7000
                    d.totalUnitValue += 7000;
                    d.totalTanks += 1;
                    if (Object.keys(this.tankOrder).length < 4) {
                        this.tankOrder.push({
                            country: country,
                            day: day
                        });
                    }
                    if (this.extendedTankOrder.length < 16) {
                        this.extendedTankOrder.push(alphabet.slice(order, order + 1));
                        this.extendedTankOrderIndex.push(day);
                    }
                }
                d.endingFunds = funds - infantryBases * 1000;
                d.endingFunds = Math.max(0, d.endingFunds);
                d.totalUnitValue += infantryBases * 1000;
                d.totalInf += infantryBases;
                this.countryData[country][day] = {
                    startingFunds: d.startingFunds,
                    endingFunds: d.endingFunds,
                    startingIncome: d.getStartingIncome(this.income),
                    endingIncome: d.getEndingIncome(this.income),
                    generatedFunds: d.generatedFunds,
                    generatedTaxedFunds: d.generatedTaxedFunds,
                    totalUnitValue: d.totalUnitValue,
                    countryName: BaseInfo.countries[country].name,
                    totalInf: d.totalInf,
                    totalTanks: d.totalTanks,
                    totalOtherDeployed: d.totalOtherDeployed,
                    repairs: d.repairs,
                    totalBases: operatingBases.length,
                }
            }
        }
        for (let country of Object.keys(this.countryData)) {
            for (let day of Object.keys(this.countryData[country])) {
                if (this.incomeFlips[country][day] == undefined) {
                    this.incomeFlips[country][day] = 0;
                }
            }
        }
        for (let country of Object.keys(this.countryData)) {
            for (let day of Object.keys(this.countryData[country])) {
                let prevDay = day - 1;
                let prevIncomeFlips = this.incomeFlips[country][prevDay];
                if (prevIncomeFlips == undefined) {
                    continue;
                }
                if (this.incomeFlips[country][day] != prevIncomeFlips) {
                    this.countryData[country][day].incomeFlips = this.incomeFlips[country][day];
                }
            }
        }
        for (let country of Object.keys(this.countryData)) {
            for (let day of Object.keys(this.countryData[country])) {
                if (this.whereFlips[country][day] != undefined) {
                    this.countryData[country][day].flips = this.whereFlips[country][day];
                }
            }
        }
    }
}
class WeightedDirectedGraph {
    constructor(e, t, n) {
        this.data = e, this.width = t, this.height = n
    }
    get length() {
        return this.data.length
    }
    getWeight(e) {
        return this.data[e]
    }
    getXY(e, t) {
        return this.data[e + t * this.width]
    }
    getNeighbors(e, t) {
        if (!(e >= 0 && e < this.width && t >= 0 && t < this.height)) throw new Error(`Graph node {x: ${e}, y: ${t}} not in bounds ${this.width},${this.height}`);
        let n = [];
        return e - 1 >= 0 && n.push({
            x: e - 1,
            y: t
        }), t - 1 >= 0 && n.push({
            x: e,
            y: t - 1
        }), e + 1 < this.width && n.push({
            x: e + 1,
            y: t
        }), t + 1 < this.height && n.push({
            x: e,
            y: t + 1
        }), n
    }
}
class Dijkstra {
    constructor(e, t, n, i) {
        // Sets up width and height for the instance
        this.width = n;
        this.height = i;

        // Stores the graph in the instance
        this.graph = e;

        // Initializes an empty array to hold start positions
        this.start = [];

        // Creates a distance array with undefined values, length is width * height
        this.distance = new Array(n * i).fill(void 0);

        // Iterates over each element in t (units)
        t.forEach((e) => {
            // Adds each starting position as an object with x, y, and a distance of 0
            this.start.push({
                x: e.x,
                y: e.y,
                dist: 0
            });
        });
    }
    makeQueue() {
        return new TinyQueue([], ((e, t) => e.dist - t.dist))
    }
    iterate(e) {
        let t = this.makeQueue(),
            n = new Array(this.width * this.height).fill(!1);
        this.start.forEach((e => {
            t.push(e), n[e.x + e.y * this.width] = !0
        }));
        let i = 0,
            o = 1;
        for (; t.length > 0;) {
            let r = e * o,
                a = t;
            for (t = this.makeQueue(); a.length > 0;) {
                if (i++ > 2e6) return alert("@steve on discord, dijkstra got stuck.");
                let {
                    x: e,
                    y: o,
                    dist: s
                } = a.pop(), l = e + o * this.width;
                this.distance[l] = s;
                let d = this.graph.getNeighbors(e, o);
                for (let i of d) {
                    let s = i.x + i.y * this.width;
                    const d = this.graph.getWeight(s);
                    if (d >= 0) {
                        let u = this.distance[l] + d;
                        !n[s] && u > r ? t.push({
                            x: e,
                            y: o,
                            dist: r
                        }) : (void 0 === this.distance[s] || u < this.distance[s]) && (a.push({
                            x: i.x,
                            y: i.y,
                            dist: u
                        }), this.distance[s] = u, n[s] = !0)
                    } else this.distance[s] = -1, n[s] = !0
                }
            }
            o++
        }
        return this.distance
    }
}
class IncomeDay {
    previousDay = null;
    //Notes where the income checks should start.
    startingBases = [];
    startingCities = [];
    recentBaseCaps = [];
    recentCityCaps = [];
    recentUsedCityCaps = [];
    // Array of Property
    bases = [];
    // Array of Property
    properties = [];
    // [pos] = CapRequest
    capRequests = new Map();
    startingPropertyCount = 0;
    endingPropertyCount = 0;
    incomeFlips = 0;
    startingFunds = 0;
    endingFunds = 0;
    totalUnitValue = 0;
    generatedFunds = 0;
    generatedTaxedFunds = 0;
    totalInf = 0;
    totalTanks = 0;
    //repair.what [{{ repair.x }}, {{ repair.y }}] was repaired for {{ repair.health }} HP [{{ repair.cost }}G]!
    repairs = [];
    // Unit ID = Amount as int
    totalOtherDeployed = {};
    leftoverRequests = [];
    getStartingIncome(funds) {
        return funds * this.startingPropertyCount;
    }
    getEndingIncome(funds) {
        return funds * this.endingPropertyCount;
    }
}
class CapRequest {
    constructor() {
        this.id = window.RequestID + 1;
        window.RequestID += 1;
    }
    id = 0;
    when = 0;
    from = new Vector2i();
    to = new Vector2i();
    //Property
    what;
    adjusted = false;
    travelDays = 0;
    // If the cap request is a Neutral Base, it must be done first.
    neutralBase = false;
    // If an infantry doesn't have to be created, it will remove one extra day.
    createInfantry = true;
    priority = 0;
    contested = false;
    chained = false;
    reason = "";
    //Property;
    next = null;
    health = 10;
    // Used to check if there is a unit assigned to the request
    // So that it isn't counted for repairs.
    unit;
    isCapturing(day) {
        return day == this.when + this.travelDays + (this.createInfantry ? 1 : 0) + (Math.ceil(20 / this.health) - 2) + (this.what ? this.what.taxDays : 0);
    }
    isCaptured(day) {
        return day >= this.when + this.travelDays + (this.createInfantry ? 1 : 0) + (Math.ceil(20 / this.health) - 2) + (this.what ? this.what.taxDays : 0);
    }
    getDayCost() {
        return Math.max(1, this.travelDays + (this.createInfantry ? 1 : 0) + (Math.ceil(20 / this.health) - 2) + (this.what ? this.what.taxDays : 0))
    }
}
class Vector2i {
    constructor(x = 0, y = 0) {
        this.x = x;
        this.y = y;
    }

    x = 0;
    y = 0;
}
class ReconData {
    country = "";
    earliestSkipRecon = 0;
    earliestNormalRecon = 0;
    // Vector2i
    bases = [];
    // {
    // what: Property
    // cost: int
    // from: Vector2i
    // }
    allHits = [];
    // Cutoff in Days
    // Basically 8 recon tiles + 1 to attack
    getHits(day = 3, cutoff = 2) {
        let data = new Map();
        for (let base of this.bases) {
            let vector = new Vector2i(base.x, base.y);
            data.set(vector, this.getHitsFrom(base, day, cutoff));
        }

        return data;
    }
    getHitsFrom(from, day = 3, cutoff = 2) {
        if (from == undefined) return [];
        let naturalHits = [];
        let interruptHits = [];
        let hits = [naturalHits, interruptHits];
        for (let hit of this.allHits) {
            let base = hit.from;
            if (base != from) continue;

            let property = hit.what;
            if (property == undefined) continue;

            let distance = hit.cost;
            if (distance == -1) continue;

            // Do you care about hitting it before it was captured?
            if (hit.base.captured != -1 && day <= hit.base.captured) continue;
            if (distance <= cutoff * 8 + 1) {
                naturalHits.push({
                    where: property.where,
                    from: base,
                });
                if (property.captured == -1 || day + cutoff < property.captured) {
                    interruptHits.push({
                        where: property.where,
                        from: base,
                    });
                }
            }
        }

        return hits;
    }
    getHitCountFrom(from, day = 3, cutoff = 2) {
        let hitData = this.getHitsFrom(from, day, cutoff);
        return [hitData[0].length, hitData[1].length];
    }
}
class Property {
    owner = "";
    travelDays = 0;
    taxDays = 0;
    captured = -1;
    where = new Vector2i();
    //Base, City, Property
    type = "Base";
    // Base: int
    distances = new Map();
    // Country: int (Smallest Possible)
    unitDistances = {};
    // Base: int
    // Country: [] as Array
    //   base_location: Vector2i
    //   cost: int (Smallest Possible)
    reconDistances = new Map();
    // Is it an enemy base? Make sure to go for it first!
    enemy = false;
    // Is it a nuetral base? Ignore the until capped.
    neutralBase = false;
    // Capping an enemy base? Disable production from there.
    disabled = false;
    flipped = false;
    // If this property is part of a chain
    chained = false;
    //CapRequest
    chain;
    from = null;
    next;
    fromRequests = [];
    //Cap Request
    capturer = null;
    asleep = false;
    ghosted = false;
}
class IncomeReport {
    name = "Automated Report"
    customReport = false;
    // Array[Vector2i];
    bases = [];
    //who: country as String
       //where [x,y] as Vector2i
          //when: int
          //from: [x,y] as Vector2i
          //originalOwner: country as String
    // Example
    // country:os
    // [3,2]=8|oO:bm|cF:[1,1]
    // contested
    // [5,8]
    properties = {}
    //where [x,y] as Vector2i
       //owner: country as String ["" is contested]
    config = {}
    report = "";
    identifier = "!=====[data]=====!";
    toText() {
        let result = ""
        result += "name:" + this.name;
        result += "<br>";
        result += "map_name:" + window.incomeGrapher.mapName;
        result += "<br>";
        result += "map_id:" + window.incomeGrapher.mapID;
        result += "<br>";
        result += this.identifier;
        result += "<br>";
        let anyContested = false;
        for (let country of Object.keys(this.properties)) {
            for (let property of this.properties[country]) {
                if (property.contested) {
                    anyContested = true;
                    break;
                }
            }
        }
        if (anyContested) {
            result += "contested";
            result += "<br>";
            for (let country of Object.keys(this.properties)) {
                for (let property of this.properties[country]) {
                    if (!property.contested) continue;
                    let code = "";
                    code += `[${property.where.x},${property.where.y}]=`;
                    code += `-1`;
                    code += "<br>";
                    result += code;
                }
            }
        }
        for (let country of Object.keys(this.properties)) {
            result += country + "<br>"
            for (let property of this.properties[country]) {
                if (property.type == "Base") {
                    result += `base:[${property.where.x},${property.where.y}]`;
                    result += "<br>";
                }
            }
            for (let property of this.properties[country]) {
                if (property.contested) continue;
                let code = "";
                code += `[${property.where.x},${property.where.y}]=`;
                code += `${property.when}`;
                if (property.originalOwner != "" && property.originalOwner != property.owner) {
                    code += `|oO:${property.originalOwner}`;
                }
                if (property.from != undefined) {
                    code += `|from:[${property.from.x},${property.from.y}]`;
                }
                code += "<br>";
                result += code;
            }
        }
        return result
    }
    //who: country as String
       //where [x,y] as Vector2i
          //when: int
          //from: [x,y] as Vector2i
          //originalOwner: country as String
    fromText(text) {
        this.properties = {};
        this.bases = [];
        let t = text.replace(/<br\s*\/?>/gi, "\n");
        const lines = t.split('\n');
        const data = {
            name: "",
            map_name: "",
            map_id: "",
        };

        let inDataSection = false;
        let country = "";
        for (const line of lines) {
            // Skip data section identifier
            if (line.startsWith('!=====[')) {
                inDataSection = !inDataSection;
                continue;
            }

            if (!inDataSection) {
                // Metadata parsing
                if (line.startsWith('name:')) {
                    data.name = line.split(':')[1];
                } else if (line.startsWith('map_name:')) {
                    data.map_name = line.split(':')[1];
                } else if (line.startsWith('map_id:')) {
                    data.map_id = line.split(':')[1];
                }
            } else {
                if (!line.startsWith('base:') && !line.startsWith('[') && line.trim() !== '') {
                    // Parse country
                    country = line.trim();
                    if (!Object.keys(this.properties).includes(country)) {
                        this.properties[country] = [];
                    }
                }
                if (country == "") continue;
                // Data section parsing
                if (line.startsWith('base:')) {
                    // Parse base coordinates
                    const coords = line.match(/\[(-?\d+),(-?\d+)\]/);
                    if (coords) {
                        this.bases.push(new Vector2i(parseInt(coords[1]), parseInt(coords[2])));
                    }
                } else if (line.match(/^\[.*?\]=/)) {
                    // Parse city information
                    const positionMatch = line.match(/^\[(-?\d+),(-?\d+)\]/);
                    const detailsMatch = line.split('=');

                    if (positionMatch && detailsMatch.length > 1) {
                        const position = new Vector2i(parseInt(positionMatch[1]), parseInt(positionMatch[2]));
                        let detailData = this.parseDetails(detailsMatch[1]);
                        let fromMatch = (detailData.fromInfo != null ? detailData.fromInfo.split(",") : null)
                        let from = (fromMatch != null ? new Vector2i(parseInt(fromMatch[0]), parseInt(fromMatch[1])) : null)
                        let data = {
                            where: position,
                            when: parseInt(detailData.captureDay),
                            owner: country,
                            originalOwner: detailData.ownerInfo,
                            from: from,
                            type: this.isCity(position) ? "City" : "Base",
                            contested: country == "contested"
                        }
                        this.properties[country].push(data);
                    }
                }
            }
        }
        let clone = Object.assign({}, this.properties);
        let sortedKeys = Object.keys(this.properties);
        sortedKeys.sort((o1, o2) => {
            let o1Data = BaseInfo.countries[o1];
            let o2Data = BaseInfo.countries[o2];

            if (o1Data == undefined && o2Data != undefined) return 1;
            if (o1Data != undefined && o2Data == undefined) return -1;
            if (o1Data == undefined && o2Data == undefined) return 0;

            return o1Data.id - o2Data.id;
        });
        this.properties = {};
        for (let key of Object.keys(clone)) {
            this.properties[key] = clone[key];
        }
        let keys = [];
        for (let key of sortedKeys) {
            if (Object.keys(BaseInfo.countries).includes(key)) keys.push(key);
        }
        window.incomeGrapher.countries = keys;
        this.name = data.name;
    }
    parseDetails(detailString) {
        // Regular expression to match the capture day, owner info, and from info
        const captureDayMatch = detailString.match(/^([^|]+)/); // First part before '|'
        const ownerInfoMatch = detailString.match(/oO:([^|]+)/); // Match 'oO:'
        const fromInfoMatch = detailString.match(/from:\[([^\]]+)\]/); // Match 'from:'

        // Extracted values (default to null if not found)
        const captureDay = captureDayMatch ? captureDayMatch[1] : -1;
        const ownerInfo = ownerInfoMatch ? ownerInfoMatch[1] : "";
        const fromInfo = fromInfoMatch ? fromInfoMatch[1] : null;

        return { captureDay, ownerInfo, fromInfo };
    };
    isCity(where) {
        if (where == null) return false;
        for (let pos of this.bases) {
            if (pos.x == where.x && pos.y == where.y) {
                return false;
            }
        }
        return true;
    }
    setFont() {
        window.incomeGrapher.ctx.setLineDash([]);
        window.incomeGrapher.ctx.font = "10px monospace";
        window.incomeGrapher.ctx.textAlign = "center";
        window.incomeGrapher.ctx.strokeStyle = "black";
        window.incomeGrapher.ctx.lineWidth = 2;
        window.incomeGrapher.ctx.fillStyle = "white";

        window.incomeGrapher.ctxRecon.setLineDash([]);
        window.incomeGrapher.ctxRecon.font = "10px monospace";
        window.incomeGrapher.ctxRecon.textAlign = "center";
        window.incomeGrapher.ctxRecon.strokeStyle = "black";
        window.incomeGrapher.ctxRecon.lineWidth = 2;
        window.incomeGrapher.ctxRecon.fillStyle = "white";
    }
    drawText(e, t, n, recon) {
        let ctx = recon ? window.incomeGrapher.ctxRecon : window.incomeGrapher.ctx;
        ctx.strokeText(e, t, n);
        ctx.fillText(e, t, n);
    }
    //who: country as String
       //where [x,y] as Vector2i
          //when: int
          //from: [x,y] as Vector2i
          //originalOwner: country as String
    BaseInfo = null;
    async renderDrawings() {
        let ctx = window.incomeGrapher.ctx;
        let height = window.incomeGrapher.height;
        let width = window.incomeGrapher.width;
        ctx.clearRect(0, 0, 16 * width, 16 * height)

        for (let country of Object.keys(this.properties)) {
            if (country == "") continue;
            let color = country != "contested" ? this.BaseInfo.countries[country].color : "0, 0, 0";
            for (let property of this.properties[country]) {
                if (country == "contested") continue;
                let x = property.where.x;
                let y = property.where.y;
                let s = x + y * width;
                let from = property.from;
                if (from == null) continue;
                let when = property.when;
                if (s >= 0 && when != -1) {
                    ctx.setLineDash([]);
                    ctx.fillStyle = `rgba(${color}, 0.15)`
                    ctx.strokeStyle = `rgba(${color}, 0.7)`;
                    // Draw filled rectangle
                    ctx.fillRect(16 * x, 16 * y, 16, 16);

                    // Set line width and draw rectangle border
                    ctx.lineWidth = 1;
                    ctx.strokeRect(16 * x, 16 * y, 16, 16);

                    // If condition `n` is true, set font and draw text `s`
                    this.setFont();
                    //this.drawText(request.getDayCost() + request.when, 16 * a + 8, 16 * t + 12);

                    // Begin a Path
                    ctx.beginPath();
                    ctx.moveTo(16 * from.x + 8, 16 * from.y + 8);
                    ctx.lineTo(16 * x + 8, 16 * y + 8);
                    ctx.strokeStyle = `rgba(${color}, 1.0)`
                    ctx.setLineDash([4, 4]);

                    // Draw the Path
                    ctx.stroke();
                }
            }
        }
        for (let country of Object.keys(this.properties)) {
            if (country == "") continue;
            let color = country != "contested" ? this.BaseInfo.countries[country].color : "0, 0, 0";
            for (let property of this.properties[country]) {
                if (property.contested) continue;
                if (property.ghosted) continue;
                let x = property.where.x;
                let y = property.where.y;
                let s = x + y * width;
                let when = property.when;
                if (s >= 0 && when > 0) {
                    // Check condition based on `c`, and if true, draw an image
                    //ctx.drawImage(inf, 16 * x, 16 * y);
                    ctx.setLineDash([]);
                    ctx.strokeStyle = "black";
                    this.drawText(`${when}`, 16 * x + 8, 16 * y + 12);
                }
            }
            for (let property of this.properties[country]) {
                if (property.contested) continue;
                if (!(property.ghosted || property.taxDays > 0)) continue;
                let x = property.where.x;
                let y = property.where.y;
                let s = x + y * width;
                let when = property.when;
                if (s >= 0 && when > 0) {
                    // Check condition based on `c`, and if true, draw an image
                    //ctx.drawImage(inf, 16 * x, 16 * y);
                    ctx.setLineDash([]);
                    ctx.strokeStyle = "black";
                    let done = false;
                    for (let c of Object.keys(window.incomeGrapher.predeployed)) {
                        let inf = await loadImage(`terrain/aw1/${c}infantry.gif`);
                        if (done) break;
                        for (let unit of window.incomeGrapher.predeployed[c]) {
                            if (unit.country == property.owner) continue;
                            let where = new Vector2i();
                            where.x = unit.startingPos ? unit.startingPos.x : unit.x;
                            where.y = unit.startingPos ? unit.startingPos.y : unit.y;

                            if (property.where.x == where.x && property.where.y == where.y) {
                                ctx.drawImage(inf, 16 * where.x, 16 * where.y);
                                done = true;
                                break;
                            }
                        }
                    }
                    if (property.ghosted) this.drawText(`${when}G`, 16 * x + 8, 16 * y + 12);
                    else if (property.taxDays > 0) this.drawText(`${when}T`, 16 * x + 8, 16 * y + 12);
                    else this.drawText(`${when}`, 16 * x + 8, 16 * y + 12);
                }
            }
        }

        let icon = new Image();
        icon.src = `terrain/moveplanner.gif`;
        for (let country of Object.keys(this.properties)) {
            for (let property of this.properties[country]) {
                if (!property.contested || property.when == 0) continue;
                let x = property.where.x;
                let y = property.where.y;
                let s = x + y * this.width;
                ctx.drawImage(icon, 16 * x + 1, 16 * y + 1, 14, 14);
            }
        }
    }
    async renderReconData(day = 3, cutoff = 2) {
        let ctx = window.incomeGrapher.ctxRecon;
        let height = window.incomeGrapher.height;
        let width = window.incomeGrapher.width;
        let data = window.incomeGrapher.reconData;
        ctx.clearRect(0, 0, 16 * width, 16 * height);

        ctx.fillStyle = `rgba(${"0, 0, 0"}, 0.45)`;
        ctx.fillRect(0, 0, 16 * width, 16 * height);

        for (let country of Object.keys(data)) {
            let reconData = data[country];
            let color = country != "contested" ? this.BaseInfo.countries[country].color : "0, 0, 0";

            // base: Property
            //     naturalHits
            //         where: Vector2i,
            //         from: base,
            //     interrupts
            //         where: Vector2i,
            //         from: base,
            let allHits = reconData.getHits(day, cutoff);

            for (let base of allHits.keys()) {
                ctx.setLineDash([]);
                ctx.fillStyle = `rgba(${color}, 0.15)`
                ctx.strokeStyle = `rgba(${color}, 0.7)`;
                // Draw filled rectangle
                ctx.fillRect(16 * base.x, 16 * base.y, 16, 16);

                // Set line width and draw rectangle border
                ctx.lineWidth = 1;
                ctx.strokeRect(16 * base.x, 16 * base.y, 16, 16);

                for (let naturalHit of allHits.get(base)[0]) {
                    let where = naturalHit.where;
                    let skip = false;

                    for (let interruptHit of allHits.get(base)[1]) {
                        if (interruptHit.where.x == where.x && interruptHit.where.y == where.y) {
                            skip = true;
                            break;
                        }
                    }

                    let s = where.x + where.y * width;
                    if (s < 0 || skip) continue;

                    // Begin a Path
                    ctx.beginPath();
                    ctx.lineWidth = 3;
                    ctx.moveTo(16 * base.x + 8, 16 * base.y + 8);
                    ctx.lineTo(16 * where.x + 8, 16 * where.y + 8);
                    ctx.strokeStyle = `rgba(${color}, .65)`
                    ctx.setLineDash([]);
                    //ctx.setLineDash([8, 12]);

                    // Draw the Path
                    ctx.stroke();

                    let recon = await loadImage(`terrain/aw1/${country}recon.gif`);
                    ctx.drawImage(recon, 16 * where.x, 16 * where.y);

                    // If condition `n` is true, set font and draw text `s`
                    this.setFont();
                    this.drawText("Slow!", 16 * where.x + 8, 16 * where.y - 4, true);

                }
                for (let interruptHit of allHits.get(base)[1]) {
                    let where = interruptHit.where;

                    let s = where.x + where.y * width;
                    if (s < 0) continue;

                    // Begin a Path
                    ctx.beginPath();
                    ctx.lineWidth = 3;
                    ctx.moveTo(16 * base.x + 8, 16 * base.y + 8);
                    ctx.lineTo(16 * where.x + 8, 16 * where.y + 8);
                    ctx.strokeStyle = `rgba(${color}, .65)`
                    ctx.setLineDash([]);
                    //ctx.setLineDash([8, 12]);

                    // Draw the Path
                    ctx.stroke();

                    let recon = await loadImage(`terrain/aw1/${country}recon.gif`);
                    ctx.drawImage(recon, 16 * where.x, 16 * where.y);

                    // If condition `n` is true, set font and draw text `s`
                    this.setFont();
                    this.drawText("Hit!", 16 * where.x + 8, 16 * where.y + 12 - 16, true);

                }
            }
        }
    }
    clearReconData() {
        let height = window.incomeGrapher.height;
        let width = window.incomeGrapher.width;
        window.incomeGrapher.ctxRecon.clearRect(0, 0, 16 * width, 16 * height);
    }
    countryData = {};
    incomeFlips = {};
    flipQueue = {};
    whereFlips = {};
    generateData() {
        window.incomeGrapher.tankOrder = [];
        window.incomeGrapher.extendedTankOrder = [];
        window.incomeGrapher.extendedTankOrderIndex = [];

        let countries = Object.keys(this.properties);
        let sortedCountries = [];
        for (let c of countries) if (c != "contested") sortedCountries.push(c);
        sortedCountries.sort((o1, o2) => Object.keys(BaseInfo.countries).indexOf(o1) - Object.keys(BaseInfo.countries).indexOf(o2));
        for (let country of sortedCountries) {
            if (country == "contested") continue;
            this.incomeFlips[country] = {};
            this.flipQueue[country] = {};
            this.whereFlips[country] = {};
            this.countryData[country] = {};
        }

        let day = 0;
        for (let country of sortedCountries) {
            if (country == "contested") continue;
            let mine = [];
            for (let prop of this.properties[country]) {
                if (prop.when < day) mine.push(prop);
            }
            let funds = mine.length * window.incomeGrapher.income;
            let infs = 0;
            for (let data of window.incomeGrapher.units) {
                if (data.id != 1) {
                    continue;
                }
                let c = data.country;
                if (c == country) infs += 1;
            }
            this.countryData[country][day] = {
                previousDay: null,
                startingFunds: 0,
                endingFunds: 0,
                startingIncome: funds,
                endingIncome: funds,
                generatedFunds: 0,
                generatedTaxedFunds: 0,
                totalUnitValue: infs * 1000,
                countryName: BaseInfo.countries[country].name,
                totalInf: infs,
                totalTanks: 0,
                flips: [],
                repairs: {},
            }
        }

        while (day < 15) {
            day += 1;
            for (let country of sortedCountries) {
                let first = sortedCountries[0] == country;
                let d = {};
                let pd = null;
                if (this.countryData[country][day - 1] != undefined) {
                    pd = this.countryData[country][day - 1];
                    d.previousDay = pd;
                    d.startingIncome = pd.endingIncome - (this.whereFlips[country][day] ? this.whereFlips[country][day].length : 0);
                    // d.startingIncome = d.startingIncome - (pd.flips ? pd.flips.length : 0);
                    d.startingFunds = pd.endingFunds + d.startingIncome;
                    d.generatedFunds = d.startingIncome + pd.generatedFunds;
                    d.generatedTaxedFunds = d.startingIncome + pd.generatedTaxedFunds;
                    d.totalUnitValue = pd.totalUnitValue;
                    d.totalInf = pd.totalInf;
                    d.totalTanks = pd.totalTanks;
                    d.totalOtherDeployed = pd.totalOtherDeployed;
                    d.countryName = pd.countryName;
                    d.flips = [];
                    d.repairs = {};
                }
                let mine = [];
                for (let prop of this.properties[country]) {
                    if (prop.when <= day) mine.push(prop);
                }
                for (let otherCountry of Object.keys(this.properties)) {
                    if (otherCountry == country) continue;
                    for (let prop of this.properties[otherCountry]) {
                        if (first) {
                            if (prop.when >= day && prop.originalOwner == country) {
                                mine.push(prop);
                                if (day == 1) {
                                    d.startingIncome += window.incomeGrapher.income;
                                    d.startingFunds += window.incomeGrapher.income;
                                    d.generatedFunds += window.incomeGrapher.income;
                                    d.generatedTaxedFunds += window.incomeGrapher.income;
                                }
                            } else if (prop.when + 1 == day && prop.originalOwner == country) {
                                if (this.whereFlips[country][day] == undefined) this.whereFlips[country][day] = [];
                                this.whereFlips[country][day].push(prop.where)
                                d.flips.push(prop.where);
                                d.startingIncome -= window.incomeGrapher.income;
                                d.startingFunds -= window.incomeGrapher.income;
                                d.generatedFunds -= window.incomeGrapher.income;
                                d.generatedTaxedFunds -= window.incomeGrapher.income;
                            }
                        } else {
                            if (prop.when > day && prop.originalOwner == country) {
                                mine.push(prop);
                                if (day == 1) {
                                    d.startingIncome += window.incomeGrapher.income;
                                    d.startingFunds += window.incomeGrapher.income;
                                    d.generatedFunds += window.incomeGrapher.income;
                                    d.generatedTaxedFunds += window.incomeGrapher.income;
                                }
                            } else if (prop.when == day && prop.originalOwner == country) {
                                d.flips.push(prop.where);
                                d.startingIncome -= window.incomeGrapher.income;
                                d.startingFunds -= window.incomeGrapher.income;
                                d.generatedFunds -= window.incomeGrapher.income;
                                d.generatedTaxedFunds -= window.incomeGrapher.income;
                            }
                        }
                    }
                }
                let ownedCount = mine.length;
                d.endingIncome = ownedCount * window.incomeGrapher.income;

                let bases = [];
                for (let prop of this.properties[country]) {
                    if (prop.when < day && !this.isCity(prop.where)) bases.push(prop);
                }

                let funds = d.startingFunds;
                let infantryBases = bases.length;
                let tankBases = 0;
                let order = sortedCountries.indexOf(country);
                while (funds >= 7000 + (infantryBases - 1) * 1000 && infantryBases > 0) {
                    tankBases += 1;
                    infantryBases -= 1;
                    funds -= 7000
                    d.totalUnitValue += 7000;
                    d.totalTanks += 1;
                    if (window.incomeGrapher.tankOrder.length < 4) {
                        window.incomeGrapher.tankOrder.push({
                            country: country,
                            day: day
                        });
                    }
                    if (window.incomeGrapher.extendedTankOrder.length < 16) {
                        window.incomeGrapher.extendedTankOrder.push(alphabet.slice(order, order + 1));
                        window.incomeGrapher.extendedTankOrderIndex.push(day);
                    }
                }

                d.endingFunds = funds - infantryBases * 1000;
                d.endingFunds = Math.max(0, d.endingFunds);
                d.totalUnitValue += infantryBases * 1000;
                d.totalInf += infantryBases;

                this.countryData[country][day] = d;
            }
        }
        window.incomeGrapher.countryData = this.countryData;
        window.incomeGrapher.countries = sortedCountries;
        window.incomeGrapher.incomeFlips = this.incomeFlips;
        window.incomeGrapher.flipQueue = this.flipQueue;
        window.incomeGrapher.whereFlips = this.whereFlips;
    }
}
function initPrevmaps() {
    Vue.component("PrevIncomeGrapher", {
        template: `
        <div id='replay-misc-controls'>
            <div ref='openBtn' class='flex v-center' style='padding: 0px 5px; cursor: pointer; user-select: none;' @click='open = !open'>
                <img src='terrain/ani/neutralcity.gif'><b>Estimate</b>
            </div>
            <div v-show='open && chartMode'
                :style="{ top: position.y + 'px',
                          right: -position.x + 'px',
                          zIndex: '1000',
                          width: '480px',
                          position: 'absolute' }">
                <div
                    class='bordertitle flex'
                    style='color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between; cursor: grab;'
                    draggable="true"
                    @dragstart="onDragStart"
                    @dragend="onDragEnd">
                    <div style="font-weight: bold; display: block; float: left;">
                        Income Charts
                    </div>
                    <div @click='manualMode = false, reconMode = true, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Recon Info
                    </div>
                    <div @click='manualMode = true, reconMode = false, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Manual Mode
                    </div>
                    <div @click='manualMode = false, reconMode = false, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; margin-right: 16px; background: #7ebeff; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        View Charts
                    </div>
                    <div style="cursor: pointer" @click="() => { open = false; manualMode = false }">
                        <img width='16' src="terrain/close.png"/>
                    </div>
                </div>
                <div id='income-grapher-visualizer' v-show='graphOpen'>
                    <div style='width: 480px; height:480px; border: 1px solid black; background: #eeeeee'>
                        <canvas id="income-graph"></canvas>
                    </div>
                    <div style="display: flex; flex-direction: column; gap: 4px;">
                        <button style="color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between;" @click='generateFundsChart()'>Chart by Income</button>
                    </div>
                    <div style="display: flex; flex-direction: column; gap: 4px;">
                        <button style="color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between;" @click='generateTotalTaxedFundsChart()'>Chart by Generated Funds (With Repair Tax)</button>
                    </div>
                    <div style="display: flex; flex-direction: column; gap: 4px;">
                        <button style="color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between;" @click='generateTotalFundsChart()'>Chart by Generated Funds (Without Repair Tax)</button>
                    </div>
                </div>
            </div>
            <div v-show='open && reconMode'
                :style="{ top: position.y + 'px',
                          right: -position.x + 'px',
                          zIndex: '1000',
                          width: '480px',
                          position: 'absolute' }">
                <div class='bordertitle flex' style='color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between; cursor: grab;'
                    draggable="true"
                    @dragstart="onDragStart"
                    @dragend="onDragEnd">
                    <div style="font-weight: bold; display: block; float: left;">
                        Recon Info
                    </div>
                    <div @click='manualMode = false, reconMode = false, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #7ebeff; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Recon Info
                    </div>
                    <div @click='manualMode = true, reconMode = false, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Manual Mode
                    </div>
                    <div @click='manualMode = false, reconMode = false, chartMode = true' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; margin-right: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        View Charts
                    </div>
                    <div style="cursor: pointer" @click="() => { open = false; manualMode = false }">
                        <img width='16' src="terrain/close.png"/>
                    </div>
                </div>
                <div style="background: #eeeeee; padding-top: 4px; border: solid 2px black">
                    <h4 style="margin-bottom: 10px;">Early Recon Build Notes</h4>
                    <div style="display: flex; flex-direction: column; text-align: center; font-weight: bold; font-size: 12px;">
                        <label style="margin-bottom: 2px; padding-bottom: 0px">Additional Notes on the First Skip/No-Skip Recon Builds.</label>
                        <label style="margin-bottom: 2px; padding-bottom: 0px">Indicates what properties they might reach from each base.</label>
                        <label style="margin-bottom: 2px; padding-bottom: 0px">The Calculator does not adjust funding and income based on these results!</label>
                        <label style="margin-bottom: 10px">Most Info will be similar unless there are neutral bases activating later!</label>
                    </div>
                    <div style="display: flex; flex-direction: column; text-align: center; font-weight: bold; font-size: 12px; border: 1px black solid">
                        <div style="display: flex; flex-direction: column; background: #0066cc; border-bottom: 1px solid black">
                            <label style="font-weight: bold; color: #ffffff; font-size: 12px;">Search From Day:
                              <input v-model.number="reconDay" type="number" max="6" min="1" style="width:96px" />
                            </label>
                            <label style="font-weight: bold; color: #ffffff; font-size: 11px; font-style: italic; margin-bottom: 2px">The Earlier The Recon, The More Properties They Can Interrupt!</label>
                            <label style="font-weight: bold; color: #ffffff; font-size: 12px;">Search X Days Deep For Recon Moves:
                              <input v-model.number="reconSearch" type="number" max="6" min="1" style="width:96px" />
                            </label>
                            <div v-show='showRecon' @click='clearReconData()' style="font-weight: bold; padding: 8px; background: #ff972b; border: 2px solid black">
                                Hide Recon Info
                            </div>
                            <div v-show='!showRecon' @click='showReconData()' style="font-weight: bold; padding: 8px; background: #7ebeff;">
                                Show Recon Info
                            </div>
                        </div>
                        <div style="width: 100%; border-bottom: 1px black solid;">
                            <div
                              v-for="(reconData, countryCode) in recons"
                              :key="countryCode"
                              :style="{
                                display: 'flex',
                                alignItems: 'center',
                                borderTop: '1px black solid',
                                paddingRight: '8px',
                                paddingLeft: '8px',
                                paddingBottom: '8px',
                                paddingTop: '8px',
                                background: getCountryColorWithAlpha(BaseInfo.countries[countryCode]?.color, 0.5) || '#eeeeee'
                              }"
                            >
                                <div style="display: flex; flex-direction: row; width: 100%">
                                    <!-- General Information -->
                                    <div style="display: flex; flex-direction: column; align-items: center; gap: 8px; width: 160px">
                                        <div style="display: flex; flex-direction: row; align-items: center">
                                            <img :src="'terrain/ani/' + countryCode + 'recon.gif'" alt="Tank Image" style="width: 24px; height: 24px;">
                                            <img
                                              :src="'terrain/aw1/' + countryCode + 'logo.gif'"
                                              style="width: 24px; height: 24px; margin-right: 5px;"
                                            >
                                            <!-- Country Name -->
                                            <strong style="font-size: 14px">{{ BaseInfo.countries[countryCode]?.name ?? 'No Data' }}</strong>
                                        </div>
                                        <div style="display: flex; flex-direction: column; align-items: center; width: 100%; background: #eee; padding: 2px; border: 1px solid black">
                                          <label style="flex-grow: 1; font-size: 14px;">Earliest Recon</label>
                                          <br>
                                          <label style="flex-grow: 1; font-size: 12px; font-style: italic;">With Base-Skips</label>
                                          <br>
                                          <strong style="font-size: 18px">{{ "Day #" + (reconData.earliestSkipRecon ?? '???') }}</strong>
                                        </div>
                                        <div style="display: flex; flex-direction: column; align-items: center; width: 100%; background: #eee; padding: 2px; border: 1px solid black">
                                          <label style="flex-grow: 1; font-size: 14px;">Earliest Recon</label>
                                          <br>
                                          <label style="flex-grow: 1; font-size: 12px; font-style: italic;">No Base-Skips</label>
                                          <br>
                                          <strong style="font-size: 18px">{{ "Day #" + (reconData.earliestNormalRecon ?? '???') }}</strong>
                                        </div>
                                    </div>
                                    <div style="border-left: 1px solid; margin-left: 8px; margin-right: 8px; width: 2px;">
                                    </div>
                                    <!-- Base Information -->
                                    <div style="display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; background: #eeeeee; border: 1px black solid;">
                                        <div v-for="(base, index) in reconData.bases" :key="index" style="padding-top: 4px; padding-bottom: 4px">
                                            <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0px;">
                                                <div style="display: flex; flex-direction: row; align-items: center; gap: 4px;">
                                                    <img
                                                      :src="'terrain/ani/' + getImageName(reconData.country) + 'base.gif'"
                                                      style="width: 16px; height: 16px; object-fit: cover; margin-right: 5px; object-position: bottom;"
                                                    >
                                                    <label>[{{ base.x }}, {{ base.y }}] can reach </label>
                                                    <label>{{ reconData.getHitCountFrom(base, reconDay, reconSearch)[0] }} enemy/cont. properties!</label>
                                                </div>
                                                <div style="display: flex; flex-direction: row; align-items: center; gap: 4px;">
                                                    <img
                                                      :src="'terrain/ani/' + reconData.country + 'recon.gif'"
                                                      style="width: 16px; height: 16px; object-fit: cover; margin-right: 5px; object-position: bottom;"
                                                    >
                                                    <label>{{ reconData.getHitCountFrom(base, reconDay, reconSearch)[1] }} are interruptable! </label>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div v-show='open && manualMode'
                :style="{ top: position.y + 'px',
                          right: -position.x + 'px',
                          zIndex: '1000',
                          width: '480px',
                          position: 'absolute' }">
                <div class='bordertitle flex' style='color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between; cursor: grab;'
                    draggable="true"
                    @dragstart="onDragStart"
                    @dragend="onDragEnd">
                    <div style="font-weight: bold; display: block; float: left;">
                        Manual Mode
                    </div>
                    <div @click='manualMode = false, reconMode = true, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Recon Info
                    </div>
                    <div @click='manualMode = false, reconMode = false, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #7ebeff; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Manual Mode
                    </div>
                    <div @click='manualMode = false, reconMode = false, chartMode = true' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; margin-right: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        View Charts
                    </div>
                    <div style="cursor: pointer" @click="() => { open = false; manualMode = false }">
                        <img width='16' src="terrain/close.png"/>
                    </div>
                </div>
                <div class='manual-mode-intro' style="background: #7ebeff; border: 1px black solid; padding: 4px; color: #000000; font-size: 12px">
                    <div style="display: flex; flex-direction: column; max-width: 288px; align-items: left; justify-content: left; margin: 0 auto;">
                        <label style='text-align: center; padding-bottom: 8px'><strong>Welcome To Manual Mode!</strong></label>
                        <label style='text-align: left; padding-bottom: 4px'>Here you can edit the calculator to specify specific builds or dictate who owns which properties.</label>
                        <label style='text-align: left; padding-bottom: 2px'>At the bottom of this panel, you can see the report as it's being built.</label>
                        <label style='text-align: left; padding-bottom: 2px'>You can save the report, customize it and even import it later!</label>
                        <label style='text-align: left; padding-bottom: 16px'>The Automated Calculator will also generate a report here.</label>
                        <label style='text-align: left; padding-bottom: 2px'>I recommend generating a report with the Automated Calculator to get used to the syntax.</label>
                        <label style='text-align: left; padding-bottom: 2px'><strong>Using the automated calculator will RESET the report!</strong></label>
                        <label style='text-align: left; padding-bottom: 2px'><strong>COPY And SAVE The Report before using it!</strong></label>
                    </div>
                </div>
                <div class="property-config-controls" style="background: #ffffff; border: 1px black solid; padding: 4px;">
                    <label><strong>Property Configurator</strong></label>
                    <div class="property-config" style="background: #eeeeee; gap: 8px">
                        <div style="display: flex; flex-direction: column">
                            <div style="display: flex; flex-direction: row; align-items: center; margin-bottom: 8px">
                                <div style="display: flex; flex-direction: row; align-items: center; margin-left: 4px; gap: 8px;">
                                    <img width='32' src="terrain/ani/neutralcity.gif"/>
                                    <strong>Property</strong>
                                </div>
                                <strong style="margin-left: auto; margin-right: 24px">Position: {{
                                        currentReport?.config?.where
                                            ? '[' + currentReport.config.where.x + ', ' + currentReport.config.where.y + ']'
                                            : '???'
                                    }}
                                </strong>
                            </div>
                            <!-- Owner -->
                            <label style="text-align: left; margin-left: 4px; margin-right: 32px;">
                              <strong>Owner: </strong>
                              <input
                                  type="text"
                                  :value="currentReport?.config?.what?.owner === 'none' ? 'None' : currentReport.config.what.owner"
                                  @input="updateOwner($event.target.value)"
                              />
                            </label>

                            <!-- Day Captured -->
                            <label style="text-align: left; margin-left: 4px; margin-right: 32px;">
                              <strong>Day Captured: </strong>
                              <input
                                  type="text"
                                  :value="currentReport?.config?.what?.when !== -1
                                      ? currentReport.config.what.when
                                      : (currentReport?.config?.what?.owner !== ''
                                          ? 'Already Captured'
                                          : 'Never')"
                                  @input="updateDayCaptured($event.target.value)"
                              />
                            </label>

                            <!-- Captured From -->
                            <label style="text-align: left; margin-left: 4px; margin-right: 32px;">
                              <strong>Captured From: </strong>
                              <input
                                  type="text"
                                  :value="currentReport?.config?.what?.from
                                    ? '[' + currentReport.config.what.from.x + ',' + currentReport.config.what.from.y + ']'
                                    : ''"
                                  @input="updateCapturedFrom($event.target.value)"
                              />
                            </label>
                            <label style="text-align: left; margin-left: 4px; margin-right: 32px"><strong>Chained Capture: </strong>
                                {{
                                    currentReport?.isCity(currentReport?.config?.what?.from)
                                        ? 'True'
                                        : 'False'
                                }}
                            </label>
                            <label style="text-align: left; margin-left: 4px; margin-right: 32px"><strong>Original Owner: </strong>
                                {{
                                    currentReport?.config?.what?.originalOwner != "" && currentReport?.config?.what?.originalOwner != currentReport?.config?.what?.owner
                                        ? BaseInfo.countries[currentReport.config.what.originalOwner].name
                                        : 'None'
                                }}
                            </label>
                        </div>
                    </div>
                </div>
                <div style="background: #ffffff; border: 1px black solid; padding: 4px;">
                    <label style="text-align: center"><strong>Controls</strong></label>
                    <div class="report-controls" style="text-align: left;">
                        <div style="background: #eeeeee; padding: 4px;">
                            <label><strong>Click a Property: </strong> Configure Property</label>
                        </div>
                        <div style="background: #eeeeee; padding: 4px; padding-top: 0px">
                            <label style="font-size: 10px">Opens the Config Panel for the Property.</label>
                        </div>
                        <div style="background: #eeeeee; padding: 4px;">
                            <label><strong>Shift-Click a Property: </strong> Link A Capture</label>
                        </div>
                        <div style="background: #eeeeee; padding: 4px; padding-top: 0px">
                            <label style="font-size: 10px">Select a Property, then the next Property To Capture.</label>
                            <br>
                            <label style="font-size: 10px">Linked From Base: Adds +1 Day to Build Infantry.</label>
                            <br>
                            <label style="font-size: 10px">Linked From City: Ignore Infantry Build Day.</label>
                            <br>
                            <label style="font-size: 10px">Auto-Calculates Travel and Capture Day</label>
                        </div>
                        <div style="background: #eeeeee; padding: 4px;">
                            <label><strong>Ctrl-Click a Property: </strong> Mark Contested</label>
                        </div>
                        <div style="background: #eeeeee; padding: 4px; padding-top: 0px">
                            <label style="font-size: 10px">Toggle a Property as Contested.</label>
                        </div>
                    </div>
                    <div style="display: flex; flex-direction: row; margin-top: 8px; align-items: center; justify-content: center; color: #ffffff; gap:16px; font-size: 12px">
                        <div v-show='linkingNextPress' @click='cancelNextPress()' style="font-weight: bold; padding: 8px; background: #ff972b; border: 2px solid black">
                            Link Capture (Manual)
                        </div>
                        <div v-show='!linkingNextPress' @click='linkNextPress()' style="font-weight: bold; padding: 8px; background: #7ebeff;">
                            Link Capture (Manual)
                        </div>
                        <div v-show='markingNextPress' @click='cancelNextPress()' style="font-weight: bold; padding: 8px; background: #ff972b; border: 2px solid black">
                            Mark Contested (Manual)
                        </div>
                        <div v-show='!markingNextPress' @click='markNextPress()' style="font-weight: bold; padding: 8px; background: #7ebeff;">
                            Mark Contested (Manual)
                        </div>
                    </div>
                    <div style="display: flex; flex-direction: row; margin-top: 8px; align-items: center; justify-content: center; color: #ffffff; gap:16px; font-size: 12px">
                        <div @click='clearCityOwnership()' style="font-weight: bold; padding: 8px; background: #7ebeff;">
                            Clear City Ownership
                        </div>
                    </div>
                </div>
                <div class="income-report" style="background: #ffffff; border: 1px black solid; padding: 4px; display: flex; flex-direction: column;">
                    <div @click='recalculateReport(), manualMode = false' style="color: #ffffff; font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; margin-right: 16px; margin-top: 8px; margin-bottom: 8px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Recalculate Manual Report
                    </div>
                    <div @click='importReport()' style="color: #ffffff; font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; margin-right: 16px; margin-top: 8px; margin-bottom: 8px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Import and Redraw
                    </div>
                    <label><strong>Income Report</strong></label>
                    <div
                        style="text-align: left; margin-left: 12px; margin-right: 32px; border: 1px black solid; padding: 4px"
                        contenteditable="true"
                        v-html="currentReport?.report || 'Paste or Generate a Report First!'"
                        @input="updateReport($event)"
                    >
                    </div>
                </div>
            </div>
            <div v-show='open && !manualMode && !chartMode && !reconMode'
                :style="{ top: position.y + 'px',
                          right: -position.x + 'px',
                          zIndex: '1000',
                          width: '480px',
                          position: 'absolute' }">
                <div class='bordertitle flex' style='color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between; cursor: grab;'
                    draggable="true"
                    @dragstart="onDragStart"
                    @dragend="onDragEnd">
                    <div style="font-weight: bold; display: block; float: left;">
                        Income Grapher   -   [Beta V5.0]
                    </div>
                    <div @click='manualMode = false, reconMode = true, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Recon Info
                    </div>
                    <div @click='manualMode = true, reconMode = false, chartMode = false' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        Manual Mode
                    </div>
                    <div @click='manualMode = false, reconMode = false, chartMode = true' style="font-weight: bold; display: block; float: right; padding-left: 4px; padding-right: 4px; margin-left: 16px; margin-right: 16px; background: #004d99; border-left: 1px #0044aa solid; border-right: 1px #0044aa solid;">
                        View Charts
                    </div>
                    <div style="cursor: pointer" @click="open = false">
                        <img width='16' src="terrain/close.png"/>
                    </div>
                </div>
                <div style='background: #fff; border: 1px black solid; padding-top: 4px'>
                    <div>
                        <label>Day #:
                          <input v-model.number="viewDay" type="number" max="15" min="1" style="width:80px" />
                        </label>
                        <label>Delay Tanks Until Day #:
                          <input v-model.number="tankDelay" type="number" max="15" min="0" style="width:80px" />
                        </label>
                        <select v-model='income'> <option v-for='opt in incomeModeOptions' :value='opt'>{{opt}}</option>\n</select>
                    </div>
                    <hr>
                    <div v-show="!showFta" style="background: #7ebeff; color: #000000;">
                        <label style="text-align: center; font-size: 24px">Currently Viewing a Manual Report</label>
                        <br>
                        <label style="text-align: center; font-size: 20px">{{getReportName()}}</label>
                    </div>
                    <div style="width: 100%; border-bottom: 1px black solid;">
                      <div
                        v-for="(countryData, countryCode) in countries"
                        :key="countryCode"
                        :style="{
                          display: 'flex',
                          alignItems: 'center',
                          borderTop: '1px black solid',
                          paddingRight: '4px',
                          background: getCountryColorWithAlpha(BaseInfo.countries[countryCode]?.color, 0.5) || '#eeeeee'
                        }"
                      >
                        <!-- Logo, Infantry Icons, and Funds/Unit Value Section in a Column Layout -->
                        <div style="display: flex; flex-direction: column; align-items: center; padding: 4px;">
                          <!-- Country Name and Logo Display -->
                          <div style="flex-shrink: 0; margin-right: 10px; text-align: center; padding: 4px; display: flex; align-items: center;">
                            <!-- Country Logo -->
                            <img
                              :src="'terrain/aw1/' + countryCode + 'logo.gif'"
                              style="width: 24px; height: 24px; margin-right: 5px;"
                            >
                            <!-- Country Name -->
                            <strong>{{ countryData[viewDay]?.countryName ?? 'No Data' }}</strong>
                          </div>
                          <!-- Funds and Unit Value Section -->
                          <div style="margin-top: 8px; background: #fff; border: 1px black solid; padding: 4px;">
                            <!-- Generated Funds -->
                            <div style="display: flex; align-items: center; justify-content: space-between; background: #eee; width: 100%; margin-bottom: 5px;">
                              <label style="font-size: 12px; margin-right: 10px;">Generated Funds:</label>
                              <strong>{{ countryData[viewDay]?.generatedFunds ?? '???' }}</strong>
                              <img src="terrain/coin.gif" style="width: 18px; margin-left: 5px;">
                            </div>
                            <!-- Total Unit Value -->
                            <div style="display: flex; align-items: center; justify-content: space-between; background: #eee; width: 100%;">
                              <label style="font-size: 12px; margin-right: 10px;">Total Unit Value:</label>
                              <strong>{{ countryData[viewDay]?.totalUnitValue ?? '???' }}</strong>
                              <img src="terrain/coin.gif" style="width: 18px; margin-left: 5px;">
                            </div>
                          </div>
                          <!-- Unit Number Display -->
                          <div style="margin-top: 8px; background: #fff; border: 1px black solid; padding: 4px; display: flex; justify-content: space-between; align-items: center;">
                              <!-- Total Infantry -->
                              <div style="display: flex; align-items: center; background: #eee; padding: 4px;">
                                  <img :src="'terrain/ani/' + countryCode + 'infantry.gif'" style="width: 18px; margin-right: 5px;">
                                  <label style="font-size: 12px; margin-right: 5px;">x</label>
                                  <strong>{{ countryData[viewDay]?.totalInf ?? '0' }}</strong>
                              </div>

                              <!-- Total Tanks -->
                              <div style="display: flex; align-items: center; background: #eee; padding: 4px;">
                                  <img :src="'terrain/ani/' + countryCode + 'tank.gif'" style="width: 18px; margin-right: 5px;">
                                  <label style="font-size: 12px; margin-right: 5px;">x</label>
                                  <strong>{{ countryData[viewDay]?.totalTanks ?? '0' }}</strong>
                              </div>
                          </div>
                          <!-- Other Unit Number Display -->
                          <div v-if="countryData[viewDay]?.totalOtherDeployed != undefined && Object.keys(countryData[viewDay]?.totalOtherDeployed).length > 0">
                              <div style="margin-top: 8px; background: #fff; border: 1px black solid; padding: 4px; display: flex; justify-content: space-between; align-items: center;">
                                  <div v-for="(count, unitName) in countryData[viewDay].totalOtherDeployed" :key="unitName">
                                      <div style="display: flex; align-items: center; background: #eee; padding: 4px;">
                                          <img :src="'terrain/ani/' + countryCode + unitName.toLowerCase() + '.gif'" style="width: 18px; margin-right: 5px;">
                                          <label style="font-size: 12px; margin-right: 5px;">x</label>
                                          <strong>{{ count ?? '0' }}</strong>
                                      </div>
                                  </div>
                              </div>
                          </div>
                          <!-- Properties Display -->
                          <div style="margin-top: 8px; background: #fff; border: 1px black solid; padding: 4px; padding-top: 0px; display: flex; justify-content: space-between; align-items: center;">
                              <!-- Total Bases -->
                              <div style="display: flex; align-items: center; background: #eee; padding: 4px;">
                                  <img :src="'terrain/ani/' + getImageName(countryCode) + 'base.gif'" style="width: 18px; margin-right: 5px;">
                                  <label style="font-size: 12px; margin-right: 5px;">x</label>
                                  <strong>{{ countryData[viewDay]?.totalBases ?? '0' }}</strong>
                              </div>
                          </div>
                        </div>
                        <!-- Labels and Coins -->
                        <div style="display: flex; flex-direction: column; justify-content: center; flex-grow: 1; text-align: left; background: #fff; border: 1px black solid; padding: 4px;">
                          <div style="display: flex; align-items: center; margin-bottom: 5px; width: 100%; background: #eee; padding: 2px;">
                              <label style="flex-grow: 1; font-size: 12px; margin-right: 20px;">Repairs (Start):</label>
                              <strong>
                                  {{ (countryData[viewDay]?.repairs && countryData[viewDay].repairs.length > 0)
                                      ? countryData[viewDay].repairs.reduce((total, repair) => total + (repair.cost || 0), 0)
                                      : 'None' }}
                              </strong>
                              <img src="terrain/coin.gif" style="width: 18px; margin-left: 5px;">
                          </div>
                          <div style="display: flex; align-items: center; margin-bottom: 5px; width: 100%; background: #eee; padding: 2px;">
                            <label style="flex-grow: 1; font-size: 12px; margin-right: 20px;">Funds (Start):</label>
                            <span style="margin-right: 4px" v-if="countryData[viewDay]?.repairs?.length >= 1">
                              <label>
                                [{{ countryData[viewDay]?.startingFunds
                                    ? countryData[viewDay].startingFunds +
                                      (countryData[viewDay]?.repairs?.reduce((total, repair) => total + (repair.cost || 0), 0) || 0)
                                    : '???' }}]
                              </label>
                            </span>
                            <span :style="{ color: countryData[viewDay]?.repairs?.length >= 1 ? 'red' : 'black', fontWeight: 'bold' }">
                              {{ countryData[viewDay]?.startingFunds
                                  ? countryData[viewDay].startingFunds
                                  : '???' }}
                            </span>
                            <img src="terrain/coin.gif" style="width: 18px; margin-left: 5px;">
                          </div>
                          <div style="display: flex; align-items: center; margin-bottom: 5px; width: 100%; background: #eee; padding: 2px;">
                            <label style="flex-grow: 1; font-size: 12px; margin-right: 20px;">Funds (End):</label>
                            <strong>{{ countryData[viewDay]?.endingFunds ?? '???' }}</strong>
                            <img src="terrain/coin.gif" style="width: 18px; margin-left: 5px;">
                          </div>
                          <div style="display: flex; align-items: center; margin-bottom: 5px; width: 100%; background: #eee; padding: 2px;">
                            <label style="flex-grow: 1; font-size: 12px; margin-right: 20px;">Income (Start):</label>
                            <strong
                              :style="{ color: countryData[viewDay]?.incomeFlips >= 1 || countryData[viewDay]?.flips.length >= 1 ? 'red' : 'black' }">
                              {{ countryData[viewDay]?.startingIncome ?? '???' }}
                            </strong>
                            <img src="terrain/capt.gif" style="width: 18px; margin-left: 5px;">
                          </div>
                          <div style="display: flex; align-items: center; width: 100%; background: #eee; padding: 2px;">
                            <label style="flex-grow: 1; font-size: 12px; margin-right: 20px;">Income (End):</label>
                            <strong>{{ countryData[viewDay]?.endingIncome ?? '???' }}</strong>
                            <img src="terrain/capt.gif" style="width: 18px; margin-left: 5px;">
                          </div>
                          <!-- Flip Information Section -->
                          <div v-if="countryData[viewDay]?.flips != undefined && countryData[viewDay]?.flips.length > 0" style="margin-top: 10px; background: #eeeeee;">
                              <strong>Flips Detected:</strong>
                              <ul style="padding-left: 20px; margin-top: 5px;">
                                  <li v-for="(flip, index) in countryData[viewDay]?.flips" :key="index">
                                      [{{ flip.x }}, {{ flip.y }}] was flipped!
                                  </li>
                              </ul>
                          </div>
                          <!-- Repair Information Section -->
                          <div v-if="countryData[viewDay]?.repairs != undefined && countryData[viewDay]?.repairs.length > 0" style="margin-top: 10px; background: #eeeeee;">
                            <strong>Repairs Detected:</strong>
                            <ul style="padding-left: 20px; margin-top: 5px;">
                              <li v-for="(repair, index) in countryData[viewDay]?.repairs" :key="index">
                                [{{ repair.x }}, {{ repair.y }}] was repaired from {{ repair.newHealth - repair.health }} -> {{ repair.newHealth }}HP [{{ repair.cost }}G]!
                                <!-- Image added here -->
                                <img :src="'terrain/ani/' + countryCode + repair.sprite + '.gif'" style="width: 18px; margin-left: 5px;" />
                              </li>
                            </ul>
                          </div>
                        </div>
                      </div>
                    </div>
                    <hr>
                    <!-- Label for the tank order list -->
                    <div style="background: #eeeeee; padding: 4px;">
                        <h4 style="margin-bottom: 4px;">Estimated Tank Order</h4>
                        <div v-for="(tank, index) in tanks" :key="index" style="display: flex; justify-content: center; align-items: center; margin-bottom: 5px; font-weight: bold;">
                          <!-- Display the day -->
                          <span style="margin-right: 8px;">Day: {{ tank.day }}</span>

                          <!-- Display the tank image based on the country code -->
                          <img :src="'terrain/ani/' + tank.country + 'tank.gif'" alt="Tank Image" style="width: 24px; height: 24px;">
                        </div>
                    </div>
                    <div style="background: #eeeeee; padding: 4px;">
                      <h4 style="margin-bottom: 4px;">Extended Tank Order</h4>
                      <div v-for="(chunk, rowIndex) in chunkedTanks" :key="rowIndex" style="display: flex; justify-content: center; align-items: center; margin-bottom: 5px; font-weight: bold;">
                        <span v-for="(tankKey, colIndex) in chunk" :key="colIndex" style="margin-right: 8px;">
                          <span style="font-size: 10px; display: inline;">{{ extendedTankIndex[rowIndex * 4 + colIndex] }}</span>{{ tankKey }}
                        </span>
                      </div>
                    </div>
                    <div v-show="showFta" style="background: #eeeeee; padding: 4px;">
                        <hr>
                        <h4 style="margin-bottom: 10px;">FTA Information</h4>
                        <div style="display:flex; flex-direction: column; align-items: center; width: 100%; gap: 4px;">
                            <div>
                                <span>{{ ftaInfo.Day1 ?? '0' }} within 1 Day(s) reach.</span>
                            </div>
                            <div>
                                <span>{{ ftaInfo.Day2 ?? '0' }} within 2 Day(s) reach.</span>
                            </div>
                            <div>
                                <span>{{ ftaInfo.Day3 ?? '0' }} within 3 Day(s) reach.</span>
                            </div>
                            <div v-if="ftaInfo.Flips > 0">
                                <span>{{ ftaInfo.Flips ?? '0' }} properties were flipped!</span>
                            </div>
                            <div v-if="ftaInfo.Neutrals > 0">
                                <span>{{ ftaInfo.Neutrals ?? '0' }} neutral bases to be captured.</span>
                            </div>
                        </div>
                    </div>
                    <hr>
                    <div style="background: #eeeeee; padding: 4px;">
                        <h4 style="margin-bottom: 10px;">Calculator Notes Appear Here</h4>
                        <div style="text-align: center; font-weight: bold; font-size: 12px;">
                          <div v-if="noteFlip">
                            Income Flips Detected!<br>
                            <span style="color: red; font-weight: bold;">(they will be marked in red)</span>
                            <br>
                            <span>on the day that it affects the other player.</span>
                          </div>
                          <div v-if="noteTransport">
                            <span style="color: red;">Transport Units Detected!</span><br>
                            <span>The calculator does not support builds with transport units!</span>
                            <br>
                            <span>They will be ignored, but the build order could be different.</span>
                          </div>
                          <div v-if="!noteFlip && !noteTransport">
                              No Income Flips or Transport Units Detected!
                              <br>
                              Calculator should operate normally! :3
                          </div>
                        </div>
                    </div>
                    <hr>
                    <div style="display: flex; flex-direction: column; gap: 4px; width:100%;">
                        <div style='padding-bottom: 2px; width: 100%;'>
                           <button style="color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between;" @click='recalculate()'>Calculate All Days</button>
                        </div>
                        <div style='padding-bottom: 2px; width: 100%;'>
                           <button style="color: #fff; background: #06c; border: 1px black solid; padding: 4px; justify-content: space-between;" @click='clear()'>Clear Drawings</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>`,
        props: {
            countries: Object,
            tanks: Array,
            recons: Object,
            extendedTanks: Array,
            extendedTanksIndex: Array,
            days: Number,
            noteFlip: {
                type: Boolean,
                default: false
            },
            noteTransport: {
                type: Boolean,
                default: false
            },
            ftaInfo: Object,
            highFunds: {
                type: Boolean,
                default: false
            },
            currentReport: Object,
        },
        data: function() {
            return {
                loaded: !1,
                open: !1,
                manualMode: !1,
                chartMode: !1,
                reconMode: !1,
                graphOpen: !0,
                drawing: !1,
                dirty: !0,
                active: !0,
                viewDay: 1,
                tankDelay: 0,
                reconDay: 3,
                reconSearch: 2,
                markingNextPress: !1,
                linkingNextPress: !1,
                showRecon: !1,
                showFta: !0,
                income: "Normal (1k/Day)",
                incomeModeOptions: ["Low Funds (500/Day)", "Normal (1k/Day)", "High Funds (2k/Day)"],
                position: { x: 200, y: 100 },
                offset: { x: 0, y: 0 },
            }
        },
        created() {
            this.currentReport.ctx = window.incomeGrapher.ctx;
            this.currentReport.BaseInfo = BaseInfo;
            this.extendedTanks = [];
            this.extendedTankIndex = [];

            this.BaseInfo = BaseInfo;
            let e = sessionStorage.incomeGrapherSettings;
            e && (e = JSON.parse(e), this.mode = e);
            window.gameMap.addEventListener("click", (e) => {
                // Check if the event listener should proceed
                if (!this.open) return; // Exit if the map is not in an 'open' state.

                // Extract properties by calling a helper function
                let data = (function(e) {
                    // Get the map's bounding rectangle
                    let t = window.gameMap.getBoundingClientRect();

                    // Calculate the x and y coordinates on the map based on click position
                    let n = Math.floor((e.clientX - t.left) / (16 * scale)); // X-coordinate
                    let i = Math.floor((e.clientY - t.top) / (16 * scale)); // Y-coordinate

                    // Check for modifier keys
                    let cM = e.shiftKey; // Shift key pressed for chainMode
                    let mC = e.ctrlKey; // Alt key pressed for cycleOwnership

                    // Clamp the x and y values to the map's boundaries
                    n = Math.max(0, Math.min(window.mapWidth - 1, n));
                    i = Math.max(0, Math.min(window.mapHeight - 1, i));

                    // Return the calculated data
                    return {
                        x: n,
                        y: i,
                        chainMode: cM,
                        markContested: mC,
                    };
                })(e);
                if (this.manualMode) {
                    if (!data.chainMode) data.chainMode = this.linkingNextPress;
                    if (!data.markContested) data.markContested = this.markingNextPress;
                    this.onClickProperty(data);
                }
            });
            this.saveSettings = _.debounce((() => {
                sessionStorage.incomeGrapherSettings = JSON.stringify(this.mode)
            }), 1500), this.$nextTick((() => this.loaded = !0))
            if (highFunds) {
                this.income = "High Funds (2k/Day)";
            }
            window.incomeGrapher.income = this.getFunds();
            window.incomeGrapher.properties = new Map();
            window.incomeGrapher.bases = new Map();
            window.incomeGrapher.propertyMap = {};
            window.incomeGrapher.assignProperties();
        },
        computed: {
            chunkedTanks() {
                const chunkSize = 4; // 4 letters per row
                const chunks = [];
                for (let i = 0; i < this.extendedTanks.length; i += chunkSize) {
                    chunks.push(this.extendedTanks.slice(i, i + chunkSize));
                }
                return chunks;
            },
            unitNames() {
                return Object.values(this.BaseInfo.units).map((e => e.name.toLowerCase().replace(" ", "")))
            },
            predeployedUnits() {
                return Array.from(window.gameMap.querySelectorAll("span > img")).filter((e => {
                    const t = e.src;
                    for (const e of this.unitNames)
                        if (t.includes(e + ".gif")) return !0;
                    return !1
                }))
            }
        },
        mounted() {
            // console.log('Component mounted');
            // console.log('Initial currentReport:', this.currentReport);
        },
        watch: {
            open(e) {
                e ? (this.predeployedUnits.forEach((e => e.style.display = "none")), window.gameMap.style.cursor = "pointer") : (this.predeployedUnits.forEach((e => e.style.display = "")), window.gameMap.style.cursor = "default")
            },
            mode: {
                handler() {
                    this.dirty = !0, this.loaded && this.saveSettings()
                },
                deep: !0
            },
            reconDay(newVal, oldVal) {
                if (this.showRecon) this.showReconData(); // Call showReconData() when reconSearch changes
            },
            reconSearch(newVal, oldVal) {
                if (this.showRecon) this.showReconData(); // Call showReconData() when reconSearch changes
            },
        },
        methods: {
            getImageName(country) {
                return BaseInfo.countries[country].name.toLowerCase().replace(/ /g, "");
            },
            onDragStart(event) {
                // Record the initial mouse position relative to the element
                this.offset.x = event.clientX - this.position.x;
                this.offset.y = event.clientY - this.position.y;
            },
            onDragEnd(event) {
                // Update the position of the element based on the drag
                this.position.x = event.clientX - this.offset.x;
                this.position.y = event.clientY - this.offset.y;
                this.position.x = Math.max(-600, this.position.x);
                this.position.y = Math.max(0, this.position.y);
            },
            getReportName() {
                return this.currentReport.name;
            },
            getCountryColorWithAlpha(rgbColor, alpha) {
                if (!rgbColor || !/^(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})$/.test(rgbColor)) {
                    return null; // Return null if invalid RGB format
                }

                // Add alpha to the RGB color
                return `rgba(${rgbColor}, ${alpha})`;
            },
            linkNextPress() {
                this.linkingNextPress = true;
                this.markingNextPress = false;
            },
            markNextPress() {
                this.markingNextPress = true;
                this.linkingNextPress = false;
            },
            cancelNextPress() {
                this.linkingNextPress = false;
                this.markingNextPress = false;
            },
            clearCityOwnership() {
                let clone = Object.assign({}, this.currentReport.properties);
                let n = {};
                n.contested = [];
                for (let country of Object.keys(clone)) {
                    for (let prop of Object.values(clone[country])) {
                        if (this.currentReport.isCity(prop)) {
                            prop.owner = "";
                            prop.when = 0;
                            n.contested.push(prop);
                        } else {
                            if (!n[country]) n[country] = [];
                            n[country].push(prop);
                        }
                        prop.when = 0;
                    }
                }
                this.currentReport.properties = n;
                this.currentReport.renderDrawings();
                this.currentReport.report = this.currentReport.toText();
            },
            updateReport(event) {
                const element = event.target;

                // Save the current cursor position
                const selection = window.getSelection();
                const range = selection.getRangeAt(0);
                const preCursorRange = range.cloneRange();
                preCursorRange.selectNodeContents(element);
                preCursorRange.setEnd(range.startContainer, range.startOffset);
                const cursorPosition = preCursorRange.toString().length;

                // Update the report content
                let text = element.innerHTML.replace(/\n/g, '<br>'); // Process newlines
                this.currentReport.report = text;

                // Restore the cursor position
                this.$nextTick(() => {
                    const newRange = document.createRange();
                    const childNodes = element.childNodes;
                    let charCount = 0;

                    for (let node of childNodes) {
                        if (node.nodeType === Node.TEXT_NODE) {
                            if (charCount + node.length >= cursorPosition) {
                                newRange.setStart(node, cursorPosition - charCount);
                                newRange.setEnd(node, cursorPosition - charCount);
                                break;
                            }
                            charCount += node.length;
                        } else {
                            charCount += node.textContent.length;
                        }
                    }

                    selection.removeAllRanges();
                    selection.addRange(newRange);
                });
            },
            importReport() {
                let report = this.currentReport;
                report.fromText(this.currentReport.report);
                report.renderDrawings();
                this.showFta = false;
            },
            recalculateReport() {
                let report = this.currentReport;
                report.generateData();
                this.showFta = false;

                this.afterManualGeneration();
            },
            onClickProperty(data) {
                if (data.chainMode) {
                    let to = new Vector2i();
                    to.x = data.x;
                    to.y = data.y;

                    let chainTo = undefined;
                    for (let country of Object.keys(this.currentReport.properties)) {
                        for (let prop of Object.values(this.currentReport.properties[country])) {
                            if (prop.where.x == to.x && prop.where.y == to.y) {
                                chainTo = prop;
                                break;
                            }
                        }
                    }

                    if (chainTo == undefined) return;
                    if (!this.currentReport.isCity(chainTo.where) && chainTo.owner != "contested") return;

                    let chainFrom = this.currentReport.config.what;
                    if (!chainFrom) return;

                    let cityChain = this.currentReport.isCity(chainFrom.where);

                    let fakeUnit = {
                        x: chainFrom.where.x,
                        y: chainFrom.where.y,
                        id: 1,
                        country: "os"
                    };

                    let graph = window.incomeGrapher.getMoveCostGraph(BaseInfo.units[fakeUnit.id].move_type, false);
                    // Search 15 days deep.
                    let pathing = new Dijkstra(graph, [fakeUnit], window.incomeGrapher.width, window.incomeGrapher.height).iterate(3 * 15);
                    let s = to.x + to.y * window.incomeGrapher.width;
                    let cost = pathing[s];
                    if (cost != -1 && cost != undefined) {
                        let travelTime = Math.ceil(cost / 3);
                        let buildDelay = cityChain ? 0 : 1;
                        let totalTravel = travelTime + buildDelay;

                        let start = chainFrom.when;
                        if (start <= 0) start = 0;

                        let capture = start + totalTravel + 1;
                        chainTo.when = capture;
                        chainTo.from = chainFrom.where;
                        chainTo.contested = false;

                        let previousOwner = chainTo.owner;
                        let newOwner = chainFrom.owner;
                        chainTo.owner = chainFrom.owner;
                        if (newOwner != previousOwner) {
                            let props = this.currentReport.properties[previousOwner]
                            if (props != undefined) {
                                let index = props.indexOf(chainTo);
                                if (index != 1) props.splice(index, 1);

                                let newPlace = this.currentReport.properties[newOwner];
                                if (newPlace == undefined) this.currentReport.properties[newOwner] = [];
                                if (!this.currentReport.properties[newOwner].includes(chainTo)) {
                                    this.currentReport.properties[newOwner].push(chainTo);
                                }

                                if (props.length <= 0) {
                                    delete this.currentReport.properties[previousOwner];
                                }
                            }
                            let contested = this.currentReport.properties.contested
                            if (contested != undefined) {
                                let index = contested.indexOf(chainTo);
                                if (index != 1) contested.splice(index, 1);

                                let newPlace = this.currentReport.properties[newOwner];
                                if (newPlace == undefined) this.currentReport.properties[newOwner] = [];
                                if (!this.currentReport.properties[newOwner].includes(chainTo)) {
                                    this.currentReport.properties[newOwner].push(chainTo);
                                }

                                if (contested.length <= 0) {
                                    delete this.currentReport.properties[previousOwner];
                                }
                            }
                        }
                        this.currentReport.config.where = chainTo.where;
                        this.currentReport.config.what = chainTo;
                        this.currentReport.renderDrawings();
                        this.currentReport.report = this.currentReport.toText();
                    }
                } else if (data.markContested) {
                    let where = new Vector2i();
                    where.x = data.x;
                    where.y = data.y;
                    let what = undefined;
                    for (let country of Object.keys(this.currentReport.properties)) {
                        for (let prop of Object.values(this.currentReport.properties[country])) {
                            if (prop.where.x == where.x && prop.where.y == where.y) {
                                what = prop;
                                break;
                            }
                        }
                    }
                    if (what == undefined) return;
                    what.owner = "none";
                    what.contested = !what.contested;
                    what.captured = -1;
                    what.from = null;
                    this.currentReport.renderDrawings();
                    this.currentReport.report = this.currentReport.toText();
                } else {
                    let where = new Vector2i();
                    where.x = data.x;
                    where.y = data.y;
                    let what = undefined;
                    for (let country of Object.keys(this.currentReport.properties)) {
                        for (let prop of Object.values(this.currentReport.properties[country])) {
                            if (prop.where.x == where.x && prop.where.y == where.y) {
                                what = prop;
                                break;
                            }
                        }
                    }
                    if (what == undefined) return;
                    let config = {
                        where: where,
                        what: what,
                    };
                    this.currentReport.config = config;
                }
            },
            updateOwner(value) {
                let valid = this.currentReport && this.currentReport.config && this.currentReport.config.what;
                if (!valid) return;

                let what = this.currentReport.config.what;
                if (Object.keys(BaseInfo.countries).includes(value)) {
                    let previousOwner = what.owner;
                    what.owner = value;
                    if (value != previousOwner) {
                        let props = this.currentReport.properties[previousOwner]
                        if (props != undefined) {
                            let index = props.indexOf(what);
                            if (index != 1) props.splice(index, 1);

                            let newPlace = this.currentReport.properties[value];
                            if (newPlace == undefined) this.currentReport.properties[value] = [];
                            if (!this.currentReport.properties[value].includes(what)) {
                                this.currentReport.properties[value].push(what);
                            }

                            if (props.length <= 0) {
                                delete this.currentReport.properties[previousOwner];
                            }
                        }
                        let contested = this.currentReport.properties.contested
                        if (contested != undefined) {
                            let index = contested.indexOf(what);
                            if (index != 1) contested.splice(index, 1);

                            let newPlace = this.currentReport.properties[value];
                            if (newPlace == undefined) this.currentReport.properties[value] = [];
                            if (!this.currentReport.properties[value].includes(what)) {
                                this.currentReport.properties[value].push(what);
                            }

                            if (contested.length <= 0) {
                                delete this.currentReport.properties[previousOwner];
                            }
                        }
                    }
                    what.contested = false;
                } else {
                    what.contested = value.toLowerCase() == "none"
                }
                this.currentReport.renderDrawings();
                this.currentReport.report = this.currentReport.toText();
            },
            updateDayCaptured(value) {
                let valid = this.currentReport && this.currentReport.config && this.currentReport.config.what;
                if (!valid) return;

                let v = parseInt(value);
                if (isNaN(v)) return;
                if (v <= 0) v = -1;

                this.currentReport.config.what.when = v;
                this.currentReport.renderDrawings();
                this.currentReport.report = this.currentReport.toText();
            },
            updateCapturedFrom(value) {
                let valid = this.currentReport && this.currentReport.config && this.currentReport.config.what;
                if (!valid) return;
                if (value == "") return;

                const match = value.match(/^\[(-?\d+),\s*(-?\d+)\]$/);
                if (match) {
                    let where = new Vector2i(parseInt(match[1], 10), parseInt(match[2], 10))
                    this.currentReport.config.what.from = where;
                } else {
                    this.currentReport.config.what.from = null;
                    //console.error("Invalid format for Captured From. Expected [x, y]");
                }
                this.currentReport.renderDrawings();
                this.currentReport.report = this.currentReport.toText();
            },
            setUnit(e, t) {
                window.incomeGrapher.units[e + t * window.incomeGrapher.width] ? window.incomeGrapher.deleteUnit(e, t) : window.incomeGrapher.setUnit(e, t, this.selectedUnit, this.selectedCountry), this.updateUnits()
            },
            deleteAllUnits() {
                window.incomeGrapher.deleteAllUnits(), this.updateUnits()
            },
            updateUnits() {
                window.gameMap.querySelectorAll('[data-analyzer="unit"]').forEach((e => {
                    e.remove()
                }));
                let e = window.incomeGrapher.units;
                for (const t in e) {
                    if (!e[t]) continue;
                    let {
                        x: n,
                        y: i,
                        id: o,
                        country: r
                    } = e[t], a = this.BaseInfo.units[o].name.toLowerCase().replace(" ", ""), s = document.createElement("img");
                    s.src = `terrain/aw1/${r}${a}.gif`, s.style.position = "absolute", s.style.left = 16 * n + "px", s.style.top = 16 * i + "px", s.style.zIndex = "120", s.dataset.analyzer = "unit", window.gameMap.append(s)
                }
            },
            selectUnit(e) {
                this.selectedUnit = e
            },
            selectCountry(e) {
                this.selectedCountry = e
            },
            async render(e) {
                let t = this.active;
                if (t) {
                    if (window.incomeGrapher.dirty || this.dirty) {
                        this.dirty = !1;
                        try {
                            this.mode[t];
                            "unitFlow" === t ? await window.incomeGrapher.drawFlow(this.mode[t]) : "capRoute" === t && window.incomeGrapher.clear()
                        } catch (e) {
                            return console.log(e), cancelAnimationFrame(this.drawing), this.drawing = !1, window.incomeGrapher.clear(), void alert("map analyzer broke")
                        }
                    }
                    this.drawing = requestAnimationFrame(this.render)
                }
            },
            toggleRendering(e) {
                cancelAnimationFrame(this.drawing), e === this.active ? (this.drawing = !1, this.active = "", window.incomeGrapher.clear()) : (this.dirty = !0, this.active = e, this.drawing = requestAnimationFrame(this.render))
            },
            swapSide() {
                window.incomeGrapher.swapSide()
            },
            getFunds() {
                if (this.income == "Low Funds (500/Day)") return 500;
                if (this.income == "High Funds (2k/Day)") return 2000;
                return 1000;
            },
            afterManualGeneration() {
                for (let country of Object.keys(window.incomeGrapher.countryData)) {
                    for (let day of Object.keys(window.incomeGrapher.countryData[country])) {
                        if (window.incomeGrapher.countryData[country][day].flips > 0) {
                            this.noteFlip = true;
                        }
                    }
                }

                this.countries = window.incomeGrapher.countryData;
                this.tanks = window.incomeGrapher.tankOrder;
                this.extendedTanks = window.incomeGrapher.extendedTankOrder;
                this.extendedTankIndex = window.incomeGrapher.extendedTankOrderIndex;
            },
            recalculate() {
                window.incomeGrapher.income = this.getFunds();
                window.incomeGrapher.tankDelay = this.tankDelay;
                window.incomeGrapher.recalculate()

                for (let country of Object.keys(window.incomeGrapher.countryData)) {
                    for (let day of Object.keys(window.incomeGrapher.countryData[country])) {
                        if (window.incomeGrapher.incomeFlips[country][day] > 0) {
                            this.noteFlip = true;
                        }
                    }
                }

                this.countries = window.incomeGrapher.countryData;
                this.tanks = window.incomeGrapher.tankOrder;
                this.extendedTanks = window.incomeGrapher.extendedTankOrder;
                this.extendedTankIndex = window.incomeGrapher.extendedTankOrderIndex;
                this.ftaInfo = window.incomeGrapher.ftaInfo;
                this.ftaInfo.Day1 = this.ftaInfo.Day1 / 2;
                this.ftaInfo.Day2 = this.ftaInfo.Day2 / 2;
                this.ftaInfo.Day3 = this.ftaInfo.Day3 / 2;
                this.ftaInfo.Neutrals = this.ftaInfo.Neutrals / 2;
                this.recons = window.incomeGrapher.reconData;
                this.graphOpen = true;

                window.generateFundChart(this.countries);
                //who: country as String
                   //where [x,y] as Vector2i
                        //when: int
                        //chainedFrom: [x,y] as Vector2i
                        //originalOwner: country as String
                this.showFta = true;
                this.currentReport.properties = {};
                this.currentReport.bases = [];
                let propertyData = {}
                for (let prop of window.incomeGrapher.properties.values()) {
                    let from = (prop.capturer && prop.capturer.from) ? prop.capturer.from : null;
                    let when = (prop.capturer && prop.capturer.from) ? prop.capturer.when + prop.capturer.getDayCost() : -1;
                    let data = {
                        where: prop.where,
                        when: when,
                        type: prop.type,
                        from: from,
                        owner: prop.owner,
                        originalOwner: prop.originalOwner,
                        contested: prop.owner == "",
                        ghosted: prop.ghosted,
                        taxDays: prop.taxDays,
                    };
                    let country = prop.owner;
                    if (country == "") country = "contested";
                    if (!Object.keys(propertyData).includes(country)) {
                        propertyData[country] = [];
                    }
                    propertyData[country].push(data);
                }
                for (let base of window.incomeGrapher.bases.values()) {
                    let country = base.owner;
                    let found = false;
                    let props = propertyData[country];
                    if (props == undefined) continue;
                    for (let entered of props) {
                        if (entered.where.x == base.where.x && entered.where.y == base.where.y) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        let from = (base.capturer && base.capturer.from) ? base.capturer.from : null;
                        let when = (base.capturer && base.capturer.from) ? base.capturer.when + base.capturer.getDayCost() : -1;
                        let data = {
                            where: base.where,
                            when: when,
                            type: base.type,
                            from: from,
                            owner: base.owner,
                            originalOwner: base.originalOwner
                        };
                        if (!Object.keys(propertyData).includes(country)) {
                            propertyData[country] = [];
                        }
                        propertyData[country].push(data);
                        this.currentReport.bases.push(base.where);
                    }
                }
                this.currentReport.properties = propertyData;
                this.currentReport.report = this.currentReport.toText();
                this.currentReport.renderDrawings();
            },
            toggleGraph() {
                this.graphOpen = !this.graphOpen;
            },
            clear() {
                window.incomeGrapher.clear();
            },
            showReconData() {
                this.showRecon = true;
                this.currentReport.renderReconData(this.reconDay, this.reconSearch);
            },
            clearReconData() {
                this.showRecon = false;
                this.currentReport.clearReconData();
            },
            generateFundsChart() {
                window.generateFundChart(this.countries);
            },
            generateTotalFundsChart() {
                window.generateTotalFundChart(this.countries);
            },
            generateTotalTaxedFundsChart() {
                window.generateTotalTaxedFundChart(this.countries);
            },
        }
    });
    let highFunds = false;
    let categories = document.querySelector("#map-categories").getElementsByClassName("small_text_14")[0];
    if (categories != undefined) {
        for (let element of categories.childNodes) {
            if (element.innerText == "High Funds") highFunds = true;
        }
    }

    let gameContainer = document.querySelector("#gamecontainer");
    if (gameContainer == undefined) return;

    let extensionPanel = document.querySelector("#vesper-extensions");
    if (extensionPanel == undefined) {
        extensionPanel = document.createElement("div");
        extensionPanel.id = "vesper-extensions";

        extensionPanel.style.background = '#98a0b8';
        extensionPanel.style.border = '2px solid #768a96';
        extensionPanel.style.display = 'flex';
        extensionPanel.style.flexDirection = 'row';
        extensionPanel.style.padding = '4px';
        extensionPanel.style.margin = '0px';
        extensionPanel.style.marginLeft = '-8px';
        extensionPanel.style.marginBottom = '8px';

        gameContainer.children[1].after(extensionPanel);
    }

    let e = document.createElement("div");
    e.id = "income-grapher-component";
    extensionPanel.append(e);

    let fP = document.querySelector("#game-header-table");
    let f = fP.querySelector(".bold.underline.game-header-header");
    let bt = f.querySelector(".bordertitle");
    let mapName = bt.innerHTML;
    let mapID = -1;

    let match = bt.outerHTML.match(/maps_id=(\d+)/);

    if (match) {
        mapID = parseInt(match[1]);
    }

    let t = [],
        n = window.mapWidth,
        i = window.mapHeight;
    for (let e = 0; e < n; e++)
        for (let n = 0; n < i; n++) terrainInfo[e] && terrainInfo[e][n] ? t.push(terrainInfo[e][n]) : t.push(buildingsInfo[e][n]);
    let o = Object.keys(BaseInfo.countries).map((e => e)).sort(((e, t) => BaseInfo.countries[e].id - BaseInfo.countries[t].id));
    let unitNames = Object.values(BaseInfo.units).map((e => e.name.toLowerCase().replace(" ", "")))
    let transportFound = false;
    let otherUnitsRead = [];
    let unitsRead = Array.from(window.gameMap.querySelectorAll("span > img"));
    unitsRead = unitsRead.reverse();
    unitsRead = unitsRead.filter((e => {
        const t = e.src;
        if (t.includes("blackboat") || t.includes("lander") || t.includes("t-copter") || t.includes("apc.gif")) {
            transportFound = true;
        }
        if (!t.includes("infantry")) {
            for (const n of unitNames) {
                if (t.includes(n + ".gif")) otherUnitsRead.push(e);
            }
            return !1;
        }
        for (const e of unitNames) {
            if (t.includes(e + ".gif")) return !0;
        }
        return !1
    }));
    let gridSize = 16;
    let unitDataArray = unitsRead.map((img, index) => {
        // Access the parent span for position
        let span = img.parentElement;

        // Initialize health variable
        let health = 10; // Default value if no matching image is found
        let healthImage = Array.from(span.querySelectorAll('img')).find(i => {
            return i.src.match(/terrain\/ani\/\d+\.gif$/)
        });

        // Extract x value if the image exists
        if (healthImage) {
            let match = healthImage.src.match(/terrain\/ani\/(\d+)\.gif$/); // Capture x
            if (match) {
                health = parseInt(match[1], 10); // Convert x to an integer
            }
        }

        // Extract left and top values from the span's style attribute
        let left = parseInt(span.style.left, 10);
        let top = parseInt(span.style.top, 10);

        // Calculate grid coordinates
        const x = Math.floor(left / gridSize);
        const y = Math.floor(top / gridSize);

        // Extract the country code from the image src
        let srcParts = img.src.split('/');
        let filename = srcParts[srcParts.length - 1]; // Get last part after the last /
        let country = filename.substring(0, 2); // First two letters before "infantry.gif"
        // Construct the unit data object
        return {
            x: x,
            y: y,
            id: 1, // or use another unique identifier if available
            country: country,
            health: health,
        };
    });
    let otherUnitDataArray = otherUnitsRead.map((img, index) => {
        // Access the parent span for position
        let span = img.parentElement;

        // Initialize health variable
        let health = 10; // Default value if no matching image is found
        let healthImage = Array.from(span.querySelectorAll('img')).find(i => {
            return i.src.match(/terrain\/ani\/\d+\.gif$/)
        });

        // Extract x value if the image exists
        if (healthImage) {
            let match = healthImage.src.match(/terrain\/ani\/(\d+)\.gif$/); // Capture x
            if (match) {
                health = parseInt(match[1], 10); // Convert x to an integer
            }
        }

        // Extract left and top values from the span's style attribute
        let left = parseInt(span.style.left, 10);
        let top = parseInt(span.style.top, 10);

        // Calculate grid coordinates
        const x = Math.floor(left / gridSize);
        const y = Math.floor(top / gridSize);

        // Extract the country code from the image src
        let srcParts = img.src.split('/');
        let filename = srcParts[srcParts.length - 1]; // Get last part after the last /
        let country = filename.substring(0, 2); // First two letters before "infantry.gif"
        let unitName = filename.replace(country, "").replace(".gif", "");
        let unitID = -1;
        for (let id of Object.keys(BaseInfo.units)) {
            if (BaseInfo.units[id].name.toLowerCase().replace(" ", "") == unitName) {
                unitID = parseInt(id);
                break;
            }
        }

        // Construct the unit data object
        return {
            x: x,
            y: y,
            id: unitID, // or use another unique identifier if available
            country: country,
            health: health,
        };
    });
    window.incomeGrapher = new IncomeGrapher;
    window.incomeGrapher.mapName = mapName;
    window.incomeGrapher.mapID = mapID;
    window.incomeGrapher.init();
    window.incomeGrapher.resize(n, i);
    window.incomeGrapher.setTerrain({
        tiles: t
    });
    window.incomeGrapher.units = unitDataArray;
    window.incomeGrapher.otherUnits = otherUnitDataArray;
    let report = new IncomeReport();
    report.config = {
        what: {
            owner: 'os',
            where: new Vector2i(0, 0),
            when: -1,
            from: new Vector2i(0, 0),
            originalOwner: "bm",
        }
    }
    window.analyzerComponent = new Vue({
        el: "#income-grapher-component",
        template: '<PrevIncomeGrapher :countries="countries" :noteTransport="noteTransport" :ftaInfo="ftaInfo" :highFunds="highFunds" :currentReport="currentReport"/>',
        data: function() {
            return {
                countries: {},
                noteTransport: transportFound,
                ftaInfo: {},
                highFunds: highFunds,
                currentReport: report,
            }
        }
    });
}
const CountryColor = {
    os: "#e25e41",
    bm: "#446eff",
    ge: "#3ec22b",
    yc: "#c5b800",
    bh: "#837c76",
    rf: "#b52643",
    gs: "#717370",
    bd: "#9a5330",
    ab: "#fca339",
    js: "#a6b696",
    ci: "#3f61c7",
    pc: "#fe68cf",
    tg: "#3acfc1",
    pl: "#a744d3",
    ar: "#5f7c0c",
    wn: "#bb534f",
    aa: "#5ed6eb",
    ne: "#574a4a",
    sc: "#89a8bc",
}
// Define the custom plugin
const customLabelPlugin = {
    id: 'customLabel',
    beforeDraw: (chart) => {
        const ctx = chart.ctx;
        ctx.save();
        ctx.font = 'bold 14px Arial';
        ctx.fillStyle = 'black';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        // Ensure the image is fully loaded before using it
        window.incomeGrapher.tankOrder.forEach((entry) => {
            const labelIndex = chart.data.labels.indexOf(entry.day.toString());
            let cIndex = window.incomeGrapher.countries.indexOf(entry.country);
            //let offset = window.incomeGrapher.countries.indexOf(entry.country) / window.incomeGrapher.countries.length;

            if (labelIndex == -1) return; // Skip if label is not found

            const x = chart.scales.x.getPixelForValue(entry.day.toString());
            const y = chart.scales.y.getPixelForValue(chart.data.datasets[cIndex].data[labelIndex]);

            // Draw the label
            ctx.fillText(`Day #${entry.day}`, x, y - 15);
            const image = new Image();
            image.src = `terrain/aw1/${entry.country}tank.gif`; // Replace with your image URL

            // Draw the image to the right of the text
            const imageWidth = 20; // Set your desired image width
            const imageHeight = 20; // Set your desired image height
            ctx.drawImage(image, x - 48, y - 15 - imageHeight / 2, imageWidth, imageHeight);
        });

        ctx.restore();
    }
};

// Register the custom plugin with Chart.js
Chart.register(customLabelPlugin);
function getColor(funds) {
    const colors = ['#FF6384', '#36A2EB', '#FFCE56', '#FF5733', '#33FF57', '#DA70D6'];
    return colors[Math.floor(funds / 1000) % colors.length];
}
function generateFundChart(chartData) {
    // this.countryData[country][day] = {
    //     startingFunds: d.startingFunds,
    //     endingFunds: d.endingFunds,
    //     startingIncome: d.getStartingIncome(this.income),
    //     endingIncome: d.getEndingIncome(this.income),
    //     generatedFunds: d.generatedFunds,
    //     totalUnitValue: d.totalUnitValue,
    //     countryName: BaseInfo.countries[country].name,
    //     totalInf: d.totalInf,
    //     totalTanks: d.totalTanks,
    //     totalOtherDeployed: d.totalOtherDeployed,
    // }
    // Chart configuration
    const staggeredData = (dataset, offset) => {
        return dataset.data.map((value, index) => ({
            x: index + offset, // Stagger the x value by adding an offset
            y: value
        }));
    };
    let datasets = [];
    let days = [];
    let adjustedDays = [];
    for (let i = 1; i < 16; i++) {
        days.push(i.toString());
        adjustedDays.push((i - 1).toString());
    }
    for (let country of Object.keys(chartData)) {
        let set = {};
        set.label = BaseInfo.countries[country].name;
        let dayData = [];
        for (let day in days) {
            let incomeEnd = chartData[country][day].endingIncome;
            dayData.push(incomeEnd);
        }
        set.data = dayData;
        //set.data = staggeredData(set, Object.keys(chartData).indexOf(country) / Object.keys(chartData).length);
        set.borderColor = CountryColor[country];
        set.borderWidth = 1;
        set.fill = false;
        datasets.push(set);
    }
    const chartConfig = {
        type: 'line', // or 'bar' or other types
        data: {
            labels: adjustedDays,
            datasets: datasets,
        },
        options: {
            scales: {
                x: {
                    type: 'linear', // Use a linear scale for x-axis
                    title: {
                        display: true,
                        text: 'Days'
                    },
                    beginAtZero: true // Adjust based on your data range
                },
                y: {
                    title: {
                        display: true,
                        text: 'Income on Day End'
                    }
                }
            },
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    display: true
                },
                tooltip: {
                    enabled: true
                },
                customLabel: {}
            }
        }
    };

    // Render the chart
    const ctx = document.getElementById('income-graph').getContext('2d');
    if (window.chart) {
        window.chart.destroy(); // Clear the previous chart if it exists
    }
    window.chart = new Chart(ctx, chartConfig);
}
function generateTotalFundChart(chartData) {
    // this.countryData[country][day] = {
    //     startingFunds: d.startingFunds,
    //     endingFunds: d.endingFunds,
    //     startingIncome: d.getStartingIncome(this.income),
    //     endingIncome: d.getEndingIncome(this.income),
    //     generatedFunds: d.generatedFunds,
    //     totalUnitValue: d.totalUnitValue,
    //     countryName: BaseInfo.countries[country].name,
    //     totalInf: d.totalInf,
    //     totalTanks: d.totalTanks,
    //     totalOtherDeployed: d.totalOtherDeployed,
    // }
    // Chart configuration
    const staggeredData = (dataset, offset) => {
        return dataset.data.map((value, index) => ({
            x: index + offset, // Stagger the x value by adding an offset
            y: value
        }));
    };
    let datasets = [];
    let days = [];
    let adjustedDays = [];
    for (let i = 1; i < 16; i++) {
        days.push(i.toString());
        adjustedDays.push((i - 1).toString());
    }
    for (let country of Object.keys(chartData)) {
        let set = {};
        set.label = BaseInfo.countries[country].name;
        let dayData = [];
        for (let day in days) {
            let incomeEnd = chartData[country][day].generatedFunds;
            dayData.push(incomeEnd);
        }
        set.data = dayData;
        set.data = staggeredData(set, Object.keys(chartData).indexOf(country) / Object.keys(chartData).length);
        set.borderColor = CountryColor[country];
        set.borderWidth = 1;
        set.fill = false;
        datasets.push(set);
    }
    const chartConfig = {
        type: 'line', // or 'bar' or other types
        data: {
            labels: adjustedDays,
            datasets: datasets,
        },
        options: {
            showLine: false,
            scales: {
                x: {
                    type: 'linear', // Use a linear scale for x-axis
                    title: {
                        display: true,
                        text: 'Days'
                    },
                    beginAtZero: true // Adjust based on your data range
                },
                y: {
                    title: {
                        display: true,
                        text: 'Generated Funds on Day End'
                    }
                }
            },
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    display: true
                },
                tooltip: {
                    enabled: true
                },
                customLabel: {}
            }
        }
    };

    // Render the chart
    const ctx = document.getElementById('income-graph').getContext('2d');
    if (window.chart) {
        window.chart.destroy(); // Clear the previous chart if it exists
    }
    window.chart = new Chart(ctx, chartConfig);
}
function generateTotalTaxedFundChart(chartData) {
    // this.countryData[country][day] = {
    //     startingFunds: d.startingFunds,
    //     endingFunds: d.endingFunds,
    //     startingIncome: d.getStartingIncome(this.income),
    //     endingIncome: d.getEndingIncome(this.income),
    //     generatedFunds: d.generatedFunds,
    //     totalUnitValue: d.totalUnitValue,
    //     countryName: BaseInfo.countries[country].name,
    //     totalInf: d.totalInf,
    //     totalTanks: d.totalTanks,
    //     totalOtherDeployed: d.totalOtherDeployed,
    // }
    // Chart configuration
    const staggeredData = (dataset, offset) => {
        return dataset.data.map((value, index) => ({
            x: index + offset, // Stagger the x value by adding an offset
            y: value
        }));
    };
    let datasets = [];
    let days = [];
    let adjustedDays = [];
    for (let i = 1; i < 16; i++) {
        days.push(i.toString());
        adjustedDays.push((i - 1).toString());
    }
    for (let country of Object.keys(chartData)) {
        let set = {};
        set.label = BaseInfo.countries[country].name;
        let dayData = [];
        for (let day in days) {
            let incomeEnd = chartData[country][day].generatedTaxedFunds;
            dayData.push(incomeEnd);
        }
        set.data = dayData;
        set.data = staggeredData(set, Object.keys(chartData).indexOf(country) / Object.keys(chartData).length);
        set.borderColor = CountryColor[country];
        set.borderWidth = 1;
        set.fill = false;
        datasets.push(set);
    }
    const chartConfig = {
        type: 'line', // or 'bar' or other types
        data: {
            labels: adjustedDays,
            datasets: datasets,
        },
        options: {
            showLine: false,
            scales: {
                x: {
                    type: 'linear', // Use a linear scale for x-axis
                    title: {
                        display: true,
                        text: 'Days'
                    },
                    beginAtZero: true // Adjust based on your data range
                },
                y: {
                    title: {
                        display: true,
                        text: 'Generated Funds on Day End'
                    }
                }
            },
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    display: true
                },
                tooltip: {
                    enabled: true
                },
                customLabel: {}
            }
        }
    };

    // Render the chart
    const ctx = document.getElementById('income-graph').getContext('2d');
    if (window.chart) {
        window.chart.destroy(); // Clear the previous chart if it exists
    }
    window.chart = new Chart(ctx, chartConfig);
}
window.generateFundChart = generateFundChart;
window.generateTotalFundChart = generateTotalFundChart;
window.generateTotalTaxedFundChart = generateTotalTaxedFundChart;
async function loadThisShit() {
    try {
        if (typeof Vue === "undefined") {
            await loadScript("js/vue.js");
        }
        await loadScript("js/tinyqueue.js");
        if (typeof _ === "undefined") {
            await loadScript("js/lodash.min.js");
        }

        const path = window.location.pathname;
        if (path.includes("prevmaps.php")) {
            initPrevmaps();
        }
    } catch (error) {
        console.error("Failed to load scripts or initialize:", error);
    }
}
window.gameMap = document.getElementById("gamemap")
loadThisShit();