stats.php 43 KB

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