stats.php 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. <?php
  2. /**
  3. * Runs view.
  4. *
  5. * Contains the view layout and ome code to present the data.
  6. *
  7. * @category View
  8. * @var Stats_Page $page The page model.
  9. * @var player get_context()->get_player() Currently selected player.
  10. * @var int get_context()->get_game_mode() Game mode.
  11. */
  12. ?>
  13. <!DOCTYPE html>
  14. <html lang='en'>
  15. <head>
  16. <meta content='text/html; charset=utf-8' http-equiv='content-type'/>
  17. <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1'/>
  18. <title><?=$page->title?></title>
  19. <link rel='shortcut icon' href='<?=$page->favicon?>'/>
  20. <!-- CSS files -->
  21. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui.css'/>
  22. <?php
  23. if (get_context()->get_game_mode() == GAME_MODE_ID::RTA){
  24. ?>
  25. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>ui-rta.css'/>
  26. <?php
  27. }
  28. ?>
  29. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>stats.css'/>
  30. <!-- Meta tags -->
  31. <link rel='canonical' href='<?=$page->canonical?>'/>
  32. <link rel='author' href='<?=$page->author?>'/>
  33. <link rel='publisher' href='<?=$page->author?>'/>
  34. <meta name='description' content='<?=$page->description?>'/>
  35. <meta property='og:title' content='<?=$page->title?>'/>
  36. <meta property='og:url' content='<?=$page->canonical?>'/>
  37. <meta property='og:description' content='<?=$page->description?>'/>
  38. <meta property='og:image' content='<?=$page->icon?>'/>
  39. <meta property='og:site_name' content='<?=$page->name?>'/>
  40. <meta property='og:type' content='website'/>
  41. <meta property='og:locale' content='en'/>
  42. <meta name='twitter:card' content='summary'/>
  43. <meta name='twitter:title' content='<?=$page->title?>'/>
  44. <meta name='twitter:description' content='<?=$page->description?>'/>
  45. <meta name='twitter:image' content='<?=$page->icon?>'/>
  46. <meta name='twitter:url' content='<?=$page->canonical?>'/>
  47. <meta name='robots' content='index follow'/>
  48. <script>
  49. function selectAreaType(){
  50. var areaType = document.getElementById('filter_area_type').options[document.getElementById('filter_area_type').selectedIndex].value;
  51. // Clear all selectors
  52. document.getElementById('filter_stage').style.display = 'none';
  53. document.getElementById('filter_difficulty').style.display = 'none';
  54. var areas = document.getElementsByClassName('filter_area');
  55. for (var i = 0; i < areas.length; i++) {
  56. areas[i].style.display = 'none';
  57. areas[i].removeAttribute('name');
  58. }
  59. // Show selected selector.
  60. switch (areaType){
  61. case '<?=AREA_TYPE_ID::SCENARIO?>':
  62. document.getElementById('filter_area_scenario').style.display = 'inline-block';
  63. document.getElementById('filter_area_scenario').setAttribute('name', 'area');
  64. populateStage(7);
  65. document.getElementById('filter_stage').style.display = 'inline-block';
  66. populateDifficulty();
  67. document.getElementById('filter_difficulty').style.display = 'inline-block';
  68. break;
  69. case '<?=AREA_TYPE_ID::CAIROS_DUNGEON?>':
  70. document.getElementById('filter_area_cairos').style.display = 'inline-block';
  71. document.getElementById('filter_area_cairos').setAttribute('name', 'area');
  72. populateStage(10);
  73. document.getElementById('filter_stage').style.display = 'inline-block';
  74. break;
  75. case '<?=AREA_TYPE_ID::RIFT_DUNGEON?>':
  76. document.getElementById('filter_area_rift_dungeon').style.display = 'inline-block';
  77. document.getElementById('filter_area_rift_dungeon').setAttribute('name', 'area');
  78. break;
  79. // TODO: Other areas
  80. // Rift Raid: Don't filter by area.
  81. // Arena: Don't filter by area.
  82. // Guild War: Don't filter by area.
  83. // Guild Siege: Don't filter by area.
  84. // Rift Raid: Don't filter by area.
  85. // Tartarus: Don't filter by area.
  86. // TOA: Don't filter by area.
  87. // Rift Raid: Don't filter by area.
  88. // WB: Don't filter by area.
  89. // Dimensional Rift: Don't filter by area.
  90. // TODO: Filter Dimensional Hole dungeon
  91. }
  92. }
  93. /**
  94. * Shows the stage selector in the filters.
  95. *
  96. * @param total The number of stages to show.
  97. */
  98. function populateStage(total){
  99. var sel = document.getElementById('filter_stage');
  100. while (sel.firstChild) {
  101. sel.removeChild(sel.firstChild);
  102. }
  103. var opt;
  104. var att;
  105. // Empty
  106. opt = document.createElement('option');
  107. tex = document.createTextNode('');
  108. opt.appendChild(tex);
  109. sel.appendChild(opt);
  110. for (var i = 1; i <= total; i ++){
  111. opt = document.createElement('option');
  112. tex = document.createTextNode('Stage ' + i);
  113. att = document.createAttribute('value');
  114. att.value = i;
  115. opt.setAttributeNode(att);
  116. opt.appendChild(tex);
  117. sel.appendChild(opt);
  118. }
  119. }
  120. /**
  121. * Shows the difficulty selector in the filter panel.
  122. *
  123. * @param labyrinth Indicates if the area type is the Tartarus
  124. * labyrinth. If so, it includes 'Easy'.
  125. * @param toa Indicates if the area type is the Tower of
  126. * Ascension. If so, it excludes 'Hell'.
  127. */
  128. function populateDifficulty(labyrinth = false, toa = false){
  129. var sel = document.getElementById('filter_difficulty');
  130. while (sel.firstChild) {
  131. sel.removeChild(sel.firstChild);
  132. }
  133. var opt;
  134. var att;
  135. var tex;
  136. // Empty
  137. opt = document.createElement('option');
  138. tex = document.createTextNode('');
  139. opt.appendChild(tex);
  140. sel.appendChild(opt);
  141. // Easy (Labyrinth only)
  142. if (labyrinth){
  143. opt = document.createElement('option');
  144. tex = document.createTextNode('Easy difficulty');
  145. att = document.createAttribute('value');
  146. att.value = '<?=DIFFICULTY_ID::EASY?>';
  147. opt.setAttributeNode(att);
  148. opt.appendChild(tex);
  149. sel.appendChild(opt);
  150. }
  151. // Normal
  152. opt = document.createElement('option');
  153. tex = document.createTextNode('Normal difficulty');
  154. att = document.createAttribute('value');
  155. att.value = '<?=DIFFICULTY_ID::NORMAL?>';
  156. opt.setAttributeNode(att);
  157. opt.appendChild(tex);
  158. sel.appendChild(opt);
  159. // Hard
  160. opt = document.createElement('option');
  161. tex = document.createTextNode('Hard difficulty');
  162. att = document.createAttribute('value');
  163. att.value = '<?=DIFFICULTY_ID::HARD?>';
  164. opt.setAttributeNode(att);
  165. opt.appendChild(tex);
  166. sel.appendChild(opt);
  167. // Hell
  168. if (!toa){
  169. opt = document.createElement('option');
  170. tex = document.createTextNode('Hell difficulty');
  171. att = document.createAttribute('value');
  172. att.value = '<?=DIFFICULTY_ID::HELL?>';
  173. opt.setAttributeNode(att);
  174. opt.appendChild(tex);
  175. sel.appendChild(opt);
  176. }
  177. }
  178. /**
  179. * Sets the values for the stage and difficulty at page load.
  180. */
  181. function initialValues(){
  182. <?php
  183. if ($page->filters["STAGE"] != null && $page->filters["STAGE"] > 0){
  184. ?>
  185. document.getElementById('filter_stage').selectedIndex = <?=$page->filters["STAGE"]?>;
  186. <?php
  187. }
  188. if ($page->filters["DIFFICULTY"] != null && $page->filters["DIFFICULTY"] > 0){
  189. ?>
  190. document.getElementById('filter_difficulty').selectedIndex = <?=$page->filters["DIFFICULTY"]?>;
  191. <?php
  192. }
  193. ?>
  194. }
  195. /**
  196. * Calls all required functions to draw all diagrams.
  197. */
  198. function populateDiagrams(){
  199. <?php
  200. if ($page->show_data){
  201. ?>
  202. diagramWin();
  203. diagramDropType();
  204. diagramDropRuneSlot();
  205. diagramDropRuneStars();
  206. diagramDropRuneQuality();
  207. <?php
  208. }
  209. ?>
  210. }
  211. /**
  212. * Generates the win rate diagram.
  213. */
  214. function diagramWin(){
  215. var canvas = document.getElementById("diagram_win");
  216. var ctx = canvas.getContext("2d");
  217. ctx.lineWidth = 2;
  218. var lastend = 0;
  219. var data = [<?=$page->win_lose[0]?>, <?=$page->win_lose[1]?>];
  220. var total = 0;
  221. var color = [
  222. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_1')).color,
  223. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_2')).color
  224. ];
  225. for(var e = 0; e < data.length; e++){
  226. total += data[e];
  227. }
  228. for (var i = 0; i < data.length; i++) {
  229. ctx.beginPath();
  230. ctx.moveTo(canvas.width / 2, canvas.height / 2);
  231. ctx.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 * (data[i] / total)), false);
  232. ctx.lineTo(canvas.width / 2, canvas.height / 2);
  233. ctx.fillStyle = '#000000';
  234. ctx.stroke();
  235. ctx.fillStyle = color[i];
  236. ctx.fill();
  237. lastend += Math.PI * 2 * (data[i] / total);
  238. }
  239. }
  240. /**
  241. * Generates the drop rate diagram.
  242. */
  243. function diagramDropType(){
  244. // TODO: Diferenciate scenario, dungeon and hall.
  245. var canvas = document.getElementById("diagram_drop_type");
  246. var ctx = canvas.getContext("2d");
  247. ctx.lineWidth = 2;
  248. var lastend = 0;
  249. var data = [
  250. <?=$page->drop_type["rune"]?>,
  251. <?=$page->drop_type["rune_craft"]?>,
  252. <?=$page->drop_type["item"]?>,
  253. <?=$page->drop_type["sd"]?>,
  254. <?=$page->drop_type["shapeshifting"]?>,
  255. <?=$page->drop_type["unit"]?>,
  256. ];
  257. var total = 0;
  258. var color = [
  259. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_1')).color,
  260. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_2')).color,
  261. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_3')).color,
  262. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_4')).color,
  263. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_5')).color,
  264. getComputedStyle(document.querySelector('div.diagram table.legend tr.color_6')).color,
  265. ];
  266. for(var e = 0; e < data.length; e++){
  267. total += data[e];
  268. }
  269. for (var i = 0; i < data.length; i++) {
  270. ctx.beginPath();
  271. ctx.moveTo(canvas.width/2, canvas.height/2);
  272. ctx.arc(canvas.width/2, canvas.height/2, canvas.height/2, lastend, lastend + (Math.PI * 2 * (data[i] / total)), false);
  273. ctx.lineTo(canvas.width/2, canvas.height/2);
  274. ctx.fillStyle = '#000000';
  275. ctx.stroke();
  276. ctx.fillStyle = color[i];
  277. ctx.fill();
  278. lastend += Math.PI * 2 * (data[i] / total);
  279. }
  280. }
  281. /**
  282. * Generates the rune slot rate diagram.
  283. */
  284. function diagramDropRuneSlot(){
  285. var canvas = document.getElementById("diagram_rune_slot");
  286. var data = [
  287. <?=$page->drop_rune_slot["1"]?>,
  288. <?=$page->drop_rune_slot["2"]?>,
  289. <?=$page->drop_rune_slot["3"]?>,
  290. <?=$page->drop_rune_slot["4"]?>,
  291. <?=$page->drop_rune_slot["5"]?>,
  292. <?=$page->drop_rune_slot["6"]?>
  293. ];
  294. var total = 6;
  295. // Polarchart base
  296. var ctx_base = canvas.getContext("2d");
  297. ctx_base.lineWidth = 1;
  298. ctx_base.font = '32px serif'
  299. ctx_base.textBaseline = 'middle'
  300. ctx_base.textAlign = 'middle'
  301. var lastend = Math.PI + Math.PI / total;
  302. var radius = Math.round((canvas.width / 2) * ((i + 1) / total));
  303. for (var i = 0; i < total; i++) {
  304. ctx_base.moveTo(canvas.width / 2, canvas.height / 2);
  305. ctx_base.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 / total), false);
  306. ctx_base.lineTo(canvas.width / 2, canvas.height / 2);
  307. ctx_base.strokeStyle = '#333333';
  308. ctx_base.stroke();
  309. lastend += (Math.PI * 2 / total);
  310. }
  311. ctx_base.fillStyle = '#33333366';
  312. ctx_base.fill();
  313. // Numbers
  314. ctx_base.fillStyle = '#ffffff';
  315. lastend = Math.PI + Math.PI / total;
  316. for (var i = 0; i < total; i ++){
  317. lastend += (Math.PI * 2 / total);
  318. tx = canvas.width / 2 + canvas.width / 2.3 * Math.cos(lastend);
  319. ty = canvas.width / 2 + canvas.width / 2.3 * Math.sin(lastend);
  320. ctx_base.fillText(i + 1, tx - 8, ty);
  321. }
  322. // Polarchart content
  323. var ctx_data = canvas.getContext("2d");
  324. max = Math.max.apply(null, data) * 1.1;
  325. var initX = 0;
  326. var initY = 0;
  327. let region = new Path2D();
  328. for (var i = 0; i < total; i++) {
  329. var r = Math.round((canvas.width / 2) * data[i] / max);
  330. var x = Math.round(r * Math.sin(Math.PI * 2 / total));
  331. var y = Math.round(r * Math.cos(Math.PI * 2 / total));
  332. // Rotate the point
  333. angle = (i + 4) * Math.PI * 2 / total;
  334. rx = x * Math.cos(angle) - y * Math.sin(angle)
  335. ry = y * Math.cos(angle) + x * Math.sin(angle)
  336. rx += canvas.width / 2;
  337. ry += canvas.width / 2;
  338. if (i == 0){
  339. region.moveTo(rx, ry);
  340. initX = rx;
  341. initY = ry;
  342. }
  343. else{
  344. region.lineTo(rx, ry);
  345. }
  346. }
  347. region.lineTo(initX, initY);
  348. ctx_data.lineWidth = 2;
  349. ctx_data.strokeStyle = '#ff0000';
  350. ctx_data.stroke(region)
  351. ctx_data.fillStyle = '#ff000055';
  352. ctx_data.fill(region)
  353. }
  354. /**
  355. * Generates the rune star rate diagram.
  356. */
  357. function diagramDropRuneStars(){
  358. var canvas = document.getElementById("diagram_rune_stars");
  359. var data = [
  360. <?=$page->drop_rune_stars["6"]?>,
  361. <?=$page->drop_rune_stars["5"]?>,
  362. <?=$page->drop_rune_stars["4"]?>,
  363. <?=$page->drop_rune_stars["3"]?>,
  364. <?=$page->drop_rune_stars["2"]?>,
  365. <?=$page->drop_rune_stars["1"]?>
  366. ];
  367. var total = 6;
  368. // Polarchart base
  369. var ctx_base = canvas.getContext("2d");
  370. ctx_base.lineWidth = 1;
  371. ctx_base.font = '32px serif'
  372. ctx_base.textBaseline = 'middle'
  373. ctx_base.textAlign = 'middle'
  374. var lastend = Math.PI + Math.PI / total;
  375. for (var i = 0; i < total; i++) {
  376. radius = Math.round((canvas.width / 2) * ((i + 1) / total));
  377. ctx_base.moveTo(canvas.width / 2, canvas.height / 2);
  378. ctx_base.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 / total), false);
  379. ctx_base.lineTo(canvas.width / 2, canvas.height / 2);
  380. ctx_base.strokeStyle = '#333333';
  381. ctx_base.stroke();
  382. lastend += (Math.PI * 2 / total);
  383. }
  384. ctx_base.fillStyle = '#33333366';
  385. ctx_base.fill();
  386. // Numbers
  387. ctx_base.fillStyle = '#ffffff';
  388. lastend = Math.PI + Math.PI / total;
  389. for (var i = 0; i < total; i ++){
  390. lastend += (Math.PI * 2 / total);
  391. tx = canvas.width / 2 + canvas.width / 2.3 * Math.cos(lastend);
  392. ty = canvas.width / 2 + canvas.width / 2.3 * Math.sin(lastend);
  393. ctx_base.fillText(6 - i, tx - 8, ty);
  394. }
  395. // Polarchart content
  396. var ctx_data = canvas.getContext("2d");
  397. max = Math.max.apply(null, data) * 1.1;
  398. var initX = 0;
  399. var initY = 0;
  400. let region = new Path2D();
  401. for (var i = 0; i < total; i++) {
  402. var r = Math.round((canvas.width / 2) * data[i] / max);
  403. var x = Math.round(r * Math.sin(Math.PI * 2 / total));
  404. var y = Math.round(r * Math.cos(Math.PI * 2 / total));
  405. // Rotate the point
  406. angle = (i + 4) * Math.PI * 2 / total;
  407. rx = x * Math.cos(angle) - y * Math.sin(angle)
  408. ry = y * Math.cos(angle) + x * Math.sin(angle)
  409. rx += canvas.width / 2;
  410. ry += canvas.width / 2;
  411. if (i == 0){
  412. region.moveTo(rx, ry);
  413. initX = rx;
  414. initY = ry;
  415. }
  416. else{
  417. region.lineTo(rx, ry);
  418. }
  419. }
  420. region.lineTo(initX, initY);
  421. ctx_data.lineWidth = 2;
  422. ctx_data.strokeStyle = '#ff0000';
  423. ctx_data.stroke(region)
  424. ctx_data.fillStyle = '#ff000055';
  425. ctx_data.fill(region)
  426. }
  427. /**
  428. * Generates the rune quality rate diagram.
  429. */
  430. function diagramDropRuneQuality(){
  431. var canvas = document.getElementById("diagram_rune_quality");
  432. var data = [
  433. <?=$page->drop_rune_quality[strval(QUALITY_ID::LEGEND)]?>,
  434. <?=$page->drop_rune_quality[strval(QUALITY_ID::HERO)]?>,
  435. <?=$page->drop_rune_quality[strval(QUALITY_ID::RARE)]?>,
  436. <?=$page->drop_rune_quality[strval(QUALITY_ID::MAGIC)]?>,
  437. <?=$page->drop_rune_quality[strval(QUALITY_ID::NORMAL)]?>
  438. ];
  439. var total = 5;
  440. // Polarchart base
  441. var ctx_base = canvas.getContext("2d");
  442. ctx_base.lineWidth = 1;
  443. //var lastend = Math.PI * 2 / (0.5 * total / Math.PI);
  444. var lastend = ((270 - (180 / (total))) * Math.PI / 180);
  445. var color = [
  446. '#f5790066', // LEGEND
  447. '#ad7fa866', // HERO
  448. '#15c6e166', // RARE
  449. '#55ff5566', // MAGIC
  450. '#cccccc66' // NORMAL
  451. ];
  452. for (var i = 0; i < total; i++) {
  453. ctx_base.beginPath();
  454. radius = Math.round((canvas.width / 2) * ((i + 1) / total));
  455. ctx_base.moveTo(canvas.width / 2, canvas.height / 2);
  456. ctx_base.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 / total), false);
  457. ctx_base.lineTo(canvas.width / 2, canvas.height / 2);
  458. ctx_base.fillStyle = color[i];
  459. ctx_base.fill();
  460. ctx_base.strokeStyle = '#333333';
  461. ctx_base.stroke();
  462. lastend += (Math.PI * 2 / total);
  463. }
  464. //ctx_base.fillStyle = '#33333366';
  465. //ctx_base.fill()
  466. // Polarchart content
  467. var ctx_data = canvas.getContext("2d");
  468. max = Math.max.apply(null, data) * 1.1;
  469. var initX = 0;
  470. var initY = 0;
  471. let region = new Path2D();
  472. for (var i = 0; i < total; i++) {
  473. var r = Math.round((canvas.width / 2) * data[i] / max);
  474. var x = Math.round(r * Math.sin(Math.PI * 2 / total));
  475. var y = Math.round(r * Math.cos(Math.PI * 2 / total));
  476. // Rotate the point
  477. // TOTALLY experimental, not reliable for a different number of sectors.
  478. angle = (i * Math.PI * 2 / total) + 2 * Math.PI / (2 * (total - 1)) + 270 * (4.6/6) * Math.PI / 180;
  479. rx = x * Math.cos(angle) - y * Math.sin(angle)
  480. ry = y * Math.cos(angle) + x * Math.sin(angle)
  481. rx += canvas.width / 2;
  482. ry += canvas.width / 2;
  483. if (i == 0){
  484. region.moveTo(rx, ry);
  485. initX = rx;
  486. initY = ry;
  487. }
  488. else{
  489. region.lineTo(rx, ry);
  490. }
  491. }
  492. region.lineTo(initX, initY);
  493. ctx_data.lineWidth = 2;
  494. ctx_data.strokeStyle = '#ff0000';
  495. ctx_data.stroke(region)
  496. ctx_data.fillStyle = '#ff000055';
  497. ctx_data.fill(region)
  498. }
  499. // TODO: Script to show/hide area selector
  500. </script>
  501. </head>
  502. <body onload='populateDiagrams();selectAreaType();initialValues();'>
  503. <?php
  504. include __DIR__ . "/inc/header.php";
  505. ?>
  506. <aside class='filters'>
  507. <h2>
  508. Statistics
  509. </h2>
  510. <form action='/<?=get_context()->get_player()-id?>/stats/' method='get' class='filter'>
  511. <table>
  512. <tr>
  513. <td class='filter'>
  514. <span>Area:</span>
  515. </td>
  516. </tr>
  517. <tr>
  518. <td class='filter'>
  519. <?php
  520. $selected = array_fill(0, 12 + 1, "");
  521. $selected[$page->filters["AREA_TYPE"]] = "selected";
  522. ?>
  523. <select name='area_type' id='filter_area_type' onChange='selectAreaType();'>
  524. <option value='0'></option>
  525. <option value='<?=AREA_TYPE_ID::SCENARIO?>' <?=$selected[AREA_TYPE_ID::SCENARIO]?>>Scenario</option>
  526. <option value='<?=AREA_TYPE_ID::CAIROS_DUNGEON?>' <?=$selected[AREA_TYPE_ID::CAIROS_DUNGEON]?>>Cairos Dungeon</option>
  527. <option value='<?=AREA_TYPE_ID::RIFT_DUNGEON?>' <?=$selected[AREA_TYPE_ID::RIFT_DUNGEON]?>>Rift Beast</option>
  528. <option value='<?=AREA_TYPE_ID::RIFT_RAID?>' <?=$selected[AREA_TYPE_ID::RIFT_RAID]?>>Rift Raid</option>
  529. <option value='<?=AREA_TYPE_ID::DIMENSIONAL_HOLE?>' <?=$selected[AREA_TYPE_ID::DIMENSIONAL_HOLE]?>>Dimensional Hole</option>
  530. </select>
  531. <?php
  532. $selected = array_fill(0, 9002, "");
  533. $selected[$page->filters["AREA"]] = "selected";
  534. ?>
  535. <select class='filter_area' id='filter_area_scenario'>
  536. <option value='0'></option>
  537. <option value='<?=AREA_TYPE_ID::SCENARIO?>' <?=$selected[AREA_TYPE_ID::SCENARIO]?>>Scenario</option>
  538. <option value='<?=AREA_TYPE_ID::CAIROS_DUNGEON?>' <?=$selected[AREA_TYPE_ID::CAIROS_DUNGEON]?>>Cairos Dungeon</option>
  539. <option value='<?=AREA_TYPE_ID::RIFT_DUNGEON?>' <?=$selected[AREA_TYPE_ID::RIFT_DUNGEON]?>>Rift Beast</option>
  540. <option value='<?=AREA_TYPE_ID::RIFT_RAID?>' <?=$selected[AREA_TYPE_ID::RIFT_RAID]?>>Rift Raid</option>
  541. <option value='<?=AREA_TYPE_ID::DIMENSIONAL_HOLE?>' <?=$selected[AREA_TYPE_ID::DIMENSIONAL_HOLE]?>>Dimensional Hole</option>
  542. <option value='<?=AREA_TYPE_ID::ARENA?>' <?=$selected[AREA_TYPE_ID::ARENA]?>>Arena</option>
  543. <option value='<?=AREA_TYPE_ID::GUILD_WAR?>' <?=$selected[AREA_TYPE_ID::GUILD_WAR]?>>Guild War</option>
  544. <option value='<?=AREA_TYPE_ID::GUILD_SIEGE?>' <?=$selected[AREA_TYPE_ID::GUILD_SIEGE]?>>Guild Siege</option>
  545. <option value='<?=AREA_TYPE_ID::TARTARUS_LABYRINTH?>' <?=$selected[AREA_TYPE_ID::TARTARUS_LABYRINTH]?>>Tartarus Labyrinth</option>
  546. <option value='<?=AREA_TYPE_ID::TRIAL_OF_ASCENSION?>' <?=$selected[AREA_TYPE_ID::TRIAL_OF_ASCENSION]?>>Trial of Ascension</option>
  547. <option value='<?=AREA_TYPE_ID::WORLD_BOSS?>' <?=$selected[AREA_TYPE_ID::WORLD_BOSS]?>>World Boss</option>
  548. <option value='<?=AREA_TYPE_ID::DIMENSIONAL_RIFT?>' <?=$selected[AREA_TYPE_ID::DIMENSIONAL_RIFT]?>>Dimensional Rift</option>
  549. </select>
  550. <select class='filter_area' id='filter_area_cairos'>
  551. <option value='0'></option>
  552. <option value='<?=DUNGEON_ID::GIANTS_KEEP?>' <?=$selected[DUNGEON_ID::GIANTS_KEEP]?>>Giant&#39;s Keep</option>
  553. <option value='<?=DUNGEON_ID::DRAGONS_LAIR?>' <?=$selected[DUNGEON_ID::DRAGONS_LAIR]?>>Dragon&#39;s Lair</option>
  554. <option value='<?=DUNGEON_ID::NECROPOLIS?>' <?=$selected[DUNGEON_ID::NECROPOLIS]?>>Necropolis</option>
  555. <option value='<?=DUNGEON_ID::HALL_OF_MAGIC?>' <?=$selected[DUNGEON_ID::HALL_OF_MAGIC]?>>Hall of Magic</option>
  556. <option value='<?=DUNGEON_ID::HALL_OF_LIGHT?>' <?=$selected[DUNGEON_ID::HALL_OF_LIGHT]?>>Hall of Light</option>
  557. <option value='<?=DUNGEON_ID::HALL_OF_DARK?>' <?=$selected[DUNGEON_ID::HALL_OF_DARK]?>>Hall of Dark</option>
  558. <option value='<?=DUNGEON_ID::HALL_OF_FIRE?>' <?=$selected[DUNGEON_ID::HALL_OF_FIRE]?>>Hall of Fire</option>
  559. <option value='<?=DUNGEON_ID::HALL_OF_WATER?>' <?=$selected[DUNGEON_ID::HALL_OF_WATER]?>>Hall of Water</option>
  560. <option value='<?=DUNGEON_ID::HALL_OF_WIND?>' <?=$selected[DUNGEON_ID::HALL_OF_WIND]?>>Hall of Wind</option>
  561. </select>
  562. <select id='filter_area_rift_dungeon' class='filter_area'>
  563. <option value='0'></option>
  564. <option value='<?=ELEMENTAL_RIFT_DUNGEON_ID::LIGHT_BEAST?>' <?=$selected[ELEMENTAL_RIFT_DUNGEON_ID::LIGHT_BEAST]?>>Light Beast</option>
  565. <option value='<?=ELEMENTAL_RIFT_DUNGEON_ID::DARK_BEAST?>' <?=$selected[ELEMENTAL_RIFT_DUNGEON_ID::DARK_BEAST]?>>Dark Beast</option>
  566. <option value='<?=ELEMENTAL_RIFT_DUNGEON_ID::FIRE_BEAST?>' <?=$selected[ELEMENTAL_RIFT_DUNGEON_ID::FIRE_BEAST]?>>Fire Beast</option>
  567. <option value='<?=ELEMENTAL_RIFT_DUNGEON_ID::ICE_BEAST?>' <?=$selected[ELEMENTAL_RIFT_DUNGEON_ID::ICE_BEAST]?>>Ice Beast</option>
  568. <option value='<?=ELEMENTAL_RIFT_DUNGEON_ID::WIND_BEAST?>' <?=$selected[ELEMENTAL_RIFT_DUNGEON_ID::WIND_BEAST]?>>Wind Beast</option>
  569. </select>
  570. <select id='filter_stage' name='stage'>
  571. </select>
  572. <select id='filter_difficulty' name='difficulty'>
  573. </select>
  574. </td>
  575. </tr>
  576. </table>
  577. <input type='submit' value='Apply'/>
  578. </form>
  579. </aside> <!-- #filters -->
  580. <main>
  581. <?php
  582. if ($page->show_data){
  583. ?>
  584. <section class='content'>
  585. <h2>
  586. Stats
  587. </h2>
  588. <article>
  589. <div id='win' class='diagram'>
  590. <h3>
  591. Victory rate
  592. </h3>
  593. <canvas id='diagram_win' width='200' height='200'></canvas>
  594. <?php
  595. $total = $page->win_lose[0] + $page->win_lose[1];
  596. // Fix divisions by 0 (dont use in total count):
  597. if ($total == 0){
  598. $total ++;
  599. }
  600. ?>
  601. <table class='legend'>
  602. <tr class='color_1'>
  603. <td>
  604. Victories:
  605. </td>
  606. <td>
  607. <?=$page->win_lose[0]?>
  608. </td>
  609. <td>
  610. (<?=number_format(($page->win_lose[0] * 100) / $total, 2, ".", ",")?>%)
  611. </td>
  612. </tr>
  613. <tr class='color_2'>
  614. <td>
  615. Defeats:
  616. </td>
  617. <td>
  618. <?=$page->win_lose[1]?>
  619. </td>
  620. <td>
  621. (<?=number_format(($page->win_lose[1] * 100) / $total, 2, ".", ",")?>%)
  622. </td>
  623. </tr>
  624. <tr class='color_0'>
  625. <td>
  626. Total:
  627. </td>
  628. <td colspan='2'>
  629. <?=($page->win_lose[0] + $page->win_lose[1])?>
  630. </td>
  631. </tr>
  632. </table>
  633. </div>
  634. <div id='drop_type' class='diagram'>
  635. <h3>
  636. Drop rate
  637. </h3>
  638. <canvas id='diagram_drop_type' width='200' height='200'></canvas>
  639. <table class='legend'>
  640. <?php
  641. // Do some calculations
  642. $rune = $page->drop_type["rune"];
  643. $rucr = $page->drop_type["rune_craft"];
  644. $item = $page->drop_type["item"];
  645. $sedu = $page->drop_type["sd"];
  646. $shap = $page->drop_type["shapeshifting"];
  647. $unit = $page->drop_type["unit"];
  648. $total = $rune + $rucr + $item + $sedu + $shap + $unit;
  649. // Fix divisions by 0:
  650. if ($total == 0){
  651. $total ++;
  652. }
  653. ?>
  654. <tr class='color_1'>
  655. <td>
  656. Rune:
  657. </td>
  658. <td>
  659. <?=$rune?>
  660. </td>
  661. <td>
  662. (<?=number_format(($rune * 100) / $total, 2, ".", ",")?>%)
  663. </td>
  664. </tr>
  665. <tr class='color_2'>
  666. <td>
  667. Rune craft item:
  668. </td>
  669. <td>
  670. <?=$rucr?>
  671. </td>
  672. <td>
  673. (<?=number_format(($rucr * 100) / $total, 2, ".", ",")?>%)
  674. </td>
  675. </tr>
  676. <tr class='color_3'>
  677. <td>
  678. Item:
  679. </td>
  680. <td>
  681. <?=$item?>
  682. </td>
  683. <td>
  684. (<?=number_format(($item * 100) / $total, 2, ".", ",")?>%)
  685. </td>
  686. </tr>
  687. <tr class='color_4'>
  688. <td>
  689. Secret Dungeon:
  690. </td>
  691. <td>
  692. <?=$sedu?>
  693. </td>
  694. <td>
  695. (<?=number_format(($sedu * 100) / $total, 2, ".", ",")?>%)
  696. </td>
  697. </tr>
  698. <tr class='color_5'>
  699. <td>
  700. Transmog Stone:
  701. </td>
  702. <td>
  703. <?=$shap?>
  704. </td>
  705. <td>
  706. (<?=number_format(($shap * 100) / $total, 2, ".", ",")?>%)
  707. </td>
  708. </tr>
  709. <tr class='color_6'>
  710. <td>
  711. Unit:
  712. </td>
  713. <td>
  714. <?=$unit?>
  715. </td>
  716. <td>
  717. (<?=number_format(($unit * 100) / $total, 2, ".", ",")?>%)
  718. </td>
  719. </tr>
  720. </table>
  721. </div>
  722. <div id='drop_rune_slot' class='diagram'>
  723. <h3>
  724. Rune drops by slot
  725. </h3>
  726. <canvas id='diagram_rune_slot' width='200' height='200'></canvas>
  727. <table class='legend'>
  728. <?php
  729. $total = array_sum($page->drop_rune_slot);
  730. // Fix divisions by 0:
  731. if ($total == 0){
  732. $total ++;
  733. }
  734. for ($i = 1; $i <= 6; $i ++){
  735. $val = $page->drop_rune_slot[strval($i)]
  736. ?>
  737. <tr class='color_0'>
  738. <td>
  739. Slot <?=$i?>:
  740. </td>
  741. <td>
  742. <?=$val?>
  743. </td>
  744. <td>
  745. (<?=number_format(($val * 100) / $total, 2, ".", ",")?>%)
  746. </td>
  747. </tr>
  748. <?php
  749. }
  750. ?>
  751. </table>
  752. </div>
  753. <div id='drop_rune_stars' class='diagram'>
  754. <h3>
  755. Rune drops by stars
  756. </h3>
  757. <canvas id='diagram_rune_stars' width='200' height='200'></canvas>
  758. <table class='legend'>
  759. <?php
  760. $total = array_sum($page->drop_rune_stars);
  761. // Fix divisions by 0:
  762. if ($total == 0){
  763. $total ++;
  764. }
  765. for ($i = 6; $i >= 1; $i --){
  766. $val = $page->drop_rune_stars[strval($i)]
  767. ?>
  768. <tr class='color_0'>
  769. <td>
  770. <?php
  771. for ($j = 1; $j <= $i; $j ++){
  772. ?>
  773. <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
  774. <?php
  775. }
  776. ?>
  777. </td>
  778. <td>
  779. <?=$val?>
  780. </td>
  781. <td>
  782. (<?=number_format(($val * 100) / $total, 2, ".", ",")?>%)
  783. </td>
  784. </tr>
  785. <?php
  786. }
  787. ?>
  788. </table>
  789. </div>
  790. <div id='drop_rune_quality' class='diagram'>
  791. <h3>
  792. Rune drops by quality
  793. </h3>
  794. <canvas id='diagram_rune_quality' width='200' height='200'></canvas>
  795. <table class='legend'>
  796. <?php
  797. $total = array_sum($page->drop_rune_quality);
  798. // Fix divisions by 0:
  799. if ($total == 0){
  800. $total ++;
  801. }
  802. ?>
  803. <tr class='color_legend'>
  804. <td>
  805. Legend:
  806. </td>
  807. <td>
  808. <?=$page->drop_rune_quality[QUALITY_ID::LEGEND]?>
  809. </td>
  810. <td>
  811. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::LEGEND] * 100) / $total, 2, ".", ",")?>%)
  812. </td>
  813. </tr>
  814. <tr class='color_hero'>
  815. <td>
  816. Hero:
  817. </td>
  818. <td>
  819. <?=$page->drop_rune_quality[QUALITY_ID::HERO]?>
  820. </td>
  821. <td>
  822. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::HERO] * 100) / $total, 2, ".", ",")?>%)
  823. </td>
  824. </tr>
  825. <tr class='color_rare'>
  826. <td>
  827. Rare:
  828. </td>
  829. <td>
  830. <?=$page->drop_rune_quality[QUALITY_ID::RARE]?>
  831. </td>
  832. <td>
  833. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::RARE] * 100) / $total, 2, ".", ",")?>%)
  834. </td>
  835. </tr>
  836. <tr class='color_magic'>
  837. <td>
  838. Magic:
  839. </td>
  840. <td>
  841. <?=$page->drop_rune_quality[QUALITY_ID::MAGIC]?>
  842. </td>
  843. <td>
  844. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::MAGIC] * 100) / $total, 2, ".", ",")?>%)
  845. </td>
  846. </tr>
  847. <tr class='color_normal'>
  848. <td>
  849. Normal:
  850. </td>
  851. <td>
  852. <?=$page->drop_rune_quality[QUALITY_ID::NORMAL]?>
  853. </td>
  854. <td>
  855. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::NORMAL] * 100) / $total, 2, ".", ",")?>%)
  856. </td>
  857. </tr>
  858. </table>
  859. </div>
  860. </article>
  861. </section>
  862. <?php
  863. }
  864. ?>
  865. </main>
  866. <?php
  867. include __DIR__ . "/inc/footer.php";
  868. ?>
  869. </body>
  870. </html>