optimizer_unit.php 95 KB

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