optimizer_unit.php 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250
  1. <?php
  2. /**
  3. * Monster view.
  4. *
  5. * Contains the view layout and some code to present the data.
  6. *
  7. * @category View
  8. * @property_read Monster_Page $page The page model.
  9. * @property_read int $UID Player ID.
  10. */
  11. ?>
  12. <!DOCTYPE html>
  13. <html lang='en'>
  14. <head>
  15. <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
  16. <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
  17. <title><?=$page->title?></title>
  18. <link rel='shortcut icon' href='<?=$page->favicon?>'/>
  19. <!-- CSS files -->
  20. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
  21. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>optimizer.css'/>
  22. <!-- Meta tags -->
  23. <link rel='canonical' href='<?=$page->canonical?>'/>
  24. <link rel='author' href='<?=$page->author?>'/>
  25. <link rel='publisher' href='<?=$page->author?>'/>
  26. <meta name='description' content='<?=$page->description?>'/>
  27. <meta property='og:title' content='<?=$page->title?>'/>
  28. <meta property='og:url' content='<?=$page->canonical?>'/>
  29. <meta property='og:description' content='<?=$page->description?>'/>
  30. <meta property='og:image' content='<?=$page->icon?>'/>
  31. <meta property='og:site_name' content='<?=$page->name?>'/>
  32. <meta property='og:type' content='website'/>
  33. <meta property='og:locale' content='en'/>
  34. <meta name='twitter:card' content='summary'/>
  35. <meta name='twitter:title' content='<?=$page->title?>'/>
  36. <meta name='twitter:description' content='<?=$page->description?>'/>
  37. <meta name='twitter:image' content='<?=$page->icon?>'/>
  38. <meta name='twitter:url' content='<?=$page->canonical?>'/>
  39. <meta name='robots' content='index follow'/>
  40. <script>
  41. /**
  42. * Unit current stats.
  43. */
  44. var current_stats = {
  45. "attack": <?=$page->unit->total_attack?>,
  46. "defense": <?=$page->unit->total_defense?>,
  47. "hp": <?=$page->unit->total_hp?>,
  48. "speed": <?=$page->unit->total_speed?>,
  49. "crit_rate": <?=$page->unit->total_crit_rate?>,
  50. "crit_damage": <?=$page->unit->total_crit_damage?>,
  51. "accuracy": <?=$page->unit->total_accuracy?>,
  52. "resistance": <?=$page->unit->total_resistance?>,
  53. "ehp": <?=$page->unit->effective_hp?>,
  54. "dmg": <?=$page->unit->effective_dmg?>
  55. }
  56. /**
  57. * Updates the value next to the sliders when they change.
  58. *
  59. * @param stat Name of the stat to set.
  60. * @param value Value of the slider.
  61. */
  62. function updateMinValue(stat, element){
  63. var value = Number(element.value);
  64. var max = Number(element.max);
  65. var min = Number(element.min);
  66. if (value < min){
  67. value = min;
  68. console.log("Correcting for min: " + value + "/" + min);
  69. }
  70. if (value > max){
  71. console.log("Correcting for max: " + value + "/" + max);
  72. value = max;
  73. }
  74. document.getElementById('lbl_min_' + stat).value = value;
  75. document.getElementById('min_' + stat).value = value;
  76. }
  77. /**
  78. * Starts the optimization.
  79. *
  80. * Checks for error in the combination of the parameters, and
  81. * shows an error window if there is an invalid conbination. If
  82. * not, builds the url to calculate the new rune combinations,
  83. * and presents th received response.
  84. *
  85. * @return false on error, true on success.
  86. */
  87. function apply(){
  88. // TODO: Check for valid set combinations
  89. var params = '';
  90. var x;
  91. // Player id - mandatory
  92. params = 'uid=<?=$UID?>';
  93. // Unit id - mandatory
  94. params += '&unit=<?=$page->unit->id?>';
  95. // Rune set 1 - mandatory
  96. params += '&set[]=' + document.getElementById('set_1').options[document.getElementById('set_1').selectedIndex].value;
  97. // Rune set 2 - mandatory
  98. params += '&set[]=' + document.getElementById('set_2').options[document.getElementById('set_2').selectedIndex].value;
  99. // Rune set 3 - optional
  100. x = document.getElementById('set_3').options[document.getElementById('set_3').selectedIndex].value;
  101. if (x != ''){
  102. params += '&set[]=' + x;
  103. }
  104. // Slot 2 - mandatory
  105. params += '&stat[]=' + document.getElementById('slot_2').options[document.getElementById('slot_2').selectedIndex].value;
  106. // Slot 4 - mandatory
  107. params += '&stat[]=' + document.getElementById('slot_4').options[document.getElementById('slot_4').selectedIndex].value;
  108. // Slot 5 - mandatory
  109. params += '&stat[]=' + document.getElementById('slot_6').options[document.getElementById('slot_6').selectedIndex].value;
  110. // Rune source - mandatory
  111. params += '&source=' + document.getElementById('rune_source').options[document.getElementById('rune_source').selectedIndex].value;
  112. // Optimizer tuning - mandatory
  113. params += '&tuning=' + document.getElementById('tuning').options[document.getElementById('tuning').selectedIndex].value;
  114. // Min HP - Optional
  115. if (Number(document.getElementById('min_hp').value) > Number(document.getElementById('min_hp').min)){
  116. params += '&min_hp=' + document.getElementById('min_hp').value;
  117. }
  118. // Min ATK - Optional
  119. if (Number(document.getElementById('min_attack').value) > Number(document.getElementById('min_attack').min)){
  120. params += '&min_attack=' + document.getElementById('min_attack').value;
  121. }
  122. // Min DEF - Optional
  123. if (Number(document.getElementById('min_defense').value) > Number(document.getElementById('min_defense').min)){
  124. params += '&min_defense=' + document.getElementById('min_defense').value;
  125. }
  126. // Min SPD - Optional
  127. if (Number(document.getElementById('min_speed').value) > Number(document.getElementById('min_speed').min)){
  128. params += '&min_speed=' + document.getElementById('min_speed').value;
  129. }
  130. // Min CRR - Optional
  131. if (Number(document.getElementById('min_crit_rate').value) > Number(document.getElementById('min_crit_rate').min)){
  132. params += '&min_crit_rate=' + document.getElementById('min_crit_rate').value;
  133. }
  134. // Min CRD - Optional
  135. if (Number(document.getElementById('min_crit_damage').value) > Number(document.getElementById('min_crit_damage').min)){
  136. params += '&min_crit_damage=' + document.getElementById('min_crit_damage').value;
  137. }
  138. // Min ACC - Optional
  139. if (Number(document.getElementById('min_accuracy').value) > Number(document.getElementById('min_accuracy').min)){
  140. params += '&min_accuracy=' + document.getElementById('min_accuracy').value;
  141. }
  142. // Min RES - Optional
  143. if (Number(document.getElementById('min_resistance').value) > Number(document.getElementById('min_resistance').min)){
  144. params += '&min_resistance=' + document.getElementById('min_resistance').value;
  145. }
  146. // Min EHP - Optional
  147. if (Number(document.getElementById('min_ehp').value) > 0){
  148. params += '&min_ehp=' + document.getElementById('min_ehp').value;
  149. }
  150. // Min DMG - Optional
  151. if (Number(document.getElementById('min_dmg').value) > 0){
  152. params += '&min_dmg=' + document.getElementById('min_dmg').value;
  153. }
  154. // Send th request
  155. var xhttp = new XMLHttpRequest();
  156. xhttp.onreadystatechange = function() {
  157. if (this.readyState == 4){
  158. if(this.status == 200) {
  159. showOptimizations(this.response, this.status);
  160. }
  161. else if (this.status == 413) { // Payload too large
  162. alert("Over 100 combination found. Plesase narow your criteria and retry.");
  163. }
  164. }
  165. };
  166. // TODO DEBUG
  167. params = "uid=8114048&unit=6441802832&set[]=1&set[]=1&set[]=4&stat[]=4&stat[]=4&stat[]=4&source=0&tuning=0&min_defense=700";
  168. xhttp.open("POST", "/action/optimize/", true);
  169. xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  170. xhttp.send(params);
  171. }
  172. function showOptimizations(content, status){
  173. var container = document.getElementById("optimizations");
  174. while (container.firstChild) {
  175. container.removeChild(container.firstChild);
  176. }
  177. var data = JSON.parse(content);
  178. if (Number(data.total) == 0){
  179. alert("No results");
  180. return;
  181. }
  182. var option;
  183. var tr;
  184. var td;
  185. var stat_table;
  186. var stat_tr;
  187. var stat_td;
  188. var span;
  189. var text;
  190. for (i = 0; i < data.options.length; i++){
  191. option = data.options[i];
  192. tr = document.createElement('tr');
  193. td = document.createElement('td');
  194. td.setAttribute('class', 'stats');
  195. stat_table = document.createElement('table');
  196. stat_table.setAttribute('class', 'stat_table');
  197. // attack
  198. stat_tr = document.createElement('tr');
  199. stat_td = document.createElement('td');
  200. stat_td.setAttribute('class', 'label');
  201. text = document.createTextNode('ATK');
  202. stat_td.appendChild(text);
  203. stat_tr.appendChild(stat_td);
  204. stat_td = document.createElement('td');
  205. stat_td.setAttribute('class', 'value');
  206. span = document.createElement('span');
  207. span.setAttribute('class', 'stat');
  208. text = document.createTextNode(option.stats.attack + " ");
  209. span.appendChild(text);
  210. stat_td.appendChild(span);
  211. span = document.createElement('span');
  212. if (Number(option.stats.attack) > Number(current_stats["attack"])){
  213. span.setAttribute('class', 'variation increment');
  214. text = document.createTextNode(option.stats.attack - current_stats["attack"]);
  215. }
  216. else if (Number(option.stats.attack) < Number(current_stats["attack"])){
  217. span.setAttribute('class', 'variation decrement');
  218. text = document.createTextNode(current_stats["attack"] - option.stats.attack);
  219. }
  220. else{
  221. span.setAttribute('class', 'variation');
  222. text = document.createTextNode(" ");
  223. }
  224. span.appendChild(text);
  225. stat_td.appendChild(span);
  226. stat_tr.appendChild(stat_td);
  227. stat_table.appendChild(stat_tr);
  228. // defense
  229. stat_tr = document.createElement('tr');
  230. stat_td = document.createElement('td');
  231. stat_td.setAttribute('class', 'label');
  232. text = document.createTextNode('DEF');
  233. stat_td.appendChild(text);
  234. stat_tr.appendChild(stat_td);
  235. stat_td = document.createElement('td');
  236. stat_td.setAttribute('class', 'value');
  237. span = document.createElement('span');
  238. span.setAttribute('class', 'stat');
  239. text = document.createTextNode(option.stats.defense + " ");
  240. span.appendChild(text);
  241. stat_td.appendChild(span);
  242. span = document.createElement('span');
  243. if (Number(option.stats.defense) > Number(current_stats["defense"])){
  244. span.setAttribute('class', 'variation increment');
  245. text = document.createTextNode(option.stats.defense - current_stats["defense"]);
  246. }
  247. else if (Number(option.stats.defense) < Number(current_stats["defense"])){
  248. span.setAttribute('class', 'variation decrement');
  249. text = document.createTextNode(current_stats["defense"] - option.stats.defense);
  250. }
  251. else{
  252. span.setAttribute('class', 'variation');
  253. text = document.createTextNode(" ");
  254. }
  255. span.appendChild(text);
  256. stat_td.appendChild(span);
  257. stat_tr.appendChild(stat_td);
  258. stat_table.appendChild(stat_tr);
  259. // hp
  260. stat_tr = document.createElement('tr');
  261. stat_td = document.createElement('td');
  262. stat_td.setAttribute('class', 'label');
  263. text = document.createTextNode('HP ');
  264. stat_td.appendChild(text);
  265. stat_tr.appendChild(stat_td);
  266. stat_td = document.createElement('td');
  267. stat_td.setAttribute('class', 'value');
  268. span = document.createElement('span');
  269. span.setAttribute('class', 'stat');
  270. text = document.createTextNode(option.stats.hp + " ");
  271. span.appendChild(text);
  272. stat_td.appendChild(span);
  273. span = document.createElement('span');
  274. if (Number(option.stats.hp) > Number(current_stats["hp"])){
  275. span.setAttribute('class', 'variation increment');
  276. text = document.createTextNode(option.stats.hp - current_stats["hp"]);
  277. }
  278. else if (Number(option.stats.hp) < Number(current_stats["hp"])){
  279. span.setAttribute('class', 'variation decrement');
  280. text = document.createTextNode(current_stats["hp"] - option.stats.hp);
  281. }
  282. else{
  283. span.setAttribute('class', 'variation');
  284. text = document.createTextNode(" ");
  285. }
  286. span.appendChild(text);
  287. stat_td.appendChild(span);
  288. stat_tr.appendChild(stat_td);
  289. stat_table.appendChild(stat_tr);
  290. // speed
  291. stat_tr = document.createElement('tr');
  292. stat_td = document.createElement('td');
  293. stat_td.setAttribute('class', 'label');
  294. text = document.createTextNode('SPD');
  295. stat_td.appendChild(text);
  296. stat_tr.appendChild(stat_td);
  297. stat_td = document.createElement('td');
  298. stat_td.setAttribute('class', 'value');
  299. span = document.createElement('span');
  300. span.setAttribute('class', 'stat');
  301. text = document.createTextNode(option.stats.speed + " ");
  302. span.appendChild(text);
  303. stat_td.appendChild(span);
  304. span = document.createElement('span');
  305. if (Number(option.stats.speed) > Number(current_stats["speed"])){
  306. span.setAttribute('class', 'variation increment');
  307. text = document.createTextNode(option.stats.speed - current_stats["speed"]);
  308. }
  309. else if (Number(option.stats.speed) < Number(current_stats["speed"])){
  310. span.setAttribute('class', 'variation decrement');
  311. text = document.createTextNode(current_stats["speed"] - option.stats.speed);
  312. }
  313. else{
  314. span.setAttribute('class', 'variation');
  315. text = document.createTextNode(" ");
  316. }
  317. span.appendChild(text);
  318. stat_td.appendChild(span);
  319. stat_tr.appendChild(stat_td);
  320. stat_table.appendChild(stat_tr);
  321. // crit_rate
  322. stat_tr = document.createElement('tr');
  323. stat_td = document.createElement('td');
  324. stat_td.setAttribute('class', 'label');
  325. text = document.createTextNode('CRR');
  326. stat_td.appendChild(text);
  327. stat_tr.appendChild(stat_td);
  328. stat_td = document.createElement('td');
  329. stat_td.setAttribute('class', 'value');
  330. span = document.createElement('span');
  331. span.setAttribute('class', 'stat');
  332. text = document.createTextNode(option.stats.crit_rate + "%");
  333. span.appendChild(text);
  334. stat_td.appendChild(span);
  335. span = document.createElement('span');
  336. if (Number(option.stats.crit_rate) > Number(current_stats["crit_rate"])){
  337. span.setAttribute('class', 'variation increment');
  338. text = document.createTextNode(option.stats.crit_rate - current_stats["crit_rate"]);
  339. }
  340. else if (Number(option.stats.crit_rate) < Number(current_stats["crit_rate"])){
  341. span.setAttribute('class', 'variation decrement');
  342. text = document.createTextNode(current_stats["crit_rate"] - option.stats.crit_rate);
  343. }
  344. else{
  345. span.setAttribute('class', 'variation');
  346. text = document.createTextNode(" ");
  347. }
  348. span.appendChild(text);
  349. stat_td.appendChild(span);
  350. stat_tr.appendChild(stat_td);
  351. stat_table.appendChild(stat_tr);
  352. // crit_damage
  353. stat_tr = document.createElement('tr');
  354. stat_td = document.createElement('td');
  355. stat_td.setAttribute('class', 'label');
  356. text = document.createTextNode('CRD');
  357. stat_td.appendChild(text);
  358. stat_tr.appendChild(stat_td);
  359. stat_td = document.createElement('td');
  360. stat_td.setAttribute('class', 'value');
  361. span = document.createElement('span');
  362. span.setAttribute('class', 'stat');
  363. text = document.createTextNode(option.stats.crit_damage + "%");
  364. span.appendChild(text);
  365. stat_td.appendChild(span);
  366. span = document.createElement('span');
  367. if (Number(option.stats.crit_damage) > Number(current_stats["crit_damage"])){
  368. span.setAttribute('class', 'variation increment');
  369. text = document.createTextNode(option.stats.crit_damage - current_stats["crit_damage"]);
  370. }
  371. else if (Number(option.stats.crit_damage) < Number(current_stats["crit_damage"])){
  372. span.setAttribute('class', 'variation decrement');
  373. text = document.createTextNode(current_stats["crit_damage"] - option.stats.crit_damage);
  374. }
  375. else{
  376. span.setAttribute('class', 'variation');
  377. text = document.createTextNode(" ");
  378. }
  379. span.appendChild(text);
  380. stat_td.appendChild(span);
  381. stat_tr.appendChild(stat_td);
  382. stat_table.appendChild(stat_tr);
  383. // accuracy
  384. stat_tr = document.createElement('tr');
  385. stat_td = document.createElement('td');
  386. stat_td.setAttribute('class', 'label');
  387. text = document.createTextNode('ACC');
  388. stat_td.appendChild(text);
  389. stat_tr.appendChild(stat_td);
  390. stat_td = document.createElement('td');
  391. stat_td.setAttribute('class', 'value');
  392. span = document.createElement('span');
  393. span.setAttribute('class', 'stat');
  394. text = document.createTextNode(option.stats.accuracy + "%");
  395. span.appendChild(text);
  396. stat_td.appendChild(span);
  397. span = document.createElement('span');
  398. if (Number(option.stats.accuracy) > Number(current_stats["accuracy"])){
  399. span.setAttribute('class', 'variation increment');
  400. text = document.createTextNode(option.stats.accuracy - current_stats["accuracy"]);
  401. }
  402. else if (Number(option.stats.accuracy) < Number(current_stats["accuracy"])){
  403. span.setAttribute('class', 'variation decrement');
  404. text = document.createTextNode(current_stats["accuracy"] - option.stats.accuracy);
  405. }
  406. else{
  407. span.setAttribute('class', 'variation');
  408. text = document.createTextNode(" ");
  409. }
  410. span.appendChild(text);
  411. stat_td.appendChild(span);
  412. stat_tr.appendChild(stat_td);
  413. stat_table.appendChild(stat_tr);
  414. // resistance
  415. stat_tr = document.createElement('tr');
  416. stat_td = document.createElement('td');
  417. stat_td.setAttribute('class', 'label');
  418. text = document.createTextNode('RES');
  419. stat_td.appendChild(text);
  420. stat_tr.appendChild(stat_td);
  421. stat_td = document.createElement('td');
  422. stat_td.setAttribute('class', 'value');
  423. span = document.createElement('span');
  424. span.setAttribute('class', 'stat');
  425. text = document.createTextNode(option.stats.resistance + "%");
  426. span.appendChild(text);
  427. stat_td.appendChild(span);
  428. span = document.createElement('span');
  429. if (Number(option.stats.resistance) > Number(current_stats["resistance"])){
  430. span.setAttribute('class', 'variation increment');
  431. text = document.createTextNode(option.stats.resistance - current_stats["resistance"]);
  432. }
  433. else if (Number(option.stats.resistance) < Number(current_stats["resistance"])){
  434. span.setAttribute('class', 'variation decrement');
  435. text = document.createTextNode(current_stats["resistance"] - option.stats.resistance);
  436. }
  437. else{
  438. span.setAttribute('class', 'variation');
  439. text = document.createTextNode(" ");
  440. }
  441. span.appendChild(text);
  442. stat_td.appendChild(span);
  443. stat_tr.appendChild(stat_td);
  444. stat_table.appendChild(stat_tr);
  445. // ehp
  446. stat_tr = document.createElement('tr');
  447. stat_td = document.createElement('td');
  448. stat_td.setAttribute('class', 'label');
  449. text = document.createTextNode('EHP');
  450. stat_td.appendChild(text);
  451. stat_tr.appendChild(stat_td);
  452. stat_td = document.createElement('td');
  453. stat_td.setAttribute('class', 'value');
  454. span = document.createElement('span');
  455. span.setAttribute('class', 'stat');
  456. text = document.createTextNode(option.stats.ehp + " ");
  457. span.appendChild(text);
  458. stat_td.appendChild(span);
  459. span = document.createElement('span');
  460. if (Number(option.stats.ehp) > Number(current_stats["ehp"])){
  461. span.setAttribute('class', 'variation increment');
  462. text = document.createTextNode(option.stats.ehp - current_stats["ehp"]);
  463. }
  464. else if (Number(option.stats.ehp) < Number(current_stats["ehp"])){
  465. span.setAttribute('class', 'variation decrement');
  466. text = document.createTextNode(current_stats["ehp"] - option.stats.ehp);
  467. }
  468. else{
  469. span.setAttribute('class', 'variation');
  470. text = document.createTextNode(" ");
  471. }
  472. span.appendChild(text);
  473. stat_td.appendChild(span);
  474. stat_tr.appendChild(stat_td);
  475. stat_table.appendChild(stat_tr);
  476. // dmg
  477. stat_tr = document.createElement('tr');
  478. stat_td = document.createElement('td');
  479. stat_td.setAttribute('class', 'label');
  480. text = document.createTextNode('DMG');
  481. stat_td.appendChild(text);
  482. stat_tr.appendChild(stat_td);
  483. stat_td = document.createElement('td');
  484. stat_td.setAttribute('class', 'value');
  485. span = document.createElement('span');
  486. span.setAttribute('class', 'stat');
  487. text = document.createTextNode(option.stats.dmg + " ");
  488. span.appendChild(text);
  489. stat_td.appendChild(span);
  490. span = document.createElement('span');
  491. if (Number(option.stats.dmg) > Number(current_stats["dmg"])){
  492. span.setAttribute('class', 'variation increment');
  493. text = document.createTextNode(option.stats.dmg - current_stats["dmg"]);
  494. }
  495. else if (Number(option.stats.dmg) < Number(current_stats["dmg"])){
  496. span.setAttribute('class', 'variation decrement');
  497. text = document.createTextNode(current_stats["dmg"] - option.stats.dmg);
  498. }
  499. else{
  500. span.setAttribute('class', 'variation');
  501. text = document.createTextNode(" ");
  502. }
  503. span.appendChild(text);
  504. stat_td.appendChild(span);
  505. stat_tr.appendChild(stat_td);
  506. stat_table.appendChild(stat_tr);
  507. // Add to the main table
  508. td.appendChild(stat_table);
  509. tr.appendChild(td);
  510. // Runes td
  511. td = document.createElement('td');
  512. td.setAttribute('class', 'runes');
  513. td.innerHTML += option.runes[6 - 1].html;
  514. td.innerHTML += option.runes[1 - 1].html;
  515. td.innerHTML += option.runes[2 - 1].html;
  516. td.innerHTML += "<br/>";
  517. td.innerHTML += option.runes[5 - 1].html;
  518. td.innerHTML += option.runes[4 - 1].html;
  519. td.innerHTML += option.runes[3 - 1].html;
  520. // Add the table
  521. tr.appendChild(td);
  522. container.appendChild(tr);
  523. }
  524. }
  525. </script>
  526. </head>
  527. <body>
  528. <?php
  529. include __DIR__ . "/inc/header.php";
  530. ?>
  531. <section id='monster' class='content'>
  532. <h2>
  533. Optimize <?=$page->unit->title?>
  534. </h2>
  535. <article id='profile'>
  536. <div id='monster_info'>
  537. <div class='monster_panel'>
  538. <?=HTML::unit_panel($page->unit)?>
  539. </div>
  540. <?php
  541. if ($page->unit->experience_level != 0){
  542. $exp_pct = ceil($page->unit->exp_gained * 100 / $page->unit->experience_level);
  543. $exp_txt = $page->unit->exp_gained . " / " . $page->unit->experience_level;
  544. }
  545. else{
  546. $exp_pct = 100;
  547. $exp_txt = "MAX";
  548. }
  549. $now = time();
  550. //$datediff = $now - $page->unit->create_time->getTimestamp();
  551. $datediff = $now - strtotime($page->unit->create_time->format('Y-m-d H:i:s'));
  552. $datediff = floor($datediff / (60 * 60 * 24));
  553. ?>
  554. <div id='monster_details'>
  555. <?php
  556. if (sizeof($page->unit->teams) > 0){
  557. ?>
  558. <div id='teams'>
  559. <h4>
  560. Teams:
  561. </h4>
  562. <ul>
  563. <?php
  564. foreach($page->unit->teams as $team){
  565. ?>
  566. <li>
  567. <a target='blank' href='/<?=$UID?>/teams/<?=$team->id?>'>
  568. <?=$team->name?>
  569. </a>
  570. </li>
  571. <?php
  572. }
  573. ?>
  574. </ul>
  575. </div>
  576. <?php
  577. }
  578. ?>
  579. </div>
  580. </div>
  581. <table id='stats'>
  582. <tr>
  583. <th>
  584. Stats
  585. </th>
  586. <th>
  587. Base
  588. </th>
  589. <th>
  590. Runes
  591. </th>
  592. <th>
  593. Artifacts
  594. </th>
  595. <th>
  596. Buildings
  597. </th>
  598. <th>
  599. Total
  600. </th>
  601. </tr>
  602. <tr>
  603. <th>
  604. ATK
  605. </th>
  606. <td class='base'>
  607. <?=$page->unit->attack?>
  608. <span class='percent'>&nbsp;</span>
  609. </td>
  610. <td class='extra'>
  611. +<?=$page->unit->rune_attack?>
  612. <span class='percent'>&nbsp;</span>
  613. </td>
  614. <td class='extra'>
  615. +<?=$page->unit->artifact_attack?>
  616. <span class='percent'>&nbsp;</span>
  617. </td>
  618. <td class='extra'>
  619. +<?=$page->unit->building_attack?>
  620. <span class='percent'>&nbsp;</span>
  621. </td>
  622. <td class='total'>
  623. <?=$page->unit->total_attack?>
  624. <span class='percent'>&nbsp;</span>
  625. </td>
  626. </tr>
  627. <tr>
  628. <th>
  629. DEF
  630. </th>
  631. <td class='base'>
  632. <?=$page->unit->defense?>
  633. <span class='percent'>&nbsp;</span>
  634. </td>
  635. <td class='extra'>
  636. +<?=$page->unit->rune_defense?>
  637. <span class='percent'>&nbsp;</span>
  638. </td>
  639. <td class='extra'>
  640. +<?=$page->unit->artifact_defense?>
  641. <span class='percent'>&nbsp;</span>
  642. </td>
  643. <td class='extra'>
  644. +<?=$page->unit->building_defense?>
  645. <span class='percent'>&nbsp;</span>
  646. </td>
  647. <td class='total'>
  648. <?=$page->unit->total_defense?>
  649. <span class='percent'>&nbsp;</span>
  650. </td>
  651. </tr>
  652. <tr>
  653. <th>
  654. HP
  655. </th>
  656. <td class='base'>
  657. <?=$page->unit->hp?>
  658. <span class='percent'>&nbsp;</span>
  659. </td>
  660. <td class='extra'>
  661. +<?=$page->unit->rune_hp?>
  662. <span class='percent'>&nbsp;</span>
  663. </td>
  664. <td class='extra'>
  665. +<?=$page->unit->artifact_hp?>
  666. <span class='percent'>&nbsp;</span>
  667. </td>
  668. <td class='extra'>
  669. +<?=$page->unit->building_hp?>
  670. <span class='percent'>&nbsp;</span>
  671. </td>
  672. <td class='total'>
  673. <?=$page->unit->total_hp?>
  674. <span class='percent'>&nbsp;</span>
  675. </td>
  676. </tr>
  677. <tr>
  678. <th>
  679. SPD
  680. </th>
  681. <td class='base'>
  682. <?=$page->unit->speed?>
  683. <span class='percent'>&nbsp;</span>
  684. </td>
  685. <td class='extra'>
  686. +<?=$page->unit->rune_speed?>
  687. <span class='percent'>&nbsp;</span>
  688. </td>
  689. <td class='extra'>
  690. +<?=$page->unit->artifact_speed?>
  691. <span class='percent'>&nbsp;</span>
  692. </td>
  693. <td class='extra'>
  694. +<?=$page->unit->building_speed?>
  695. <span class='percent'>&nbsp;</span>
  696. </td>
  697. <td class='total'>
  698. <?=$page->unit->total_speed?>
  699. <span class='percent'>&nbsp;</span>
  700. </td>
  701. </tr>
  702. <tr>
  703. <th>
  704. CRR
  705. </th>
  706. <td class='base'>
  707. <?=$page->unit->crit_rate?>
  708. <span class='percent'>%</span>
  709. </td>
  710. <td class='extra'>
  711. +<?=$page->unit->rune_crit_rate?>
  712. <span class='percent'>%</span>
  713. </td>
  714. <td class='extra'>
  715. +<?=$page->unit->artifact_crit_rate?>
  716. <span class='percent'>%</span>
  717. </td>
  718. <td class='extra'>
  719. +<?=$page->unit->building_crit_rate?>
  720. <span class='percent'>%</span>
  721. </td>
  722. <td class='total'>
  723. <?=$page->unit->total_crit_rate?>
  724. <span class='percent'>%</span>
  725. </td>
  726. </tr>
  727. <tr>
  728. <th>
  729. CRD
  730. </th>
  731. <td class='base'>
  732. <?=$page->unit->crit_damage?>
  733. <span class='percent'>%</span>
  734. </td>
  735. <td class='extra'>
  736. +<?=$page->unit->rune_crit_damage?>
  737. <span class='percent'>%</span>
  738. </td>
  739. <td class='extra'>
  740. +<?=$page->unit->artifact_crit_damage?>
  741. <span class='percent'>%</span>
  742. </td>
  743. <td class='extra'>
  744. +<?=$page->unit->building_crit_damage?>
  745. <span class='percent'>%</span>
  746. </td>
  747. <td class='total'>
  748. <?=$page->unit->total_crit_damage?>
  749. <span class='percent'>%</span>
  750. </td>
  751. </tr>
  752. <tr>
  753. <th>
  754. ACC
  755. </th>
  756. <td class='base'>
  757. <?=$page->unit->accuracy?>
  758. <span class='percent'>%</span>
  759. </td>
  760. <td class='extra'>
  761. +<?=$page->unit->rune_accuracy?>
  762. <span class='percent'>%</span>
  763. </td>
  764. <td class='extra'>
  765. +<?=$page->unit->artifact_accuracy?>
  766. <span class='percent'>%</span>
  767. </td>
  768. <td class='extra'>
  769. +<?=$page->unit->building_accuracy?>
  770. <span class='percent'>%</span>
  771. </td>
  772. <td class='total'>
  773. <?=$page->unit->total_accuracy?>
  774. <span class='percent'>%</span>
  775. </td>
  776. </tr>
  777. <tr>
  778. <th>
  779. RES
  780. </th>
  781. <td class='base'>
  782. <?=$page->unit->resistance?>
  783. <span class='percent'>%</span>
  784. </td>
  785. <td class='extra'>
  786. +<?=$page->unit->rune_resistance?>
  787. <span class='percent'>%</span>
  788. </td>
  789. <td class='extra'>
  790. +<?=$page->unit->artifact_resistance?>
  791. <span class='percent'>%</span>
  792. </td>
  793. <td class='extra'>
  794. +<?=$page->unit->building_resistance?>
  795. <span class='percent'>%</span>
  796. </td>
  797. <td class='total'>
  798. <?=$page->unit->total_resistance?>
  799. <span class='percent'>%</span>
  800. </td>
  801. </tr>
  802. <tr>
  803. <th colspan='5'>
  804. Effective HP
  805. </th>
  806. <td class='total'>
  807. <?=$page->unit->effective_hp?>
  808. <span class='percent'>&nbsp;</span>
  809. </td>
  810. </tr>
  811. <tr>
  812. <th colspan='5'>
  813. Effective DMG
  814. </th>
  815. <td class='total'>
  816. <?=$page->unit->effective_dmg?>
  817. <span class='percent'>&nbsp;</span>
  818. </td>
  819. </tr>
  820. </table>
  821. <div id='artifacts'>
  822. <?=HTML::artifact_table($page->unit->artifact_type)?>
  823. <?=HTML::artifact_table($page->unit->artifact_element)?>
  824. </div>
  825. </article> <!-- #profile -->
  826. <article id='current_runes'>
  827. <?php
  828. $total_efficiency = 0;
  829. $total_max_efficiency = 0;
  830. $total_reached_efficiency = 0;
  831. $total_level = 0;
  832. $total_stars = 0;
  833. $total_value = 0;
  834. $total_runes = 0;
  835. $show_list = [6, 1, 2, 5, 4, 3];
  836. //foreach ($page->unit->rune as $rune){
  837. foreach ($show_list as $i){
  838. $rune = $page->unit->rune[$i - 1];
  839. $total_efficiency += $rune->efficiency;
  840. $total_max_efficiency += $rune->max_efficiency;
  841. $total_reached_efficiency += ($rune->efficiency * 100 / $rune->max_efficiency);
  842. $total_level += $rune->level;
  843. $total_stars += $rune->stars;
  844. $total_value += $rune->value;
  845. $total_runes ++;
  846. ?>
  847. <?=HTML::rune_table($rune)?>
  848. <?php
  849. if ($i == 2){
  850. ?>
  851. <br/>
  852. <?php
  853. }
  854. }
  855. ?>
  856. </article>
  857. <article id='rune_averages'>
  858. <table id='table_averages'>
  859. <tr>
  860. <td class='title'>
  861. Avg. level:
  862. </td>
  863. <td class='value'>
  864. <?=number_format($total_level / $total_runes, 2)?>
  865. </td>
  866. </tr>
  867. <tr>
  868. <td class='title'>
  869. Avg. stars:
  870. </td>
  871. <td class='value'>
  872. <?=number_format($total_stars / $total_runes, 2)?>
  873. </td>
  874. </tr>
  875. <tr>
  876. <td class='title'>
  877. Avg. value:
  878. </td>
  879. <td class='value'>
  880. <?=number_format($total_value / $total_runes, 2, '.', '')?>
  881. </td>
  882. </tr>
  883. <tr>
  884. <td class='title'>
  885. Total value:
  886. </td>
  887. <td class='value'>
  888. <?=$total_value?>
  889. </td>
  890. </tr>
  891. <tr>
  892. <td class='title'>
  893. Avg. efficiency:
  894. </td>
  895. <td class='value'>
  896. <?=number_format($total_efficiency / $total_runes, 2)?>%
  897. </td>
  898. </tr>
  899. <tr>
  900. <td class='title'>
  901. Avg. max. efficiency:
  902. </td>
  903. <td class='value'>
  904. <?=number_format($total_max_efficiency / $total_runes, 2)?>%
  905. </td>
  906. </tr>
  907. <tr>
  908. <td class='title'>
  909. Avg. reached efficiency:
  910. </td>
  911. <td class='value'>
  912. <?=number_format($total_reached_efficiency / $total_runes, 2)?>%
  913. </td>
  914. </tr>
  915. </table>
  916. </article>
  917. </section> <!-- runes -->
  918. <section id='parameters' class='content'>
  919. <h2>
  920. Optimization parameters
  921. </h2>
  922. <article>
  923. <table>
  924. <tr>
  925. <td class='name'>
  926. Rune sets
  927. </td>
  928. <td class='value'>
  929. <?php
  930. $reflect = new ReflectionClass("RUNE_SET_ID");
  931. ?>
  932. <select id='set_1'>
  933. <?php
  934. foreach($reflect->getConstants() as $name => $id){
  935. $selected = "";
  936. if (in_array($id, $filters["MAIN"])){
  937. $selected = "selected='selected'";
  938. }
  939. ?>
  940. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  941. <?php
  942. }
  943. ?>
  944. </select>
  945. <select id='set_2'>
  946. <?php
  947. foreach($reflect->getConstants() as $name => $id){
  948. $selected = "";
  949. if (in_array($id, $filters["MAIN"])){
  950. $selected = "selected='selected'";
  951. }
  952. ?>
  953. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  954. <?php
  955. }
  956. ?>
  957. </select>
  958. <select id='set_3'>
  959. <option value='' <?=$selected?>></option>
  960. <?php
  961. foreach($reflect->getConstants() as $name => $id){
  962. $selected = "";
  963. if (in_array($id, $filters["MAIN"])){
  964. $selected = "selected='selected'";
  965. }
  966. ?>
  967. <option value='<?=$id?>' <?=$selected?>><?=substr($name, 0, 7)?></option>
  968. <?php
  969. }
  970. ?>
  971. </select>
  972. </td>
  973. <td class='empty'>
  974. </td>
  975. <td class='name'>
  976. Min HP
  977. </td>
  978. <td class='value'>
  979. <input id='min_hp' type='range' value='<?=$page->unit->total_hp?>' min='<?=$page->unit->hp?>' max='50000' oninput='updateMinValue("hp", this);'>
  980. <input type='number' id='lbl_min_hp' value='<?=$page->unit->total_hp?>' min='<?=$page->unit->hp?>' max='50000' onChange='updateMinValue("hp", this);'></input>
  981. </td>
  982. </tr>
  983. <tr>
  984. <td class='name'>
  985. Even slots
  986. </td>
  987. <td class='value'>
  988. <select id='slot_2'>
  989. <option value='<?=RUNE_STAT_ID::HP_P?>'>HP%</option>
  990. <option value='<?=RUNE_STAT_ID::ATK_P?>'>ATK%</option>
  991. <option value='<?=RUNE_STAT_ID::DEF_P?>'>DEF%</option>
  992. <option value='<?=RUNE_STAT_ID::SPD?>'>SPD</option>
  993. </select>
  994. <select id='slot_4'>
  995. <option value='<?=RUNE_STAT_ID::HP_P?>'>HP%</option>
  996. <option value='<?=RUNE_STAT_ID::ATK_P?>'>ATK%</option>
  997. <option value='<?=RUNE_STAT_ID::DEF_P?>'>DEF%</option>
  998. <option value='<?=RUNE_STAT_ID::CRR?>'>CRR</option>
  999. <option value='<?=RUNE_STAT_ID::CRR?>'>CRD</option>
  1000. </select>
  1001. <select id='slot_6'>
  1002. <option value='<?=RUNE_STAT_ID::HP_P?>'>HP%</option>
  1003. <option value='<?=RUNE_STAT_ID::ATK_P?>'>ATK%</option>
  1004. <option value='<?=RUNE_STAT_ID::DEF_P?>'>DEF%</option>
  1005. <option value='<?=RUNE_STAT_ID::ACC?>'>ACC</option>
  1006. <option value='<?=RUNE_STAT_ID::RES?>'>RES</option>
  1007. </select>
  1008. </td>
  1009. <td class='empty'>
  1010. </td>
  1011. <td class='name'>
  1012. Min ATK
  1013. </td>
  1014. <td class='value'>
  1015. <input id='min_attack' type='range' value='<?=$page->unit->total_attack?>' min='<?=$page->unit->attack?>' max='4000' oninput='updateMinValue("attack", this);'>
  1016. <input type='number' id='lbl_min_attack' value='<?=$page->unit->total_attack?>' min='<?=$page->unit->attack?>' max='4000' onChange='updateMinValue("attack", this);'></input>
  1017. </td>
  1018. </tr>
  1019. <tr>
  1020. <td class='name'>
  1021. Use runes from
  1022. </td>
  1023. <td class='value'>
  1024. <select id='rune_source'>
  1025. <option value='0'>Storage only</option>
  1026. <option value='1'>Units in no teams</option>
  1027. <option value='2'>Units in teams with 0 score</option>
  1028. <option value='3'>Units with lower overall score</option>
  1029. <option value='4'>All runes</option>
  1030. </select>
  1031. </td>
  1032. <td class='empty'>
  1033. </td>
  1034. <td class='name'>
  1035. Min DEF
  1036. </td>
  1037. <td class='value'>
  1038. <input id='min_defense' type='range' value='<?=$page->unit->total_defense?>' min='<?=$page->unit->defense?>' max='4000' oninput='updateMinValue("defense", this);'>
  1039. <input type='number' id='lbl_min_defense' value='<?=$page->unit->total_defense?>' min='<?=$page->unit->defense?>' max='4000' onChange='updateMinValue("defense", this);'></input>
  1040. </td>
  1041. </tr>
  1042. <tr>
  1043. <td class='name'>
  1044. Tune optimizer for
  1045. </td>
  1046. <td class='value'>
  1047. <select id='tuning'>
  1048. <option value='0'>Rune current levels</option>
  1049. <option value='1'>+12</option>
  1050. <option value='2'>2/4/6 +15, 1/3/5 + 12</option>
  1051. <option value='3'>+15</option>
  1052. </select>
  1053. </td>
  1054. <td class='empty'>
  1055. </td>
  1056. <td class='name'>
  1057. Min SPD
  1058. </td>
  1059. <td class='value'>
  1060. <input id='min_speed' type='range' value='<?=$page->unit->total_speed?>' min='<?=$page->unit->speed?>' max='400' oninput='updateMinValue("speed", this);'>
  1061. <input type='number' id='lbl_min_speed' value='<?=$page->unit->total_speed?>' min='<?=$page->unit->speed?>' max='400' onChange='updateMinValue("speed", this);'></input>
  1062. </td>
  1063. </tr>
  1064. <tr>
  1065. <td class='empty'>
  1066. </td>
  1067. <td class='empty'>
  1068. </td>
  1069. <td class='empty'>
  1070. </td>
  1071. <td class='name'>
  1072. Min CRR
  1073. </td>
  1074. <td class='value'>
  1075. <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);'>
  1076. <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>%
  1077. </td>
  1078. </tr>
  1079. <tr>
  1080. <td class='empty'>
  1081. </td>
  1082. <td class='empty'>
  1083. </td>
  1084. <td class='empty'>
  1085. </td>
  1086. <td class='name'>
  1087. Min CRD
  1088. </td>
  1089. <td class='value'>
  1090. <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);'>
  1091. <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>%
  1092. </td>
  1093. </tr>
  1094. <tr>
  1095. <td class='empty'>
  1096. </td>
  1097. <td class='empty'>
  1098. </td>
  1099. <td class='empty'>
  1100. </td>
  1101. <td class='name'>
  1102. Min ACC
  1103. </td>
  1104. <td class='value'>
  1105. <input id='min_accuracy' type='range' value='<?=$page->unit->total_accuracy?>' min='<?=$page->unit->accuracy?>' max='85' oninput='updateMinValue("accuracy", this);'>
  1106. <input type='number' id='lbl_min_accuracy' value='<?=$page->unit->total_accuracy?>' min='<?=$page->unit->accuracy?>' max='85' onChange='updateMinValue("accuracy", this);'></input>%
  1107. </td>
  1108. </tr>
  1109. <tr>
  1110. <td class='empty'>
  1111. </td>
  1112. <td class='empty'>
  1113. </td>
  1114. <td class='empty'>
  1115. </td>
  1116. <td class='name'>
  1117. Min RES
  1118. </td>
  1119. <td class='value'>
  1120. <input id='min_resistance' type='range' value='<?=$page->unit->total_resistance?>' min='<?=$page->unit->resistance?>' max='85' oninput='updateMinValue("resistance", this);'>
  1121. <input type='number' id='lbl_min_resistance' value='<?=$page->unit->total_resistance?>' min='<?=$page->unit->resistance?>' max='85' onChange='updateMinValue("resistance", this);'></input>%
  1122. </td>
  1123. </tr>
  1124. <tr>
  1125. <td class='empty'>
  1126. </td>
  1127. <td class='empty'>
  1128. </td>
  1129. <td class='empty'>
  1130. </td>
  1131. <td class='name'>
  1132. Min EHP
  1133. </td>
  1134. <td class='value'>
  1135. <input id='min_ehp' type='range' value='<?=$page->unit->effective_hp?>' min='0' max='200000' oninput='updateMinValue("ehp", this);'>
  1136. <input type='number' id='lbl_min_ehp' value='<?=$page->unit->effective_hp?>' min='0' max='200000' onChange='updateMinValue("ehp", this);'></input>
  1137. </td>
  1138. </tr>
  1139. <tr>
  1140. <td class='action'>
  1141. <input type='button' value='Apply' onClick='apply();'/>
  1142. </td>
  1143. <td class='empty'>
  1144. </td>
  1145. <td class='empty'>
  1146. </td>
  1147. <td class='name'>
  1148. Min DMG
  1149. </td>
  1150. <td class='value'>
  1151. <input id='min_dmg' type='range' value='<?=$page->unit->effective_dmg?>' min='0' max='7000' oninput='updateMinValue("dmg", this);'>
  1152. <input type='number' id='lbl_min_dmg' value='<?=$page->unit->effective_dmg?>' min='0' max='7000' onChange='updateMinValue("dmg", this);'></input>
  1153. </td>
  1154. </tr>
  1155. </table>
  1156. </article>
  1157. </section>
  1158. <section id='results' class='content'>
  1159. <h2>
  1160. Optimization results
  1161. </h2>
  1162. <article>
  1163. <table>
  1164. <tbody id='optimizations'>
  1165. </tbody>
  1166. </table>
  1167. </article>
  1168. </section>
  1169. <?php
  1170. include __DIR__ . "/inc/footer.php";
  1171. ?>
  1172. </body>
  1173. </html>