optimizer_unit.php 89 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777
  1. <?php
  2. /**
  3. * Monster view.
  4. *
  5. * Contains the view layout and some code to present the data.
  6. *
  7. * @category View
  8. * @property_read Monster_Page $page The page model.
  9. * @property_read int $UID Player ID.
  10. */
  11. ?>
  12. <!DOCTYPE html>
  13. <html lang='en'>
  14. <head>
  15. <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
  16. <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
  17. <title><?=$page->title?></title>
  18. <link rel='shortcut icon' href='<?=$page->favicon?>'/>
  19. <!-- CSS files -->
  20. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
  21. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>optimizer.css'/>
  22. <!-- Meta tags -->
  23. <link rel='canonical' href='<?=$page->canonical?>'/>
  24. <link rel='author' href='<?=$page->author?>'/>
  25. <link rel='publisher' href='<?=$page->author?>'/>
  26. <meta name='description' content='<?=$page->description?>'/>
  27. <meta property='og:title' content='<?=$page->title?>'/>
  28. <meta property='og:url' content='<?=$page->canonical?>'/>
  29. <meta property='og:description' content='<?=$page->description?>'/>
  30. <meta property='og:image' content='<?=$page->icon?>'/>
  31. <meta property='og:site_name' content='<?=$page->name?>'/>
  32. <meta property='og:type' content='website'/>
  33. <meta property='og:locale' content='en'/>
  34. <meta name='twitter:card' content='summary'/>
  35. <meta name='twitter:title' content='<?=$page->title?>'/>
  36. <meta name='twitter:description' content='<?=$page->description?>'/>
  37. <meta name='twitter:image' content='<?=$page->icon?>'/>
  38. <meta name='twitter:url' content='<?=$page->canonical?>'/>
  39. <meta name='robots' content='index follow'/>
  40. <script>
  41. /**
  42. * Unit current stats.
  43. */
  44. var current_stats = {
  45. "attack": <?=$page->unit->total_attack?>,
  46. "defense": <?=$page->unit->total_defense?>,
  47. "hp": <?=$page->unit->total_hp?>,
  48. "speed": <?=$page->unit->total_speed?>,
  49. "crit_rate": <?=$page->unit->total_crit_rate?>,
  50. "crit_damage": <?=$page->unit->total_crit_damage?>,
  51. "accuracy": <?=$page->unit->total_accuracy?>,
  52. "resistance": <?=$page->unit->total_resistance?>,
  53. "ehp": <?=$page->unit->effective_hp?>,
  54. "dmg": <?=$page->unit->effective_dmg?>
  55. }
  56. var base_stats = {
  57. "attack": <?=$page->unit->attack?>,
  58. "defense": <?=$page->unit->defense?>,
  59. "hp": <?=$page->unit->hp?>,
  60. "speed": <?=$page->unit->speed?>,
  61. "crit_rate": <?=$page->unit->crit_rate?>,
  62. "crit_damage": <?=$page->unit->crit_damage?>,
  63. "accuracy": <?=$page->unit->accuracy?>,
  64. "resistance": <?=$page->unit->resistance?>,
  65. "ehp": <?=$page->unit->effective_hp?>,
  66. "dmg": <?=$page->unit->effective_dmg?>
  67. }
  68. <?php
  69. // Get current rune sets
  70. $sets = [];
  71. foreach ($page->unit->rune as $rune){
  72. if (!in_array($rune->type->id, $sets)){
  73. array_push($sets, $rune->type->id);
  74. }
  75. }
  76. for ($i = sizeof($sets); $i < 3; $i ++){
  77. array_push($sets, 0);
  78. }
  79. ?>
  80. var current_sets = [<?=$sets[0]?>, <?=$sets[1]?>, <?=$sets[2]?>];
  81. // Get current main stats in even slots
  82. <?php
  83. $mains = [0, 0, 0];
  84. foreach ($page->unit->rune as $rune){
  85. if ($rune->slot % 2 == 0){
  86. $mains[($rune->slot / 2) - 1] = $rune->main_stat;
  87. }
  88. }
  89. ?>
  90. /**
  91. * To calculate time.
  92. */
  93. var timestamp = 0;
  94. /**
  95. * Enables or disables a new search.
  96. *
  97. * When disabled, the apply button will be disabled and a waiting
  98. * icon will be shown.
  99. *
  100. * @param enable true to enable, false to disable.
  101. */
  102. function enableNewSearch(enable){
  103. if (enable === true){
  104. document.getElementById('apply').removeAttribute('disabled');
  105. document.getElementById('wait').style.display = 'none';
  106. }
  107. else{
  108. document.getElementById('apply').setAttribute('disabled', 'disabled');
  109. document.getElementById('wait').style.display = 'block';
  110. }
  111. }
  112. /**
  113. * Updates the value next to the sliders when they change.
  114. *
  115. * @param stat Name of the stat to set.
  116. * @param value Value of the slider.
  117. */
  118. function updateMinValue(stat, element){
  119. var value = Number(element.value);
  120. var max = Number(element.max);
  121. var min = Number(element.min);
  122. if (value < min){
  123. value = min;
  124. }
  125. if (value > max){
  126. value = max;
  127. }
  128. document.getElementById('lbl_min_' + stat).value = value;
  129. document.getElementById('min_' + stat).value = value;
  130. }
  131. /**
  132. * Resets filter to the unit's current stat status.
  133. *
  134. * @param stat Name of the stat to set.
  135. */
  136. function resetFilter(stat){
  137. document.getElementById('lbl_min_' + stat).value = current_stats[stat];
  138. document.getElementById('min_' + stat).value = current_stats[stat];
  139. }
  140. /**
  141. * Sets a filter to it's lowest possible value.
  142. *
  143. * @param stat Name of the stat to set.
  144. */
  145. function removeFilter(stat){
  146. document.getElementById('lbl_min_' + stat).value = document.getElementById('lbl_min_' + stat).min;
  147. document.getElementById('min_' + stat).value = document.getElementById('min_' + stat).min;
  148. }
  149. function log(text){
  150. var log_window = document.getElementById('log_window');
  151. var span = document.createElement('span');
  152. span.setAttribute('class', 'log_message');
  153. text = document.createTextNode(text);
  154. span.appendChild(text);
  155. log_window.appendChild(span);
  156. log_window.scrollTo(0, 2 * log_window.offsetHeight);
  157. }
  158. function clearLog(){
  159. const elements = document.querySelectorAll('.log_message');
  160. Array.from(elements).forEach((element, index) => {
  161. element.remove();
  162. });
  163. }
  164. /**
  165. * Starts the optimization.
  166. *
  167. * Checks for error in the combination of the parameters, and
  168. * shows an error window if there is an invalid conbination. If
  169. * not, builds the url to fetch all candidate runes.
  170. *
  171. * @return false on error, true on success.
  172. */
  173. function apply(){
  174. log("Start optimization...");
  175. var params = '';
  176. var x;
  177. // Player id - mandatory
  178. params = 'uid=<?=$UID?>';
  179. // Unit id - mandatory
  180. params += '&unit=<?=$page->unit->id?>';
  181. // Rune set 1 - mandatory
  182. params += '&set[]=' + document.getElementById('set_1').options[document.getElementById('set_1').selectedIndex].value;
  183. // Rune set 2 - mandatory
  184. params += '&set[]=' + document.getElementById('set_2').options[document.getElementById('set_2').selectedIndex].value;
  185. // Rune set 3 - optional
  186. x = document.getElementById('set_3').options[document.getElementById('set_3').selectedIndex].value;
  187. if (x != ''){
  188. params += '&set[]=' + x;
  189. }
  190. // Slot 2 - mandatory
  191. params += '&stat[]=' + document.getElementById('slot_2').options[document.getElementById('slot_2').selectedIndex].value;
  192. // Slot 4 - mandatory
  193. params += '&stat[]=' + document.getElementById('slot_4').options[document.getElementById('slot_4').selectedIndex].value;
  194. // Slot 5 - mandatory
  195. params += '&stat[]=' + document.getElementById('slot_6').options[document.getElementById('slot_6').selectedIndex].value;
  196. // Rune source - mandatory
  197. params += '&source=' + document.getElementById('rune_source').options[document.getElementById('rune_source').selectedIndex].value;
  198. // Optimizer tuning - mandatory
  199. params += '&tuning=' + document.getElementById('tuning').options[document.getElementById('tuning').selectedIndex].value;
  200. // Limit combinations - mandatory
  201. params += '&limit=' + document.getElementById('limit').value;
  202. // Min HP - Optional
  203. if (Number(document.getElementById('min_hp').value) > Number(document.getElementById('min_hp').min)){
  204. params += '&min_hp=' + document.getElementById('min_hp').value;
  205. }
  206. // Min ATK - Optional
  207. if (Number(document.getElementById('min_attack').value) > Number(document.getElementById('min_attack').min)){
  208. params += '&min_attack=' + document.getElementById('min_attack').value;
  209. }
  210. // Min DEF - Optional
  211. if (Number(document.getElementById('min_defense').value) > Number(document.getElementById('min_defense').min)){
  212. params += '&min_defense=' + document.getElementById('min_defense').value;
  213. }
  214. // Min SPD - Optional
  215. if (Number(document.getElementById('min_speed').value) > Number(document.getElementById('min_speed').min)){
  216. params += '&min_speed=' + document.getElementById('min_speed').value;
  217. }
  218. // Min CRR - Optional
  219. if (Number(document.getElementById('min_crit_rate').value) > Number(document.getElementById('min_crit_rate').min)){
  220. params += '&min_crit_rate=' + document.getElementById('min_crit_rate').value;
  221. }
  222. // Min CRD - Optional
  223. if (Number(document.getElementById('min_crit_damage').value) > Number(document.getElementById('min_crit_damage').min)){
  224. params += '&min_crit_damage=' + document.getElementById('min_crit_damage').value;
  225. }
  226. // Min ACC - Optional
  227. if (Number(document.getElementById('min_accuracy').value) > Number(document.getElementById('min_accuracy').min)){
  228. params += '&min_accuracy=' + document.getElementById('min_accuracy').value;
  229. }
  230. // Min RES - Optional
  231. if (Number(document.getElementById('min_resistance').value) > Number(document.getElementById('min_resistance').min)){
  232. params += '&min_resistance=' + document.getElementById('min_resistance').value;
  233. }
  234. // Min EHP - Optional
  235. if (Number(document.getElementById('min_ehp').value) > 0){
  236. params += '&min_ehp=' + document.getElementById('min_ehp').value;
  237. }
  238. // Min DMG - Optional
  239. if (Number(document.getElementById('min_dmg').value) > 0){
  240. params += '&min_dmg=' + document.getElementById('min_dmg').value;
  241. }
  242. // Send the request
  243. var xhttp = new XMLHttpRequest();
  244. xhttp.onreadystatechange = function() {
  245. if (this.readyState == 4){
  246. if (this.status == 200) {
  247. time = ((+ new Date()) - timestamp) / 1000;
  248. calculateOptimizations(this.response, time);
  249. }
  250. else{
  251. enableNewSearch(true);
  252. var time = ((+ new Date()) - timestamp) / 1000;
  253. log('Error ' + this.status + '(' + time + 's)');
  254. showMessage('Error', 'Unexpected error ' + this.status);
  255. }
  256. }
  257. };
  258. // DEBUG
  259. //params = 'uid=8114048&unit=6441802832&limit=6&set[]=2&set[]=4&set[]=4&stat[]=4&stat[]=4&stat[]=4&source=0&tuning=2&min_defense=800';
  260. // Clear result table, disable button and show spinner
  261. var container = document.getElementById('optimizations');
  262. while (container.firstChild) {
  263. container.removeChild(container.firstChild);
  264. }
  265. enableNewSearch(false);
  266. document.getElementById('results').style.display = 'none';
  267. // Start timer
  268. timestamp = + new Date();
  269. // Make the request
  270. xhttp.open('POST', '/action/optimize_get_rune_list/', true);
  271. xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  272. xhttp.send(params);
  273. }
  274. /**
  275. * Checks if a rune combination is a valid set. To do so, checks:
  276. *
  277. * - That the sets are valid
  278. * - That the sets are the same as requested
  279. * - That it complies with the filters min values.
  280. *
  281. * @param candidates Array of 6 runes
  282. * @return true if the set matches the criteria, false otherwise.
  283. */
  284. function valid_set(candidates){
  285. // Number of applied sets with the current candidates.
  286. var sets = {
  287. 'RUNE_SET_<?=RUNE_SET_ID::ENERGY?>': 0, // ENERGY
  288. 'RUNE_SET_<?=RUNE_SET_ID::GUARD?>': 0, // GUARD
  289. 'RUNE_SET_<?=RUNE_SET_ID::SWIFT?>': 0, // SWIFT
  290. 'RUNE_SET_<?=RUNE_SET_ID::BLADE?>': 0, // BLADE
  291. 'RUNE_SET_<?=RUNE_SET_ID::RAGE?>': 0, // RAGE
  292. 'RUNE_SET_<?=RUNE_SET_ID::FOCUS?>': 0, // FOCUS
  293. 'RUNE_SET_<?=RUNE_SET_ID::ENDURE?>': 0, // ENDURE
  294. 'RUNE_SET_<?=RUNE_SET_ID::FATAL?>': 0, // FATAL
  295. 'RUNE_SET_<?=RUNE_SET_ID::DESPAIR?>': 0, // DESPAIR
  296. 'RUNE_SET_<?=RUNE_SET_ID::VAMPIRE?>': 0, // VAMPIRE
  297. 'RUNE_SET_<?=RUNE_SET_ID::VIOLENT?>': 0, // VIOLENT
  298. 'RUNE_SET_<?=RUNE_SET_ID::NEMESIS?>': 0, // NEMESIS
  299. 'RUNE_SET_<?=RUNE_SET_ID::WILL?>': 0, // WILL
  300. 'RUNE_SET_<?=RUNE_SET_ID::SHIELD?>': 0, // SHIELD
  301. 'RUNE_SET_<?=RUNE_SET_ID::REVENGE?>': 0, // REVENGE
  302. 'RUNE_SET_<?=RUNE_SET_ID::DESTROY?>': 0, // DESTROY
  303. 'RUNE_SET_<?=RUNE_SET_ID::FIGHT?>': 0, // FIGHT
  304. 'RUNE_SET_<?=RUNE_SET_ID::DETERMINATION?>': 0, // DETERMINATION
  305. 'RUNE_SET_<?=RUNE_SET_ID::ENHANCE?>': 0, // ENHANCE
  306. 'RUNE_SET_<?=RUNE_SET_ID::ACCURACY?>': 0, // ACCURACY
  307. 'RUNE_SET_<?=RUNE_SET_ID::TOLERANCE?>': 0 // TOLERANCE
  308. };
  309. for (var i = 0; i <= 5; i ++){
  310. sets['RUNE_SET_' + candidates[i].TYPE] ++;
  311. }
  312. // TEST I think i dont need to check for valid sets, only that
  313. // they match the requested sets.
  314. /*for (var i = 0; i < sets.length; i ++){
  315. switch (i){
  316. case <?=RUNE_SET_ID::ENERGY?>:
  317. case <?=RUNE_SET_ID::GUARD?>:
  318. case <?=RUNE_SET_ID::NEMESIS?>:
  319. case <?=RUNE_SET_ID::BLADE?>:
  320. case <?=RUNE_SET_ID::FOCUS?>:
  321. case <?=RUNE_SET_ID::ENDURE?>:
  322. case <?=RUNE_SET_ID::WILL?>:
  323. case <?=RUNE_SET_ID::SHIELD?>:
  324. case <?=RUNE_SET_ID::REVENGE?>:
  325. case <?=RUNE_SET_ID::DESTROY?>:
  326. case <?=RUNE_SET_ID::FIGHT?>:
  327. case <?=RUNE_SET_ID::DETERMINATION?>:
  328. case <?=RUNE_SET_ID::ENHANCE?>:
  329. case <?=RUNE_SET_ID::ACCURACY?>:
  330. case <?=RUNE_SET_ID::TOLERANCE?>:
  331. if (sets[i] % 2 != 0){
  332. return false;
  333. }
  334. break;
  335. case <?=RUNE_SET_ID::DESPAIR?>:
  336. case <?=RUNE_SET_ID::SWIFT?>:
  337. case <?=RUNE_SET_ID::RAGE?>:
  338. case <?=RUNE_SET_ID::FATAL?>:
  339. case <?=RUNE_SET_ID::VAMPIRE?>:
  340. case <?=RUNE_SET_ID::VIOLENT?>:
  341. if (sets[i] != 4 && sets[i] != 0){
  342. return false;
  343. }
  344. break;
  345. }
  346. }*/
  347. // Its a valid set, but does it match the requested sets?
  348. var requested_sets = {
  349. 'RUNE_SET_<?=RUNE_SET_ID::ENERGY?>': 0, // ENERGY
  350. 'RUNE_SET_<?=RUNE_SET_ID::GUARD?>': 0, // GUARD
  351. 'RUNE_SET_<?=RUNE_SET_ID::SWIFT?>': 0, // SWIFT
  352. 'RUNE_SET_<?=RUNE_SET_ID::BLADE?>': 0, // BLADE
  353. 'RUNE_SET_<?=RUNE_SET_ID::RAGE?>': 0, // RAGE
  354. 'RUNE_SET_<?=RUNE_SET_ID::FOCUS?>': 0, // FOCUS
  355. 'RUNE_SET_<?=RUNE_SET_ID::ENDURE?>': 0, // ENDURE
  356. 'RUNE_SET_<?=RUNE_SET_ID::FATAL?>': 0, // FATAL
  357. 'RUNE_SET_<?=RUNE_SET_ID::DESPAIR?>': 0, // DESPAIR
  358. 'RUNE_SET_<?=RUNE_SET_ID::VAMPIRE?>': 0, // VAMPIRE
  359. 'RUNE_SET_<?=RUNE_SET_ID::VIOLENT?>': 0, // VIOLENT
  360. 'RUNE_SET_<?=RUNE_SET_ID::NEMESIS?>': 0, // NEMESIS
  361. 'RUNE_SET_<?=RUNE_SET_ID::WILL?>': 0, // WILL
  362. 'RUNE_SET_<?=RUNE_SET_ID::SHIELD?>': 0, // SHIELD
  363. 'RUNE_SET_<?=RUNE_SET_ID::REVENGE?>': 0, // REVENGE
  364. 'RUNE_SET_<?=RUNE_SET_ID::DESTROY?>': 0, // DESTROY
  365. 'RUNE_SET_<?=RUNE_SET_ID::FIGHT?>': 0, // FIGHT
  366. 'RUNE_SET_<?=RUNE_SET_ID::DETERMINATION?>': 0, // DETERMINATION
  367. 'RUNE_SET_<?=RUNE_SET_ID::ENHANCE?>': 0, // ENHANCE
  368. 'RUNE_SET_<?=RUNE_SET_ID::ACCURACY?>': 0, // ACCURACY
  369. 'RUNE_SET_<?=RUNE_SET_ID::TOLERANCE?>': 0 // TOLERANCE
  370. };
  371. var selected_1 = document.getElementById('set_1').options[document.getElementById('set_1').selectedIndex].value;
  372. var selected_2 = document.getElementById('set_2').options[document.getElementById('set_2').selectedIndex].value;
  373. var selected_3 = document.getElementById('set_3').options[document.getElementById('set_3').selectedIndex].value;
  374. var requested_values = [
  375. document.getElementById('set_1').options[document.getElementById('set_1').selectedIndex].value,
  376. document.getElementById('set_2').options[document.getElementById('set_2').selectedIndex].value,
  377. document.getElementById('set_3').options[document.getElementById('set_3').selectedIndex].value
  378. ];
  379. for (var i = 0; i < 3; i ++){
  380. switch (requested_values[i]){
  381. case '<?=RUNE_SET_ID::ENERGY?>':
  382. case '<?=RUNE_SET_ID::GUARD?>':
  383. case '<?=RUNE_SET_ID::NEMESIS?>':
  384. case '<?=RUNE_SET_ID::BLADE?>':
  385. case '<?=RUNE_SET_ID::FOCUS?>':
  386. case '<?=RUNE_SET_ID::ENDURE?>':
  387. case '<?=RUNE_SET_ID::WILL?>':
  388. case '<?=RUNE_SET_ID::SHIELD?>':
  389. case '<?=RUNE_SET_ID::REVENGE?>':
  390. case '<?=RUNE_SET_ID::DESTROY?>':
  391. case '<?=RUNE_SET_ID::FIGHT?>':
  392. case '<?=RUNE_SET_ID::DETERMINATION?>':
  393. case '<?=RUNE_SET_ID::ENHANCE?>':
  394. case '<?=RUNE_SET_ID::ACCURACY?>':
  395. case '<?=RUNE_SET_ID::TOLERANCE?>':
  396. requested_sets['RUNE_SET_' + requested_values[i]] += 2;
  397. break;
  398. case '<?=RUNE_SET_ID::DESPAIR?>':
  399. case '<?=RUNE_SET_ID::SWIFT?>':
  400. case '<?=RUNE_SET_ID::RAGE?>':
  401. case '<?=RUNE_SET_ID::FATAL?>':
  402. case '<?=RUNE_SET_ID::VAMPIRE?>':
  403. case '<?=RUNE_SET_ID::VIOLENT?>':
  404. requested_sets['RUNE_SET_' + i] += 4;
  405. break;
  406. }
  407. }
  408. if (JSON.stringify(sets) !== JSON.stringify(requested_sets)){
  409. return false;
  410. }
  411. // Compare with filters
  412. var new_stats = {
  413. "ATK": base_stats["attack"],
  414. "DEF": base_stats["defense"],
  415. "HP": base_stats["hp"],
  416. "SPD": base_stats["speed"],
  417. "CRR": base_stats["crit_rate"],
  418. "CRD": base_stats["crit_damage"],
  419. "ACC": base_stats["accuracy"],
  420. "RES": base_stats["resistance"],
  421. "EHP": 0,
  422. "DMG": 0
  423. }
  424. for (var i = 0; i <= 5; i ++){
  425. new_stats["ATK"] += candidates[i].ATK;
  426. new_stats["DEF"] += candidates[i].DEF;
  427. new_stats["HP"] += candidates[i].HP;
  428. new_stats["SPD"] += candidates[i].SPD;
  429. new_stats["CRR"] += candidates[i].CRR;
  430. new_stats["CRD"] += candidates[i].CRD;
  431. new_stats["ACC"] += candidates[i].ACC;
  432. new_stats["RES"] += candidates[i].RES;
  433. }
  434. new_stats["EHP"] = Math.ceil((((new_stats["DEF"] * 3.5) + 1140) * new_stats["HP"]) / 1000);
  435. new_stats["DMG"] = Math.ceil((new_stats["ATK"] * (100 - new_stats["CRR"]) / 100) + ((new_stats["ATK"] + (new_stats["ATK"] * new_stats["CRD"] / 100)) * new_stats["CRR"] / 100));
  436. if (
  437. new_stats["ATK"] >= document.getElementById('min_attack').value &&
  438. new_stats["DEF"] >= document.getElementById('min_defense').value &&
  439. new_stats["HP"] >= document.getElementById('min_hp').value &&
  440. new_stats["SPD"] >= document.getElementById('min_speed').value &&
  441. new_stats["CRR"] >= document.getElementById('min_crit_rate').value &&
  442. new_stats["CRD"] >= document.getElementById('min_crit_damage').value &&
  443. new_stats["ACC"] >= document.getElementById('min_accuracy').value &&
  444. new_stats["RES"] >= document.getElementById('min_resistance').value &&
  445. new_stats["EHP"] >= document.getElementById('min_ehp').value &&
  446. new_stats["DMG"] >= document.getElementById('min_dmg').value
  447. ){
  448. return true;
  449. }
  450. return false;
  451. }
  452. /**
  453. * Parses the received runes and looks for valid candidates.
  454. * Once it's done, it calls the server agai to get rune info.
  455. *
  456. * @param content JSON received from server.
  457. */
  458. async function calculateOptimizations(content, time){
  459. var container = document.getElementById('optimizations');
  460. var data = JSON.parse(content);
  461. // Create a 0-index array grouped by slot
  462. var candidates = [
  463. data[1],
  464. data[2],
  465. data[3],
  466. data[4],
  467. data[5],
  468. data[6]
  469. ];
  470. // Calculate total combinations.
  471. var total_runes = data[1].length + data[2].length + data[3].length + data[4].length + data[5].length + data[6].length;
  472. var total_combinations = data[1].length * data[2].length * data[3].length * data[4].length * data[5].length * data[6].length;
  473. if (total_combinations == 0){
  474. var time = ((+ new Date()) - timestamp) / 1000;
  475. log('No rune combinations found (' + time + 's)');
  476. showMessage('No results', 'No runes found matching your criteria.');
  477. }
  478. var time = ((+ new Date()) - timestamp) / 1000;
  479. log(total_runes + ' runes found (' + total_combinations + ' combinations) (' + time + 's)');
  480. // TODO Prevent user on high numbers
  481. var checked_combinations = 0;
  482. // Valid combinations that match the minimum requeriments
  483. var valid_combinations = [];
  484. // Counters to keep track on array indexes
  485. var counters = [0, 0, 0, 0, 0, 0];
  486. // Loop all posible combinations. When a valid set is found,
  487. // add it to valid_combinations
  488. while (true){
  489. if (valid_set([
  490. candidates[0][counters[0]],
  491. candidates[1][counters[1]],
  492. candidates[2][counters[2]],
  493. candidates[3][counters[3]],
  494. candidates[4][counters[4]],
  495. candidates[5][counters[5]]
  496. ])){
  497. valid_combinations.push({
  498. 'score': 0,
  499. 'runes': [
  500. candidates[0][counters[0]],
  501. candidates[1][counters[1]],
  502. candidates[2][counters[2]],
  503. candidates[3][counters[3]],
  504. candidates[4][counters[4]],
  505. candidates[5][counters[5]]
  506. ]
  507. });
  508. }
  509. // Increase counters
  510. checked_combinations ++;
  511. counters[5] ++;
  512. if (counters[5] >= candidates[5].length){
  513. counters[5] = 0;
  514. counters[4] ++;
  515. }
  516. if (counters[4] >= candidates[4].length){
  517. counters[4] = 0;
  518. counters[3] ++;
  519. }
  520. if (counters[3] >= candidates[3].length){
  521. counters[3] = 0;
  522. counters[2] ++;
  523. }
  524. if (counters[2] >= candidates[2].length){
  525. counters[2] = 0;
  526. counters[1] ++;
  527. }
  528. if (counters[1] >= candidates[1].length){
  529. counters[1] = 0;
  530. counters[0] ++;
  531. }
  532. if (counters[0] >= candidates[0].length){
  533. break;
  534. }
  535. /*if (checked_combinations % 1000 == 0){
  536. console.log("COMBINATIONS CHECKED: " + checked_combinations + " / " + total_combinations + "(" + (checked_combinations * 100 / total_combinations) + "%)");
  537. console.log(" 0: " + counters[0] + "/" + candidates[0].length);
  538. console.log(" 1: " + counters[1] + "/" + candidates[1].length);
  539. console.log(" 2: " + counters[2] + "/" + candidates[2].length);
  540. console.log(" 3: " + counters[3] + "/" + candidates[3].length);
  541. console.log(" 4: " + counters[4] + "/" + candidates[4].length);
  542. console.log(" 5: " + counters[5] + "/" + candidates[5].length);
  543. }*/
  544. }
  545. // If no valid combinations: exit now
  546. if (valid_combinations.length == 0){
  547. enableNewSearch(true);
  548. var time = ((+ new Date()) - timestamp) / 1000;
  549. log('No suitable combination found (' + time + 's).');
  550. showMessage('No results', 'No suitable combination found. Plesase relax your criteria and retry.');
  551. }
  552. // Foreach valid combination, rate it and sort the array
  553. for (var i = 0; i < valid_combinations.length; i ++){
  554. for (var r = 0; r < 6; r ++){
  555. valid_combinations[i]['score'] += valid_combinations[i]["runes"][r]["ATK"];
  556. valid_combinations[i]['score'] += valid_combinations[i]["runes"][r]["DEF"];
  557. valid_combinations[i]['score'] += (valid_combinations[i]["runes"][r]["HP"] / 15);
  558. valid_combinations[i]['score'] += (valid_combinations[i]["runes"][r]["SPD"] * 1.5);
  559. valid_combinations[i]['score'] += (valid_combinations[i]["runes"][r]["CRR"] * 1.2);
  560. valid_combinations[i]['score'] += (valid_combinations[i]["runes"][r]["CRD"] * 1.2);
  561. valid_combinations[i]['score'] += (valid_combinations[i]["runes"][r]["ACC"] * 1.2);
  562. valid_combinations[i]['score'] += (valid_combinations[i]["runes"][r]["ATK"] * 1.2);
  563. }
  564. }
  565. var time = ((+ new Date()) - timestamp) / 1000;
  566. log(valid_combinations.length + ' suitable combinations found (' + time + 's)');
  567. valid_combinations.sort(function(a, b) {return b['score'] - a['score'];});
  568. if (valid_combinations.length > document.getElementById('limit').value){
  569. var time = ((+ new Date()) - timestamp) / 1000;
  570. log('Selecting the ' + document.getElementById('limit').value + ' best combinations (' + time + 's)');
  571. valid_combinations = valid_combinations.slice(0, document.getElementById('limit').value);
  572. }
  573. // Request to fetch the runes.
  574. var xhttp = new XMLHttpRequest();
  575. xhttp.onreadystatechange = function() {
  576. if (this.readyState == 4){
  577. if (this.status == 200) {
  578. //time = ((+ new Date()) - timestamp) / 1000;
  579. presentOptions(this.response, timestamp);
  580. }
  581. else{
  582. enableNewSearch(true);
  583. showMessage('Error', 'Unexpected error ' + this.status);
  584. }
  585. }
  586. };
  587. params = 'uid=<?=$UID?>&unit=<?=$page->unit->id?>&tuning=' + document.getElementById('tuning').options[document.getElementById('tuning').selectedIndex].value;
  588. params += '&options=' + JSON.stringify(valid_combinations);
  589. xhttp.open('POST', '/action/optimize_get_options/', true);
  590. xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  591. xhttp.send(params);
  592. return;
  593. }
  594. /**
  595. * Displays the options.
  596. *
  597. * Builds a table with the calculated options and their scores.
  598. * If none. It will show a message. In any case, it reenables the search
  599. * button
  600. *
  601. * @param content Response from /action/optimize_get_options/
  602. * @param timestamp Time counter
  603. */
  604. function presentOptions(content, timestamp){
  605. var container = document.getElementById('optimizations');
  606. var data = JSON.parse(content);
  607. if (data.length == 0){
  608. enableNewSearch(true);
  609. return;
  610. }
  611. var option;
  612. var tr;
  613. var td;
  614. var stat_table;
  615. var stat_tr;
  616. var stat_td;
  617. var span;
  618. var text;
  619. for (i = 0; i < data.length; i++){
  620. option = data[i];
  621. tr = document.createElement('tr');
  622. td = document.createElement('td');
  623. td.setAttribute('class', 'option_stats');
  624. stat_table = document.createElement('table');
  625. stat_table.setAttribute('class', 'stat_table');
  626. // attack
  627. stat_tr = document.createElement('tr');
  628. stat_td = document.createElement('td');
  629. stat_td.setAttribute('class', 'label');
  630. text = document.createTextNode('ATK');
  631. stat_td.appendChild(text);
  632. stat_tr.appendChild(stat_td);
  633. stat_td = document.createElement('td');
  634. stat_td.setAttribute('class', 'value');
  635. span = document.createElement('span');
  636. span.setAttribute('class', 'stat');
  637. text = document.createTextNode(option.stats.attack + " ");
  638. span.appendChild(text);
  639. stat_td.appendChild(span);
  640. span = document.createElement('span');
  641. if (Number(option.stats.attack) > Number(current_stats["attack"])){
  642. span.setAttribute('class', 'variation increment');
  643. text = document.createTextNode(option.stats.attack - current_stats["attack"]);
  644. }
  645. else if (Number(option.stats.attack) < Number(current_stats["attack"])){
  646. span.setAttribute('class', 'variation decrement');
  647. text = document.createTextNode(current_stats["attack"] - option.stats.attack);
  648. }
  649. else{
  650. span.setAttribute('class', 'variation');
  651. text = document.createTextNode(" ");
  652. }
  653. span.appendChild(text);
  654. stat_td.appendChild(span);
  655. stat_tr.appendChild(stat_td);
  656. stat_table.appendChild(stat_tr);
  657. // defense
  658. stat_tr = document.createElement('tr');
  659. stat_td = document.createElement('td');
  660. stat_td.setAttribute('class', 'label');
  661. text = document.createTextNode('DEF');
  662. stat_td.appendChild(text);
  663. stat_tr.appendChild(stat_td);
  664. stat_td = document.createElement('td');
  665. stat_td.setAttribute('class', 'value');
  666. span = document.createElement('span');
  667. span.setAttribute('class', 'stat');
  668. text = document.createTextNode(option.stats.defense + " ");
  669. span.appendChild(text);
  670. stat_td.appendChild(span);
  671. span = document.createElement('span');
  672. if (Number(option.stats.defense) > Number(current_stats["defense"])){
  673. span.setAttribute('class', 'variation increment');
  674. text = document.createTextNode(option.stats.defense - current_stats["defense"]);
  675. }
  676. else if (Number(option.stats.defense) < Number(current_stats["defense"])){
  677. span.setAttribute('class', 'variation decrement');
  678. text = document.createTextNode(current_stats["defense"] - option.stats.defense);
  679. }
  680. else{
  681. span.setAttribute('class', 'variation');
  682. text = document.createTextNode(" ");
  683. }
  684. span.appendChild(text);
  685. stat_td.appendChild(span);
  686. stat_tr.appendChild(stat_td);
  687. stat_table.appendChild(stat_tr);
  688. // hp
  689. stat_tr = document.createElement('tr');
  690. stat_td = document.createElement('td');
  691. stat_td.setAttribute('class', 'label');
  692. text = document.createTextNode('HP ');
  693. stat_td.appendChild(text);
  694. stat_tr.appendChild(stat_td);
  695. stat_td = document.createElement('td');
  696. stat_td.setAttribute('class', 'value');
  697. span = document.createElement('span');
  698. span.setAttribute('class', 'stat');
  699. text = document.createTextNode(option.stats.hp + " ");
  700. span.appendChild(text);
  701. stat_td.appendChild(span);
  702. span = document.createElement('span');
  703. if (Number(option.stats.hp) > Number(current_stats["hp"])){
  704. span.setAttribute('class', 'variation increment');
  705. text = document.createTextNode(option.stats.hp - current_stats["hp"]);
  706. }
  707. else if (Number(option.stats.hp) < Number(current_stats["hp"])){
  708. span.setAttribute('class', 'variation decrement');
  709. text = document.createTextNode(current_stats["hp"] - option.stats.hp);
  710. }
  711. else{
  712. span.setAttribute('class', 'variation');
  713. text = document.createTextNode(" ");
  714. }
  715. span.appendChild(text);
  716. stat_td.appendChild(span);
  717. stat_tr.appendChild(stat_td);
  718. stat_table.appendChild(stat_tr);
  719. // speed
  720. stat_tr = document.createElement('tr');
  721. stat_td = document.createElement('td');
  722. stat_td.setAttribute('class', 'label');
  723. text = document.createTextNode('SPD');
  724. stat_td.appendChild(text);
  725. stat_tr.appendChild(stat_td);
  726. stat_td = document.createElement('td');
  727. stat_td.setAttribute('class', 'value');
  728. span = document.createElement('span');
  729. span.setAttribute('class', 'stat');
  730. text = document.createTextNode(option.stats.speed + " ");
  731. span.appendChild(text);
  732. stat_td.appendChild(span);
  733. span = document.createElement('span');
  734. if (Number(option.stats.speed) > Number(current_stats["speed"])){
  735. span.setAttribute('class', 'variation increment');
  736. text = document.createTextNode(option.stats.speed - current_stats["speed"]);
  737. }
  738. else if (Number(option.stats.speed) < Number(current_stats["speed"])){
  739. span.setAttribute('class', 'variation decrement');
  740. text = document.createTextNode(current_stats["speed"] - option.stats.speed);
  741. }
  742. else{
  743. span.setAttribute('class', 'variation');
  744. text = document.createTextNode(" ");
  745. }
  746. span.appendChild(text);
  747. stat_td.appendChild(span);
  748. stat_tr.appendChild(stat_td);
  749. stat_table.appendChild(stat_tr);
  750. // crit_rate
  751. stat_tr = document.createElement('tr');
  752. stat_td = document.createElement('td');
  753. stat_td.setAttribute('class', 'label');
  754. text = document.createTextNode('CRR');
  755. stat_td.appendChild(text);
  756. stat_tr.appendChild(stat_td);
  757. stat_td = document.createElement('td');
  758. stat_td.setAttribute('class', 'value');
  759. span = document.createElement('span');
  760. span.setAttribute('class', 'stat');
  761. text = document.createTextNode(option.stats.crit_rate + "%");
  762. span.appendChild(text);
  763. stat_td.appendChild(span);
  764. span = document.createElement('span');
  765. if (Number(option.stats.crit_rate) > Number(current_stats["crit_rate"])){
  766. span.setAttribute('class', 'variation increment');
  767. text = document.createTextNode(option.stats.crit_rate - current_stats["crit_rate"]);
  768. }
  769. else if (Number(option.stats.crit_rate) < Number(current_stats["crit_rate"])){
  770. span.setAttribute('class', 'variation decrement');
  771. text = document.createTextNode(current_stats["crit_rate"] - option.stats.crit_rate);
  772. }
  773. else{
  774. span.setAttribute('class', 'variation');
  775. text = document.createTextNode(" ");
  776. }
  777. span.appendChild(text);
  778. stat_td.appendChild(span);
  779. stat_tr.appendChild(stat_td);
  780. stat_table.appendChild(stat_tr);
  781. // crit_damage
  782. stat_tr = document.createElement('tr');
  783. stat_td = document.createElement('td');
  784. stat_td.setAttribute('class', 'label');
  785. text = document.createTextNode('CRD');
  786. stat_td.appendChild(text);
  787. stat_tr.appendChild(stat_td);
  788. stat_td = document.createElement('td');
  789. stat_td.setAttribute('class', 'value');
  790. span = document.createElement('span');
  791. span.setAttribute('class', 'stat');
  792. text = document.createTextNode(option.stats.crit_damage + "%");
  793. span.appendChild(text);
  794. stat_td.appendChild(span);
  795. span = document.createElement('span');
  796. if (Number(option.stats.crit_damage) > Number(current_stats["crit_damage"])){
  797. span.setAttribute('class', 'variation increment');
  798. text = document.createTextNode(option.stats.crit_damage - current_stats["crit_damage"]);
  799. }
  800. else if (Number(option.stats.crit_damage) < Number(current_stats["crit_damage"])){
  801. span.setAttribute('class', 'variation decrement');
  802. text = document.createTextNode(current_stats["crit_damage"] - option.stats.crit_damage);
  803. }
  804. else{
  805. span.setAttribute('class', 'variation');
  806. text = document.createTextNode(" ");
  807. }
  808. span.appendChild(text);
  809. stat_td.appendChild(span);
  810. stat_tr.appendChild(stat_td);
  811. stat_table.appendChild(stat_tr);
  812. // accuracy
  813. stat_tr = document.createElement('tr');
  814. stat_td = document.createElement('td');
  815. stat_td.setAttribute('class', 'label');
  816. text = document.createTextNode('ACC');
  817. stat_td.appendChild(text);
  818. stat_tr.appendChild(stat_td);
  819. stat_td = document.createElement('td');
  820. stat_td.setAttribute('class', 'value');
  821. span = document.createElement('span');
  822. span.setAttribute('class', 'stat');
  823. text = document.createTextNode(option.stats.accuracy + "%");
  824. span.appendChild(text);
  825. stat_td.appendChild(span);
  826. span = document.createElement('span');
  827. if (Number(option.stats.accuracy) > Number(current_stats["accuracy"])){
  828. span.setAttribute('class', 'variation increment');
  829. text = document.createTextNode(option.stats.accuracy - current_stats["accuracy"]);
  830. }
  831. else if (Number(option.stats.accuracy) < Number(current_stats["accuracy"])){
  832. span.setAttribute('class', 'variation decrement');
  833. text = document.createTextNode(current_stats["accuracy"] - option.stats.accuracy);
  834. }
  835. else{
  836. span.setAttribute('class', 'variation');
  837. text = document.createTextNode(" ");
  838. }
  839. span.appendChild(text);
  840. stat_td.appendChild(span);
  841. stat_tr.appendChild(stat_td);
  842. stat_table.appendChild(stat_tr);
  843. // resistance
  844. stat_tr = document.createElement('tr');
  845. stat_td = document.createElement('td');
  846. stat_td.setAttribute('class', 'label');
  847. text = document.createTextNode('RES');
  848. stat_td.appendChild(text);
  849. stat_tr.appendChild(stat_td);
  850. stat_td = document.createElement('td');
  851. stat_td.setAttribute('class', 'value');
  852. span = document.createElement('span');
  853. span.setAttribute('class', 'stat');
  854. text = document.createTextNode(option.stats.resistance + "%");
  855. span.appendChild(text);
  856. stat_td.appendChild(span);
  857. span = document.createElement('span');
  858. if (Number(option.stats.resistance) > Number(current_stats["resistance"])){
  859. span.setAttribute('class', 'variation increment');
  860. text = document.createTextNode(option.stats.resistance - current_stats["resistance"]);
  861. }
  862. else if (Number(option.stats.resistance) < Number(current_stats["resistance"])){
  863. span.setAttribute('class', 'variation decrement');
  864. text = document.createTextNode(current_stats["resistance"] - option.stats.resistance);
  865. }
  866. else{
  867. span.setAttribute('class', 'variation');
  868. text = document.createTextNode(" ");
  869. }
  870. span.appendChild(text);
  871. stat_td.appendChild(span);
  872. stat_tr.appendChild(stat_td);
  873. stat_table.appendChild(stat_tr);
  874. // ehp
  875. stat_tr = document.createElement('tr');
  876. stat_td = document.createElement('td');
  877. stat_td.setAttribute('class', 'label');
  878. text = document.createTextNode('EHP');
  879. stat_td.appendChild(text);
  880. stat_tr.appendChild(stat_td);
  881. stat_td = document.createElement('td');
  882. stat_td.setAttribute('class', 'value');
  883. span = document.createElement('span');
  884. span.setAttribute('class', 'stat');
  885. text = document.createTextNode(option.stats.ehp + " ");
  886. span.appendChild(text);
  887. stat_td.appendChild(span);
  888. span = document.createElement('span');
  889. if (Number(option.stats.ehp) > Number(current_stats["ehp"])){
  890. span.setAttribute('class', 'variation increment');
  891. text = document.createTextNode(option.stats.ehp - current_stats["ehp"]);
  892. }
  893. else if (Number(option.stats.ehp) < Number(current_stats["ehp"])){
  894. span.setAttribute('class', 'variation decrement');
  895. text = document.createTextNode(current_stats["ehp"] - option.stats.ehp);
  896. }
  897. else{
  898. span.setAttribute('class', 'variation');
  899. text = document.createTextNode(" ");
  900. }
  901. span.appendChild(text);
  902. stat_td.appendChild(span);
  903. stat_tr.appendChild(stat_td);
  904. stat_table.appendChild(stat_tr);
  905. // dmg
  906. stat_tr = document.createElement('tr');
  907. stat_td = document.createElement('td');
  908. stat_td.setAttribute('class', 'label');
  909. text = document.createTextNode('DMG');
  910. stat_td.appendChild(text);
  911. stat_tr.appendChild(stat_td);
  912. stat_td = document.createElement('td');
  913. stat_td.setAttribute('class', 'value');
  914. span = document.createElement('span');
  915. span.setAttribute('class', 'stat');
  916. text = document.createTextNode(option.stats.dmg + " ");
  917. span.appendChild(text);
  918. stat_td.appendChild(span);
  919. span = document.createElement('span');
  920. if (Number(option.stats.dmg) > Number(current_stats["dmg"])){
  921. span.setAttribute('class', 'variation increment');
  922. text = document.createTextNode(option.stats.dmg - current_stats["dmg"]);
  923. }
  924. else if (Number(option.stats.dmg) < Number(current_stats["dmg"])){
  925. span.setAttribute('class', 'variation decrement');
  926. text = document.createTextNode(current_stats["dmg"] - option.stats.dmg);
  927. }
  928. else{
  929. span.setAttribute('class', 'variation');
  930. text = document.createTextNode(" ");
  931. }
  932. span.appendChild(text);
  933. stat_td.appendChild(span);
  934. stat_tr.appendChild(stat_td);
  935. stat_table.appendChild(stat_tr);
  936. // Add to the main table
  937. td.appendChild(stat_table);
  938. tr.appendChild(td);
  939. // Runes td
  940. td = document.createElement('td');
  941. td.setAttribute('class', 'runes');
  942. td.innerHTML += option.runes[6 - 1].html;
  943. td.innerHTML += option.runes[1 - 1].html;
  944. td.innerHTML += option.runes[2 - 1].html;
  945. td.innerHTML += "<br/>";
  946. td.innerHTML += option.runes[5 - 1].html;
  947. td.innerHTML += option.runes[4 - 1].html;
  948. td.innerHTML += option.runes[3 - 1].html;
  949. // Add the table
  950. tr.appendChild(td);
  951. container.appendChild(tr);
  952. // Make the section visible
  953. document.getElementById('results').style.display = 'block';
  954. }
  955. time = ((+ new Date()) - timestamp) / 1000;
  956. log('Done in ' + time + ' seconds');
  957. enableNewSearch(true);
  958. }
  959. /**
  960. * Function to sort rune combinations based on their score.
  961. *
  962. * @param a One combination.
  963. * @param b Other combination.
  964. * @return Numeric index for sorting.
  965. */
  966. function sortOptions(a, b) {
  967. return b["score"] - a["score"];
  968. }
  969. /**
  970. * Displays a pop-up message.
  971. *
  972. * @param title Message title.
  973. * @param text Message content.
  974. */
  975. function showMessage(title, text){
  976. document.getElementById('message_title').innerHTML = title;
  977. document.getElementById('message_text').innerHTML = text;
  978. document.getElementById('message_container').style.display = 'block';
  979. }
  980. /**
  981. * Closes the message pop-up.
  982. */
  983. function closeMessage(){
  984. document.getElementById('message_container').style.display = 'none';
  985. }
  986. /**
  987. * DEBUG FUNCTION
  988. *
  989. * Sets filters to a known value for debugging.
  990. */
  991. function debug(){
  992. document.getElementById('set_1').selectedIndex = 0;
  993. document.getElementById('set_2').selectedIndex = 0;
  994. document.getElementById('set_3').selectedIndex = 1;
  995. removeFilter('attack');
  996. removeFilter('defense');
  997. removeFilter('speed');
  998. removeFilter('crit_rate');
  999. removeFilter('crit_damage');
  1000. removeFilter('accuracy');
  1001. removeFilter('resistance');
  1002. removeFilter('ehp');
  1003. removeFilter('dmg');
  1004. document.getElementById('lbl_min_hp').value = 13500;
  1005. updateMinValue('hp', document.getElementById('lbl_min_hp'));
  1006. }
  1007. </script>
  1008. </head>
  1009. <body>
  1010. <?php
  1011. include __DIR__ . "/inc/header.php";
  1012. ?>
  1013. <aside>
  1014. <h2>
  1015. Optimize <?=$page->unit->title?>
  1016. </h2>
  1017. <div id='monster_info'>
  1018. <div class='monster_panel'>
  1019. <?=HTML::unit_panel($page->unit)?>
  1020. </div>
  1021. <?php
  1022. if ($page->unit->experience_level != 0){
  1023. $exp_pct = ceil($page->unit->exp_gained * 100 / $page->unit->experience_level);
  1024. $exp_txt = $page->unit->exp_gained . " / " . $page->unit->experience_level;
  1025. }
  1026. else{
  1027. $exp_pct = 100;
  1028. $exp_txt = "MAX";
  1029. }
  1030. $now = time();
  1031. //$datediff = $now - $page->unit->create_time->getTimestamp();
  1032. $datediff = $now - strtotime($page->unit->create_time->format('Y-m-d H:i:s'));
  1033. $datediff = floor($datediff / (60 * 60 * 24));
  1034. ?>
  1035. <div id='monster_details'>
  1036. <?php
  1037. if (sizeof($page->unit->teams) > 0){
  1038. ?>
  1039. <div id='teams'>
  1040. <h4>
  1041. Teams:
  1042. </h4>
  1043. <ul>
  1044. <?php
  1045. foreach($page->unit->teams as $team){
  1046. ?>
  1047. <li>
  1048. <a target='blank' href='/<?=$UID?>/teams/<?=$team->id?>'>
  1049. <?=$team->name?>
  1050. </a>
  1051. </li>
  1052. <?php
  1053. }
  1054. ?>
  1055. </ul>
  1056. </div>
  1057. <?php
  1058. }
  1059. ?>
  1060. </div>
  1061. </div>
  1062. </aside>
  1063. <main>
  1064. <section id='monster' class='content'>
  1065. <h2>
  1066. Optimize <?=$page->unit->title?>
  1067. </h2>
  1068. <article id='profile'>
  1069. <table id='stats'>
  1070. <tr>
  1071. <th>
  1072. Stats
  1073. </th>
  1074. <th>
  1075. Base
  1076. </th>
  1077. <th>
  1078. Runes
  1079. </th>
  1080. <th>
  1081. Artifacts
  1082. </th>
  1083. <th>
  1084. Buildings
  1085. </th>
  1086. <th>
  1087. Total
  1088. </th>
  1089. </tr>
  1090. <tr>
  1091. <th>
  1092. ATK
  1093. </th>
  1094. <td class='base'>
  1095. <?=$page->unit->attack?>
  1096. <span class='percent'>&nbsp;</span>
  1097. </td>
  1098. <td class='extra'>
  1099. +<?=$page->unit->rune_attack?>
  1100. <span class='percent'>&nbsp;</span>
  1101. </td>
  1102. <td class='extra'>
  1103. +<?=$page->unit->artifact_attack?>
  1104. <span class='percent'>&nbsp;</span>
  1105. </td>
  1106. <td class='extra'>
  1107. +<?=$page->unit->building_attack?>
  1108. <span class='percent'>&nbsp;</span>
  1109. </td>
  1110. <td class='total'>
  1111. <?=$page->unit->total_attack?>
  1112. <span class='percent'>&nbsp;</span>
  1113. </td>
  1114. </tr>
  1115. <tr>
  1116. <th>
  1117. DEF
  1118. </th>
  1119. <td class='base'>
  1120. <?=$page->unit->defense?>
  1121. <span class='percent'>&nbsp;</span>
  1122. </td>
  1123. <td class='extra'>
  1124. +<?=$page->unit->rune_defense?>
  1125. <span class='percent'>&nbsp;</span>
  1126. </td>
  1127. <td class='extra'>
  1128. +<?=$page->unit->artifact_defense?>
  1129. <span class='percent'>&nbsp;</span>
  1130. </td>
  1131. <td class='extra'>
  1132. +<?=$page->unit->building_defense?>
  1133. <span class='percent'>&nbsp;</span>
  1134. </td>
  1135. <td class='total'>
  1136. <?=$page->unit->total_defense?>
  1137. <span class='percent'>&nbsp;</span>
  1138. </td>
  1139. </tr>
  1140. <tr>
  1141. <th>
  1142. HP
  1143. </th>
  1144. <td class='base'>
  1145. <?=$page->unit->hp?>
  1146. <span class='percent'>&nbsp;</span>
  1147. </td>
  1148. <td class='extra'>
  1149. +<?=$page->unit->rune_hp?>
  1150. <span class='percent'>&nbsp;</span>
  1151. </td>
  1152. <td class='extra'>
  1153. +<?=$page->unit->artifact_hp?>
  1154. <span class='percent'>&nbsp;</span>
  1155. </td>
  1156. <td class='extra'>
  1157. +<?=$page->unit->building_hp?>
  1158. <span class='percent'>&nbsp;</span>
  1159. </td>
  1160. <td class='total'>
  1161. <?=$page->unit->total_hp?>
  1162. <span class='percent'>&nbsp;</span>
  1163. </td>
  1164. </tr>
  1165. <tr>
  1166. <th>
  1167. SPD
  1168. </th>
  1169. <td class='base'>
  1170. <?=$page->unit->speed?>
  1171. <span class='percent'>&nbsp;</span>
  1172. </td>
  1173. <td class='extra'>
  1174. +<?=$page->unit->rune_speed?>
  1175. <span class='percent'>&nbsp;</span>
  1176. </td>
  1177. <td class='extra'>
  1178. +<?=$page->unit->artifact_speed?>
  1179. <span class='percent'>&nbsp;</span>
  1180. </td>
  1181. <td class='extra'>
  1182. +<?=$page->unit->building_speed?>
  1183. <span class='percent'>&nbsp;</span>
  1184. </td>
  1185. <td class='total'>
  1186. <?=$page->unit->total_speed?>
  1187. <span class='percent'>&nbsp;</span>
  1188. </td>
  1189. </tr>
  1190. <tr>
  1191. <th>
  1192. CRR
  1193. </th>
  1194. <td class='base'>
  1195. <?=$page->unit->crit_rate?>
  1196. <span class='percent'>%</span>
  1197. </td>
  1198. <td class='extra'>
  1199. +<?=$page->unit->rune_crit_rate?>
  1200. <span class='percent'>%</span>
  1201. </td>
  1202. <td class='extra'>
  1203. +<?=$page->unit->artifact_crit_rate?>
  1204. <span class='percent'>%</span>
  1205. </td>
  1206. <td class='extra'>
  1207. +<?=$page->unit->building_crit_rate?>
  1208. <span class='percent'>%</span>
  1209. </td>
  1210. <td class='total'>
  1211. <?=$page->unit->total_crit_rate?>
  1212. <span class='percent'>%</span>
  1213. </td>
  1214. </tr>
  1215. <tr>
  1216. <th>
  1217. CRD
  1218. </th>
  1219. <td class='base'>
  1220. <?=$page->unit->crit_damage?>
  1221. <span class='percent'>%</span>
  1222. </td>
  1223. <td class='extra'>
  1224. +<?=$page->unit->rune_crit_damage?>
  1225. <span class='percent'>%</span>
  1226. </td>
  1227. <td class='extra'>
  1228. +<?=$page->unit->artifact_crit_damage?>
  1229. <span class='percent'>%</span>
  1230. </td>
  1231. <td class='extra'>
  1232. +<?=$page->unit->building_crit_damage?>
  1233. <span class='percent'>%</span>
  1234. </td>
  1235. <td class='total'>
  1236. <?=$page->unit->total_crit_damage?>
  1237. <span class='percent'>%</span>
  1238. </td>
  1239. </tr>
  1240. <tr>
  1241. <th>
  1242. ACC
  1243. </th>
  1244. <td class='base'>
  1245. <?=$page->unit->accuracy?>
  1246. <span class='percent'>%</span>
  1247. </td>
  1248. <td class='extra'>
  1249. +<?=$page->unit->rune_accuracy?>
  1250. <span class='percent'>%</span>
  1251. </td>
  1252. <td class='extra'>
  1253. +<?=$page->unit->artifact_accuracy?>
  1254. <span class='percent'>%</span>
  1255. </td>
  1256. <td class='extra'>
  1257. +<?=$page->unit->building_accuracy?>
  1258. <span class='percent'>%</span>
  1259. </td>
  1260. <td class='total'>
  1261. <?=$page->unit->total_accuracy?>
  1262. <span class='percent'>%</span>
  1263. </td>
  1264. </tr>
  1265. <tr>
  1266. <th>
  1267. RES
  1268. </th>
  1269. <td class='base'>
  1270. <?=$page->unit->resistance?>
  1271. <span class='percent'>%</span>
  1272. </td>
  1273. <td class='extra'>
  1274. +<?=$page->unit->rune_resistance?>
  1275. <span class='percent'>%</span>
  1276. </td>
  1277. <td class='extra'>
  1278. +<?=$page->unit->artifact_resistance?>
  1279. <span class='percent'>%</span>
  1280. </td>
  1281. <td class='extra'>
  1282. +<?=$page->unit->building_resistance?>
  1283. <span class='percent'>%</span>
  1284. </td>
  1285. <td class='total'>
  1286. <?=$page->unit->total_resistance?>
  1287. <span class='percent'>%</span>
  1288. </td>
  1289. </tr>
  1290. <tr>
  1291. <th colspan='5'>
  1292. Effective HP
  1293. </th>
  1294. <td class='total'>
  1295. <?=$page->unit->effective_hp?>
  1296. <span class='percent'>&nbsp;</span>
  1297. </td>
  1298. </tr>
  1299. <tr>
  1300. <th colspan='5'>
  1301. Effective DMG
  1302. </th>
  1303. <td class='total'>
  1304. <?=$page->unit->effective_dmg?>
  1305. <span class='percent'>&nbsp;</span>
  1306. </td>
  1307. </tr>
  1308. </table>
  1309. <div id='artifacts'>
  1310. <?=HTML::artifact_table($page->unit->artifact_type)?>
  1311. <?=HTML::artifact_table($page->unit->artifact_element)?>
  1312. </div>
  1313. </article> <!-- #profile -->
  1314. <article id='current_runes'>
  1315. <?php
  1316. $show_list = [6, 1, 2, 5, 4, 3];
  1317. //foreach ($page->unit->rune as $rune){
  1318. foreach ($show_list as $i){
  1319. $rune = $page->unit->rune[$i - 1];
  1320. ?>
  1321. <?=HTML::rune_table($rune)?>
  1322. <?php
  1323. if ($i == 2){
  1324. ?>
  1325. <br/>
  1326. <?php
  1327. }
  1328. }
  1329. ?>
  1330. </article>
  1331. </section> <!-- runes -->
  1332. <section id='parameters' class='content'>
  1333. <h2>
  1334. Optimization parameters
  1335. </h2>
  1336. <article>
  1337. <table id='parameters'>
  1338. <tr>
  1339. <td class='name'>
  1340. Rune sets
  1341. </td>
  1342. <td class='value'>
  1343. <?php
  1344. $reflect = new ReflectionClass("RUNE_SET_ID");
  1345. ?>
  1346. <select id='set_1'>
  1347. <?php
  1348. foreach($reflect->getConstants() as $name => $id){
  1349. $selected = "";
  1350. if ($id == $sets[0]){
  1351. $selected = "selected='selected'";
  1352. }
  1353. ?>
  1354. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  1355. <?php
  1356. }
  1357. ?>
  1358. </select>
  1359. <select id='set_2'>
  1360. <?php
  1361. foreach($reflect->getConstants() as $name => $id){
  1362. $selected = "";
  1363. if ($id == $sets[1]){
  1364. $selected = "selected='selected'";
  1365. }
  1366. ?>
  1367. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  1368. <?php
  1369. }
  1370. ?>
  1371. </select>
  1372. <select id='set_3'>
  1373. <option value='' <?=$selected?>></option>
  1374. <?php
  1375. foreach($reflect->getConstants() as $name => $id){
  1376. $selected = "";
  1377. if ($id == $sets[2]){
  1378. $selected = "selected='selected'";
  1379. }
  1380. ?>
  1381. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  1382. <?php
  1383. }
  1384. ?>
  1385. </select>
  1386. </td>
  1387. <td class='empty'>
  1388. </td>
  1389. <td class='name'>
  1390. Min HP
  1391. </td>
  1392. <td class='value'>
  1393. <input id='min_hp' type='range' value='<?=$page->unit->total_hp?>' min='<?=$page->unit->hp?>' max='50000' oninput='updateMinValue("hp", this);'>
  1394. <input type='number' id='lbl_min_hp' value='<?=$page->unit->total_hp?>' min='<?=$page->unit->hp?>' max='50000' onChange='updateMinValue("hp", this);'></input></input><span class='slider_percent'> </span>
  1395. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("hp");'>
  1396. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1397. </a>
  1398. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("hp");'>
  1399. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1400. </a>
  1401. </td>
  1402. </tr>
  1403. <tr>
  1404. <td class='name'>
  1405. Even slots
  1406. </td>
  1407. <td class='value'>
  1408. <select id='slot_2'>
  1409. <option value='<?=RUNE_STAT_ID::HP_P?>' <?=($mains[0] == RUNE_STAT_ID::HP_P) ? ("selected='selected'") : ("");?>>HP%</option>
  1410. <option value='<?=RUNE_STAT_ID::ATK_P?>' <?=($mains[0] == RUNE_STAT_ID::ATK_P) ? ("selected='selected'") : ("");?>>ATK%</option>
  1411. <option value='<?=RUNE_STAT_ID::DEF_P?>' <?=($mains[0] == RUNE_STAT_ID::DEF_P) ? ("selected='selected'") : ("");?>>DEF%</option>
  1412. <option value='<?=RUNE_STAT_ID::SPD?>' <?=($mains[0] == RUNE_STAT_ID::SPD) ? ("selected='selected'") : ("");?>>SPD</option>
  1413. </select>
  1414. <select id='slot_4'>
  1415. <option value='<?=RUNE_STAT_ID::HP_P?>' <?=($mains[1] == RUNE_STAT_ID::HP_P) ? ("selected='selected'") : ("");?>>HP%</option>
  1416. <option value='<?=RUNE_STAT_ID::ATK_P?>' <?=($mains[1] == RUNE_STAT_ID::ATK_P) ? ("selected='selected'") : ("");?>>ATK%</option>
  1417. <option value='<?=RUNE_STAT_ID::DEF_P?>' <?=($mains[1] == RUNE_STAT_ID::DEF_P) ? ("selected='selected'") : ("");?>>DEF%</option>
  1418. <option value='<?=RUNE_STAT_ID::CRR?>' <?=($mains[1] == RUNE_STAT_ID::CRR) ? ("selected='selected'") : ("");?>>CRR</option>
  1419. <option value='<?=RUNE_STAT_ID::CRR?>' <?=($mains[1] == RUNE_STAT_ID::CRD) ? ("selected='selected'") : ("");?>>CRD</option>
  1420. </select>
  1421. <select id='slot_6'>
  1422. <option value='<?=RUNE_STAT_ID::HP_P?>' <?=($mains[2] == RUNE_STAT_ID::HP_P) ? ("selected='selected'") : ("");?>>HP%</option>
  1423. <option value='<?=RUNE_STAT_ID::ATK_P?>' <?=($mains[2] == RUNE_STAT_ID::ATK_P) ? ("selected='selected'") : ("");?>>ATK%</option>
  1424. <option value='<?=RUNE_STAT_ID::DEF_P?>' <?=($mains[2] == RUNE_STAT_ID::DEF_P) ? ("selected='selected'") : ("");?>>DEF%</option>
  1425. <option value='<?=RUNE_STAT_ID::ACC?>' <?=($mains[2] == RUNE_STAT_ID::ACC) ? ("selected='selected'") : ("");?>>ACC</option>
  1426. <option value='<?=RUNE_STAT_ID::RES?>' <?=($mains[2] == RUNE_STAT_ID::RES) ? ("selected='selected'") : ("");?>>RES</option>
  1427. </select>
  1428. </td>
  1429. <td class='empty'>
  1430. </td>
  1431. <td class='name'>
  1432. Min ATK
  1433. </td>
  1434. <td class='value'>
  1435. <input id='min_attack' type='range' value='<?=$page->unit->total_attack?>' min='<?=$page->unit->attack?>' max='4000' oninput='updateMinValue("attack", this);'>
  1436. <input type='number' id='lbl_min_attack' value='<?=$page->unit->total_attack?>' min='<?=$page->unit->attack?>' max='4000' onChange='updateMinValue("attack", this);'></input><span class='slider_percent'> </span>
  1437. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("attack");'>
  1438. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1439. </a>
  1440. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("attack");'>
  1441. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1442. </a>
  1443. </td>
  1444. </tr>
  1445. <tr>
  1446. <td class='name'>
  1447. Use runes from
  1448. </td>
  1449. <td class='value'>
  1450. <select id='rune_source'>
  1451. <option value='0'>Storage only</option>
  1452. <option value='1'>Units in no teams</option>
  1453. <option value='2'>Units in teams with 0 score</option>
  1454. <option value='3'>Units with lower overall score</option>
  1455. <option value='4'>All runes</option>
  1456. </select>
  1457. </td>
  1458. <td class='empty'>
  1459. </td>
  1460. <td class='name'>
  1461. Min DEF
  1462. </td>
  1463. <td class='value'>
  1464. <input id='min_defense' type='range' value='<?=$page->unit->total_defense?>' min='<?=$page->unit->defense?>' max='4000' oninput='updateMinValue("defense", this);'>
  1465. <input type='number' id='lbl_min_defense' value='<?=$page->unit->total_defense?>' min='<?=$page->unit->defense?>' max='4000' onChange='updateMinValue("defense", this);'></input><span class='slider_percent'> </span>
  1466. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("defense");'>
  1467. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1468. </a>
  1469. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("defense");'>
  1470. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1471. </a>
  1472. </td>
  1473. </tr>
  1474. <tr>
  1475. <td class='name'>
  1476. Tune optimizer for
  1477. </td>
  1478. <td class='value'>
  1479. <select id='tuning'>
  1480. <option value='0'>Rune current levels</option>
  1481. <option value='1'>+12</option>
  1482. <option value='2'>2/4/6 +15, 1/3/5 + 12</option>
  1483. <option value='3'>+15</option>
  1484. </select>
  1485. </td>
  1486. <td class='empty'>
  1487. </td>
  1488. <td class='name'>
  1489. Min SPD
  1490. </td>
  1491. <td class='value'>
  1492. <input id='min_speed' type='range' value='<?=$page->unit->total_speed?>' min='<?=$page->unit->speed?>' max='400' oninput='updateMinValue("speed", this);'>
  1493. <input type='number' id='lbl_min_speed' value='<?=$page->unit->total_speed?>' min='<?=$page->unit->speed?>' max='400' onChange='updateMinValue("speed", this);'></input><span class='slider_percent'> </span>
  1494. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("speed");'>
  1495. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1496. </a>
  1497. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("speed");'>
  1498. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1499. </a>
  1500. </td>
  1501. </tr>
  1502. <tr>
  1503. <td class='empty'>
  1504. Max. combinations
  1505. </td>
  1506. <td class='empty'>
  1507. <input id='limit' type='number' value='10' max='100' min='1'>
  1508. </td>
  1509. <td class='empty'>
  1510. </td>
  1511. <td class='name'>
  1512. Min CRR
  1513. </td>
  1514. <td class='value'>
  1515. <input id='min_crit_rate' type='range' value='<?=$page->unit->total_crit_rate?>' min='<?=$page->unit->crit_rate?>' max='100' oninput='updateMinValue("crit_rate", this);'>
  1516. <input type='number' id='lbl_min_crit_rate' value='<?=$page->unit->total_crit_rate?>' min='<?=$page->unit->crit_rate?>' max='100' onChange='updateMinValue("crit_rate", this);'></input><span class='slider_percent'>%</span>
  1517. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("crit_rate");'>
  1518. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1519. </a>
  1520. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("crit_rate");'>
  1521. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1522. </a>
  1523. </td>
  1524. </tr>
  1525. <tr>
  1526. <td id='log' colspan='2' rowspan='4'>
  1527. <div id='log_title'>
  1528. LOG
  1529. <span id='log_clear' onClick='clearLog();'>
  1530. clear
  1531. </span>
  1532. </div>
  1533. <div id='log_window'>
  1534. </div>
  1535. </td>
  1536. <td class='empty'>
  1537. </td>
  1538. <td class='name'>
  1539. Min CRD
  1540. </td>
  1541. <td class='value'>
  1542. <input id='min_crit_damage' type='range' value='<?=$page->unit->total_crit_damage?>' min='<?=$page->unit->crit_damage?>' max='400' oninput='updateMinValue("crit_damage", this);'>
  1543. <input type='number' id='lbl_min_crit_damage' value='<?=$page->unit->total_crit_damage?>' min='<?=$page->unit->crit_damage?>' max='400' onChange='updateMinValue("crit_damage", this);'></input><span class='slider_percent'>%</span>
  1544. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("crit_damage");'>
  1545. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1546. </a>
  1547. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("crit_damage");'>
  1548. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1549. </a>
  1550. </td>
  1551. </tr>
  1552. <tr>
  1553. <!--<td class='empty'>
  1554. </td>-->
  1555. <!--<td class='empty'>
  1556. </td>-->
  1557. <td class='empty'>
  1558. </td>
  1559. <td class='name'>
  1560. Min ACC
  1561. </td>
  1562. <td class='value'>
  1563. <input id='min_accuracy' type='range' value='<?=$page->unit->total_accuracy?>' min='<?=$page->unit->accuracy?>' max='85' oninput='updateMinValue("accuracy", this);'>
  1564. <input type='number' id='lbl_min_accuracy' value='<?=$page->unit->total_accuracy?>' min='<?=$page->unit->accuracy?>' max='85' onChange='updateMinValue("accuracy", this);'></input><span class='slider_percent'>%</span>
  1565. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("accuracy");'>
  1566. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1567. </a>
  1568. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("accuracy");'>
  1569. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1570. </a>
  1571. </td>
  1572. </tr>
  1573. <tr>
  1574. <!--<td class='empty'>
  1575. </td>-->
  1576. <!--<td class='empty'>
  1577. </td>-->
  1578. <td class='empty'>
  1579. </td>
  1580. <td class='name'>
  1581. Min RES
  1582. </td>
  1583. <td class='value'>
  1584. <input id='min_resistance' type='range' value='<?=$page->unit->total_resistance?>' min='<?=$page->unit->resistance?>' max='85' oninput='updateMinValue("resistance", this);'>
  1585. <input type='number' id='lbl_min_resistance' value='<?=$page->unit->total_resistance?>' min='<?=$page->unit->resistance?>' max='85' onChange='updateMinValue("resistance", this);'></input><span class='slider_percent'>%</span>
  1586. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("resistance");'>
  1587. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1588. </a>
  1589. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("resistance");'>
  1590. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1591. </a>
  1592. </td>
  1593. </tr>
  1594. <tr>
  1595. <!--<td class='empty'>
  1596. </td>-->
  1597. <!--<td class='empty'>
  1598. </td>-->
  1599. <td class='empty'>
  1600. </td>
  1601. <td class='name'>
  1602. Min EHP
  1603. </td>
  1604. <td class='value'>
  1605. <input id='min_ehp' type='range' value='<?=$page->unit->effective_hp?>' min='0' max='200000' oninput='updateMinValue("ehp", this);'>
  1606. <input type='number' id='lbl_min_ehp' value='<?=$page->unit->effective_hp?>' min='0' max='200000' onChange='updateMinValue("ehp", this);'></input><span class='slider_percent'> </span>
  1607. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("ehp");'>
  1608. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1609. </a>
  1610. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("ehp");'>
  1611. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1612. </a>
  1613. </td>
  1614. </tr>
  1615. <tr>
  1616. <td class='action'>
  1617. <input id='apply' type='button' value='Apply' onClick='apply();'/>
  1618. <!--<input id='apply' type='button' value='DEBUG' onClick='debug();'/>-->
  1619. </td>
  1620. <td class='empty'>
  1621. <img id='wait' src='<?=URL::IMG["ICON"] . "wait.gif";?>'>
  1622. </td>
  1623. <td class='empty'>
  1624. </td>
  1625. <td class='name'>
  1626. Min DMG
  1627. </td>
  1628. <td class='value'>
  1629. <input id='min_dmg' type='range' value='<?=$page->unit->effective_dmg?>' min='0' max='7000' oninput='updateMinValue("dmg", this);'>
  1630. <input type='number' id='lbl_min_dmg' value='<?=$page->unit->effective_dmg?>' min='0' max='7000' onChange='updateMinValue("dmg", this);'></input><span class='slider_percent'> </span>
  1631. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("dmg");'>
  1632. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1633. </a>
  1634. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("dmg");'>
  1635. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1636. </a>
  1637. </td>
  1638. </tr>
  1639. </table>
  1640. </article>
  1641. </section>
  1642. <section id='results' class='content'>
  1643. <h2>
  1644. Optimization results
  1645. </h2>
  1646. <article>
  1647. <table id='table_optimizations'>
  1648. <tbody id='optimizations'>
  1649. </tbody>
  1650. </table>
  1651. </article>
  1652. </section>
  1653. </main>
  1654. <div id='message_container'>
  1655. <section class='content'>
  1656. <h2 id='message_title'>
  1657. Message
  1658. </h2>
  1659. <article>
  1660. <p id='message_text'>
  1661. Message Text
  1662. </p>
  1663. </article>
  1664. <input type='button' value='OK' id='message_button' onclick='closeMessage();'/>
  1665. </section>
  1666. </div>
  1667. <?php
  1668. include __DIR__ . "/inc/footer.php";
  1669. ?>
  1670. </body>
  1671. </html>