Advertisement
madalino

resources balancer AM

Jun 1st, 2021 (edited)
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2.  
  3. var backgroundColor = "#32313f";
  4. var borderColor = "#3e6147";
  5. var headerColor = "#202825";
  6. var titleColor = "#ffffdf";
  7. var headerColorEven = "#2F4F4F";
  8.  
  9. var headerWood="#001a33"
  10. var headerWoodEven="#002e5a"
  11.  
  12. var headerStone="#3b3b00"
  13. var headerStoneEven="#626200"
  14.  
  15. var headerIron="#1e003b"
  16. var headerIronEven="#3c0076"
  17.  
  18.  
  19.  
  20. if(typeof(TWMap) !="undefined" )
  21.     var  originalSpawnSector = TWMap.mapHandler.spawnSector;
  22.  
  23. var translations={
  24.     en_DK:{
  25.             "today at":"today at",
  26.             "tomorrow at":"tomorrow at",
  27.             "on":"on"
  28.         },
  29.     en_US:{
  30.         "today at":"today at",
  31.         "tomorrow at":"tomorrow at",
  32.         "on":"on",
  33.     },
  34.     pt_PT:{
  35.         "today at":"hoje às",
  36.         "tomorrow at":"amanhã às",
  37.         "on":"a"
  38.     },
  39.     es_ES:{
  40.         "today at":"hoy a las",
  41.         "tomorrow at":"mañana a las",
  42.         "on":"el",
  43.     },
  44.     ro_RO:{
  45.         "today at":"astăzi",
  46.         "tomorrow at":"mâine",
  47.         "on":"data",
  48.     }
  49.  
  50.    
  51. }
  52.  
  53.  
  54. tt("today at")//test translation
  55.  
  56. function addStyle(){
  57.     let css =`
  58.     .shadow20 {
  59.     text-shadow: 0 0 4px black, 0 0 4px black, 0 0 4px black, 0 0 4px black, 0 0 4px black;
  60.     }
  61.  
  62.     `,
  63.     head = document.head || document.getElementsByTagName('head')[0],
  64.     style = document.createElement('style');
  65.    
  66.     head.appendChild(style);
  67.     style.type = 'text/css';
  68.     if (style.styleSheet){
  69.         // This is required for IE8 and below.
  70.         style.styleSheet.cssText = css;
  71.     } else {
  72.         style.appendChild(document.createTextNode(css));
  73.     }
  74. }
  75. addStyle()
  76.  
  77. function createMainInterface(){
  78.     let message_info_factor=`<p>if the factor is 0 your villages will receive resources only for building construction(from account manager)\n</p>
  79.                             <p>if the factor is 1 resources will be distributed equally, at the end of balancing every village will have the same amount of resources\n</p>
  80.                             <p>if it's for example 0.2 in this case your villages will receive 20% from average value of each resources and in adition will receive enough resources for building construction(from account manager)</p>`
  81.    let message_info_construction=`<p>set for how many hours the villages should have resources for building construction\n</p>
  82.                                    <p> your account manager must be active and your villages must have a template construction active,
  83.                                    otherwise this setting will be ignored `
  84.    
  85.    let message_info_cluster=`<p>if it's set to 1 cluster then balancing resources will be globally and for 2 or more it will be locally per each cluster\n</p>
  86.                             <p>a larger number of clusters results in a shorter maximum travel time and balanced more locally which is less optimal \n</p>
  87.                             <p>every time the script is run clusters are calculated randomly and they may not be optimally calculated  every time so look for maximum travel distance \n</p>`
  88.    
  89.    
  90.     html_info = `
  91.     <div id="div_container" class="ui-widget-content div_remove" style="width:850px;background-color:${backgroundColor};cursor:move;z-index:50;">
  92.         <div class="close-btn"  onclick="$('#div_container').remove()" style="position:absolute;top:10px;right: 10px;"><b><a href=#><font color="${titleColor}">X</font></b></a></div>
  93.         <div class="close-btn btn_close"  onclick="$('#div_tables, #table_main').toggle(500)" style="position:absolute;top:10px;right: 35px;"><b><a href=#><font color="${titleColor}">-</font></b></a></div>
  94.  
  95.         <h2><center style="margin:10px"><u><font color="${titleColor}">Resources Balancer</font></u></center></h2>
  96.         <center>
  97.             <table id="table_main"  border="1" style="width: 50%;background-color:${backgroundColor};border-color:${borderColor}">
  98.                 <tr>
  99.                     <td style="text-align:center; width:auto; background-color:${headerColor}" >
  100.                         <center style="margin:5px"><font color="${titleColor}">reserve merchants</font></center>
  101.                     </td>
  102.                     <td style="text-align:left; width:auto; background-color:${headerColor}" >
  103.                     <center style="margin:5px">
  104.                         <div style="display:flex">
  105.                             <div><center><input type="number" id="nr_merchants_reserve" style="text-align:center;" min="0" max="10000" placeholder="15" value="0"></center></div>
  106.                             <div style="margin-left:5px"><center style="margin:1px"><a href="#" onclick="UI.InfoMessage('how many merchants do you want to keep home',4000)"><img src="https://dsen.innogamescdn.com/asset/dbeaf8db/graphic/questionmark.png" style="width: 13px; height: 13px"/></a></center></div>
  107.                         </div>
  108.                     </center>
  109.                     </td>
  110.                 </tr>
  111.                 <tr>
  112.                     <td style="text-align:center; width:auto; background-color:${headerColor}" >
  113.                         <center style="margin:5px"><font color="${titleColor}">construction time[hours]</font></center>
  114.                     </td>
  115.                     <td style="text-align:left; width:auto; background-color:${headerColor}" >
  116.                     <center style="margin:5px">
  117.                         <div style="display:flex">
  118.                             <div><center><input type="number" id="time_construction" style="text-align:center;" min="0" max="10000" placeholder="0" value="0"></center></div>
  119.                             <div style="margin-left:5px"><center style="margin:1px"><a href="#" onclick="UI.InfoMessage(\`${message_info_construction}\`,15000)"><img src="https://dsen.innogamescdn.com/asset/dbeaf8db/graphic/questionmark.png" style="width: 13px; height: 13px"/></a></center></div>
  120.                         </div>
  121.                     </center>
  122.                     </td>
  123.                 </tr>
  124.  
  125.                 <tr>
  126.                     <td style="text-align:center; width:auto; background-color:${headerColor}" >
  127.                         <center style="margin:5px"><font color="${titleColor}">average factor[0-1]</font></center>
  128.                     </td>
  129.                     <td style="text-align:left; width:auto; background-color:${headerColor}" >
  130.                     <center style="margin:5px">
  131.                         <div style="display:flex">
  132.                             <div><center><input type="number" id="nr_average_factor" style="text-align:center;" min="0" max="10000" placeholder="1" value="1"></center></div>
  133.                             <div style="margin-left:5px"><center style="margin:1px"><a href="#" onclick="UI.InfoMessage(\`${message_info_factor}\`,20000)"><img src="https://dsen.innogamescdn.com/asset/dbeaf8db/graphic/questionmark.png" style="width: 13px; height: 13px"/></a></center></div>
  134.                         </div>
  135.                     </center>
  136.                     </td>
  137.                 </tr>
  138.  
  139.                 <tr>
  140.                     <td style="text-align:center; width:auto; background-color:${headerColor}" >
  141.                         <center style="margin:5px"><font color="${titleColor}">number of clusters</font></center>
  142.                     </td>
  143.                     <td style="text-align:left; width:auto; background-color:${headerColor}" >
  144.                     <center style="margin:5px">
  145.                         <div style="display:flex">
  146.                             <div><center><input type="number" id="nr_clusters" style="text-align:center;" min="0" max="10000" placeholder="1" value="1"></center></div>
  147.                             <div style="margin-left:5px"><center style="margin:1px"><a href="#" onclick="UI.InfoMessage(\`${message_info_cluster}\`,20000)"><img src="https://dsen.innogamescdn.com/asset/dbeaf8db/graphic/questionmark.png" style="width: 13px; height: 13px"/></a></center></div>
  148.                         </div>
  149.                     </center>
  150.                     </td>
  151.                 </tr>
  152.  
  153.                 <tr hidden id="tr_merchant_capacity">
  154.                     <td style="text-align:center; width:auto; background-color:${headerColor}" >
  155.                         <center style="margin:5px"><font color="${titleColor}">merchant capacity</font></center>
  156.                     </td>
  157.                     <td style="text-align:left; width:auto; background-color:${headerColor}" >
  158.                     <center style="margin:5px">
  159.                         <div style="display:flex">
  160.                             <div><center><input type="number" id="merchant_capacity" style="text-align:center;" min="0" max="10000" placeholder="1000" value='1000'></center></div>
  161.                             <div style="margin-left:5px"><center style="margin:1px"><a href="#" onclick="UI.InfoMessage('set merchant capacity to either 1000 or 1500',3000)"><img src="https://dsen.innogamescdn.com/asset/dbeaf8db/graphic/questionmark.png" style="width: 13px; height: 13px"/></a></center></div>
  162.                         </div>
  163.                     </center>
  164.                     </td>
  165.                 </tr>
  166.             </table>
  167.         </center>
  168.         <center>
  169.             <input class="btn evt-confirm-btn btn-confirm-yes" type="button" onclick="balancingResources()" style="margin:10px" value="start">
  170.         </center>
  171.  
  172.         <div id="div_tables" hidden>
  173.             <center><div id="table_stats" style="width:100%"></div></center><br>
  174.             <center><div id="table_view" style="height:500px;width:100%;overflow:auto"></div></center>
  175.         </div>
  176.        
  177.     </div>
  178.     `;
  179.     ////////////////////////////////////////add and remove window from page///////////////////////////////////////////
  180.     $("#div_container").remove()
  181.     $("#contentContainer").eq(0).prepend(html_info);
  182.     $("#mobileContent").eq(0).prepend(html_info);
  183.  
  184.     //for mobile browser
  185.  
  186.  
  187.  
  188.     if(game_data.device=="desktop"){
  189.         $("#div_container").css("position","fixed");
  190.         $("#div_container").draggable();
  191.     }
  192.  
  193.  
  194.     if(game_data.locale=="pt_PT"){
  195.         $("#tr_merchant_capacity").show()
  196.     }
  197.  
  198.  
  199.  
  200.  
  201.  
  202.     //initialization settings
  203.     if(localStorage.getItem(game_data.world+"settings_resources_balancer2")!=null ){
  204.         //initialize input numbers
  205.         let list_input=JSON.parse(localStorage.getItem(game_data.world+"settings_resources_balancer2"))
  206.         $('#div_container input[type=number]').each(function (index,elem) {
  207.             this.value=list_input[index]
  208.         });
  209.     }
  210.  
  211.  
  212.     //save settings
  213.     $("#div_container input[type=number]").on("click input change",()=>{
  214.         console.log("save settings")
  215.         let list_input=[]
  216.  
  217.         //save inputs
  218.         $('#div_container input[type=number]').each(function () {
  219.             // var checked = this.checked
  220.             var value=this.value
  221.             // console.log(value)
  222.             list_input.push(value)
  223.         });
  224.    
  225.      
  226.         let data=JSON.stringify(list_input)
  227.         let data_localStorage=localStorage.getItem(game_data.world+"settings_resources_balancer2")
  228.         console.log(data)
  229.         console.log(data_localStorage)
  230.         if(data!=data_localStorage){
  231.             localStorage.setItem(game_data.world+"settings_resources_balancer2",data)
  232.         }
  233.     })
  234.  
  235.    
  236. }
  237.  
  238. createMainInterface()
  239.  
  240.  
  241.  
  242. async function balancingResources(){
  243.  
  244.     let time_construction_total=parseInt(document.getElementById("time_construction").value)
  245.     let averageFactor=parseFloat(document.getElementById("nr_average_factor").value)
  246.     let reserveMerchants=parseInt(document.getElementById("nr_merchants_reserve").value)
  247.     let merchantCapacity=parseInt(document.getElementById("merchant_capacity").value)
  248.     let nrClusters=parseInt(document.getElementById("nr_clusters").value)
  249.  
  250.     reserveMerchants=(Number.isNaN(reserveMerchants)==true || reserveMerchants<0 )?0:reserveMerchants //by default are 0 merchants as reserver
  251.     nrClusters=(Number.isNaN(nrClusters)==true || nrClusters<1 )?1:nrClusters //by default is one cluster
  252.     time_construction_total=(Number.isNaN(time_construction_total)==true || time_construction_total<0 )?20:time_construction_total//if something is not right by default is 20hours
  253.    
  254.     averageFactor=(Number.isNaN(averageFactor)==true)?1:(averageFactor<0)?0:(averageFactor>1)?1:averageFactor //if>1 is 1 if <0 is 0 if is NaN is 1
  255.     merchantCapacity=(Number.isNaN(merchantCapacity)==true)?1000:(merchantCapacity<1000)?1000:(merchantCapacity>1500)?1500:merchantCapacity //capacitiy is 1000 but for .PT might be 1500
  256.    
  257.    
  258.  
  259.     console.log("reserveMerchants",reserveMerchants)
  260.     console.log("time_construction_total",time_construction_total)
  261.     console.log("averageFactor",averageFactor)
  262.     console.log("merchantCapacity",merchantCapacity)
  263.     time_construction_total=time_construction_total*3600
  264.  
  265.  
  266.  
  267.     $("#div_container").remove()
  268.     let {list_production, map_farm_usage} = await getDataProduction().catch(err=>alert(err))
  269.     let map_incoming = await getDataIncoming().catch(err=>alert(err))
  270.     let map_resources_get_AM = await getResourcesForAM(time_construction_total,map_farm_usage).catch(err=>alert(err))
  271.     let list_production_home=JSON.parse(JSON.stringify(list_production))
  272.  
  273.     console.log("list_production",list_production)
  274.     console.log("map_farm_usage",map_farm_usage)
  275.     console.log("map_incoming",map_incoming)
  276.     console.log("map_resources_get_AM",map_resources_get_AM)
  277.  
  278.  
  279.     let start=new Date().getTime()
  280.  
  281.  
  282.  
  283.  
  284.     ///////////////////////////////////////////////get clusters///////////////////////////////////////
  285.     let kmeans_coords=[]
  286.     for(let i=0;i<list_production.length;i++){
  287.         kmeans_coords.push([
  288.                 parseInt(list_production[i].coord.split("|")[0]),
  289.                 parseInt(list_production[i].coord.split("|")[1])
  290.             ])
  291.     }
  292.     console.log(kmeans_coords)
  293.     let options={
  294.         numberOfClusters:nrClusters,
  295.         maxIterations:100
  296.     }
  297.     let clusters= getClusters(kmeans_coords,options)
  298.     console.log("clusters",clusters)
  299.  
  300.     let list_production_cluster=[]
  301.     let list_production_home_cluster=[]
  302.     let map_draw_on_map=new Map()
  303.  
  304.     for(let i=0;i<clusters.length;i++){// for each cluster
  305.         let list_coords=clusters[i].data
  306.         let list_prod=[],list_prod_home=[]
  307.         // console.log(list_coords)
  308.         for(let j=0;j<list_coords.length;j++){//for each village of a cluster
  309.             let coord=list_coords[j].join("|")
  310.             for(let k=0;k<list_production.length;k++){//search in the main list
  311.                 if(list_production[k].coord == coord){
  312.                     list_prod.push(list_production[k])
  313.                     list_prod_home.push(list_production_home[k])
  314.                     console.log(`label_cluster: ${i}`)
  315.  
  316.                     //add incoming and then show on the map
  317.                     let total_resources_get=0
  318.                     if(map_incoming.has(coord)){
  319.                         total_resources_get=map_incoming.get(coord).wood+map_incoming.get(coord).stone+map_incoming.get(coord).iron
  320.                     }
  321.                     map_draw_on_map.set(list_production[k].id,{
  322.                         label_cluster:i,
  323.                         villageId:list_production[k].id,
  324.                         total_resources_get:total_resources_get,
  325.                         total_resources_send:0
  326.                     })
  327.  
  328.                     break;
  329.                 }
  330.             }
  331.         }
  332.  
  333.         list_production_cluster.push(list_prod)
  334.         list_production_home_cluster.push(list_prod_home)
  335.     }
  336.     console.log("list_production_cluster",list_production_cluster)
  337.  
  338.  
  339.  
  340.     /////////////////////////////////////////////calculate total nr of resources and global average////////////////////////////////////////
  341.  
  342.     let total_wood_home=0,total_stone_home=0,total_iron_home=0
  343.     let avg_wood_total=0,avg_stone_total=0,avg_iron_total=0
  344.  
  345.     for(let i=0;i<list_production.length;i++){
  346.         let coord=list_production[i].coord
  347.         if(map_incoming.has(coord)){
  348.             list_production[i].wood  += map_incoming.get(coord).wood
  349.             list_production[i].stone += map_incoming.get(coord).stone
  350.             list_production[i].iron  += map_incoming.get(coord).iron
  351.  
  352.             //in case minting a village might have huge cantity of resources underway
  353.             list_production[i].wood = Math.min(list_production[i].wood , list_production[i].capacity)
  354.             list_production[i].stone= Math.min(list_production[i].stone, list_production[i].capacity)
  355.             list_production[i].iron = Math.min(list_production[i].iron , list_production[i].capacity)
  356.  
  357.         }
  358.         avg_wood_total +=list_production[i].wood/list_production.length
  359.         avg_stone_total+=list_production[i].stone/list_production.length
  360.         avg_iron_total +=list_production[i].iron/list_production.length
  361.  
  362.         total_wood_home +=list_production[i].wood
  363.         total_stone_home+=list_production[i].stone
  364.         total_iron_home +=list_production[i].iron
  365.     }
  366.  
  367.     // //////////////////////////////////update list_production with all incoming resources ,get average for each resource/////////////////////////
  368.  
  369.     let list_launches=[]
  370.     let list_clusters_stats=[]
  371.  
  372.     let total_wood_send_stats=0,total_stone_send_stats=0,total_iron_send_stats=0
  373.     let total_wood_get_stats=0,total_stone_get_stats=0,total_iron_get_stats=0
  374.  
  375.     for(let i=0;i<list_production_cluster.length;i++){
  376.         console.log(`--------------cluster:${i}----------------`)
  377.  
  378.         let list_prod=list_production_cluster[i]
  379.         let list_prod_home=list_production_home_cluster[i]
  380.  
  381.         let avg_wood=0,avg_stone=0,avg_iron=0
  382.         let avg_wood_factor=0,avg_stone_factor=0,avg_iron_factor=0
  383.         let total_wood_send=0,total_stone_send=0,total_iron_send=0
  384.         let total_wood_get=0,total_stone_get=0,total_iron_get=0
  385.         let list_res_send=[],list_res_get=[]
  386.         let total_wood_cluster=0,total_stone_cluster=0,total_iron_cluster=0
  387.  
  388.  
  389.         for(let j=0;j<list_prod.length;j++){
  390.  
  391.             avg_wood+=list_prod[j].wood/list_prod.length
  392.             avg_stone+=list_prod[j].stone/list_prod.length
  393.             avg_iron+=list_prod[j].iron/list_prod.length
  394.  
  395.             total_wood_cluster+=list_prod[j].wood
  396.             total_stone_cluster+=list_prod[j].stone
  397.             total_iron_cluster+=list_prod[j].iron
  398.  
  399.         }
  400.  
  401.  
  402.         avg_wood_factor   = avg_wood  * averageFactor//reduce avg with a factor [0-1]
  403.         avg_stone_factor  = avg_stone * averageFactor
  404.         avg_iron_factor   = avg_iron  * averageFactor
  405.  
  406.  
  407.         // console.log("list_prod_home",list_prod_home)
  408.         // console.log("list_prod",list_prod)
  409.  
  410.  
  411.         /////////////////////////////////////calculates resources send and get for each village//////////////////////////////////////////////////
  412.         for(let j=0;j<list_prod.length;j++){
  413.             let coord=list_prod[j].coord
  414.             let name=list_prod[j].name
  415.             let id=list_prod[j].id
  416.             let merchants=list_prod[j].merchants
  417.             merchants-=reserveMerchants
  418.  
  419.             let capacity=list_prod[j].capacity*0.95
  420.             let capacity_travel=merchants*merchantCapacity
  421.  
  422.             let avg_wood_res = avg_wood_factor
  423.             let avg_stone_res = avg_stone_factor
  424.             let avg_iron_res = avg_iron_factor
  425.  
  426.             //here are added resources needed for AM construction
  427.             if(map_resources_get_AM.has(list_prod[j].coord)){
  428.                 let obj_res_AM = map_resources_get_AM.get(list_prod[j].coord)
  429.  
  430.                 avg_wood_res  += obj_res_AM.total_wood
  431.                 avg_stone_res += obj_res_AM.total_stone
  432.                 avg_iron_res  += obj_res_AM.total_iron
  433.                 list_prod[j].time_finished=obj_res_AM.time_finished
  434.             }
  435.             else{
  436.                 list_prod[j].time_finished=0//added later to see for how many hours do j have resources at home
  437.             }
  438.  
  439.             let diff_wood =list_prod[j].wood - Math.round(avg_wood_res)
  440.             let diff_stone =list_prod[j].stone - Math.round(avg_stone_res)
  441.             let diff_iron =list_prod[j].iron - Math.round(avg_iron_res)
  442.  
  443.             // console.log(`aici ba prod:${list_prod[j].iron}, avg: ${Math.round(avg_iron_res)}`)
  444.  
  445.             //in case diff>0 check if there are available res at home
  446.             diff_wood=(diff_wood < 0)?diff_wood:(list_prod_home[j].wood - diff_wood > 0)?diff_wood: (list_prod_home[j].wood)
  447.             diff_stone=(diff_stone < 0)?diff_stone:(list_prod_home[j].stone - diff_stone > 0)?diff_stone: (list_prod_home[j].stone)
  448.             diff_iron=(diff_iron < 0)?diff_iron:(list_prod_home[j].iron - diff_iron > 0)?diff_iron: (list_prod_home[j].iron)
  449.  
  450.             // console.log(`coord ${coord} merch:${merchants} cap:${capacity}, wood:${diff_wood}, stone:${diff_stone}, iron:${diff_iron}`)
  451.  
  452.             let total_res_available=0
  453.             total_res_available=(diff_wood>0)?  total_res_available+diff_wood :  total_res_available
  454.             total_res_available=(diff_stone>0)? total_res_available+diff_stone : total_res_available
  455.             total_res_available=(diff_iron>0)?  total_res_available+diff_iron :  total_res_available
  456.  
  457.             // console.log("total_res_available",total_res_available)
  458.             let norm_factor=(capacity_travel <= total_res_available) ? capacity_travel/total_res_available:1//normalize to the number of merchant available
  459.             let send_wood=0,send_stone=0,send_iron=0
  460.             let get_wood=0,get_stone=0,get_iron=0
  461.             // console.log("norm_factor",norm_factor)
  462.  
  463.             send_wood =(diff_wood>0) ?  parseInt(diff_wood * norm_factor):send_wood
  464.             send_stone=(diff_stone>0) ?  parseInt(diff_stone* norm_factor):send_stone
  465.             send_iron =(diff_iron>0) ?  parseInt(diff_iron * norm_factor):send_iron
  466.             // console.log(`send---->wood:${send_wood}, stone:${send_stone}, iron:${send_iron}`)
  467.            
  468.             //firstly check if needs res(diff_res<0) then check if after balance wh will overflow and if it overflows send only res to fill 95% of wh
  469.             get_wood =(diff_wood>0) ?get_wood :(list_prod[j].wood +Math.abs(diff_wood) < capacity)? Math.abs(diff_wood) : capacity-list_prod[j].wood
  470.             get_stone=(diff_stone>0)?get_stone:(list_prod[j].stone+Math.abs(diff_stone)< capacity)? Math.abs(diff_stone): capacity-list_prod[j].stone
  471.             get_iron =(diff_iron>0) ?get_iron :(list_prod[j].iron +Math.abs(diff_iron) < capacity)? Math.abs(diff_iron) : capacity-list_prod[j].iron
  472.             // console.log(`get---->wood:${get_wood}, stone:${get_stone}, iron:${get_iron}`)
  473.             // console.log("------------------------------------------------------")
  474.            
  475.  
  476.  
  477.  
  478.  
  479.             total_wood_send+=send_wood
  480.             total_stone_send+=send_stone
  481.             total_iron_send+=send_iron
  482.  
  483.             total_wood_get+=get_wood
  484.             total_stone_get+=get_stone
  485.             total_iron_get+=get_iron
  486.  
  487.             let obj_send={
  488.                 coord:coord,
  489.                 id:id,
  490.                 name:name
  491.             }
  492.             let obj_get={
  493.                 coord:coord,
  494.                 id:id,
  495.                 name:name
  496.             }
  497.  
  498.             obj_send.wood =(send_wood  > 0)?send_wood :0
  499.             obj_send.stone=(send_stone > 0)?send_stone:0
  500.             obj_send.iron =(send_iron  > 0)?send_iron :0
  501.             if(obj_send.wood > 0 || obj_send.stone > 0 || obj_send.iron > 0)
  502.                 list_res_send.push(obj_send)
  503.            
  504.             obj_get.wood =(get_wood  > 0)?parseInt(get_wood) :0
  505.             obj_get.stone=(get_stone > 0)?parseInt(get_stone):0
  506.             obj_get.iron =(get_iron  > 0)?parseInt(get_iron) :0
  507.             if(obj_get.wood > 0 || obj_get.stone > 0 || obj_get.iron > 0)
  508.                 list_res_get.push(obj_get)
  509.  
  510.  
  511.  
  512.  
  513.         }
  514.  
  515.         // console.log("end results")
  516.         // console.log("avg wood: " + avg_wood)
  517.         // console.log("avg stone: "+ avg_stone)
  518.         // console.log("avg iron: " + avg_iron)
  519.         // console.log(`send---> wood:${total_wood_send}, stone:${total_stone_send}, iron:${total_iron_send}`)
  520.         // console.log(`get----> wood:${total_wood_get}, stone:${total_stone_get}, iron:${total_iron_get}`)
  521.  
  522.         /////////////////////////////////////////normalization resources,if send resources< get resources =>normalize///////////////////////////
  523.         let norm_wood=(total_wood_get>total_wood_send)?(total_wood_send/total_wood_get):1
  524.         let norm_stone=(total_stone_get>total_stone_send)?(total_stone_send/total_stone_get):1
  525.         let norm_iron=(total_iron_get>total_iron_send)?(total_iron_send/total_iron_get):1
  526.  
  527.         //////////////////////////////////////////normalize each res///////////////////////////////////////////////////////////////////
  528.         for(let j=0;j<list_res_get.length;j++){
  529.             list_res_get[j].wood =parseInt(list_res_get[j].wood *norm_wood)
  530.             list_res_get[j].stone=parseInt(list_res_get[j].stone*norm_stone)
  531.             list_res_get[j].iron =parseInt(list_res_get[j].iron *norm_iron)
  532.         }
  533.  
  534.         // console.log("list_res_send",list_res_send)
  535.         // console.log("list_res_get",list_res_get)
  536.  
  537.  
  538.  
  539.  
  540.         let list_maxDistance=[]
  541.         // ////////////////////////////////////////////////////calculates launches///////////////////////////////////////
  542.         for(let j=0;j<list_res_get.length;j++){
  543.             let coord_destination=list_res_get[j].coord
  544.             let id_destination=list_res_get[j].id
  545.             let name_destination=list_res_get[j].name
  546.            
  547.             //////////////////////////////////////////////////////calculate distance/////////////////////////////////////
  548.             let max_distance=0;
  549.             for(let k=0;k<list_res_send.length;k++){
  550.                 let distance=calcDistance(list_res_get[j].coord,list_res_send[k].coord)
  551.                 list_res_send[k].distance=distance
  552.                 max_distance=(max_distance > distance) ? max_distance :distance
  553.             }
  554.             list_res_send.sort((o1,o2)=>{
  555.                 return (o1.distance>o2.distance)?1:(o1.distance<o2.distance)?-1:0
  556.             })
  557.  
  558.             let obj_launch={
  559.                 wood:0,
  560.                 stone:0,
  561.                 iron:0
  562.             }
  563.  
  564.             for(let k=0;k<list_res_send.length;k++){
  565.                 let coord_origin=list_res_send[k].coord
  566.                 let id_origin=list_res_send[k].id
  567.                 let name_origin=list_res_send[k].name
  568.  
  569.                 // if resources send >0 then return minimum between send and ged othervise return current value
  570.                 let send_wood=(list_res_send[k].wood   > 0) ? Math.min(list_res_get[j].wood  , list_res_send[k].wood)  : 0
  571.                 let send_stone=(list_res_send[k].stone > 0) ? Math.min(list_res_get[j].stone , list_res_send[k].stone)  : 0
  572.                 let send_iron=(list_res_send[k].iron   > 0) ? Math.min(list_res_get[j].iron  , list_res_send[k].iron)  : 0
  573.  
  574.  
  575.  
  576.                 obj_launch.wood +=send_wood
  577.                 obj_launch.stone +=send_stone
  578.                 obj_launch.iron +=send_iron
  579.  
  580.                 list_res_get[j].wood -= send_wood
  581.                 list_res_get[j].stone -= send_stone
  582.                 list_res_get[j].iron -= send_iron
  583.  
  584.                 list_res_send[k].wood -= send_wood
  585.                 list_res_send[k].stone -= send_stone
  586.                 list_res_send[k].iron -= send_iron
  587.  
  588.  
  589.                 let total_send=send_wood+send_stone+send_iron
  590.  
  591.                 //stupid bug, if a resource has xxx699 must get rid of 699
  592.                 let restDivision=total_send%merchantCapacity
  593.                 let minim_resources= (merchantCapacity==1000)?700:1200// special case for PT
  594.                 if(restDivision < minim_resources){
  595.                     if(send_wood>restDivision){
  596.                         send_wood-=restDivision
  597.                         total_send-=restDivision
  598.                     }
  599.                     else if(send_stone>restDivision){
  600.                         send_stone-=restDivision
  601.                         total_send-=restDivision
  602.                     }
  603.                     else if(send_iron>restDivision){
  604.                         send_iron-=restDivision
  605.                         total_send-=restDivision
  606.                     }                  
  607.                 }
  608.  
  609.  
  610.                 list_maxDistance.push(list_res_send[k].distance)
  611.  
  612.                 if(total_send>=minim_resources)
  613.                 list_launches.push({
  614.                     total_send:total_send,
  615.                     wood:send_wood,
  616.                     stone:send_stone,
  617.                     iron:send_iron,
  618.                     coord_origin:coord_origin,
  619.                     name_origin:name_origin,
  620.                     id_destination:id_destination,
  621.                     id_origin:id_origin,
  622.                     coord_destination:coord_destination,
  623.                     name_destination:name_destination,
  624.                     distance:list_res_send[k].distance
  625.                 })
  626.  
  627.                 let total_get=list_res_get[j].wood+list_res_get[j].stone+list_res_get[j].iron
  628.                 if(total_get < minim_resources){
  629.                     // console.log("done sending here")
  630.                     break;
  631.                 }
  632.             }
  633.         }
  634.         total_wood_send_stats +=total_wood_send
  635.         total_stone_send_stats+=total_stone_send
  636.         total_iron_send_stats +=total_iron_send
  637.  
  638.         total_wood_get_stats +=total_wood_get
  639.         total_stone_get_stats+=total_stone_get
  640.         total_iron_get_stats +=total_iron_get
  641.  
  642.  
  643.         //calc distance max
  644.         let max_distance=0
  645.         for(let j=0;j<list_maxDistance.length;j++){
  646.             if(max_distance < list_maxDistance[j])
  647.                 max_distance = list_maxDistance[j]
  648.         }
  649.  
  650.         //add stats for cluster
  651.         list_clusters_stats.push({
  652.             nr_coords:clusters[i].data.length,
  653.             center: parseInt(clusters[i].mean[0])+"|"+parseInt(clusters[i].mean[1]),
  654.             max_distance:max_distance,
  655.  
  656.             avg_wood:Math.round(avg_wood),
  657.             avg_stone:Math.round(avg_stone),
  658.             avg_iron:Math.round(avg_iron),
  659.  
  660.             total_wood_send:total_wood_send,
  661.             total_stone_send:total_stone_send,
  662.             total_iron_send:total_iron_send,
  663.  
  664.             total_wood_get:total_wood_get,
  665.             total_stone_get:total_stone_get,
  666.             total_iron_get:total_iron_get,
  667.  
  668.             total_wood_cluster:total_wood_cluster,
  669.             total_stone_cluster:total_stone_cluster,
  670.             total_iron_cluster:total_iron_cluster
  671.         })
  672.  
  673.     }
  674.  
  675.     console.log("list_clusters_stats",list_clusters_stats)
  676.  
  677.  
  678.     // list_launches.sort((o1,o2)=>{
  679.     //     return (o1.total_send > o2.total_send)?-1:(o1.total_send < o2.total_send)?1:0
  680.     // })
  681.     list_clusters_stats.sort((o1,o2)=>{
  682.         return (o1.max_distance > o2.max_distance)?-1:(o1.max_distance < o2.max_distance)?1:0
  683.     })
  684.  
  685.     // how many merchants are sent on each village
  686.     let map_nr_merchants=new Map()
  687.     for(let i=0;i<list_launches.length;i++){
  688.         let nr_merchants=list_launches[i].wood+list_launches[i].stone+list_launches[i].iron
  689.         nr_merchants=Math.ceil(nr_merchants/merchantCapacity)
  690.  
  691.         if(map_nr_merchants.has(list_launches[i].coord_origin)){
  692.             let nr_update=map_nr_merchants.get(list_launches[i].coord_origin)
  693.             map_nr_merchants.set(list_launches[i].coord_origin,nr_merchants+nr_update)
  694.         }
  695.         else{
  696.             map_nr_merchants.set(list_launches[i].coord_origin,nr_merchants)
  697.  
  698.         }
  699.     }
  700.     console.log("map nr merchants",map_nr_merchants)
  701.     for(let i=0;i<list_production.length;i++){
  702.         let nr_merchants=0
  703.         if(map_nr_merchants.get(list_production[i].coord))
  704.             nr_merchants=map_nr_merchants.get(list_production[i].coord)
  705.  
  706.         // console.log(`coord: ${list_production[i].coord},merchants calculated: ${nr_merchants} vs theory: ${list_production[i].merchants}`)
  707.         list_production[i].merchantAvailable = list_production[i].merchants - nr_merchants
  708.     }
  709.  
  710.  
  711.     /////////////////////////////////////////////////////////////some statistics///////////////////////////////////
  712.     let obj_stats={}
  713.     obj_stats.avg_wood=Math.round(avg_wood_total)
  714.     obj_stats.avg_stone=Math.round(avg_stone_total)
  715.     obj_stats.avg_iron=Math.round(avg_iron_total)
  716.  
  717.     obj_stats.total_wood_send=Math.round(total_wood_send_stats)
  718.     obj_stats.total_stone_send=Math.round(total_stone_send_stats)
  719.     obj_stats.total_iron_send=Math.round(total_iron_send_stats)
  720.  
  721.     obj_stats.total_wood_get=Math.round(total_wood_get_stats)
  722.     obj_stats.total_stone_get=Math.round(total_stone_get_stats)
  723.     obj_stats.total_iron_get=Math.round(total_iron_get_stats)
  724.  
  725.     obj_stats.total_wood_home=Math.round(total_wood_home)
  726.     obj_stats.total_stone_home=Math.round(total_stone_home)
  727.     obj_stats.total_iron_home=Math.round(total_iron_home)
  728.  
  729.     ///////////////////////////////////////////////////////////end result of balancing//////////////////////////////
  730.     for(let i=0;i<list_production.length;i++){
  731.         for(let j=0;j<list_launches.length;j++){
  732.             if(list_production[i].coord == list_launches[j].coord_destination){
  733.                 list_production[i].wood +=list_launches[j].wood
  734.                 list_production[i].stone+=list_launches[j].stone
  735.                 list_production[i].iron +=list_launches[j].iron
  736.             }
  737.             else if(list_production[i].coord == list_launches[j].coord_origin){
  738.                 list_production[i].wood -=list_launches[j].wood
  739.                 list_production[i].stone-=list_launches[j].stone
  740.                 list_production[i].iron -=list_launches[j].iron
  741.             }
  742.             list_production[i].result_wood =list_production[i].wood -Math.round(avg_wood_total)
  743.             list_production[i].result_stone=list_production[i].stone-Math.round(avg_stone_total)
  744.             list_production[i].result_iron =list_production[i].iron -Math.round(avg_iron_total)
  745.             list_production[i].result_total=list_production[i].result_wood+list_production[i].result_stone+list_production[i].result_iron
  746.         }
  747.  
  748.     }
  749.     list_production.sort((o1,o2)=>{
  750.         return (o1.result_total>o2.result_total)?1:(o1.result_total<o2.result_total)?-1:0
  751.     })
  752.  
  753.  
  754.     let map_launches_mass=new Map()
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.     for(let i=0;i<list_launches.length;i++){
  763.         let target_id=list_launches[i].id_destination
  764.         let origin_id=list_launches[i].id_origin
  765.         let woodKey=`resource[${origin_id}][wood]`
  766.         let stoneKey=`resource[${origin_id}][stone]`
  767.         let ironKey=`resource[${origin_id}][iron]`
  768.         let send_resources={}
  769.  
  770.         //create a map with every launch
  771.         if(map_launches_mass.has(target_id)){
  772.             let obj_update=map_launches_mass.get(target_id)
  773.             obj_update.send_resources[woodKey]=list_launches[i].wood
  774.             obj_update.send_resources[stoneKey]=list_launches[i].stone
  775.             obj_update.send_resources[ironKey]=list_launches[i].iron
  776.  
  777.             obj_update.total_send+=list_launches[i].total_send
  778.             obj_update.total_wood+=list_launches[i].wood
  779.             obj_update.total_stone+=list_launches[i].stone
  780.             obj_update.total_iron+=list_launches[i].iron
  781.  
  782.             obj_update.distance=Math.max(obj_update.distance,list_launches[i].distance)
  783.             map_launches_mass.set(target_id,obj_update)
  784.  
  785.         }else{
  786.             send_resources[woodKey]=list_launches[i].wood
  787.             send_resources[stoneKey]=list_launches[i].stone
  788.             send_resources[ironKey]=list_launches[i].iron
  789.  
  790.             map_launches_mass.set(target_id,{
  791.                 target_id:target_id,
  792.                 coord_destination:list_launches[i].coord_destination,
  793.                 name_destination:list_launches[i].name_destination,
  794.                 send_resources:send_resources,
  795.                 total_send:list_launches[i].total_send,
  796.                 total_wood:list_launches[i].wood,
  797.                 total_stone:list_launches[i].stone,
  798.                 total_iron:list_launches[i].iron,
  799.                 distance:list_launches[i].distance
  800.             })
  801.         }
  802.  
  803.  
  804.  
  805.  
  806.         if(map_draw_on_map.has(target_id)){
  807.             let obj_update=map_draw_on_map.get(target_id)
  808.             obj_update.total_resources_get+=list_launches[i].wood+list_launches[i].stone+list_launches[i].iron
  809.             map_draw_on_map.set(target_id,obj_update)
  810.         }
  811.  
  812.         if(map_draw_on_map.has(origin_id)){
  813.             let obj_update=map_draw_on_map.get(origin_id)
  814.             obj_update.total_resources_send+=list_launches[i].wood+list_launches[i].stone+list_launches[i].iron
  815.  
  816.  
  817.             map_draw_on_map.set(origin_id,obj_update)
  818.         }
  819.  
  820.  
  821.  
  822.  
  823.  
  824.     }
  825.  
  826.     let list_launches_mass=Array.from(map_launches_mass.entries()).map(e=>e[1])
  827.     list_launches_mass.sort((o1,o2)=>{
  828.         return (o1.total_send > o2.total_send)?-1:(o1.total_send < o2.total_send)?1:0
  829.     })
  830.  
  831.     console.log("list_production",list_production)
  832.     console.log("list_launches",list_launches)
  833.     console.log("list_launches_mass",list_launches_mass)
  834.     console.log("map_draw_on_map",map_draw_on_map)
  835.  
  836.     let stop= new Date().getTime()
  837.     console.log("time process: "+(stop-start))
  838.    
  839.  
  840.     createMainInterface()
  841.     $("#div_tables").show()
  842.     createTable(list_launches_mass,obj_stats,list_production,list_clusters_stats)
  843.  
  844.     if (typeof (TWMap) != 'undefined') {
  845.         console.log("map page")
  846.         document.getElementById("map_container").remove()
  847.         TWMap.mapHandler.spawnSector=originalSpawnSector
  848.  
  849.         let random_color=[]
  850.         for(let i=0;i<clusters.length;i++){
  851.             let opacity=0.2
  852.             let randomColor=getRandomColor(opacity)
  853.             random_color.push(randomColor)
  854.         }
  855.         console.log(random_color)
  856.  
  857.         addInfoOnMap(map_draw_on_map,random_color)
  858.         TWMap.init();
  859.  
  860.     }
  861.  
  862.  
  863. }
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871. function hitCountApi(){
  872.     $.getJSON(`https://api.countapi.xyz/hit/${countNameSpace}/${countApiKey}`, response=>{
  873.         console.log(`This script has been run ${response.value} times`);
  874.     });
  875. }
  876. // hitCountApi()
  877.  
  878.  
  879. ///////////////////////////////////////////////////////////////////get all resources from page combined production//////////////////////////////////////////////////
  880.  
  881.  
  882. function getDataProduction(){
  883.  
  884.     return new Promise((resolve,reject)=>{
  885.         let link_combined_production=game_data.link_base_pure+"overview_villages&mode=prod"
  886.         document.body.innerHTML+=`<div id='page_info' hidden>${httpGet(link_combined_production)}</div>`
  887.         //get pages for all incoming
  888.         let list_pages=[]
  889.    
  890.         if(document.getElementById("page_info").getElementsByClassName("vis")[1].getElementsByTagName("select").length>0){
  891.             Array.from(document.getElementById("page_info").getElementsByClassName("vis")[1].getElementsByTagName("select")[0]).forEach(function(item){
  892.                 list_pages.push(item.value)
  893.             })
  894.             list_pages.pop();
  895.         }
  896.         else if(document.getElementById("page_info").getElementsByClassName("paged-nav-item").length>0){//all pages from the current folder
  897.             let nr=0;
  898.             Array.from(document.getElementById("page_info").getElementsByClassName("paged-nav-item")).forEach(function(item){
  899.                 let current=item.href;
  900.                 current=current.split("page=")[0]+"page="+nr
  901.                 nr++;
  902.                 list_pages.push(current);
  903.             })
  904.         }
  905.         else{
  906.             list_pages.push(link_combined_production);
  907.         }
  908.         list_pages=list_pages.reverse();
  909.    
  910.    
  911.         // go to every page and get incoming
  912.         let list_production=[]
  913.         let map_farm_usage=new Map()
  914.         function ajaxRequest (urls) {
  915.             let current_url
  916.             if(urls.length>0){
  917.                 current_url=urls.pop()
  918.             }
  919.             else{
  920.                 current_url="stop"
  921.             }
  922.             console.log(current_url)
  923.             let start_ajax=new Date().getTime()
  924.             if (urls.length >= 0 && current_url!="stop") {
  925.                 $.ajax({
  926.                     url: current_url,
  927.                     method: 'get',
  928.                     success: (data) => {
  929.                         // document.body.innerHTML=data
  930.                         document.body.innerHTML+=`<div id="info_html" hidden>${data}</div>`
  931.    
  932.                         let table_production=Array.from($("#info_html").find(".row_a, .row_b"))
  933.    
  934.                         for(let i=0;i<table_production.length;i++){
  935.                             let name=table_production[i].getElementsByClassName("quickedit-vn")[0].innerText
  936.                             let coord=table_production[i].getElementsByClassName("quickedit-vn")[0].innerText.match(/[0-9]{3}\|[0-9]{3}/)[0]
  937.                             let id=table_production[i].getElementsByClassName("quickedit-vn")[0].getAttribute("data-id")
  938.                            
  939.                             let wood=parseInt(table_production[i].getElementsByClassName("wood")[0].innerText.replace(".",""))
  940.                             let stone=parseInt(table_production[i].getElementsByClassName("stone")[0].innerText.replace(".",""))
  941.                             let iron=parseInt(table_production[i].getElementsByClassName("iron")[0].innerText.replace(".",""))
  942.                             let merchants=parseInt(table_production[i].querySelector("a[href*='market']").innerText.split("/")[0])
  943.                             let merchants_total=parseInt(table_production[i].querySelector("a[href*='market']").innerText.split("/")[1])
  944.                             let capacity=parseInt(table_production[i].children[4].innerText)
  945.                             let points=parseInt(table_production[i].children[2].innerText.replace(".",""))
  946.                             let farm_current_pop=parseInt(table_production[i].children[6].innerText.split("/")[0])
  947.                             let farm_total_pop=parseInt(table_production[i].children[6].innerText.split("/")[1])
  948.                             let farm_usage=farm_current_pop/farm_total_pop
  949.                            
  950.                             let obj={
  951.                                 coord:coord,
  952.                                 id:id,
  953.                                 wood:wood,
  954.                                 stone:stone,
  955.                                 iron:iron,
  956.                                 name:name,
  957.                                 merchants:merchants,
  958.                                 merchants_total:merchants_total,
  959.                                 capacity:capacity,
  960.                                 points:points,
  961.  
  962.                             }
  963.                             list_production.push(obj)
  964.  
  965.                             map_farm_usage.set(coord,farm_usage)
  966.                         }
  967.                         document.getElementById("info_html").remove()
  968.                         let stop_ajax=new Date().getTime();
  969.                         let diff=stop_ajax-start_ajax
  970.                         console.log("wait: "+diff)
  971.                         window.setTimeout(function(){
  972.                             ajaxRequest (list_pages)
  973.                             UI.SuccessMessage("get production page: "+urls.length)
  974.                         },200-diff)
  975.                     },
  976.                     error: (err)=>{
  977.                         reject(err)
  978.                     }
  979.                 })
  980.                
  981.             }
  982.             else
  983.             {
  984.                 document.getElementById("page_info").remove()
  985.                 UI.SuccessMessage("done")
  986.                 resolve({
  987.                     list_production:list_production,
  988.                     map_farm_usage:map_farm_usage
  989.                 })
  990.                 // console.log(list_production)
  991.    
  992.                
  993.             }
  994.         }
  995.         ajaxRequest(list_pages);
  996.    
  997.     })
  998. }
  999.  
  1000. ///////////////////////////////////////////////////////////////////get all resources from page incoming transport//////////////////////////////////////////////////
  1001.  
  1002. function getDataIncoming(){
  1003.     return new Promise((resolve,reject)=>{
  1004.         let link_combined_production=game_data.link_base_pure+"overview_villages&mode=trader&type=inc"
  1005.         document.body.innerHTML+=`<div id='page_info' hidden>${httpGet(link_combined_production)}</div>`
  1006.         //get pages for all incoming
  1007.         let list_pages=[]
  1008.  
  1009.         if(document.getElementById("page_info").getElementsByClassName("vis")[1].getElementsByTagName("select").length>0){
  1010.             Array.from(document.getElementById("page_info").getElementsByClassName("vis")[1].getElementsByTagName("select")[0]).forEach(function(item){
  1011.                 list_pages.push(item.value)
  1012.             })
  1013.             list_pages.pop();
  1014.         }
  1015.         else if(document.getElementById("page_info").getElementsByClassName("paged-nav-item").length>0){//all pages from the current folder
  1016.             let nr=0;
  1017.             Array.from(document.getElementById("page_info").getElementsByClassName("paged-nav-item")).forEach(function(item){
  1018.                 let current=item.href;
  1019.                 current=current.split("page=")[0]+"page="+nr
  1020.                 nr++;
  1021.                 list_pages.push(current);
  1022.             })
  1023.         }
  1024.         else{
  1025.             list_pages.push(link_combined_production);
  1026.         }
  1027.         list_pages=list_pages.reverse();
  1028.  
  1029.  
  1030.         // go to every page and get incoming
  1031.         let  map_incoming=new Map()
  1032.         function ajaxRequest (urls) {
  1033.             let current_url
  1034.             if(urls.length>0){
  1035.                 current_url=urls.pop()
  1036.             }
  1037.             else{
  1038.                 current_url="stop"
  1039.             }
  1040.             console.log(current_url)
  1041.             let start_ajax=new Date().getTime()
  1042.             if (urls.length >= 0 && current_url!="stop") {
  1043.                 $.ajax({
  1044.                     url: current_url,
  1045.                     method: 'get',
  1046.                     success: (data) => {
  1047.                         // document.body.innerHTML=data
  1048.                         document.body.innerHTML+=`<div id="info_html" hidden>${data}</div>`
  1049.  
  1050.                         let table_incoming=Array.from($("#info_html").find(".row_a, .row_b"))
  1051.  
  1052.                         for(let i=0;i<table_incoming.length;i++){
  1053.                             let coord=table_incoming[i].children[4].innerText.match(/[0-9]{3}\|[0-9]{3}/)[0]
  1054.  
  1055.                             let wood=parseInt($(table_incoming[i]).find(".wood").parent().text().replace(".",""))
  1056.                             let stone=parseInt($(table_incoming[i]).find(".stone").parent().text().replace(".",""))
  1057.                             let iron=parseInt($(table_incoming[i]).find(".iron").parent().text().replace(".",""))
  1058.                             wood=(Number.isNaN(wood) ==true)?0:wood
  1059.                             stone=(Number.isNaN(stone) ==true)?0:stone
  1060.                             iron=(Number.isNaN(iron) ==true)?0:iron
  1061.  
  1062.  
  1063.                             let obj={
  1064.                                 wood:wood,
  1065.                                 stone:stone,
  1066.                                 iron:iron,
  1067.                             }
  1068.                             if(map_incoming.has(coord)){
  1069.                                 let obj_update=map_incoming.get(coord)
  1070.                                 obj_update.wood+=wood
  1071.                                 obj_update.stone+=stone
  1072.                                 obj_update.iron+=iron
  1073.                                 map_incoming.set(coord,obj_update)
  1074.                             }
  1075.                             else{
  1076.                                 map_incoming.set(coord,obj)
  1077.                             }
  1078.                         }
  1079.                         document.getElementById("info_html").remove()
  1080.                         let stop_ajax=new Date().getTime();
  1081.                         let diff=stop_ajax-start_ajax
  1082.                         console.log("wait: "+diff)
  1083.                         window.setTimeout(function(){
  1084.                             ajaxRequest (list_pages)
  1085.                             UI.SuccessMessage("get incoming page: "+urls.length)
  1086.                         },200-diff)
  1087.                     },
  1088.                     error:(err)=>{
  1089.                         reject(err)
  1090.                     }
  1091.                 })
  1092.            
  1093.             }
  1094.             else
  1095.             {
  1096.                 document.getElementById("page_info").remove()
  1097.                 UI.SuccessMessage("done")
  1098.                 resolve(map_incoming)
  1099.                 // console.log(map_incoming)
  1100.  
  1101.                
  1102.             }
  1103.         }
  1104.         ajaxRequest(list_pages);
  1105.     })
  1106.  
  1107. }
  1108.  
  1109.  
  1110.  
  1111. function httpGet(theUrl){
  1112.     var xmlHttp = new XMLHttpRequest();
  1113.     xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
  1114.     xmlHttp.send( null );
  1115.     return xmlHttp.responseText;
  1116. }
  1117.  
  1118.  
  1119.  function calcDistance(coord1,coord2)
  1120.         {
  1121.             let x1=parseInt(coord1.split("|")[0])
  1122.             let y1=parseInt(coord1.split("|")[1])
  1123.             let x2=parseInt(coord2.split("|")[0])
  1124.             let y2=parseInt(coord2.split("|")[1])
  1125.    
  1126.             return Math.sqrt( (x1-x2)*(x1-x2) +  (y1-y2)*(y1-y2) );
  1127. }
  1128.  
  1129. ///////////////////////////////////////////////////////////////////create interface +tables//////////////////////////////////////////////////
  1130.  
  1131. async function createTable(list_launches,obj_stats,list_production,list_clusters_stats){
  1132.  
  1133.  
  1134.  
  1135.  
  1136.    
  1137.     ////////////////////////////////////////////////////////////////////table send resources/////////////////////////////////////////////////////////////////////
  1138.     let html_prod_table=`
  1139.         <table  class="" border="1" style="width: 100%;background-color:${backgroundColor};border-color:${borderColor}">
  1140.         <thead>
  1141.         <tr>
  1142.             <td style="text-align:center; width:auto; background-color:${headerColor}" >
  1143.                 <center style="margin:5px"><font color="${titleColor}">nr</font></center>
  1144.             </td>
  1145.             <td style="text-align:center; width:auto; background-color:${headerColor}" >
  1146.                 <center style="margin:5px"><font color="${titleColor}">target</font></center>
  1147.             </td>
  1148.             <td style="text-align:center; width:auto; background-color:${headerColor}">
  1149.                 <center style="margin:5px"><a href="#" id="sort_distance"><font color="${titleColor}" >max distance</font></a></center>
  1150.             </td>
  1151.             <td style="text-align:center; width:auto; background-color:${headerColor}">
  1152.                 <center style="margin:5px"><a href="#" id="sort_total"><font color="${titleColor}">total send</font></a></center>
  1153.             </td>
  1154.             <td style="text-align:center; width:auto; background-color:${headerColor}">
  1155.                 <center style="margin:5px"><a href="#" id="sort_wood"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/wood.png"/></a></center>
  1156.             </td>
  1157.             <td style="text-align:center; width:auto; background-color:${headerColor}">
  1158.                 <center style="margin:5px"><a href="#" id="sort_stone"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/stone.png"/></a></center>
  1159.             </td>
  1160.             <td style="text-align:center; width:auto; background-color:${headerColor}">
  1161.                 <center style="margin:5px"><a href="#" id="sort_iron"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/iron.png"/></a></center>
  1162.             </td>
  1163.             <td style="text-align:center; width:auto; background-color:${headerColor}">
  1164.                 <center style="margin:5px"><font color="${titleColor}">send</font></center>
  1165.             </td>                    
  1166.         </tr>
  1167.         </thead>
  1168.         <tbody>`
  1169.  
  1170.     for(let i=0;i<list_launches.length;i++){
  1171.         let target_id = list_launches[i].target_id
  1172.         let wood = list_launches[i].total_wood
  1173.         let stone = list_launches[i].total_stone
  1174.         let iron = list_launches[i].total_iron
  1175.         let origin_id=list_launches[i].id_origin
  1176.         let data=JSON.stringify(list_launches[i].send_resources)
  1177.  
  1178.  
  1179.         let header=(i%2==0)?headerColor:headerColorEven
  1180.        
  1181.         html_prod_table+=`
  1182.             <tr id="delete_row" >
  1183.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1184.                     <center style="margin:5px"><font color="${titleColor}">${i+1}</font></center>
  1185.                 </td>            
  1186.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1187.                     <a href="${game_data.link_base_pure}info_village&id=${list_launches[i].target_id}"><center><font color="${titleColor}">${list_launches[i].name_destination}</font></center></a>
  1188.                 </td>
  1189.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1190.                     <center style="margin:5px"><font color="${titleColor}">${list_launches[i].distance.toFixed(1)}</font></center>
  1191.                 </td>
  1192.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1193.                     <center style="margin:5px"><b><font color="${titleColor}">${formatNumber(list_launches[i].total_send)}</font></b></center>
  1194.                 </td>
  1195.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1196.                     <center style="margin:5px"><font color="${titleColor}">${formatNumber(wood)}</font></center>
  1197.                 </td>
  1198.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1199.                     <center style="margin:5px"><font color="${titleColor}">${formatNumber(stone)}</font></center>
  1200.                 </td>
  1201.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1202.                     <center style="margin:5px"><font color="${titleColor}">${formatNumber(iron)}</font></center>
  1203.                 </td>
  1204.                 <td style="text-align:center; width:auto; background-color:${header}" >
  1205.                     <center style="margin:5px"><input class="btn btn_send" target_id="${target_id}" data='${data}'  type="button" value="send"></center>
  1206.                 </td>
  1207.             </tr>`
  1208.     }
  1209.  
  1210.     html_prod_table+=`
  1211.             </tbody>
  1212.         </table>`
  1213.  
  1214.     document.getElementById("table_view").innerHTML=html_prod_table
  1215.  
  1216.  
  1217.     ///////////////////////////////////////////////////////////////////add event for each button send//////////////////////////////////////////////
  1218.     $(".btn_send").on("click",async(event)=>{
  1219.  
  1220.         if($(event.target).is(":disabled")==false){
  1221.             let target_id=$(event.target).attr("target_id")
  1222.             let data=JSON.parse($(event.target).attr("data"))
  1223.             console.log(target_id,data)
  1224.            
  1225.    
  1226.             $(".btn_send").attr("disabled", true)
  1227.    
  1228.             let start=new Date().getTime()
  1229.             sendResources(target_id,data)
  1230.             let stop=new Date().getTime()
  1231.             let diff_time=stop-start
  1232.             // console.log("ajax time: "+(diff_time))
  1233.    
  1234.             window.setTimeout(()=>{
  1235.                 $(event.target).closest("#delete_row").remove()
  1236.                 $(".btn_send").attr("disabled", false)
  1237.             },200-diff_time)
  1238.  
  1239.         }
  1240.  
  1241.     })
  1242.  
  1243.    
  1244.     ////////////////////////////////////////////////////////////////////table statistics/////////////////////////////////////////////////////////////////////
  1245.  
  1246.     let html_stats_table=`
  1247.         <table id="table_stats"  border="1" style="width: 100%;background-color:${backgroundColor};border-color:${borderColor}">
  1248.         <tr>
  1249.             <td style="text-align:left; width:200px; background-color:${headerColor}" >
  1250.        
  1251.             <div  style="display:flex;margin-left:25px">
  1252.                 <div><center style="margin:5px"><input class="btn evt-confirm-btn btn-confirm-yes" id="btn_result" type="button" value="results"></center></div>
  1253.                 <div><center style="margin:5px"><input class="btn evt-confirm-btn btn-confirm-yes" id="btn_cluster" type="button" value="clusters"></center></div>
  1254.             </div>
  1255.          
  1256.             </td>
  1257.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1258.                 <center style="margin:5px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/wood.png"/></center>
  1259.             </td>
  1260.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1261.                 <center style="margin:5px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/stone.png"/></center>
  1262.             </td>
  1263.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1264.                 <center style="margin:5px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/iron.png"/></center>
  1265.             </td>
  1266.         </tr>
  1267.         <tr>
  1268.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1269.                 <center style="margin:5px"><font  color="${titleColor}">total </font></center>
  1270.             </td>
  1271.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1272.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_wood_home)} </font></center>
  1273.             </td>
  1274.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1275.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_stone_home)} </font></center>
  1276.             </td>
  1277.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1278.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_iron_home)} </font></center>
  1279.             </td>
  1280.         </tr>
  1281.         <tr>
  1282.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1283.                 <center style="margin:5px"><font  color="${titleColor}">average </font></center>
  1284.             </td>
  1285.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1286.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.avg_wood)} </font></center>
  1287.             </td>
  1288.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1289.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.avg_stone)} </font></center>
  1290.             </td>
  1291.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1292.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.avg_iron)} </font></center>
  1293.             </td>
  1294.         </tr>
  1295.         <tr>
  1296.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1297.                 <center style="margin:5px"><font  color="${titleColor}">surplus </font></center>
  1298.             </td>
  1299.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1300.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_wood_send)} </font></center>
  1301.             </td>
  1302.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1303.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_stone_send)} </font></center>
  1304.             </td>
  1305.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1306.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_iron_send)} </font></center>
  1307.             </td>
  1308.         </tr>
  1309.         <tr>
  1310.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1311.                 <center style="margin:5px"><font  color="${titleColor}">deficit </font></center>
  1312.             </td>
  1313.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1314.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_wood_get)} </font></center>
  1315.             </td>
  1316.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1317.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_stone_get)} </font></center>
  1318.             </td>
  1319.             <td style="text-align:left; width:auto; background-color:${headerColor}" >
  1320.                 <center style="margin:5px"><font  color="${titleColor}">${formatNumber(obj_stats.total_iron_get)} </font></center>
  1321.             </td>
  1322.         </tr>
  1323.  
  1324.     </table>
  1325.     `
  1326.     document.getElementById("table_stats").innerHTML=html_stats_table
  1327.  
  1328.  
  1329.     //////////////////////////////////////////////add event for results button +create table for end of balancing//////////////////////////////////////////////
  1330.     $("#btn_result").on("click",()=>{
  1331.         createTableResults(list_production)
  1332.     })
  1333.     $("#btn_cluster").on("click",()=>{
  1334.         createTableClusters(list_clusters_stats)
  1335.     })
  1336.    
  1337.    
  1338.  
  1339.  
  1340.  
  1341.     ///////////////////////////////////////////////////////////add event for sorting/////////////////////////////////////////////////
  1342.     document.getElementById("sort_distance").addEventListener("click",()=>{
  1343.         list_launches.sort((o1,o2)=>{
  1344.             return (parseFloat(o1.distance) > parseFloat(o2.distance))?1:(parseFloat(o1.distance) < parseFloat(o2.distance))?-1:0
  1345.         })
  1346.         document.getElementById("table_stats").innerHTML=""
  1347.         createTable(list_launches,obj_stats,list_production,list_clusters_stats)
  1348.  
  1349.     })
  1350.     document.getElementById("sort_total").addEventListener("click",()=>{
  1351.         list_launches.sort((o1,o2)=>{
  1352.             return (o1.total_send > o2.total_send)?-1:(o1.total_send < o2.total_send)?1:0
  1353.         })
  1354.         document.getElementById("table_view").innerHTML=""
  1355.         createTable(list_launches,obj_stats,list_production,list_clusters_stats)
  1356.  
  1357.     })
  1358.     document.getElementById("sort_wood").addEventListener("click",()=>{
  1359.         list_launches.sort((o1,o2)=>{
  1360.             return (o1.total_wood > o2.total_wood)?-1:(o1.total_wood < o2.total_wood)?1:0
  1361.         })
  1362.         document.getElementById("table_view").innerHTML=""
  1363.         createTable(list_launches,obj_stats,list_production,list_clusters_stats)
  1364.  
  1365.     })
  1366.     document.getElementById("sort_stone").addEventListener("click",()=>{
  1367.         list_launches.sort((o1,o2)=>{
  1368.             return (o1.total_stone > o2.total_stone)?-1:(o1.total_stone < o2.total_stone)?1:0
  1369.         })
  1370.         document.getElementById("table_view").innerHTML=""
  1371.         createTable(list_launches,obj_stats,list_production,list_clusters_stats)
  1372.  
  1373.     })
  1374.     document.getElementById("sort_iron").addEventListener("click",()=>{
  1375.         list_launches.sort((o1,o2)=>{
  1376.             return (o1.total_iron > o2.total_iron)?-1:(o1.total_iron < o2.total_iron)?1:0
  1377.         })
  1378.         document.getElementById("table_view").innerHTML=""
  1379.         createTable(list_launches,obj_stats,list_production,list_clusters_stats)
  1380.  
  1381.     })
  1382.  
  1383.  
  1384.  
  1385.  
  1386.     //////////////////////////////////////////////add event for key enter//////////////////////////////////////////////////
  1387.     if(document.getElementsByClassName("btn_send").length>0){
  1388.         document.getElementsByClassName("btn_send")[0].focus()
  1389.     }
  1390.  
  1391.     window.onkeydown = function(e) {
  1392.         // console.log(e.which)
  1393.         if(e.which == 13 ){
  1394.  
  1395.             if(document.getElementsByClassName("btn_send").length>0){
  1396.                 document.getElementsByClassName("btn_send")[0].click()
  1397.             }
  1398.         }
  1399.         // e.preventDefault()
  1400.     }
  1401.  
  1402.  
  1403. }
  1404.  
  1405. function formatNumber(number){
  1406.     return new Intl.NumberFormat().format(number)
  1407. }
  1408.  
  1409.  
  1410.  
  1411. ///////////////////////////////////////////////////////////////////create table for results////////////////////////////
  1412.  
  1413. function createTableResults(list_production){
  1414.     let html_end_result=`
  1415.     <center><div id="table_results" style="height:800px;width:800px;overflow:auto">
  1416.     <table id="table_stats"  border="1" style="width: 100%;background-color:${backgroundColor};border-color:${borderColor};border-collapse: collapse;">
  1417.     <tr>
  1418.         <th style="text-align:left; width:auto; background-color:${headerColor};position: sticky;top:0" >
  1419.             <center style="margin:10px"><font  color="${titleColor}">coord </font></center>
  1420.         </th>
  1421.         <th style="text-align:left; width:20px; background-color:${headerColor};position: sticky;top:0" >
  1422.             <a href="#" id="order_points"><center style="margin:10px"><font  color="${titleColor}">points</font></center></a>
  1423.         </th>
  1424.         <th style="text-align:left; width:20px; background-color:${headerColor};position: sticky;top:0" >
  1425.             <a href="#" id="order_merchants"><center style="margin:10px"><font  color="${titleColor}">merchants</font></center></a>
  1426.         </th>
  1427.         <th style="text-align:left; width:20px; background-color:${headerColor};position: sticky;top:0">
  1428.             <center style="margin:5px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/main.png"/>
  1429.                 <a href="#" id="order_hours"><font  color="${titleColor}">[hours] </font> </a>
  1430.             </center>
  1431.         </th>
  1432.         <th style="text-align:left; width:auto; background-color:${headerColor};position: sticky;top:0" colspan="2" >
  1433.             <a href="#" class="order_deficit">
  1434.                 <center style="margin:10px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/wood.png"/></center>
  1435.             </a>
  1436.             </th>
  1437.         <th style="text-align:left; width:auto; background-color:${headerColor};position: sticky;top:0" colspan="2">
  1438.             <a href="#" class="order_deficit">
  1439.                 <center style="margin:10px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/stone.png"/></center>
  1440.             </a>
  1441.         </th>
  1442.         <th style="text-align:left; width:auto; background-color:${headerColor};position: sticky;top:0" colspan="2">
  1443.             <a href="#" class="order_deficit">
  1444.                 <center style="margin:10px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/iron.png"/></center>
  1445.             </a>
  1446.         </th>
  1447.         <th style="text-align:left; width:auto; background-color:${headerColor};position: sticky;top:0" >
  1448.             <a href="#" id="order_wh">
  1449.                 <center style="margin:10px"><img src="https://dsen.innogamescdn.com/asset/04d88c84/graphic/buildings/storage.png"/></center>
  1450.             </a>
  1451.         </th>
  1452.     </tr>`
  1453.  
  1454.  
  1455.    
  1456.     for(let i=0;i<list_production.length;i++){
  1457.  
  1458.         let header_wood =(i%2==0)?headerWood :headerWoodEven
  1459.         let header_stone=(i%2==0)?headerStone:headerStoneEven
  1460.         let header_iron =(i%2==0)?headerIron :headerIronEven
  1461.  
  1462.         let greenColor="#013e27",greenColorEven="#026440"//green
  1463.         let redColor="#5f0000",redColorEven="#9a0000"//red
  1464.         let gray="#202825",grayEven="#313e39"
  1465.  
  1466.         let header_status_wood,header_status_stone,header_status_iron,header_status_wh
  1467.         if(i%2==0){
  1468.             header_status_wood =(parseInt(list_production[i].result_wood) >=0)?greenColor:redColor
  1469.             header_status_stone=(parseInt(list_production[i].result_stone)>=0)?greenColor:redColor
  1470.             header_status_iron =(parseInt(list_production[i].result_iron) >=0)?greenColor:redColor
  1471.             header_status_wh=gray
  1472.         }
  1473.         else{
  1474.             header_status_wood =(parseInt(list_production[i].result_wood) >=0)?greenColorEven:redColorEven
  1475.             header_status_stone=(parseInt(list_production[i].result_stone)>=0)?greenColorEven:redColorEven
  1476.             header_status_iron =(parseInt(list_production[i].result_iron) >=0)?greenColorEven:redColorEven
  1477.             header_status_wh=grayEven
  1478.         }
  1479.  
  1480.         html_end_result+=`
  1481.         <tr >
  1482.             <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1483.                 <a href="${game_data.link_base_pure}info_village&id=${list_production[i].id}"><center><font color="${titleColor}">${list_production[i].coord}</font></center></a>
  1484.             </td>
  1485.             <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1486.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].points)} </font></center>
  1487.             </td>
  1488.             <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1489.                 <center style="margin:0px"><font  color="${titleColor}"><b>${list_production[i].merchantAvailable}</b> / ${list_production[i].merchants_total} </font></center>
  1490.             </td>
  1491.             <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1492.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].time_finished)} </font></center>
  1493.             </td>
  1494.             <td style="text-align:left; width:auto; background-color:${header_wood}" >
  1495.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].wood)} </font></center>
  1496.             </td>
  1497.             <td style="text-align:left; width:auto; background-color:${header_status_wood}" >
  1498.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].result_wood)} </font></center>
  1499.             </td>
  1500.  
  1501.             <td style="text-align:left; width:auto; background-color:${header_stone}" >
  1502.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].stone)} </font></center>
  1503.             </td>
  1504.             <td style="text-align:left; width:auto; background-color:${header_status_stone}" >
  1505.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].result_stone)} </font></center>
  1506.             </td>
  1507.  
  1508.             <td style="text-align:left; width:auto; background-color:${header_iron}" >
  1509.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].iron)} </font></center>
  1510.             </td>
  1511.             <td style="text-align:left; width:auto; background-color:${header_status_iron}" >
  1512.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].result_iron)} </font></center>
  1513.             </td>
  1514.  
  1515.             <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1516.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_production[i].capacity)} </font></center>
  1517.             </td>
  1518.         </tr>
  1519.         `
  1520.     }
  1521.        
  1522.  
  1523.     html_end_result+=`
  1524.     </table>
  1525.     </div></center>
  1526.     `
  1527.     Dialog.show("content",html_end_result)
  1528.     $("#order_points").on("click",()=>{
  1529.         list_production.sort((o1,o2)=>{
  1530.             return (o1.points>o2.points)?1:(o1.points<o2.points)?-1:0
  1531.         })
  1532.         console.log("order by points")
  1533.         $(".popup_box_close").click()
  1534.         createTableResults(list_production)
  1535.  
  1536.     })
  1537.     $("#order_merchants").on("click",()=>{
  1538.         list_production.sort((o1,o2)=>{
  1539.             return (o1.merchantAvailable>o2.merchantAvailable)?1:(o1.merchantAvailable<o2.merchantAvailable)?-1:0
  1540.         })
  1541.         console.log("order by merchants")
  1542.         $(".popup_box_close").click()
  1543.         createTableResults(list_production)
  1544.  
  1545.     })
  1546.     $("#order_hours").on("click",()=>{
  1547.         list_production.sort((o1,o2)=>{
  1548.             return (o1.time_finished>o2.time_finished)?-1:(o1.time_finished<o2.time_finished)?1:0
  1549.         })
  1550.         console.log("order by construction time")
  1551.         console.log(list_production)
  1552.         $(".popup_box_close").click()
  1553.         createTableResults(list_production)
  1554.  
  1555.     })
  1556.     $(".order_deficit").on("click",()=>{
  1557.         list_production.sort((o1,o2)=>{
  1558.             return (o1.result_total>o2.result_total)?1:(o1.result_total<o2.result_total)?-1:0
  1559.  
  1560.         })
  1561.         console.log("order by deficit/surplus")
  1562.         $(".popup_box_close").click()
  1563.         createTableResults(list_production)
  1564.  
  1565.     })
  1566.     $("#order_wh").on("click",()=>{
  1567.         list_production.sort((o1,o2)=>{
  1568.             return (o1.capacity>o2.capacity)?1:(o1.capacity<o2.capacity)?-1:0
  1569.  
  1570.         })
  1571.         console.log("order by warehouse capacity")
  1572.         $(".popup_box_close").click()
  1573.         createTableResults(list_production)
  1574.  
  1575.     })
  1576.  
  1577.  
  1578. }
  1579.  
  1580. ///////////////////////////////////////////////////////////////////create table for clusters////////////////////////////
  1581.  
  1582. function createTableClusters(list_clusters_stats){
  1583.     let html_end_result=`
  1584.     <center><div id="table_results" style="height:800px;width:700px;overflow:auto">
  1585.     <table id="table_stats"  border="1" style="width: 20%;background-color:${backgroundColor};border-color:${borderColor};border-collapse: collapse;">
  1586.     <tr>
  1587.         <th style="text-align:left; width:100%; background-color:${headerColor};position: sticky;top:0" >
  1588.             <center style="margin:10px"><font  color="${titleColor}">nr </font></center>
  1589.         </th>
  1590.         <th style="text-align:left; width:100%; background-color:${headerColor};position: sticky;top:0" >
  1591.             <center style="margin:10px"><font  color="${titleColor}">coords/cluster</font></center>
  1592.         </th>
  1593.         <th style="text-align:left; width:20px; background-color:${headerColor};position: sticky;top:0" >
  1594.             <center style="margin:10px"><font  color="${titleColor}">center of cluster</font></center>
  1595.         </th>
  1596.         <th style="text-align:left; width:100%; background-color:${headerColor};position: sticky;top:0" >
  1597.             <center style="margin:10px"><font  color="${titleColor}">resources</font></center>
  1598.         </th>
  1599.         <th style="text-align:left; width:100%; background-color:${headerColor};position: sticky;top:0" >
  1600.             <center style="margin:10px"><font  color="${titleColor}">max distance</font></center>
  1601.         </th>
  1602.  
  1603.    
  1604.     </tr>`
  1605.  
  1606.  
  1607.    
  1608.     for(let i=0;i<list_clusters_stats.length;i++){
  1609.  
  1610.         let gray="#202825",grayEven="#313e39"
  1611.         let header_status_wh = (i%2==0)?gray:grayEven
  1612.  
  1613.  
  1614.  
  1615.         html_end_result+=`
  1616.         <tr >
  1617.             <td style="text-align:left; width:100%; background-color:${header_status_wh}" >
  1618.                 <center style="margin:0px"><font  color="${titleColor}">${i+1} </font></center>
  1619.             </td>
  1620.             <td style="text-align:left; width:100%; background-color:${header_status_wh}" >
  1621.                 <center style="margin:0px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].nr_coords)} </font></center>
  1622.             </td>
  1623.             <td style="text-align:left; width:100%; background-color:${header_status_wh}" >
  1624.                 <center style="margin:0px"><font  color="${titleColor}">${list_clusters_stats[i].center} </font></center>
  1625.             </td>
  1626.             <td style="text-align:left; width:100%; background-color:${header_status_wh}" >
  1627.                 <center>
  1628.                 <table id="table_stats"  border="1" style="width: auto;background-color:${backgroundColor};border-color:${borderColor};margin:10px">
  1629.                     <tr>
  1630.                         <td style="text-align:left; width:auto; background-color:${headerColorEven}" >
  1631.                             <center style="margin:0px"><font  color="${titleColor}">type</font></center>
  1632.                         </td>
  1633.                         <td style="text-align:left; width:auto; background-color:${headerColorEven}" >
  1634.                             <center style="margin:5px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/wood.png"/></center>
  1635.                         </td>
  1636.                         <td style="text-align:left; width:auto; background-color:${headerColorEven}" >
  1637.                             <center style="margin:5px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/stone.png"/></center>
  1638.                         </td>
  1639.                         <td style="text-align:left; width:auto; background-color:${headerColorEven}" >
  1640.                             <center style="margin:5px"><img src="https://dsen.innogamescdn.com/asset/c2e59f13/graphic/buildings/iron.png"/></center>
  1641.                         </td>
  1642.                     </tr>
  1643.                     <tr>
  1644.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1645.                             <center style="margin:5px"><font  color="${titleColor}">total </font></center>
  1646.                         </td>
  1647.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1648.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_wood_cluster)} </font></center>
  1649.                         </td>
  1650.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1651.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_stone_cluster)} </font></center>
  1652.                         </td>
  1653.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1654.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_iron_cluster)} </font></center>
  1655.                         </td>
  1656.                     </tr>
  1657.                     <tr>
  1658.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1659.                             <center style="margin:5px"><font  color="${titleColor}">average </font></center>
  1660.                         </td>
  1661.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1662.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].avg_wood)} </font></center>
  1663.                         </td>
  1664.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1665.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].avg_stone)} </font></center>
  1666.                         </td>
  1667.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1668.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].avg_iron)} </font></center>
  1669.                         </td>
  1670.                     </tr>
  1671.                     <tr>
  1672.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1673.                             <center style="margin:5px"><font  color="${titleColor}">surplus </font></center>
  1674.                         </td>
  1675.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1676.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_wood_send)} </font></center>
  1677.                         </td>
  1678.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1679.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_stone_send)} </font></center>
  1680.                         </td>
  1681.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1682.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_iron_send)} </font></center>
  1683.                         </td>
  1684.                     </tr>
  1685.                     <tr>
  1686.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1687.                             <center style="margin:5px"><font  color="${titleColor}">deficit </font></center>
  1688.                         </td>
  1689.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1690.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_wood_get)} </font></center>
  1691.                         </td>
  1692.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1693.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_stone_get)} </font></center>
  1694.                         </td>
  1695.                         <td style="text-align:left; width:auto; background-color:${header_status_wh}" >
  1696.                             <center style="margin:5px"><font  color="${titleColor}">${formatNumber(list_clusters_stats[i].total_iron_get)} </font></center>
  1697.                         </td>
  1698.                     </tr>
  1699.                 </table>
  1700.                 </center>
  1701.             </td>
  1702.  
  1703.             <td style="text-align:left; width:100%; background-color:${header_status_wh}" >
  1704.                 <center style="margin:0px"><font  color="${titleColor}">${list_clusters_stats[i].max_distance.toFixed(1)} </font></center>
  1705.             </td>
  1706.         </tr>
  1707.         `
  1708.     }
  1709.        
  1710.  
  1711.     html_end_result+=`
  1712.     </table>
  1713.     </div></center>
  1714.     `
  1715.     Dialog.show("content",html_end_result)
  1716. }
  1717.  
  1718.  
  1719.  
  1720.  
  1721. /////////////////////////////////////////////////////////////////function for sending resources//////////////////////////////////////////////////
  1722.  
  1723.  
  1724.  
  1725. function sendResources (target_id,data) {
  1726.     let options={
  1727.         "village":target_id,
  1728.         "ajaxaction" : "call",
  1729.         "h" : window.csrf_token,    
  1730.     }
  1731.  
  1732.     TribalWars.post("market",options, data, function(response) {
  1733.         console.log(response)
  1734.         UI.SuccessMessage(response.success,1000)
  1735.     }, function(error){
  1736.         console.log(error)
  1737.     });
  1738. }
  1739.  
  1740.  
  1741. /////////////////////////////////////////////////////////////////function for getting resources for AM buildings//////////////////////////////////////////////////
  1742.  
  1743.  
  1744. async function getResourcesForAM(time_construction_total,map_farm_usage){
  1745.     let {map_construction_templates, map_coord_templates} = await getTemplates().catch(e=>alert(e))
  1746.     let map_buildings = await getDataBuildings().catch(e=>alert(e))
  1747.     let map_constants_buildings = getConstantsTwBuildings()
  1748.     console.log("map_construction_templates",map_construction_templates)
  1749.     console.log("map_coord_templates",map_coord_templates)
  1750.     console.log("map_buildings",map_buildings)
  1751.  
  1752.     console.log("map_constants_buildings",map_constants_buildings)
  1753.  
  1754.     return new Promise((resolve,reject)=>{
  1755.    
  1756.         if(time_construction_total==0)
  1757.             resolve(new Map())
  1758.  
  1759.        
  1760.         let map_resources_get_AM=new Map()
  1761.    
  1762.         //add construction time for each building
  1763.         Array.from(map_buildings.keys()).forEach(key=>{
  1764.             if(key.includes("_time_queued")){
  1765.                 map_resources_get_AM.set(key.replace("_time_queued",""),{
  1766.                     total_wood:0,
  1767.                     total_stone:0,
  1768.                     total_iron:0,
  1769.                     time_finished:Math.round(map_buildings.get(key)/3600)
  1770.                 })
  1771.  
  1772.             }
  1773.         })
  1774.  
  1775.         Array.from(map_coord_templates.keys()).forEach(key=>{//for every coord which have a AM construction template
  1776.             let coord=key
  1777.             let count_time_construction=map_buildings.get(coord+"_time_queued")//if a village has already queued building then get time when last building is finished
  1778.             let template_name=map_coord_templates.get(coord)//get name template for the current village and then get the whole template tree from AM
  1779.             let list_template=map_construction_templates.get(template_name)
  1780.             // console.log("template_name",template_name)
  1781.             // console.log(list_template)
  1782.    
  1783.             //special case if a village doesn't have farm to max lv then check if farm is >99% used and then request to build farm 1 lv
  1784.             if(map_buildings.get(coord+"_farm")<30 && map_farm_usage.get(coord)>=0.99){
  1785.                 let lv_building_HQ=map_buildings.get(coord+"_main")
  1786.                 let lv_building_current=map_buildings.get(coord+"_farm")//curent building from building page
  1787.                 let obj_constants_buildings=map_constants_buildings.get("farm")
  1788.  
  1789.                 let list_info_construction=calculateTimeAndResConstruction(lv_building_HQ, lv_building_current, obj_constants_buildings)
  1790.                 let time_construction=list_info_construction[0]
  1791.                 let total_wood=list_info_construction[1]
  1792.                 let total_stone=list_info_construction[2]
  1793.                 let total_iron=list_info_construction[3]
  1794.                 count_time_construction+=time_construction
  1795.  
  1796.                 map_resources_get_AM.set(coord,{
  1797.                     total_wood:total_wood,
  1798.                     total_stone:total_stone,
  1799.                     total_iron:total_iron,
  1800.                     time_finished:Math.round(count_time_construction/3600)
  1801.                 })
  1802.             }
  1803.    
  1804.             for(let i=0;i<list_template.length;i++){//for every building from AM template
  1805.                 let name_building=list_template[i].name
  1806.                 let key_building=coord+"_"+name_building//the key for getting current building from building page is 'coord_name(building)'
  1807.    
  1808.                 let lv_building_AM=list_template[i].level_absolute//level building from AM template
  1809.                 let lv_building_current=map_buildings.get(key_building)//curent building from building page
  1810.    
  1811.                 if(lv_building_AM>lv_building_current){//means current building must be constructed
  1812.                     let nr_levels=lv_building_AM-lv_building_current //lv building from AM can have 2-3 level above the current lv from building page
  1813.                     for(let j=0;j<nr_levels;j++){
  1814.    
  1815.                         //calculate time and resources needed for this lv
  1816.                         lv_building_current++//need to construct this building with 1 lv
  1817.                         let lv_building_HQ=map_buildings.get(coord+"_main")
  1818.                         let obj_constants_buildings=map_constants_buildings.get(name_building)
  1819.                         // console.log(`coord:${coord}, name_building: ${name_building} lv_building_current: ${lv_building_current}`)
  1820.                         let list_info_construction=calculateTimeAndResConstruction(lv_building_HQ, lv_building_current, obj_constants_buildings)
  1821.                         let time_construction=list_info_construction[0]
  1822.                         let total_wood=list_info_construction[1]
  1823.                         let total_stone=list_info_construction[2]
  1824.                         let total_iron=list_info_construction[3]                        
  1825.    
  1826.                         count_time_construction+=time_construction
  1827.                         //update map with res needed for this lv building
  1828.                         if(map_resources_get_AM.has(coord)){
  1829.                             let obj_update = map_resources_get_AM.get(coord)
  1830.                             obj_update.total_wood += total_wood
  1831.                             obj_update.total_stone += total_stone
  1832.                             obj_update.total_iron += total_iron
  1833.                             obj_update.time_finished = Math.round(count_time_construction/3600)
  1834.                             map_resources_get_AM.set(coord,obj_update)
  1835.                            
  1836.                         }
  1837.                         else{
  1838.                             map_resources_get_AM.set(coord,{
  1839.                                 total_wood:total_wood,
  1840.                                 total_stone:total_stone,
  1841.                                 total_iron:total_iron,
  1842.                                 time_finished:Math.round(count_time_construction/3600)
  1843.                             })
  1844.                         }
  1845.                        
  1846.                         if(count_time_construction>time_construction_total){//this village has reached the number of res needed( construction time )
  1847.                             break;
  1848.                         }
  1849.    
  1850.    
  1851.                     }
  1852.                 }
  1853.    
  1854.                 if(count_time_construction>time_construction_total){//this village has reached the number of res needed( construction time )
  1855.                     break;
  1856.                 }
  1857.             }
  1858.    
  1859.          
  1860.         })
  1861.    
  1862.    
  1863.         // console.log("map_resources_get_AM",map_resources_get_AM)
  1864.         resolve(map_resources_get_AM)
  1865.    
  1866.     })
  1867.  
  1868.  
  1869. }
  1870.  
  1871.  
  1872. /////////////////////////////////////////////////////////////////get //////////////////////////////////////////////////
  1873.  
  1874.  
  1875. function getTemplates(){
  1876.     return new Promise((resolve,reject)=>{
  1877.  
  1878.         if(game_data.features.AccountManager.active == false){//AM is not active
  1879.             resolve({
  1880.                 map_coord_templates:new Map(),
  1881.                 map_construction_templates:new Map()
  1882.             })
  1883.         }
  1884.  
  1885.  
  1886.  
  1887.  
  1888.         let link_combined_production=game_data.link_base_pure+"am_village"
  1889.         document.body.innerHTML+=`<div id='page_am' hidden>${httpGet(link_combined_production)}</div>`
  1890.         //get pages for all incoming
  1891.         let list_pages=[]
  1892.  
  1893.         if($("#village_table").prev().find("select").length>0){
  1894.             Array.from($("#village_table").prev().find("select").get(0)).forEach(function(item){
  1895.                 list_pages.push(item.value)
  1896.             })
  1897.         }
  1898.         else if($("#village_table").prev().find(".paged-nav-item").length>0){//all pages from the current folder
  1899.             let nr_pages=$("#village_table").prev().find(".paged-nav-item").length
  1900.             for(let i=nr_pages-2;i>=0;i--){
  1901.                 let link=game_data.link_base_pure+`am_village&page=${i}`
  1902.                 list_pages.push(link);
  1903.             }
  1904.        
  1905.         }
  1906.         else{
  1907.             list_pages.push(link_combined_production);
  1908.         }
  1909.         list_pages=list_pages.reverse();
  1910.         console.log(list_pages)
  1911.  
  1912.         // go to every page and get template
  1913.         let map_coord_templates=new Map()
  1914.         let map_construction_templates=new Map()
  1915.         async function ajaxRequest (urls) {
  1916.             let current_url
  1917.             if(urls.length>0){
  1918.                 current_url=urls.pop()
  1919.             }
  1920.             else{
  1921.                 current_url="stop"
  1922.             }
  1923.             console.log(current_url)
  1924.             let start_ajax=new Date().getTime()
  1925.             if (urls.length >= 0 && current_url!="stop") {
  1926.                 $.ajax({
  1927.                     url: current_url,
  1928.                     method: 'get',
  1929.                     success: (data) => {
  1930.                         // document.body.innerHTML=data
  1931.                         document.body.innerHTML+=`<div id="page_am" hidden>${data}</div>`
  1932.  
  1933.                         let table_construction=Array.from($("#page_am").find(".row_a, .row_b"))
  1934.                         for(let i=0;i<table_construction.length;i++){
  1935.                             let coord=table_construction[i].children[0].innerText.match(/[0-9]{3}\|[0-9]{3}/)[0]
  1936.                             let template_name=table_construction[i].children[1].innerText.trim()
  1937.                             // console.log(template_name)
  1938.                             if(template_name!=""){
  1939.                                 map_coord_templates.set(coord,template_name)
  1940.                                 map_construction_templates.set(template_name,0)
  1941.                             }
  1942.  
  1943.                         }
  1944.  
  1945.                
  1946.                         document.getElementById("page_am").remove()
  1947.                         let stop_ajax=new Date().getTime();
  1948.                         let diff=stop_ajax-start_ajax
  1949.                         console.log("wait: "+diff)
  1950.                         window.setTimeout(function(){
  1951.                             ajaxRequest (list_pages)
  1952.                             UI.SuccessMessage("get AM construction page: "+urls.length)
  1953.                         },200-diff)
  1954.                     },
  1955.                     error:(err)=>{
  1956.                         reject(err)
  1957.                     }
  1958.                 })
  1959.            
  1960.             }
  1961.             else
  1962.             {
  1963.                 //get templates name
  1964.                 let table_name_tamplate=Array.from($("select[name=template]").eq(0).find("option"))
  1965.                 for(let i=0;i<table_name_tamplate.length;i++){
  1966.  
  1967.                     let link=game_data.link_base_pure+`am_village&mode=queue&template=${table_name_tamplate[i].value}`
  1968.                     let name
  1969.                     if(i<3)//only for the first 3 default template remove parantesis
  1970.                         name=table_name_tamplate[i].innerText.replaceAll("\n","").replaceAll("\t","").replace(/\(\w+\)/,"")
  1971.                     else
  1972.                         name=table_name_tamplate[i].innerText.replaceAll("\n","").replaceAll("\t","")
  1973.  
  1974.                     if(map_construction_templates.has(name)){
  1975.                         // console.log(name)
  1976.                         let data=await ajaxPromise(link)
  1977.                         document.body.innerHTML+=`<div id='page_am_template' hidden>${data}</div>`
  1978.  
  1979.                         let template_construction=[]
  1980.                         Array.from($("#page_am_template .sortable_row")).forEach(item=>{
  1981.                             template_construction.push({
  1982.                                 name:item.getAttribute("data-building"),
  1983.                                 level_relative:parseInt($(item).find(".level_relative").text()),
  1984.                                 level_absolute:parseInt($(item).find(".level_absolute").text().match(/\d+/)[0])
  1985.                             })
  1986.                         })
  1987.                         map_construction_templates.set(name,template_construction)
  1988.                         $("#page_am_template").remove()
  1989.                     }
  1990.                    
  1991.                 }
  1992.                
  1993.                
  1994.  
  1995.  
  1996.                 // console.log("map_construction_templates",map_construction_templates)
  1997.  
  1998.                 // console.log("map_coord_templates",map_coord_templates)
  1999.                 document.getElementById("page_am").remove()
  2000.                 UI.SuccessMessage("done")
  2001.                 resolve({
  2002.                     map_coord_templates:map_coord_templates,
  2003.                     map_construction_templates:map_construction_templates
  2004.                 })
  2005.                 // console.log(map_incoming)
  2006.  
  2007.                
  2008.             }
  2009.         }
  2010.         ajaxRequest(list_pages);
  2011.     })
  2012.  
  2013. }
  2014.  
  2015.  
  2016. function ajaxPromise(link){
  2017.     return new Promise((resolve,reject)=>{
  2018.  
  2019.         let startAjax=new Date().getTime()
  2020.         $.ajax({
  2021.             url: link,
  2022.             method: 'get',
  2023.             success: (data) => {
  2024.    
  2025.                 let stopAjax=new Date().getTime()
  2026.                 let difAjax=stopAjax-startAjax
  2027.                 // console.log("wait ",difAjax)
  2028.                 window.setTimeout(()=>{
  2029.                     resolve(data)
  2030.                 },200-difAjax)
  2031.  
  2032.             },error:(data)=>{
  2033.                 reject(data)
  2034.             }
  2035.  
  2036.         })
  2037.     })
  2038. }
  2039.  
  2040.  
  2041. function getDataBuildings(){
  2042.  
  2043.     return new Promise((resolve,reject)=>{
  2044.         let link_combined_production=game_data.link_base_pure+"overview_villages&mode=buildings"
  2045.         document.body.innerHTML+=`<div id='page_buildings' hidden>${httpGet(link_combined_production)}</div>`
  2046.         //get pages for all incoming
  2047.         let list_pages=[]
  2048.    
  2049.         if(document.getElementById("page_buildings").getElementsByClassName("vis")[1].getElementsByTagName("select").length>0){
  2050.             Array.from(document.getElementById("page_buildings").getElementsByClassName("vis")[1].getElementsByTagName("select")[0]).forEach(function(item){
  2051.                 list_pages.push(item.value)
  2052.             })
  2053.             list_pages.pop();
  2054.         }
  2055.         else if(document.getElementById("page_buildings").getElementsByClassName("paged-nav-item").length>0){//all pages from the current folder
  2056.             let nr=0;
  2057.             Array.from(document.getElementById("page_buildings").getElementsByClassName("paged-nav-item")).forEach(function(item){
  2058.                 let current=item.href;
  2059.                 current=current.split("page=")[0]+"page="+nr
  2060.                 nr++;
  2061.                 list_pages.push(current);
  2062.             })
  2063.            
  2064.         }
  2065.         else{
  2066.             list_pages.push(link_combined_production);
  2067.         }
  2068.         list_pages=list_pages
  2069.         console.log(list_pages)
  2070.    
  2071.        
  2072.         // go to every page and get incoming
  2073.         let  map_buildings=new Map()
  2074.         function ajaxRequest (urls) {
  2075.             let current_url
  2076.             if(urls.length>0){
  2077.                 current_url=urls.pop()
  2078.             }
  2079.             else{
  2080.                 current_url="stop"
  2081.             }
  2082.             console.log(current_url)
  2083.             let start_ajax=new Date().getTime()
  2084.             if (urls.length >= 0 && current_url!="stop") {
  2085.                 $.ajax({
  2086.                     url: current_url,
  2087.                     method: 'get',
  2088.                     success: (data) => {
  2089.                         // document.body.innerHTML=data
  2090.                         document.body.innerHTML+=`<div id="page_buildings" hidden>${data}</div>`
  2091.    
  2092.                         let table_buildings=Array.from($("#page_buildings").find(".row_a, .row_b"))
  2093.                         for(let i=0;i<table_buildings.length;i++){
  2094.                             let coord=$(table_buildings[i]).find(".nowrap").text().match(/[0-9]{3}\|[0-9]{3}/)[0]
  2095.                             // console.log(table_buildings[i])
  2096.                             let time_last_construnction=$(table_buildings[i]).find(".queue_icon img").last().attr("title")
  2097.                             if(time_last_construnction==undefined){//has building queued
  2098.                                 time_last_construnction=0
  2099.                             }
  2100.                             else{
  2101.                                 time_last_construnction=time_last_construnction.split("-")[1]
  2102.                                 time_last_construnction=getFinishTime(time_last_construnction)
  2103.                             }
  2104.                             // console.log(time_last_construnction)
  2105.                             map_buildings.set(coord+"_time_queued",time_last_construnction)
  2106.                            
  2107.  
  2108.                             let buildings=$(table_buildings[i]).find(".upgrade_building")
  2109.                             for(let j=0;j<buildings.length;j++){
  2110.                                 let name=buildings[j].classList[1].replace("b_","")
  2111.                                 let level=parseInt(buildings[j].innerText)
  2112.                                 // console.log(`name: ${name}, level:${level}`)
  2113.                                 let key=coord+"_"+name
  2114.                                 map_buildings.set(key,level)
  2115.                             }
  2116.  
  2117.  
  2118.  
  2119.                             //add queued buildings
  2120.                             let list_queued=Array.from($(table_buildings[i]).find(".queue_icon img")).map(e=>e.src.match(/\w+.png/)[0].replace(".png",""))
  2121.                             // console.log(list_queued)
  2122.                             for(let j=0;j<list_queued.length;j++){
  2123.                                 let key=coord+"_"+list_queued[j]
  2124.  
  2125.                                 if(map_buildings.has(key)){
  2126.                                     let value=map_buildings.get(key)
  2127.                                     map_buildings.set(key,value+1)
  2128.                                 }else{
  2129.                                     map_buildings.set(key,1)
  2130.                                 }
  2131.                             }
  2132.  
  2133.                         }
  2134.  
  2135.  
  2136.                         document.getElementById("page_buildings").remove()
  2137.                         let stop_ajax=new Date().getTime();
  2138.                         let diff=stop_ajax-start_ajax
  2139.                         console.log("wait: "+diff)
  2140.                         window.setTimeout(function(){
  2141.                             ajaxRequest (list_pages)
  2142.                             UI.SuccessMessage("get building page: "+urls.length)
  2143.                         },200-diff)
  2144.                     },
  2145.                     error: (err)=>{
  2146.                         reject(err)
  2147.                     }
  2148.                 })
  2149.                
  2150.             }
  2151.             else
  2152.             {
  2153.                 document.getElementById("page_buildings").remove()
  2154.                 UI.SuccessMessage("done")
  2155.                 console.log("map_buildings heeeeeeeerere",map_buildings)
  2156.                 resolve(map_buildings)
  2157.      
  2158.             }
  2159.         }
  2160.         ajaxRequest(list_pages);
  2161.    
  2162.     })
  2163. }
  2164.  
  2165.  
  2166. function tt(string) {
  2167.     var gameLocale = game_data.locale;
  2168.  
  2169.     if (translations[gameLocale] != undefined) {
  2170.         return translations[gameLocale][string];
  2171.     } else {
  2172.         let error=`No translation found for <b>${gameLocale}</b>`
  2173.         UI.ErrorMessage(error,4000);
  2174.         throw Error(error)
  2175.     }
  2176. }
  2177.  
  2178.  
  2179. function getFinishTime(time_finished){
  2180.     var date_finished=""
  2181.     let server_date=document.getElementById("serverDate").innerText.split("/")
  2182.     if(time_finished.includes(tt("today at"))){    //today
  2183.         date_finished=server_date[1]+"/"+server_date[0]+"/"+server_date[2]+" "+time_finished.match(/\d+:\d+/)[0]
  2184.     }
  2185.     else if(time_finished.includes(tt("tomorrow at"))){    //tomorrow
  2186.         var tomorrow_date=new Date(server_date[1]+"/"+server_date[0]+"/"+server_date[2]);
  2187.         tomorrow_date.setDate(tomorrow_date.getDate()+1);
  2188.         date_finished= ("0"+(tomorrow_date.getMonth()+1)).slice(-2)+"/"+("0"+tomorrow_date.getDate()).slice(-2)+"/"+tomorrow_date.getFullYear()+" "+time_finished.match(/\d+:\d+/)[0];
  2189.     }else if(time_finished.includes(tt("on"))){  //on
  2190.         var on=time_finished.match(/\d+.\d+/)[0].split(".");
  2191.         date_finished=on[1]+"/"+on[0]+"/"+server_date[2]+" "+time_finished.match(/\d+:\d+/)[0];
  2192.     }
  2193.     date_finished=new Date(date_finished).getTime()
  2194.  
  2195.     let serverTime=document.getElementById("serverTime").innerText
  2196.     let serverDate=document.getElementById("serverDate").innerText.split("/")
  2197.     serverDate=serverDate[1]+"/"+serverDate[0]+"/"+serverDate[2]
  2198.     let date_current=new Date(serverDate+" "+serverTime).getTime()
  2199.  
  2200.     let result_seconds=parseInt((date_finished-date_current)/1000)
  2201.  
  2202.     return result_seconds;
  2203. }
  2204.  
  2205. function getConstantsTwBuildings(){
  2206.     if (localStorage.getItem(game_data.world+"constantBuildings") !== null) {
  2207.         let map_constants_buildings = new Map(JSON.parse(localStorage.getItem(game_data.world+"constantBuildings")))
  2208.         console.log("constant building world already exist")
  2209.         return map_constants_buildings
  2210.     }
  2211.     else{ //Get data from xml and save it in localStorage to avoid excessive XML requests to server
  2212.             let data=httpGet("/interface.php?func=get_building_info") //Load world data
  2213.             document.body.innerHTML +=`<div id='load_html' hidden>${data}</div>`
  2214.            
  2215.             let map_constants_buildings=new Map()
  2216.             let list_buildings=document.getElementsByTagName("config")[0].children
  2217.             for(let i=0;i<list_buildings.length;i++){
  2218.                 let name_building=list_buildings[i].tagName.toLowerCase()
  2219.                 let wood=Number(list_buildings[i].getElementsByTagName("wood")[0].innerText)
  2220.                 let stone=Number(list_buildings[i].getElementsByTagName("stone")[0].innerText)
  2221.                 let iron=Number(list_buildings[i].getElementsByTagName("iron")[0].innerText)
  2222.  
  2223.  
  2224.  
  2225.                 let wood_factor=Number(list_buildings[i].getElementsByTagName("wood_factor")[0].innerText)
  2226.                 let stone_factor=Number(list_buildings[i].getElementsByTagName("stone_factor")[0].innerText)
  2227.                 let iron_factor=Number(list_buildings[i].getElementsByTagName("iron_factor")[0].innerText)
  2228.  
  2229.                 let build_time=Number(list_buildings[i].getElementsByTagName("build_time")[0].innerText)
  2230.                 let build_time_factor=Number(list_buildings[i].getElementsByTagName("build_time_factor")[0].innerText)
  2231.  
  2232.                 map_constants_buildings.set(name_building,{
  2233.                     wood:wood,
  2234.                     stone:stone,
  2235.                     iron:iron,
  2236.                     wood_factor:wood_factor,
  2237.                     stone_factor:stone_factor,
  2238.                     iron_factor:iron_factor,
  2239.                     build_time:build_time,
  2240.                     build_time_factor:build_time_factor
  2241.                 })
  2242.             }
  2243.             document.getElementById("load_html").remove()
  2244.             let data_save=JSON.stringify(Array.from(map_constants_buildings.entries()))
  2245.             localStorage.setItem(game_data.world+"constantBuildings",data_save);
  2246.             console.log("save speed world")
  2247.         return map_constants_buildings
  2248.     }
  2249.  
  2250. }
  2251.  
  2252.  
  2253. function calculateTimeAndResConstruction(hg, level, obj_data) {
  2254.     //https://gist.github.com/amiuhle/61b0334997805ada0e99
  2255.  
  2256.     var exponent = Math.max(-13, (level - 1 - 14 / (level-1)));
  2257.     var baseTime = obj_data.build_time * 1.18 * Math.pow(obj_data.build_time_factor, exponent);
  2258.     var time = baseTime * Math.pow(1.05, -hg);
  2259.     let total_wood = Math.round(obj_data.wood * Math.pow(obj_data.wood_factor, level - 1))
  2260.     let total_stone = Math.round(obj_data.stone * Math.pow(obj_data.stone_factor, level - 1))
  2261.     let total_iron = Math.round(obj_data.iron * Math.pow(obj_data.iron_factor, level - 1))
  2262.  
  2263.     return [Math.round(time), total_wood , total_stone, total_iron];
  2264. }
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270. /////////////////////////////////////////////////////////k-means////////////////////////////////////////////////////////
  2271. // https://github.com/shudima/dimas-kmeans/blob/master/dimas-kmeans.js
  2272.  
  2273.  
  2274.  
  2275.  
  2276. function getClusters(data, options) {
  2277.     let result_cluster=[]
  2278.     let maxDistanceGlobal=999999;
  2279.     let repeat=50;
  2280.  
  2281.     for(let rep=0;rep<repeat;rep++){
  2282.         let result=insideGetCluster(data,options)
  2283.         if(maxDistanceGlobal > result.maxDistance){
  2284.             maxDistanceGlobal=result.maxDistance
  2285.             result_cluster=result
  2286.         }
  2287.     }
  2288.     console.log("maxDistanceGlobal",maxDistanceGlobal)
  2289.  
  2290.     // throw new Error("stop")
  2291.     return result_cluster
  2292. }
  2293.  
  2294.  
  2295. function insideGetCluster(data,options){
  2296.     var numberOfClusters, distanceFunction, vectorFunction, minMaxValues, maxIterations;
  2297.  
  2298.     if (!options || !options.numberOfClusters) { numberOfClusters = 1 }
  2299.     else { numberOfClusters = options.numberOfClusters; }
  2300.  
  2301.     if (!options || !options.distanceFunction) { distanceFunction = getDistance; }
  2302.     else { distanceFunction = options.distanceFunction; }
  2303.    
  2304.     if (!options || !options.vectorFunction) { vectorFunction = defaultVectorFunction; }
  2305.     else { vectorFunction = options.vectorFunction; }
  2306.    
  2307.     if (!options || !options.maxIterations) { maxIterations = 1000; }
  2308.     else { maxIterations = options.maxIterations; }
  2309.  
  2310.     let result_cluster=getClustersWithParams(data, numberOfClusters, distanceFunction, vectorFunction, maxIterations).clusters;
  2311.  
  2312.     ////calculate max distance
  2313.  
  2314.     let maxDistance=0;
  2315.     for(let i=0;i<result_cluster.length;i++){//for each cluster
  2316.         let list_coord=result_cluster[i].data
  2317.         for(let j=0;j<list_coord.length;j++){
  2318.             for(let k=j+1;k<list_coord.length;k++){
  2319.                 let dist=getDistance(list_coord[j],list_coord[k])
  2320.                 maxDistance=(maxDistance > dist)?maxDistance:dist
  2321.             }
  2322.         }
  2323.     }
  2324.     // console.log("maxDistance",maxDistance)
  2325.     result_cluster.maxDistance=maxDistance
  2326.     return result_cluster
  2327.  
  2328.    
  2329. }
  2330.  
  2331.  
  2332. function getClustersWithParams(data ,numberOfClusters, distanceFunction, vectorFunction, maxIterations) {
  2333.  
  2334.     let means=[]
  2335.     for(let i=0;i<numberOfClusters;i++){
  2336.         let random_index=parseInt(Math.random()*Object.keys(data).length)
  2337.         means.push(data[random_index])
  2338.     }
  2339.  
  2340.  
  2341.     // console.log("means",means)
  2342.     var clusters = createClusters(means);
  2343.  
  2344.     var prevMeansDistance = 999999;
  2345.  
  2346.     var numOfInterations = 0;
  2347.     var iterations = [];
  2348.  
  2349.  
  2350.     while(numOfInterations < maxIterations) {
  2351.  
  2352.         initClustersData(clusters);
  2353.  
  2354.         assignDataToClusters(data, clusters, distanceFunction, vectorFunction);
  2355.  
  2356.         updateMeans(clusters, vectorFunction);
  2357.  
  2358.         var meansDistance = getMeansDistance(clusters, vectorFunction, distanceFunction);
  2359.  
  2360.         //iterations.push(meansDistance);
  2361.         // console.log(numOfInterations + ': ' + meansDistance);
  2362.         numOfInterations++;
  2363.     }
  2364.    
  2365.     // console.log(getMeansDistance(clusters, vectorFunction, distanceFunction));
  2366.  
  2367.     return { clusters: clusters, iterations: iterations };
  2368. }
  2369.  
  2370. function defaultVectorFunction(vector) {
  2371.     return vector;
  2372. }
  2373.  
  2374.  
  2375. function getMeansDistance(clusters, vectorFunction, distanceFunction) {
  2376.  
  2377.     var meansDistance = 0;
  2378.  
  2379.     clusters.forEach(function (cluster) {
  2380.  
  2381.         cluster.data.forEach(function (vector) {
  2382.  
  2383.             meansDistance = meansDistance + Math.pow(distanceFunction(cluster.mean, vectorFunction(vector)), 2);
  2384.         });
  2385.     });
  2386.  
  2387.  
  2388.     return meansDistance;
  2389. }
  2390.  
  2391. function updateMeans(clusters, vectorFunction) {
  2392.  
  2393.     clusters.forEach(function (cluster) {
  2394.         updateMean(cluster, vectorFunction);
  2395.  
  2396.     });
  2397. }
  2398.  
  2399.  
  2400. function updateMean(cluster, vectorFunction) {
  2401.  
  2402.     var newMean = [];
  2403.  
  2404.     for (var i = 0; i < cluster.mean.length; i++) {
  2405.         newMean.push(getMean(cluster.data, i, vectorFunction));
  2406.     };
  2407.  
  2408.  
  2409.     cluster.mean = newMean;
  2410.  
  2411. }
  2412.  
  2413. function getMean(data, index, vectorFunction) {
  2414.     var sum =  0;
  2415.     var total = data.length;
  2416.  
  2417.     if(total == 0) return 0;
  2418.  
  2419.     data.forEach(function (vector) {
  2420.  
  2421.             sum = sum + vectorFunction(vector)[index];
  2422.     });
  2423.  
  2424.  
  2425.     return sum / total;
  2426. }
  2427.  
  2428. function assignDataToClusters(data, clusters, distanceFunction, vectorFunction) {
  2429.  
  2430.  
  2431.     data.forEach(function (vector) {
  2432.         var cluster = findClosestCluster(vectorFunction(vector), clusters, distanceFunction);
  2433.  
  2434.         if(!cluster.data) cluster.data = [];
  2435.        
  2436.         cluster.data.push(vector);
  2437.     });
  2438. }
  2439.  
  2440. function findClosestCluster(vector, clusters, distanceFunction) {
  2441.  
  2442.     var closest = {};
  2443.     var minDistance = 9999999;
  2444.  
  2445.     clusters.forEach(function (cluster) {
  2446.        
  2447.         var distance = distanceFunction(cluster.mean, vector);
  2448.         if (distance < minDistance) {
  2449.             minDistance = distance;
  2450.             closest = cluster;
  2451.         };
  2452.     });
  2453.  
  2454.     return closest;
  2455. }
  2456.  
  2457. function initClustersData(clusters) {
  2458.     clusters.forEach(function (cluster) {
  2459.         cluster.data = [];
  2460.     });
  2461. }
  2462.  
  2463. function createClusters(means) {
  2464.     var clusters = [];
  2465.  
  2466.     means.forEach(function (mean) {
  2467.         var cluster = { mean : mean, data : []};
  2468.  
  2469.         clusters.push(cluster);
  2470.     });
  2471.  
  2472.     return clusters;
  2473. }
  2474.  
  2475.  
  2476. function getDistance(vector1, vector2) {
  2477.     var sum = 0;
  2478.  
  2479.     for (var i = 0; i < vector1.length; i++) {
  2480.         sum = sum + Math.pow(vector1[i] - vector2[i],2)
  2481.     };
  2482.  
  2483.     return Math.sqrt(sum);
  2484.  
  2485. }
  2486.  
  2487.  
  2488.  
  2489. ///////////////////////////////////////////////////////show data on the map///////////////////////////////////////
  2490.  
  2491. function addInfoOnMap(mapInfoResources,random_color){
  2492.     let drawInfo=true
  2493.     console.log("sa mor eu de nu mrge",mapInfoResources)
  2494.     TWMap.mapHandler.spawnSector = function (data, sector) {
  2495.         originalSpawnSector.call(TWMap.mapHandler, data, sector);
  2496.         console.log(`spawn area map`)
  2497.  
  2498.         if(drawInfo==true){
  2499.             drawInfo=false
  2500.             window.setTimeout(() => {
  2501.  
  2502.                 let visibleSectors=TWMap.map._visibleSectors
  2503.                 Object.keys(visibleSectors).forEach(key=>{
  2504.                     let elements=visibleSectors[key]._elements
  2505.                     Object.keys(elements).forEach(key=>{
  2506.                         let villageId=elements[key].id.match(/\d+/)
  2507.                         // console.log(villageId)
  2508.                         if(villageId!=null){
  2509.                             if(mapInfoResources.has(villageId[0])){
  2510.                                 let obj=mapInfoResources.get(villageId[0])
  2511.                                 // console.log(obj)
  2512.                                 // console.log(`label cluster: ${obj.label_cluster}, color random: `)
  2513.                                 // console.log(random_color[obj.label_cluster])
  2514.                                 createMapInfo(obj,random_color[obj.label_cluster])
  2515.                             }
  2516.                         }  
  2517.                     })
  2518.                 })
  2519.                 drawInfo=true
  2520.             }, 50);
  2521.         }
  2522.     };
  2523. }
  2524.  
  2525.  
  2526. function createMapInfo(obj,random_color){
  2527.  
  2528.     try {
  2529.         console.log(random_color)
  2530.         if(document.getElementById(`info_extra${obj.villageId}`) == null ){
  2531.             let greenColor="#026440"
  2532.             let redColor="#E80000"
  2533.             let villageImg=document.getElementById(`map_village_${obj.villageId}`)
  2534.  
  2535.             let parent=document.getElementById(`map_village_${obj.villageId}`).parentElement
  2536.             let leftImg=villageImg.style.left
  2537.             let topImg=villageImg.style.top
  2538.  
  2539.             while(document.getElementById(`map_icons_${obj.villageId}`)!=null){
  2540.                 document.getElementById(`map_icons_${obj.villageId}`).remove()
  2541.             }
  2542.             if(document.getElementById(`map_cmdicons_${obj.villageId}_0`)!=null)
  2543.                 document.getElementById(`map_cmdicons_${obj.villageId}_0`).remove()
  2544.             if(document.getElementById(`map_cmdicons_${obj.villageId}_1`)!=null)
  2545.                 document.getElementById(`map_cmdicons_${obj.villageId}_1`).remove()
  2546.  
  2547.  
  2548.             let html_info=`
  2549.                 <div class="border_info" id="info_extra${obj.villageId}" style="position:absolute;left:${leftImg};top:${topImg};width:51px;height:36px;z-index:3; ${`background-color:${random_color.colorOpacity};outline:${random_color.color} solid 2px`}"></div>
  2550.                 <center><font color="${titleColor}"  class="shadow20" style="position:absolute;left:${leftImg};top:${topImg};width:14px;height:14px;z-index:4;margin-left:0px;; font-size: 12px">nr:${obj.label_cluster} </font></center>
  2551.                 <center><font color="${greenColor}"  class="shadow20" style="position:absolute;left:${leftImg};top:${topImg};width:14px;height:14px;z-index:4;margin-left:0px;margin-top:11px; font-size: 12px">${parseInt(obj.total_resources_get/1000)}k </font></center>
  2552.                 <center><font color="${redColor}"  class="shadow20" style="position:absolute;left:${leftImg};top:${topImg};width:14px;height:14px;z-index:4;margin-left:0px;margin-top:23px; font-size: 12px">${parseInt(obj.total_resources_send/1000)}k </font></center>
  2553.                 `
  2554.             $(html_info).appendTo(parent);
  2555.  
  2556.  
  2557.         }
  2558.  
  2559.     } catch (error) {
  2560.        
  2561.     }
  2562. }
  2563.  
  2564.  
  2565. function getRandomColor(opacity) {
  2566.     let  color = 'rgb(';
  2567.     let colorOpacity = 'rgba(';
  2568.  
  2569.     for (let i = 0; i < 3; i++) {
  2570.         let randomNr=Math.floor(Math.random() * 255)
  2571.         color += randomNr + ',';
  2572.         colorOpacity += randomNr + ',';
  2573.  
  2574.     }
  2575.     color=color.substr(0,color.length-1)  + ')';
  2576.     colorOpacity=colorOpacity + opacity + ')';
  2577.  
  2578.     return {
  2579.         color:color,
  2580.         colorOpacity:colorOpacity
  2581.     }
  2582.  
  2583. }
  2584.  
  2585.  
  2586.  
  2587.  
  2588.  
  2589.  
  2590.  
  2591.  
  2592.  
  2593.  
  2594.  
  2595.  
  2596.  
  2597.  
  2598.  
  2599.  
  2600.  
  2601.  
  2602.  
  2603.  
  2604.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement