Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*Sadye's report analyzer(=custom farm assistant)*/
- var settings = {
- worldSpeed: 1.5,
- unitSpeed: 0.6,
- sortOn: "distance", //also timesinceattack
- ignoreTooLittleScouts: true,
- minTroops: 0.01,
- discountFactor: 1.01,
- filterIgnoreTypes: "none",
- filterIgnoreIfTroops: false,
- filterMaxWall: 20,
- filterMaxDistance: 20,
- filterMaxReadAge: 24,
- filterMaxUseAge: 6,
- }
- // Script dat reports analyseert en sorteert op afstand en wall
- "undefined" == typeof window.$.twAjax && (window.$.twAjax = function() {
- var a = function(a, b) {
- this.options = a, this.promise = b
- },
- b = function() {
- var a = [],
- b = !1,
- c = function() {
- var b = a[0];
- $.ajax(b.options).done(function() {
- b.promise.resolve.apply(null, arguments), a.splice(b, 1), d()
- }).fail(function() {
- b.promise.reject.apply(null, arguments), d()
- })
- },
- d = function() {
- a.length ? (b = !0, c()) : b = !1
- },
- e = function(c) {
- a.push(c), b || d()
- };
- return {
- push: e
- }
- }();
- return function(c) {
- var d = $.Deferred();
- return b.push(new a(c, d)), d
- }
- }());
- // Indien coordinaten gegeven -> Lees muur level uit rapporten of schat muur a.d.h. verloren troepen
- // Anders -> Vind dorpen in omgeving en sorteer op afstand/muur (allebei instelbaar met min, max)
- var data = {};
- var currentAttacks = {};
- var unitTypes = ["spear", "sword", "axe", "archer", "spy", "light", "marcher", "heavy", "ram", "catapult", "snob", "knight", ];
- var buildingTypes = ["main", "hide", "market", "storage", "stable", "smith", "barracks", "place", "wall", "iron", "clay", "wood", "farm", "church", "watchtower", "statue", "garage", "snob"];
- var minLight = [1, 4, 32, 87, 170, 281];
- function init() {
- $('#content_value').html('<h3> .Sadye's coordinate grabber </h3> <div id="request_data" class="vis"><h4>Press load new reports to retrieve all new reports!</h4></div> <div id="am_widget_Farm" data-widget="Farm" class="am_widget vis spaced"> <h4> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/icons/configuration.png" title="" alt="" class=""> Filter and sort settings </h4> <div class="body"> <div id="plunder_list_filters" style="display:inline-block;background-color:#f4e4bc;margin:2px 2px 0 2px"> <div style="padding:2px 5px 2px 8px;float:left"> <div> <label for="sort">Sort on</label> <select id="sort" name="sort"> <option value="distance">Distance</option> <option value="wall">Wall</option> <option value="time">Time</option> <option value="expected_res">Expected res</option> <option value="expected_res_per_field">Expected res per field</option> </select> </div> <div> <label title="Dicounts the expected gs with this factor each hour" for="discount_factor">Discount factor (if unsure, set to 1)</label> <br> <input type="text" maxlength="5" name="discount_factor" id="discount_factor" value="1.00"> </div> <div> <input style="width:20px" type="text" maxlength="2" name="filter_distance_max" id="filter_distance_max" value="20"><label for="filter_distance_max">Max distance</label> </div> </div> <div style="padding:2px 5px 2px 8px;float:left"> <div> <label for="ignore_types">Ignore: </label> <select id="ignore_types" name="ignore_types"> <option value="none">None</option> <option value="players">Players</option> <option value="barbs">Barbs</option> </select> </div> <div> <input type="checkbox" name="filter_troops_in_village" id="filter_troops_in_village"><label for="filter_troops_in_village">Ignore if troops in village</label> <br> </div> <div> <input style="width:20px" type="text" maxlength="2" name="filter_wall_level_max" id="filter_wall_level_max" value="21"><label for="filter_wall_level_max">Max wall level</label> </div> </div> <div style="padding:2px 5px 2px 8px;float:left"> <div> <input style="width:20px" type="text" maxlength="2" name="filter_max_read_age" id="filter_max_read_age" value="24"><label for="filter_max_read_age">Max interpret age of report</label> </div><div> <input style="width:20px" type="text" maxlength="2" name="filter_max_use_age" id="filter_max_use_age" value="6"><label for="filter_max_use_age">Max age of report for res calculation </label> </div> </div> <div style="width:100%;padding:2px 5px 2px 5px;float:left"><button id="apply_settings" class="btn">Apply settings</button><button id="load_new_reports" class="btn">Load new reports</button></div> </div> <div class="vis"> <form id="farm_units"> <table id="units_home" style="width:100%"> <tbody><tr><th class="vis"><h4>Available</h4></th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_spear.png" title="" alt="" class=""> </th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_sword.png" title="" alt="" class=""> </th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_axe.png" title="" alt="" class=""> </th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_archer.png" title="" alt="" class=""> </th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_spy.png" title="" alt="" class=""> </th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_light.png" title="" alt="" class=""> </th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_marcher.png" title="" alt="" class=""> </th> <th style="width:50px;text-align:center" class="fm_unit"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_heavy.png" title="" alt="" class=""> </th> </tr><tr> <td>This village</td> <td style="text-align:center" class="unit-item unit-item-spear hidden" id="spear">0</td><td style="text-align:center" class="unit-item unit-item-sword hidden" id="sword">0</td><td style="text-align:center" class="unit-item unit-item-axe hidden" id="axe">0</td><td style="text-align:center" class="unit-item unit-item-archer hidden" id="archer">0</td><td style="text-align:center" class="unit-item unit-item-spy hidden" id="spy">0</td><td style="text-align:center" class="unit-item unit-item-light" id="light">3</td><td style="text-align:center" class="unit-item unit-item-marcher hidden" id="marcher">0</td><td style="text-align:center" class="unit-item unit-item-heavy hidden" id="heavy">0</td> </tr> </tbody></table> </form> </div> <table id="plunder_list" style="width:100%"> <tbody><tr> <th> </th><th> </th> <th> </th> <th title="is a Player?"><span class="icon header knight"></span></th> <th>Dorp</th> <th>Time</th> <th><span class="icon header ressources"> </span></th> <th><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/buildings/wall.png" class=""></th> <th><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/rechts.png" class=""></th> <th colspan="2"> <img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/questionmark.png" title="Send the minimum amount of light" width="13" height="13" class=""> </th> <th><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/questionmark.png" width="13" height="13" class=""></th> <th><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/questionmark.png" width="13" height="13" class=""></th> <th><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/buildings/place.png" class=""></th> </tr> </tbody> </table> </div>');
- retrieveOldReports();
- //analyzeReports();
- populateTable();
- applySettings();
- updateHomeUnits(true);
- updateCurrentAttacks(true);
- $('#apply_settings').click(function() {
- applySettings();
- });
- $('#load_new_reports').click(function() {
- analyzeReports();
- applySettings();
- });
- }
- function updateHomeUnits(autorefresh) {
- $.twAjax({
- url: "game.php?village=" + game_data.village.id + "&screen=place&ajax=home_units&client_time=" + Math.round(new Date().getTime() / 1000),
- }).done(function(result) {
- var units = JSON.parse(result);
- for (var unit in units) {
- if (parseInt(units[unit])) {
- $('#' + unit).removeClass('hidden').text(units[unit]);
- } else {
- $('#' + unit).addClass('hidden').text('0');
- }
- }
- if (autorefresh) {
- window.setTimeout(function() {
- updateHomeUnits(true);
- }, 10 * 1000);
- }
- });
- }
- function updateCurrentAttacks(autorefresh) {
- currentAttacks = {};
- $.twAjax({
- url: "game.php?village=" + game_data.village.id + "&screen=place"
- }).done(function(result) {
- // read current attacjs
- $(result).find('tr.command-row td:first-child').each(function(i, e) {
- var type = $(e).find('span').data('command-type');
- var coords = $(e).text().match(/\d{2,3}\|\d{2,3}/)[0];
- if (!currentAttacks[coords]) {
- currentAttacks[coords] = {};
- }
- currentAttacks[coords][type] = true;
- });
- // update in table
- console.log("Removing attack images");
- $('td a:contains("|") img').remove(); // remove all current attack images
- $('td a:contains("|")').each(function(i, e) {
- var coords = $(e).text().trim().match(/\d{2,3}\|\d{2,3}/);
- //console.log("Calculating attack images for " + coords);
- var attackImages = $(e).text();
- if (currentAttacks[coords]) {
- if (currentAttacks[coords].attack) {
- attackImages += '<img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/command/attack_small.png">';
- }
- if (currentAttacks[coords].return) {
- attackImages += '<img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/command/return_attack_small.png">';
- }
- }
- $(e).html(attackImages);
- });
- if (autorefresh) {
- window.setTimeout(function() {
- updateCurrentAttacks(true);
- }, 10 * 1000);
- }
- });
- }
- function applySettings() {
- settings.sortOn = $('#sort').val();
- settings.filterIgnoreTypes = $('#ignore_types').val();
- settings.filterIgnoreIfTroops = $('#filter_troops_in_village').is(':checked');
- settings.filterMaxWall = parseInt($('#filter_wall_level_max').val());
- settings.filterMaxDistance = parseInt($('#filter_distance_max').val());
- settings.filterMaxReadAge = parseInt($('#filter_max_read_age').val());
- settings.filterMaxUseAge = parseInt($('#filter_max_use_age').val());
- settings.discountFactor = parseFloat($('#discount_factor').val());
- console.log(settings.discountFactor);
- updateCurrentAttacks(false);
- populateTable();
- }
- function sendAttack(frameId, url, coords, expectedRes, overrideReport, justScouts) {
- var callback = function(frameId, overrideReport, justScouts) {
- var frame = $('#frame_' + frameId).contents();
- var targetAttack = frame.find("#target_attack");
- var error = frame.find('.error_box');
- if (error.length > 0) {
- console.warn("Error: " + error);
- alert("Error: " + error.text());
- $('#frame_' + frameId).remove();
- return;
- }
- else if (targetAttack.length > 0) {
- // some calculations to send min or max amount
- var lc = parseInt(frame.find('#unit_input_light').data('all-count'));
- var spy = parseInt(frame.find('#unit_input_spy').data('all-count'));
- var spyToSend = Math.min(spy, 1);
- if (spy === 0 && !settings.ignoreTooLittleScouts || (justScouts && spy < justScouts)) {
- //alert("Not enough spy!");
- console.warn("Not enough spy for " + coords);
- $('#frame_' + frameId).remove();
- return;
- }
- if (justScouts) {
- // we know from previous if that we have enough spy
- frame.find("#unit_input_spy").val(justScouts);
- targetAttack.click();
- return;
- }
- var minLc = 1;
- var maxLc = Math.ceil(expectedRes / 80);
- if (data[coords].buildingData && minLight[data[coords].buildingData.wall]) {
- minLc = minLight[data[coords].buildingData.wall];
- }
- if (lc < minLc && !overrideReport) {
- alert("Not enough LC!");
- console.warn("Not enough LC for " + coords);
- $('#frame_' + frameId).remove();
- return;
- }
- var lcToSend = Math.max(minLc, Math.min(maxLc, lc));
- if (!overrideReport) {
- frame.find('#unit_input_light').val(lcToSend);
- } else {
- console.log("spy: " + spyToSend + " LC: " + minLc + " p: " + game_data.village.points * settings.minTroops);
- if (minLc/4 + spyToSend/2 < Math.floor(game_data.village.points * settings.minTroops)) {
- minLc = Math.ceil((Math.floor(game_data.village.points * settings.minTroops) - 2*spyToSend) / 4);
- }
- console.log("spy: " + spyToSend + " LC: " + minLc + " p: " + game_data.village.points * settings.minTroops);
- frame.find('#unit_input_light').val(minLc);
- }
- frame.find("#unit_input_spy").val(spyToSend);
- targetAttack.click();
- } else {
- frame.find('#troop_confirm_go').click();
- updateHomeUnits();
- $('#frame_' + frameId).load(function() {
- $(this).remove();
- })
- }
- }
- $('<iframe id="frame_' + frameId + '" src="' + url + '" />').load(function(event) {
- return callback(frameId, overrideReport, justScouts);
- }).css({
- width: '100px',
- height: '100px',
- position: 'absolute',
- left: '-100px',
- top: '-100px',
- }).appendTo('body').hide();
- }
- function populateTable() {
- $('#plunder_list tr:gt(0)').remove();
- var sortedData = [];
- for (var key in data) {
- sortedData.push(data[key]);
- }
- //console.log(sortedData);
- var serverTime = getServerTime(document);
- sortedData = sortedData.filter(function(e, i, arr) {
- if (e.isPlayer && settings.filterIgnoreTypes == "players" || !e.isPlayer && settings.filterIgnoreTypes == "barbs") {
- return false;
- }
- if (settings.filterIgnoreIfTroops) {
- for (var i in e.enemyHome) {
- if (e.enemyHome[i] != 0) return false;
- }
- }
- var d = getDistance(game_data.village.coord, e.coords);
- if (d >= settings.filterMaxDistance) {
- return false;
- }
- if (e.buildingData && e.buildingData.wall >= settings.filterMaxWall) {
- return false;
- }
- return true;
- });
- sortedData.sort(function(a, b) {
- if (settings.sortOn == "wall") {
- if (a.buildingData && b.buildingData) {
- if (a.buildingData.wall !== b.buildingData.wall) {
- return a.buildingData.wall - b.buildingData.wall;
- } else {
- return getDistance(a.coords, game_data.village.coord) - getDistance(b.coords, game_data.village.coord);
- }
- } else if (a.buildingData) {
- return -1;
- } else {
- return 1;
- }
- } else if (settings.sortOn == "expected_res") {
- if (a.buildingData && b.buildingData) {
- //var serverTime = getServerTime(document);
- return getExpectedRes(b.coords, serverTime, false, false) - getExpectedRes(a.coords, serverTime, false, false);
- } else if (a.buildingData) {
- return -1;
- } else {
- return 1;
- }
- } else if (settings.sortOn == "expected_res_per_field") {
- if (a.buildingData && b.buildingData) {
- //var serverTime = getServerTime(document);
- return getExpectedRes(b.coords, serverTime, false, false) / getDistance(b.coords, game_data.village.coord) - getExpectedRes(a.coords, serverTime, false, false) / getDistance(a.coords, game_data.village.coord);
- } else if (a.buildingData) {
- return -1;
- } else {
- return 1;
- }
- }
- else if (settings.sortOn == "time") {
- return b.lastAttack.getTime() - a.lastAttack.getTime();
- }
- return getDistance(a.coords, game_data.village.coord) - getDistance(b.coords, game_data.village.coord);
- });
- for (var i in sortedData) {
- var resLeft = 0; // res left (assuming no hauls since our last haul)
- var resLeftString = ""; // ? if we etimate buildings, ?? if we estimate buildings and res left
- if (sortedData[i].scoutRes) {
- if (sortedData[i].scoutBuilding) {
- // all data
- resLeft = Math.round(getExpectedRes(sortedData[i].coords, getServerTime(document), false, false), 0);
- } else {
- resLeftString = "~";
- resLeft = Math.round(getExpectedRes(sortedData[i].coords, getServerTime(document), false, {
- storage: 5,
- hide: 3,
- wood: 2,
- clay: 2,
- iron: 2
- }), 0);
- }
- } else if (!sortedData[i].fullHaul) {
- resLeftString = "~~";
- resLeft = Math.round(getExpectedRes(sortedData[i].coords, getServerTime(document), 0, {
- storage: 5,
- hide: 3,
- wood: 2,
- clay: 2,
- iron: 2
- }), 0);
- } else {
- resLeftString = "~~";
- resLeft = Math.round(getExpectedRes(sortedData[i].coords, getServerTime(document), 50, {
- storage: 5,
- hide: 3,
- wood: 2,
- clay: 2,
- iron: 2
- }), 0);
- }
- if (resLeft < 0) {
- resLeft = 0;
- resLeftString = "";
- }
- // build attack images
- var attackImages = "";
- if (currentAttacks[sortedData[i].coords]) {
- if (currentAttacks[sortedData[i].coords].attack) {
- attackImages += '<img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/command/attack_small.png">';
- }
- if (currentAttacks[sortedData[i].coords].return) {
- attackImages += '<img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/command/return_attack_small.png">';
- }
- }
- var dateString = leadingZero(sortedData[i].lastAttack.getUTCHours()) + ":" + leadingZero(sortedData[i].lastAttack.getUTCMinutes()) + ":" + leadingZero(sortedData[i].lastAttack.getUTCSeconds());
- if (serverTime.getDate() == sortedData[i].lastAttack.getDate()) {
- dateString = "Today, " + dateString;
- } else {
- dateString = leadingZero(sortedData[i].lastAttack.getUTCDate()) + "-" + leadingZero(sortedData[i].lastAttack.getUTCMonth() + 1) + "-" + sortedData[i].lastAttack.getUTCFullYear() + " " + dateString;
- }
- $('#plunder_list tbody').append('<tr class="row_' + (i % 2 == 1 ? 'a' : 'b') + '">\
- <td><a href="#/" onclick="deleteVillage(\''+ sortedData[i].coords +'\');"><img src="https://dsnl.innogamescdn.com/8.72/32238/graphic/delete.png"></a></td>\
- <td><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/dots/' + sortedData[i].dots + '.png"></td>\
- <td><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/max_loot/' + (sortedData[i].fullHaul ? 1 : 0) + '.png" class=""></td>\
- <td>' + (sortedData[i].isPlayer ? '<a target="_blank" href="game.php?village=' + game_data.village.id + '&screen=info_player&id=' + sortedData[i].playerId + '" title="' + sortedData[i].playerName + '" class="icon header knight"> <a>' : ' ') + '</td>\
- <td><a target="_blank" href="game.php?village=' + game_data.village.id + '&screen=report&mode=all&group_id=0&view=' + sortedData[i].reportId + '">(' + sortedData[i].coords + ') ' + attackImages + '</a></td>\
- <td>' + dateString + '</td>\
- <td title="Best estimate of res at arrival"><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/max_loot/1.png">' + (resLeftString + resLeft) + ' <span style="float:right;" title="Per field of travel">(' + resLeftString + Math.round(resLeft / getDistance(sortedData[i].coords, game_data.village.coord)) + ')</span></td>\
- <td>' + (sortedData[i].buildingData ? sortedData[i].buildingData.wall : "?") + '</td>\
- <td>' + Math.round(getDistance(game_data.village.coord, sortedData[i].coords) * 10) / 10 + '</td>\
- <td><a target="_blank" href="game.php?village=' + game_data.village.id + '&screen=info_village&id=' + sortedData[i].villageId + '"><span class="icon header village"></span></a></td>\
- <td><a class="farm_icon_a farm_icon" href="#/" onclick="javascript:sendAttack(\'' + sortedData[i].villageId + '\', \'' + 'game.php?village=' + game_data.village.id + '&screen=place&target=' + sortedData[i].villageId + '\', \'' + sortedData[i].coords + '\', ' + resLeft + ', true, false);$(this).css({opacity: \'0.5\'});"></a></td>\
- <td><a class="farm_icon_c farm_icon" href="#/" onclick="javascript:sendAttack(\'' + sortedData[i].villageId + '\', \'' + 'game.php?village=' + game_data.village.id + '&screen=place&target=' + sortedData[i].villageId + '\', \'' + sortedData[i].coords + '\', ' + resLeft + ', false, false);$(this).css({opacity: \'0.5\'});"></a></td>\
- <td><a href="#/" onclick="javascript:sendAttack(\'' + sortedData[i].villageId + '\', \'' + 'game.php?village=' + game_data.village.id + '&screen=place&target=' + sortedData[i].villageId + '\', \'' + sortedData[i].coords + '\', ' + resLeft + ', true, '+ (sortedData[i].isPlayer ? 5 : 1)+');$(this).css({opacity: \'0.5\'});"><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/unit/unit_spy.png"></a></td>\
- <td><a target="_blank" href="game.php?village=' + game_data.village.id + '&screen=place&target=' + sortedData[i].villageId + '"><img src="https://dsnl.innogamescdn.com/8.71/32187/graphic/buildings/place.png"></a></td>\
- </tr>');
- //console.log(sortedData[i].scoutRes, sortedData[i].scoutBuilding, sortedData[i].coords, getServerTime(document));
- // -> OLD SEND ATTACK CODE//<a target="_blank" href="game.php?village=' + game_data.village.id + '&screen=place&target=' + sortedData[i].villageId + '&light=' + Math.max((sortedData[i].buildingData && minLight[sortedData[i].buildingData.wall] ? minLight[sortedData[i].buildingData.wall] : 0), Math.ceil(resLeft / 80)) + '&spy=1" class="farm_icon farm_icon_c" onclick="$(this).css({opacity:\'.5\'});sendAttack()"></a>
- //frameId, url, coords, expectedRes
- //sendAttack(sortedData[i].villageId, 'game.php?village=' + game_data.village.id + '&screen=place&target=' + sortedData[i].villageId, sortedData[i].coords, resLeft)
- }
- }
- var deleteVillage = function(coords) {
- if (window.confirm("Are you sure?")) {
- delete data[coords];
- // store in localstorage
- localStorage.setItem(game_data.world + "_sadye_rep_data", JSON.stringify(data));
- populateTable();
- }
- }
- var leadingZero = function(string) {
- if (parseInt(string) < 10) {
- return "0" + string;
- }
- return string;
- }
- var getExpectedRes = function(coords, serverTime, assumeRes, assumeBuildings) {
- let lastReport = data[coords];
- let distance = getDistance(game_data.village.coord, coords);
- // travel time for LC/
- let travelTimeInHours = distance / 10 / settings.worldSpeed / settings.unitSpeed;
- // max 6 hours
- let timePassedInHours = Math.min((serverTime.getTime() - lastReport.lastAttack.getTime()) / (1000 * 60 * 60), settings.filterMaxUseAge);
- //console.debug(coords + ". Distance: " + distance + ". Travel time: " + travelTimeInHours + ". Time since attack: " + timePassedInHours);
- let maxStorage = null;
- let maxHide = null
- let resOver = null;
- let resPerHour = null;
- if (assumeBuildings !== false) {
- //console.debug("Assuming buildings!");
- maxStorage = getMaxStorage(assumeBuildings.storage);
- //console.log(maxStorage);
- maxHide = getMaxHiding(assumeBuildings.hide);
- //console.log(maxHide);
- resPerHour = getResPerHour(assumeBuildings.wood) + getResPerHour(assumeBuildings.clay) + getResPerHour(assumeBuildings.iron);
- //console.log(resPerHour);
- } else {
- maxStorage = getMaxStorage(lastReport.buildingData.storage);
- maxHide = getMaxHiding(lastReport.buildingData.hide);
- resPerHour = getResPerHour(lastReport.buildingData.wood) + getResPerHour(lastReport.buildingData.clay) + getResPerHour(lastReport.buildingData.iron);
- }
- //console.debug("maxStorage: " + maxStorage + ". maxHide: " + maxHide + ". resPerHour: " + resPerHour);
- if (assumeRes !== false) {
- console.debug("Assuming res left")
- resOver = assumeRes;
- } else {
- resOver = lastReport.resLeft;
- }
- let maxLoot = maxStorage - maxHide;
- let tempRes = resOver + (timePassedInHours) * resPerHour;
- let expectedRes = Math.min(maxLoot, tempRes)
- //console.debug("Expected res for " + coords + "@" + unit + ": " + expectedRes);
- if (settings.discountFactor != 1) {
- expectedRes = expectedRes / (Math.pow(settings.discountFactor, timePassedInHours + travelTimeInHours));
- //console.log(timePassedInHours, travelTimeInHours);
- }
- //console.debug("Expected discounted res for " + coords + "@" + unit + ": " + expectedRes);
- return expectedRes;
- }
- function analyzeReports() {
- $('#load_new_reports').prop('disabled', true).addClass('btn-disabled');
- var reportsToAnalyze = [];
- var listUrl = ["/game.php?village=" + game_data.village.id + "&screen=report&mode=attack&group_id=0&from=", "/game.php?village=" + game_data.village.id + "&screen=report&mode=attack&group_id="];
- var reportUrl = "/game.php?village=" + game_data.village.id + "&screen=report&mode=attack&view=";
- var currentRun = getServerTime(document);
- var lastRun = JSON.parse(localStorage.getItem(game_data.world + "_sadye_rep_lastrun"));
- var lastRun = lastRun ? new Date(lastRun) : null;
- console.log(lastRun);
- var maxPages = [-1, -1]; // first one is normal, second one farmAssistant
- var currentPage = [0, 0];
- var totalReports;
- var reportsLeft;
- var parsingTwoLists;
- let finished = [false, false];
- var newReports = true;
- $.twAjax({
- url: listUrl[0] + currentPage[0],
- }).done(function(result) {
- parsingTwoLists = $(result).find('a:contains("[Farm")').attr('href').match(/id=(\d+)/)[1]; // contains the id of the fa-map or nothing
- console.log("Interpreting normal list")
- handleList(result, false);
- console.log("Parsing two lists: ", parsingTwoLists);
- if (parsingTwoLists) {
- listUrl[1] = listUrl[1] + parsingTwoLists + "&from=";
- // if we have fa, also load that one
- $.twAjax({
- url: listUrl[1] + currentPage[1],
- }).done(function(result) {
- handleList(result, parsingTwoLists);
- });
- }
- });
- $(document).ajaxStop(function() {
- $(this).unbind("ajaxStop");
- localStorage.setItem(game_data.world + "_sadye_rep_lastrun", JSON.stringify(currentRun));
- console.log("Ajaxstop!");
- if (newReports) {
- populateTable();
- newReports = false;
- }
- $('#load_new_reports').prop('disabled', false).removeClass('btn-disabled');
- $()
- });
- var handleList = function(result, farmAssistantMap) {
- if (farmAssistantMap) {
- if (maxPages[1] === -1) {
- maxPages[1] = getMaxPages(result);
- console.log("Set maxpages in FA-map: " + maxPages[1]);
- }
- } else {
- if (maxPages[0] === -1) {
- maxPages[0] = getMaxPages(result);
- }
- }
- $('#request_data h4').text("Updating data. Retrieving scannable reports. Current page: " + ((farmAssistantMap ? currentPage[1] + currentPage[0] : currentPage[0]) + 1) + "/" + (farmAssistantMap ? maxPages[0] + maxPages[1] : maxPages[0]));
- $(result).find('#report_list tr td:nth-of-type(3)').each(function(i, e) {
- // retrieve some info
- let coords = $(e).siblings().find('.quickedit-label').text().match(/\d{1,3}\|\d{1,3}/g);
- coords = coords[coords.length - 1];
- let id = $(e).siblings().find("[data-id]").attr('data-id');
- let dateTime = $(e).text().split(" ");
- let dateString = "20" + dateTime[0].split(".").reverse().join("-");
- let receivedAt = new Date(dateString + "T" + dateTime[1] + "Z");
- let now = getServerTime(result);
- if (now.getTime() - receivedAt.getTime() >= 1000 * 60 * 60 * settings.filterMaxReadAge) {
- // older than 24 -> we can immediately stop
- console.debug("Skipped " + coords + " received at " + receivedAt.toUTCString() + " because > " + settings.filterMaxReadAge + " hours.");
- if (farmAssistantMap) { // denote whuch loop is finished
- finished[1] = true;
- } else {
- finished[0] = true;
- }
- return false; //break out of each-loop
- } else if (lastRun && lastRun.getTime() - receivedAt.getTime() >= 1000 * 60) {
- // the report was already caught in the last run
- console.debug("Skipped " + coords + " received at " + receivedAt.toUTCString() + " because we caught it last run. (Start of last run: " + lastRun + ")");
- if (farmAssistantMap) { // denote whuch loop is finished
- finished[1] = true;
- } else {
- finished[0] = true;
- }
- return false;
- } else if (data[coords] && data[coords].scoutBuilding && receivedAt.getTime() - data[coords].scoutBuilding.getTime() <= 60 * 1000) {
- // we already have data from less than a minute later
- console.debug("Skipped " + coords + " received at " + receivedAt.toUTCString() + " last building scout is more recent (" + data[coords].scoutBuilding.toUTCString() + ")");
- } else {
- // valid report
- console.debug("Added! Lastrun: " + (lastRun ? lastRun.toUTCString() : "--no such run--") + ". Received: " + receivedAt.toUTCString());
- reportsToAnalyze.push(id);
- }
- });
- if (parsingTwoLists) { // we are running two in parallel
- if (farmAssistantMap) { // we are in the farm assistant map part
- if (finished[1] || currentPage[1] == maxPages[1] - 1) { // fa map is done
- finished[1] = true; // set this to true, so the other one can also check this
- if (finished[0]) { // all are finished, so handle the finished list
- listFinished();
- }
- } else {
- // we are not done reading reports in the FA-map, so open next page
- currentPage[1]++;
- console.debug("Going to next page in FA-map: " + (currentPage[1] + 1));
- $.twAjax({
- url: listUrl[1] + (currentPage[1] * 12),
- }).done(function(result) {
- handleList(result, farmAssistantMap);
- });
- }
- } else {
- // we are in the normal map
- if (finished[0] || currentPage[0] == maxPages[0] - 1) {
- finished[0] = true;
- if (finished[1]) {
- listFinished();
- }
- } else {
- currentPage[0]++;
- console.debug("Going to next page in normal map: " + (currentPage[0] + 1));
- $.twAjax({
- url: listUrl[0] + (currentPage[0] * 12),
- }).done(function(result) {
- handleList(result, false);
- });
- }
- }
- } else { // no farm assistant map
- if (finished[0] || currentPage[0] == maxPages[0] - 1) {
- // all is done
- listFinished();
- } else {
- // load the next page
- currentPage[0]++;
- console.debug("Going to next page: " + (currentPage[0] + 1));
- $.twAjax({
- url: listUrl[0] + (currentPage[0] * 12),
- }).done(function(result) {
- handleList(result, false);
- });
- }
- }
- }
- var listFinished = function() {
- console.log("Finished reading list of reports!");
- totalReports = reportsToAnalyze.length;
- reportsLeft = totalReports;
- $('#request_data h4').text("Updating data. " + Math.round((totalReports - reportsLeft) / totalReports * 100, 0) + "% (" + (reportsLeft) + " reports left)");
- // start interpreting
- while (reportsToAnalyze.length > 0) {
- var id = reportsToAnalyze.shift();
- $.twAjax({
- url: reportUrl + id,
- async: true
- }).done(function(result) {
- reportsLeft--;
- handleReport(result, id);
- $('#request_data h4').text("Updating data. " + Math.round((totalReports - reportsLeft) / totalReports * 100, 0) + "% (" + (reportsLeft) + " reports left)");
- if (reportsLeft === 0) {
- $('#request_data h4').text("Ready! (read " + totalReports + " reports)");
- $('#load_new_reports').removeClass('btn-disabled').prop('disabled', false);
- }
- });
- }
- $.twAjax({
- url: listUrl[0] // so that we don't end up in farm assistant map
- });
- if (reportsLeft === 0) {
- $('#request_data h4').text("Ready! (read " + totalReports + " reports)");
- $('#load_new_reports').removeClass('btn-disabled').prop('disabled', false);
- }
- }
- var handleReport = function(result) {
- let reportHolder = $(result);
- let coords = reportHolder.find('span.quickedit-label').text().trim().match(/\d{1,3}\|\d{1,3}/g);
- coords = coords[coords.length - 1];
- // arrival time
- let arrival = reportHolder.find('.small.grey').parent().text().trim().split(" ");
- arrival[0] = arrival[0].split(".").reverse().join("-"); //fixes date
- arrival[1] = arrival[1].replace(/:([^:]*)$/, "." + '$1'); //fixes time (replace last : with .)
- arrival = new Date("20" + arrival[0] + "T" + arrival[1] + "Z"); // sets the date
- if (data[coords] && data[coords].scoutBuilding && arrival.getTime() <= data[coords].scoutBuilding.getTime()) {
- // if we have already scouted the buildings here and this report is older than our most recent building reports
- // we have nothing to gain from it, so we can ignore it
- console.debug("Skipping " + coords + " because we have fresher building data. Current: " + arrival.toUTCString() + ", in db: " + data[coords].scoutBuilding.toUTCString());
- return;
- }
- // luck
- let luck = parseFloat(reportHolder.find('.nobg b').text().trim().replace("%", ""));
- // report id
- let reportId = reportHolder.find('th span.quickedit').data('id');
- // dots
- let dots = reportHolder.find('.vis th img').eq(4).attr('src').match(/dots\/(.+)\.png/)[1];
- // send from
- let sentFromId = parseInt(reportHolder.find('[data-id].village_anchor').eq(0).attr('data-id'));
- let villageId = parseInt(reportHolder.find('[data-id].village_anchor').eq(1).attr('data-id'));
- let sentFromCoords = reportHolder.find('[data-id].village_anchor').eq(0).text().trim().match(/\d{1,3}\|\d{1,3}/g);
- sentFromCoords = sentFromCoords[sentFromCoords.length - 1];
- // units send and lost
- let unitsSent = {};
- let unitsDied = {};
- for (let i in unitTypes) { // i is a string, wtf
- unitsSent[unitTypes[i]] = parseInt(reportHolder.find('#attack_info_att_units .unit-item').eq(i).text().trim());
- unitsDied[unitTypes[i]] = parseInt(reportHolder.find('#attack_info_att_units .unit-item').eq(unitTypes.length + parseInt(i)).text().trim());
- if (isNaN(unitsDied[unitTypes[i]])) {
- unitsDied[unitTypes[i]] = -1;
- }
- }
- // is player
- let isPlayer = reportHolder.find('#attack_info_def th').eq(1).text().trim() !== "---";
- let playerName = reportHolder.find('#attack_info_def th').eq(1).text().trim();
- let playerId = isPlayer ? reportHolder.find('#attack_info_def th a').attr('href').match(/id=(\d+)/)[1] : null;
- let enemyHome = null;
- let enemyDied = null;
- // if atleast on troop survived, we have data on their troops
- for (let i in unitsSent) {
- if (unitsSent[i] != unitsDied[i]) {
- // we have at least one surviving troop
- // instantiate objects
- enemyHome = {};
- enemyDied = {};
- // parse their units
- // this ignores militia
- for (let i in unitTypes) { // i is a string, wtf
- enemyHome[unitTypes[i]] = parseInt(reportHolder.find('#attack_info_def_units .unit-item').eq(i).text().trim());
- // note the length + 1 (because we ignore the mob)
- enemyDied[unitTypes[i]] = parseInt(reportHolder.find('#attack_info_def_units .unit-item').eq(unitTypes.length + 1 + parseInt(i)).text().trim());
- if (isNaN(enemyDied[unitTypes[i]])) {
- enemyDied[unitTypes[i]] = -1;
- }
- }
- break;
- }
- }
- // results
- let resTaken = reportHolder.find('#attack_results tr td').eq(1).text().trim().split("/");
- let maxResTaken = parseInt(resTaken[1]);
- resTaken = parseInt(resTaken[0]);
- // keep track of what level we scouted
- let scoutLevel = 0;
- // res left (if no data == null)
- let resLeft = null;
- // buildings scouted (no data -> null)
- let buildingData = null;
- // troops outside village
- let enemyAway = null;
- // scout info
- if (reportHolder.find("#attack_spy_resources").length > 0) {
- // we have scouted resources
- scoutLevel = 1;
- let resArray = reportHolder.find('#attack_spy_resources tr:first .nowrap').text().trim().split(" ");
- for (let i in resArray) {
- let p = parseInt(resArray[i].replace(".", ""));
- if (!isNaN(p)) {
- resLeft += p;
- }
- }
- } else if (resTaken < maxResTaken) {
- // if we didnt have full haul we can assume no res left
- resLeft = 0;
- } else {
- // if we did have full haul we have no info, so signify with -1
- resLeft = -1;
- }
- if (reportHolder.find('#attack_spy_building_data').length > 0) {
- // we have scouted buildings
- scoutLevel = 2;
- // init buildingData
- buildingData = {};
- // parse them to array
- let parsedData = JSON.parse(reportHolder.find('#attack_spy_building_data').val());
- // parse them in a new array
- for (let i in parsedData) {
- // for all data that we have, store them in buildingdata as building:level
- buildingData[parsedData[i].id] = parseInt(parsedData[i].level);
- }
- // then run over all buildings and set them to 0 if they don't exist yet
- for (let i in buildingTypes) {
- if (buildingData[buildingTypes[i]] == undefined) {
- buildingData[buildingTypes[i]] = 0;
- }
- }
- }
- if (reportHolder.find('#attack_spy_away').length > 0) {
- // we have data on troops away
- scoutLevel = 3;
- // init enemy away
- enemyAway = {};
- for (let i in unitTypes) { // i is a string, wtf
- enemyAway[unitTypes[i]] = parseInt(reportHolder.find('#attack_spy_away .unit-item').eq(i).text().trim());
- }
- }
- // we have interpreted all there is,
- // now store it
- // first retrieve the old report (to overwrite it)
- let report = {};
- if (data[coords]) {
- report = data[coords];
- }
- report['playerId'] = playerId;
- report['reportId'] = reportId;
- report['playerName'] = playerName;
- report['villageId'] = villageId;
- report['dots'] = dots;
- report['coords'] = coords;
- report['lastAttack'] = arrival;
- report['luck'] = luck;
- report['sentFromId'] = sentFromId;
- report['sentFromCoords'] = sentFromCoords;
- report['isPlayer'] = isPlayer;
- report['unitsSent'] = unitsSent;
- report['unitsDied'] = unitsDied;
- if (enemyHome) {
- report['enemyHome'] = enemyHome;
- report['enemyDied'] = enemyDied;
- }
- // do not save resTaken and maxResTaken because we can infer all we need to know from resLeft
- //report['resTaken'] = resTaken;
- //report['maxResTaken'] = maxResTaken;
- report['fullHaul'] = resTaken == maxResTaken;
- report['resLeft'] = resLeft; //-1 signifies no data
- if (buildingData) {
- report['buildingData'] = buildingData;
- }
- if (enemyAway) {
- report['enemyAway'] = enemyAway;
- }
- // store when the last scout was
- if (scoutLevel) {
- if (scoutLevel >= 1) {
- report['scoutRes'] = arrival;
- }
- if (scoutLevel >= 2) {
- report['scoutBuilding'] = arrival;
- }
- if (scoutLevel >= 3) {
- report['scoutAway'] = arrival;
- }
- }
- // store to data object
- data[coords] = report;
- // store in localstorage
- localStorage.setItem(game_data.world + "_sadye_rep_data", JSON.stringify(data));
- console.debug(report);
- }
- var getMaxPages = function(result) {
- let t = $(result).find('.paged-nav-item:last');
- if (t && t.length > 0) {
- // found atleast one page
- t = t.text().trim(); //yields "[xx]"
- t = parseInt(t.substring(1, t.length - 1));
- } else {
- // no extra pages found
- t = 1;
- }
- return t;
- }
- }
- var getServerTime = function(result) {
- let serverTime = $(result).find('#serverTime').text().split(":"); //[7; 14; 05] for example
- serverTime[0] = parseInt(serverTime[0]) < 10 ? "0" + serverTime[0] : serverTime[0];
- let serverDate = $(result).find('#serverDate').text().split("/").reverse().join("-");
- return new Date(serverDate + "T" + serverTime.join(":") + "Z");
- }
- var getResPerHour = function(level) {
- if (level == 0) {
- return 5;
- }
- return settings.worldSpeed * 30 * Math.pow(1.163118, level - 1);
- }
- var getDistance = function(opp, me) {
- let a = opp.split("|");
- let b = me.split("|");
- return Math.sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]));
- }
- var getMaxStorage = function(level) {
- return Math.round(1000 * Math.pow(1.2294934, (level - 1)));
- }
- var getMaxHiding = function(level) {
- return Math.round(150 * Math.pow((4 / 3), (level - 1)));
- }
- var retrieveOldReports = function() {
- let tempReports = JSON.parse(localStorage.getItem(game_data.world + "_sadye_rep_data"));
- console.log(tempReports);
- if (tempReports) {
- // parse dates as objects
- for (let i in tempReports) {
- if (tempReports[i].scoutRes) {
- tempReports[i].scoutRes = new Date(tempReports[i].scoutRes);
- }
- if (tempReports[i].scoutBuilding) {
- tempReports[i].scoutBuilding = new Date(tempReports[i].scoutBuilding);
- }
- if (tempReports[i].scoutAway) {
- tempReports[i].scoutAway = new Date(tempReports[i].scoutAway);
- }
- if (tempReports[i].lastAttack) {
- tempReports[i].lastAttack = new Date(tempReports[i].lastAttack);
- }
- }
- console.log("Reports succesfully loaded.");
- data = tempReports;
- } else {
- console.warn("Failed to load reports. Maybe none yet?");
- }
- }
- init();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement