optimizer_unit.php 88 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769
  1. <?php
  2. /**
  3. * Monster view.
  4. *
  5. * Contains the view layout and some code to present the data.
  6. *
  7. * @category View
  8. * @var Monster_Page $page The page model.
  9. * @var 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. $now = time();
  1023. //$datediff = $now - $page->unit->create_time->getTimestamp();
  1024. $datediff = $now - strtotime($page->unit->create_time->format('Y-m-d H:i:s'));
  1025. $datediff = floor($datediff / (60 * 60 * 24));
  1026. ?>
  1027. <div id='monster_details'>
  1028. <?php
  1029. if (sizeof($page->unit->teams) > 0){
  1030. ?>
  1031. <div id='teams'>
  1032. <h4>
  1033. Teams:
  1034. </h4>
  1035. <ul>
  1036. <?php
  1037. foreach($page->unit->teams as $team){
  1038. ?>
  1039. <li>
  1040. <a target='blank' href='/<?=$UID?>/teams/<?=$team->id?>'>
  1041. <?=$team->name?>
  1042. </a>
  1043. </li>
  1044. <?php
  1045. }
  1046. ?>
  1047. </ul>
  1048. </div>
  1049. <?php
  1050. }
  1051. ?>
  1052. </div>
  1053. </div>
  1054. </aside>
  1055. <main>
  1056. <section id='monster' class='content'>
  1057. <h2>
  1058. Optimize <?=$page->unit->title?>
  1059. </h2>
  1060. <article id='profile'>
  1061. <table id='stats'>
  1062. <tr>
  1063. <th>
  1064. Stats
  1065. </th>
  1066. <th>
  1067. Base
  1068. </th>
  1069. <th>
  1070. Runes
  1071. </th>
  1072. <th>
  1073. Artifacts
  1074. </th>
  1075. <th>
  1076. Buildings
  1077. </th>
  1078. <th>
  1079. Total
  1080. </th>
  1081. </tr>
  1082. <tr>
  1083. <th>
  1084. ATK
  1085. </th>
  1086. <td class='base'>
  1087. <?=$page->unit->attack?>
  1088. <span class='percent'>&nbsp;</span>
  1089. </td>
  1090. <td class='extra'>
  1091. +<?=$page->unit->rune_attack?>
  1092. <span class='percent'>&nbsp;</span>
  1093. </td>
  1094. <td class='extra'>
  1095. +<?=$page->unit->artifact_attack?>
  1096. <span class='percent'>&nbsp;</span>
  1097. </td>
  1098. <td class='extra'>
  1099. +<?=$page->unit->building_attack?>
  1100. <span class='percent'>&nbsp;</span>
  1101. </td>
  1102. <td class='total'>
  1103. <?=$page->unit->total_attack?>
  1104. <span class='percent'>&nbsp;</span>
  1105. </td>
  1106. </tr>
  1107. <tr>
  1108. <th>
  1109. DEF
  1110. </th>
  1111. <td class='base'>
  1112. <?=$page->unit->defense?>
  1113. <span class='percent'>&nbsp;</span>
  1114. </td>
  1115. <td class='extra'>
  1116. +<?=$page->unit->rune_defense?>
  1117. <span class='percent'>&nbsp;</span>
  1118. </td>
  1119. <td class='extra'>
  1120. +<?=$page->unit->artifact_defense?>
  1121. <span class='percent'>&nbsp;</span>
  1122. </td>
  1123. <td class='extra'>
  1124. +<?=$page->unit->building_defense?>
  1125. <span class='percent'>&nbsp;</span>
  1126. </td>
  1127. <td class='total'>
  1128. <?=$page->unit->total_defense?>
  1129. <span class='percent'>&nbsp;</span>
  1130. </td>
  1131. </tr>
  1132. <tr>
  1133. <th>
  1134. HP
  1135. </th>
  1136. <td class='base'>
  1137. <?=$page->unit->hp?>
  1138. <span class='percent'>&nbsp;</span>
  1139. </td>
  1140. <td class='extra'>
  1141. +<?=$page->unit->rune_hp?>
  1142. <span class='percent'>&nbsp;</span>
  1143. </td>
  1144. <td class='extra'>
  1145. +<?=$page->unit->artifact_hp?>
  1146. <span class='percent'>&nbsp;</span>
  1147. </td>
  1148. <td class='extra'>
  1149. +<?=$page->unit->building_hp?>
  1150. <span class='percent'>&nbsp;</span>
  1151. </td>
  1152. <td class='total'>
  1153. <?=$page->unit->total_hp?>
  1154. <span class='percent'>&nbsp;</span>
  1155. </td>
  1156. </tr>
  1157. <tr>
  1158. <th>
  1159. SPD
  1160. </th>
  1161. <td class='base'>
  1162. <?=$page->unit->speed?>
  1163. <span class='percent'>&nbsp;</span>
  1164. </td>
  1165. <td class='extra'>
  1166. +<?=$page->unit->rune_speed?>
  1167. <span class='percent'>&nbsp;</span>
  1168. </td>
  1169. <td class='extra'>
  1170. +<?=$page->unit->artifact_speed?>
  1171. <span class='percent'>&nbsp;</span>
  1172. </td>
  1173. <td class='extra'>
  1174. +<?=$page->unit->building_speed?>
  1175. <span class='percent'>&nbsp;</span>
  1176. </td>
  1177. <td class='total'>
  1178. <?=$page->unit->total_speed?>
  1179. <span class='percent'>&nbsp;</span>
  1180. </td>
  1181. </tr>
  1182. <tr>
  1183. <th>
  1184. CRR
  1185. </th>
  1186. <td class='base'>
  1187. <?=$page->unit->crit_rate?>
  1188. <span class='percent'>%</span>
  1189. </td>
  1190. <td class='extra'>
  1191. +<?=$page->unit->rune_crit_rate?>
  1192. <span class='percent'>%</span>
  1193. </td>
  1194. <td class='extra'>
  1195. +<?=$page->unit->artifact_crit_rate?>
  1196. <span class='percent'>%</span>
  1197. </td>
  1198. <td class='extra'>
  1199. +<?=$page->unit->building_crit_rate?>
  1200. <span class='percent'>%</span>
  1201. </td>
  1202. <td class='total'>
  1203. <?=$page->unit->total_crit_rate?>
  1204. <span class='percent'>%</span>
  1205. </td>
  1206. </tr>
  1207. <tr>
  1208. <th>
  1209. CRD
  1210. </th>
  1211. <td class='base'>
  1212. <?=$page->unit->crit_damage?>
  1213. <span class='percent'>%</span>
  1214. </td>
  1215. <td class='extra'>
  1216. +<?=$page->unit->rune_crit_damage?>
  1217. <span class='percent'>%</span>
  1218. </td>
  1219. <td class='extra'>
  1220. +<?=$page->unit->artifact_crit_damage?>
  1221. <span class='percent'>%</span>
  1222. </td>
  1223. <td class='extra'>
  1224. +<?=$page->unit->building_crit_damage?>
  1225. <span class='percent'>%</span>
  1226. </td>
  1227. <td class='total'>
  1228. <?=$page->unit->total_crit_damage?>
  1229. <span class='percent'>%</span>
  1230. </td>
  1231. </tr>
  1232. <tr>
  1233. <th>
  1234. ACC
  1235. </th>
  1236. <td class='base'>
  1237. <?=$page->unit->accuracy?>
  1238. <span class='percent'>%</span>
  1239. </td>
  1240. <td class='extra'>
  1241. +<?=$page->unit->rune_accuracy?>
  1242. <span class='percent'>%</span>
  1243. </td>
  1244. <td class='extra'>
  1245. +<?=$page->unit->artifact_accuracy?>
  1246. <span class='percent'>%</span>
  1247. </td>
  1248. <td class='extra'>
  1249. +<?=$page->unit->building_accuracy?>
  1250. <span class='percent'>%</span>
  1251. </td>
  1252. <td class='total'>
  1253. <?=$page->unit->total_accuracy?>
  1254. <span class='percent'>%</span>
  1255. </td>
  1256. </tr>
  1257. <tr>
  1258. <th>
  1259. RES
  1260. </th>
  1261. <td class='base'>
  1262. <?=$page->unit->resistance?>
  1263. <span class='percent'>%</span>
  1264. </td>
  1265. <td class='extra'>
  1266. +<?=$page->unit->rune_resistance?>
  1267. <span class='percent'>%</span>
  1268. </td>
  1269. <td class='extra'>
  1270. +<?=$page->unit->artifact_resistance?>
  1271. <span class='percent'>%</span>
  1272. </td>
  1273. <td class='extra'>
  1274. +<?=$page->unit->building_resistance?>
  1275. <span class='percent'>%</span>
  1276. </td>
  1277. <td class='total'>
  1278. <?=$page->unit->total_resistance?>
  1279. <span class='percent'>%</span>
  1280. </td>
  1281. </tr>
  1282. <tr>
  1283. <th colspan='5'>
  1284. Effective HP
  1285. </th>
  1286. <td class='total'>
  1287. <?=$page->unit->effective_hp?>
  1288. <span class='percent'>&nbsp;</span>
  1289. </td>
  1290. </tr>
  1291. <tr>
  1292. <th colspan='5'>
  1293. Effective DMG
  1294. </th>
  1295. <td class='total'>
  1296. <?=$page->unit->effective_dmg?>
  1297. <span class='percent'>&nbsp;</span>
  1298. </td>
  1299. </tr>
  1300. </table>
  1301. <div id='artifacts'>
  1302. <?=HTML::artifact_table($page->unit->artifact_type)?>
  1303. <?=HTML::artifact_table($page->unit->artifact_element)?>
  1304. </div>
  1305. </article> <!-- #profile -->
  1306. <article id='current_runes'>
  1307. <?php
  1308. $show_list = [6, 1, 2, 5, 4, 3];
  1309. //foreach ($page->unit->rune as $rune){
  1310. foreach ($show_list as $i){
  1311. $rune = $page->unit->rune[$i - 1];
  1312. ?>
  1313. <?=HTML::rune_table($rune)?>
  1314. <?php
  1315. if ($i == 2){
  1316. ?>
  1317. <br/>
  1318. <?php
  1319. }
  1320. }
  1321. ?>
  1322. </article>
  1323. </section> <!-- runes -->
  1324. <section id='parameters' class='content'>
  1325. <h2>
  1326. Optimization parameters
  1327. </h2>
  1328. <article>
  1329. <table id='parameters'>
  1330. <tr>
  1331. <td class='name'>
  1332. Rune sets
  1333. </td>
  1334. <td class='value'>
  1335. <?php
  1336. $reflect = new ReflectionClass("RUNE_SET_ID");
  1337. ?>
  1338. <select id='set_1'>
  1339. <?php
  1340. foreach($reflect->getConstants() as $name => $id){
  1341. $selected = "";
  1342. if ($id == $sets[0]){
  1343. $selected = "selected='selected'";
  1344. }
  1345. ?>
  1346. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  1347. <?php
  1348. }
  1349. ?>
  1350. </select>
  1351. <select id='set_2'>
  1352. <?php
  1353. foreach($reflect->getConstants() as $name => $id){
  1354. $selected = "";
  1355. if ($id == $sets[1]){
  1356. $selected = "selected='selected'";
  1357. }
  1358. ?>
  1359. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  1360. <?php
  1361. }
  1362. ?>
  1363. </select>
  1364. <select id='set_3'>
  1365. <option value='' <?=$selected?>></option>
  1366. <?php
  1367. foreach($reflect->getConstants() as $name => $id){
  1368. $selected = "";
  1369. if ($id == $sets[2]){
  1370. $selected = "selected='selected'";
  1371. }
  1372. ?>
  1373. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  1374. <?php
  1375. }
  1376. ?>
  1377. </select>
  1378. </td>
  1379. <td class='empty'>
  1380. </td>
  1381. <td class='name'>
  1382. Min HP
  1383. </td>
  1384. <td class='value'>
  1385. <input id='min_hp' type='range' value='<?=$page->unit->total_hp?>' min='<?=$page->unit->hp?>' max='50000' oninput='updateMinValue("hp", this);'>
  1386. <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>
  1387. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("hp");'>
  1388. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1389. </a>
  1390. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("hp");'>
  1391. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1392. </a>
  1393. </td>
  1394. </tr>
  1395. <tr>
  1396. <td class='name'>
  1397. Even slots
  1398. </td>
  1399. <td class='value'>
  1400. <select id='slot_2'>
  1401. <option value='<?=RUNE_STAT_ID::HP_P?>' <?=($mains[0] == RUNE_STAT_ID::HP_P) ? ("selected='selected'") : ("");?>>HP%</option>
  1402. <option value='<?=RUNE_STAT_ID::ATK_P?>' <?=($mains[0] == RUNE_STAT_ID::ATK_P) ? ("selected='selected'") : ("");?>>ATK%</option>
  1403. <option value='<?=RUNE_STAT_ID::DEF_P?>' <?=($mains[0] == RUNE_STAT_ID::DEF_P) ? ("selected='selected'") : ("");?>>DEF%</option>
  1404. <option value='<?=RUNE_STAT_ID::SPD?>' <?=($mains[0] == RUNE_STAT_ID::SPD) ? ("selected='selected'") : ("");?>>SPD</option>
  1405. </select>
  1406. <select id='slot_4'>
  1407. <option value='<?=RUNE_STAT_ID::HP_P?>' <?=($mains[1] == RUNE_STAT_ID::HP_P) ? ("selected='selected'") : ("");?>>HP%</option>
  1408. <option value='<?=RUNE_STAT_ID::ATK_P?>' <?=($mains[1] == RUNE_STAT_ID::ATK_P) ? ("selected='selected'") : ("");?>>ATK%</option>
  1409. <option value='<?=RUNE_STAT_ID::DEF_P?>' <?=($mains[1] == RUNE_STAT_ID::DEF_P) ? ("selected='selected'") : ("");?>>DEF%</option>
  1410. <option value='<?=RUNE_STAT_ID::CRR?>' <?=($mains[1] == RUNE_STAT_ID::CRR) ? ("selected='selected'") : ("");?>>CRR</option>
  1411. <option value='<?=RUNE_STAT_ID::CRR?>' <?=($mains[1] == RUNE_STAT_ID::CRD) ? ("selected='selected'") : ("");?>>CRD</option>
  1412. </select>
  1413. <select id='slot_6'>
  1414. <option value='<?=RUNE_STAT_ID::HP_P?>' <?=($mains[2] == RUNE_STAT_ID::HP_P) ? ("selected='selected'") : ("");?>>HP%</option>
  1415. <option value='<?=RUNE_STAT_ID::ATK_P?>' <?=($mains[2] == RUNE_STAT_ID::ATK_P) ? ("selected='selected'") : ("");?>>ATK%</option>
  1416. <option value='<?=RUNE_STAT_ID::DEF_P?>' <?=($mains[2] == RUNE_STAT_ID::DEF_P) ? ("selected='selected'") : ("");?>>DEF%</option>
  1417. <option value='<?=RUNE_STAT_ID::ACC?>' <?=($mains[2] == RUNE_STAT_ID::ACC) ? ("selected='selected'") : ("");?>>ACC</option>
  1418. <option value='<?=RUNE_STAT_ID::RES?>' <?=($mains[2] == RUNE_STAT_ID::RES) ? ("selected='selected'") : ("");?>>RES</option>
  1419. </select>
  1420. </td>
  1421. <td class='empty'>
  1422. </td>
  1423. <td class='name'>
  1424. Min ATK
  1425. </td>
  1426. <td class='value'>
  1427. <input id='min_attack' type='range' value='<?=$page->unit->total_attack?>' min='<?=$page->unit->attack?>' max='4000' oninput='updateMinValue("attack", this);'>
  1428. <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>
  1429. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("attack");'>
  1430. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1431. </a>
  1432. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("attack");'>
  1433. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1434. </a>
  1435. </td>
  1436. </tr>
  1437. <tr>
  1438. <td class='name'>
  1439. Use runes from
  1440. </td>
  1441. <td class='value'>
  1442. <select id='rune_source'>
  1443. <option value='0'>Storage only</option>
  1444. <option value='1'>Units in no teams</option>
  1445. <option value='2'>Units in teams with 0 score</option>
  1446. <option value='3'>Units with lower overall score</option>
  1447. <option value='4'>All runes</option>
  1448. </select>
  1449. </td>
  1450. <td class='empty'>
  1451. </td>
  1452. <td class='name'>
  1453. Min DEF
  1454. </td>
  1455. <td class='value'>
  1456. <input id='min_defense' type='range' value='<?=$page->unit->total_defense?>' min='<?=$page->unit->defense?>' max='4000' oninput='updateMinValue("defense", this);'>
  1457. <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>
  1458. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("defense");'>
  1459. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1460. </a>
  1461. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("defense");'>
  1462. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1463. </a>
  1464. </td>
  1465. </tr>
  1466. <tr>
  1467. <td class='name'>
  1468. Tune optimizer for
  1469. </td>
  1470. <td class='value'>
  1471. <select id='tuning'>
  1472. <option value='0'>Rune current levels</option>
  1473. <option value='1'>+12</option>
  1474. <option value='2'>2/4/6 +15, 1/3/5 + 12</option>
  1475. <option value='3'>+15</option>
  1476. </select>
  1477. </td>
  1478. <td class='empty'>
  1479. </td>
  1480. <td class='name'>
  1481. Min SPD
  1482. </td>
  1483. <td class='value'>
  1484. <input id='min_speed' type='range' value='<?=$page->unit->total_speed?>' min='<?=$page->unit->speed?>' max='400' oninput='updateMinValue("speed", this);'>
  1485. <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>
  1486. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("speed");'>
  1487. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1488. </a>
  1489. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("speed");'>
  1490. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1491. </a>
  1492. </td>
  1493. </tr>
  1494. <tr>
  1495. <td class='empty'>
  1496. Max. combinations
  1497. </td>
  1498. <td class='empty'>
  1499. <input id='limit' type='number' value='10' max='100' min='1'>
  1500. </td>
  1501. <td class='empty'>
  1502. </td>
  1503. <td class='name'>
  1504. Min CRR
  1505. </td>
  1506. <td class='value'>
  1507. <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);'>
  1508. <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>
  1509. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("crit_rate");'>
  1510. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1511. </a>
  1512. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("crit_rate");'>
  1513. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1514. </a>
  1515. </td>
  1516. </tr>
  1517. <tr>
  1518. <td id='log' colspan='2' rowspan='4'>
  1519. <div id='log_title'>
  1520. LOG
  1521. <span id='log_clear' onClick='clearLog();'>
  1522. clear
  1523. </span>
  1524. </div>
  1525. <div id='log_window'>
  1526. </div>
  1527. </td>
  1528. <td class='empty'>
  1529. </td>
  1530. <td class='name'>
  1531. Min CRD
  1532. </td>
  1533. <td class='value'>
  1534. <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);'>
  1535. <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>
  1536. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("crit_damage");'>
  1537. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1538. </a>
  1539. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("crit_damage");'>
  1540. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1541. </a>
  1542. </td>
  1543. </tr>
  1544. <tr>
  1545. <!--<td class='empty'>
  1546. </td>-->
  1547. <!--<td class='empty'>
  1548. </td>-->
  1549. <td class='empty'>
  1550. </td>
  1551. <td class='name'>
  1552. Min ACC
  1553. </td>
  1554. <td class='value'>
  1555. <input id='min_accuracy' type='range' value='<?=$page->unit->total_accuracy?>' min='<?=$page->unit->accuracy?>' max='85' oninput='updateMinValue("accuracy", this);'>
  1556. <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>
  1557. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("accuracy");'>
  1558. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1559. </a>
  1560. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("accuracy");'>
  1561. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1562. </a>
  1563. </td>
  1564. </tr>
  1565. <tr>
  1566. <!--<td class='empty'>
  1567. </td>-->
  1568. <!--<td class='empty'>
  1569. </td>-->
  1570. <td class='empty'>
  1571. </td>
  1572. <td class='name'>
  1573. Min RES
  1574. </td>
  1575. <td class='value'>
  1576. <input id='min_resistance' type='range' value='<?=$page->unit->total_resistance?>' min='<?=$page->unit->resistance?>' max='85' oninput='updateMinValue("resistance", this);'>
  1577. <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>
  1578. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("resistance");'>
  1579. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1580. </a>
  1581. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("resistance");'>
  1582. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1583. </a>
  1584. </td>
  1585. </tr>
  1586. <tr>
  1587. <!--<td class='empty'>
  1588. </td>-->
  1589. <!--<td class='empty'>
  1590. </td>-->
  1591. <td class='empty'>
  1592. </td>
  1593. <td class='name'>
  1594. Min EHP
  1595. </td>
  1596. <td class='value'>
  1597. <input id='min_ehp' type='range' value='<?=$page->unit->effective_hp?>' min='0' max='200000' oninput='updateMinValue("ehp", this);'>
  1598. <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>
  1599. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("ehp");'>
  1600. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1601. </a>
  1602. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("ehp");'>
  1603. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1604. </a>
  1605. </td>
  1606. </tr>
  1607. <tr>
  1608. <td class='action'>
  1609. <input id='apply' type='button' value='Apply' onClick='apply();'/>
  1610. <!--<input id='apply' type='button' value='DEBUG' onClick='debug();'/>-->
  1611. </td>
  1612. <td class='empty'>
  1613. <img id='wait' src='<?=URL::IMG["ICON"] . "wait.gif";?>'>
  1614. </td>
  1615. <td class='empty'>
  1616. </td>
  1617. <td class='name'>
  1618. Min DMG
  1619. </td>
  1620. <td class='value'>
  1621. <input id='min_dmg' type='range' value='<?=$page->unit->effective_dmg?>' min='0' max='7000' oninput='updateMinValue("dmg", this);'>
  1622. <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>
  1623. <a title='Remove filter' class='filter_control a_button' onclick='removeFilter("dmg");'>
  1624. <img alt='Remove filter' src='<?=URL::IMG["ICON"]?>nok.png'/>
  1625. </a>
  1626. <a title='Reset filter' class='filter_control a_button' onclick='resetFilter("dmg");'>
  1627. <img alt='Reset filter' src='<?=URL::IMG["ICON"]?>edit.png'/>
  1628. </a>
  1629. </td>
  1630. </tr>
  1631. </table>
  1632. </article>
  1633. </section>
  1634. <section id='results' class='content'>
  1635. <h2>
  1636. Optimization results
  1637. </h2>
  1638. <article>
  1639. <table id='table_optimizations'>
  1640. <tbody id='optimizations'>
  1641. </tbody>
  1642. </table>
  1643. </article>
  1644. </section>
  1645. </main>
  1646. <div id='message_container'>
  1647. <section class='content'>
  1648. <h2 id='message_title'>
  1649. Message
  1650. </h2>
  1651. <article>
  1652. <p id='message_text'>
  1653. Message Text
  1654. </p>
  1655. </article>
  1656. <input type='button' value='OK' id='message_button' onclick='closeMessage();'/>
  1657. </section>
  1658. </div>
  1659. <?php
  1660. include __DIR__ . "/inc/footer.php";
  1661. ?>
  1662. </body>
  1663. </html>