stats.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. <?php
  2. /**
  3. * Runs view.
  4. *
  5. * Contains the view layout and ome code to present the data.
  6. *
  7. * @category View
  8. * @property_read Stats_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?>stats.css'/>
  22. <link rel='stylesheet' type='text/css' href='<?=URL::CSS?>filters.css'/>
  23. <!-- Meta tags -->
  24. <link rel='canonical' href='<?=$page->canonical?>'/>
  25. <link rel='author' href='<?=$page->author?>'/>
  26. <link rel='publisher' href='<?=$page->author?>'/>
  27. <meta name='description' content='<?=$page->description?>'/>
  28. <meta property='og:title' content='<?=$page->title?>'/>
  29. <meta property='og:url' content='<?=$page->canonical?>'/>
  30. <meta property='og:description' content='<?=$page->description?>'/>
  31. <meta property='og:image' content='<?=$page->icon?>'/>
  32. <meta property='og:site_name' content='<?=$page->name?>'/>
  33. <meta property='og:type' content='website'/>
  34. <meta property='og:locale' content='en'/>
  35. <meta name='twitter:card' content='summary'/>
  36. <meta name='twitter:title' content='<?=$page->title?>'/>
  37. <meta name='twitter:description' content='<?=$page->description?>'/>
  38. <meta name='twitter:image' content='<?=$page->icon?>'/>
  39. <meta name='twitter:url' content='<?=$page->canonical?>'/>
  40. <meta name='robots' content='index follow'/>
  41. <script>
  42. /**
  43. * Shows or hiddes the filters panel.
  44. */
  45. function toggleFilters(){
  46. var content = document.getElementById('filters_content');
  47. var slid = document.getElementById('filters_slid');
  48. if (content.style.maxHeight != '30em'){
  49. content.style.maxHeight = '30em';
  50. slid.style.transform = 'rotate(90deg)';
  51. }
  52. else{
  53. content.style.maxHeight = '0px';
  54. slid.style.transform = 'rotate(0deg)';
  55. }
  56. };
  57. function populateDiagrams(){
  58. diagramWin();
  59. diagramDropType();
  60. diagramDropRuneSlot();
  61. diagramDropRuneStars();
  62. diagramDropRuneQuality();
  63. }
  64. function diagramWin(){
  65. var canvas = document.getElementById("diagram_win");
  66. var ctx = canvas.getContext("2d");
  67. ctx.lineWidth = 2;
  68. var lastend = 0;
  69. var data = [<?=$page->win_lose[0]?>, <?=$page->win_lose[1]?>];
  70. var total = 0;
  71. var color = ['#00ff00','#ff0000'];
  72. for(var e = 0; e < data.length; e++){
  73. total += data[e];
  74. }
  75. for (var i = 0; i < data.length; i++) {
  76. ctx.beginPath();
  77. ctx.moveTo(canvas.width / 2, canvas.height / 2);
  78. ctx.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 * (data[i] / total)), false);
  79. ctx.lineTo(canvas.width / 2, canvas.height / 2);
  80. ctx.fillStyle = '#000000';
  81. ctx.stroke();
  82. ctx.fillStyle = color[i];
  83. ctx.fill();
  84. lastend += Math.PI * 2 * (data[i] / total);
  85. }
  86. }
  87. function diagramDropType(){
  88. // TODO: Diferenciate scenario, dungeon and hall.
  89. var canvas = document.getElementById("diagram_drop_type");
  90. var ctx = canvas.getContext("2d");
  91. ctx.lineWidth = 2;
  92. var lastend = 0;
  93. var data = [
  94. <?=$page->drop_type["rune"]?>,
  95. <?=$page->drop_type["rune_craft"]?>,
  96. <?=$page->drop_type["item"]?>,
  97. <?=$page->drop_type["sd"]?>,
  98. <?=$page->drop_type["shapeshifting"]?>,
  99. <?=$page->drop_type["unit"]?>,
  100. ];
  101. var total = 0;
  102. var color = ['#00ff00', '#ff0000', '#0000ff' , '#ffff00', '#ff00ff', '#00ffff'];
  103. for(var e = 0; e < data.length; e++){
  104. total += data[e];
  105. }
  106. for (var i = 0; i < data.length; i++) {
  107. ctx.beginPath();
  108. ctx.moveTo(canvas.width/2, canvas.height/2);
  109. ctx.arc(canvas.width/2, canvas.height/2, canvas.height/2, lastend, lastend + (Math.PI * 2 * (data[i] / total)), false);
  110. ctx.lineTo(canvas.width/2, canvas.height/2);
  111. ctx.fillStyle = '#000000';
  112. ctx.stroke();
  113. ctx.fillStyle = color[i];
  114. ctx.fill();
  115. lastend += Math.PI * 2 * (data[i] / total);
  116. }
  117. }
  118. function diagramDropRuneSlot(){
  119. var canvas = document.getElementById("diagram_rune_slot");
  120. var data = [
  121. <?=$page->drop_rune_slot["1"]?>,
  122. <?=$page->drop_rune_slot["2"]?>,
  123. <?=$page->drop_rune_slot["3"]?>,
  124. <?=$page->drop_rune_slot["4"]?>,
  125. <?=$page->drop_rune_slot["5"]?>,
  126. <?=$page->drop_rune_slot["6"]?>
  127. ];
  128. var total = 6;
  129. // Polarchart base
  130. var ctx_base = canvas.getContext("2d");
  131. ctx_base.lineWidth = 1;
  132. var lastend = Math.PI / total;
  133. for (var i = 0; i < total; i++) {
  134. radius = Math.round((canvas.width / 2) * ((i + 1) / total));
  135. ctx_base.moveTo(canvas.width / 2, canvas.height / 2);
  136. ctx_base.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 / total), false);
  137. ctx_base.lineTo(canvas.width / 2, canvas.height / 2);
  138. ctx_base.strokeStyle = '#333333';
  139. ctx_base.stroke();
  140. lastend += (Math.PI * 2 / total);
  141. }
  142. ctx_base.fillStyle = '#33333366';
  143. ctx_base.fill()
  144. // Polarchart content
  145. var ctx_data = canvas.getContext("2d");
  146. max = Math.max.apply(null, data) * 1.1;
  147. var initX = 0;
  148. var initY = 0;
  149. let region = new Path2D();
  150. for (var i = 0; i < total; i++) {
  151. var r = Math.round((canvas.width / 2) * data[i] / max);
  152. var x = Math.round(r * Math.sin(Math.PI * 2 / total));
  153. var y = Math.round(r * Math.cos(Math.PI * 2 / total));
  154. // Rotate the point
  155. angle = (i + 4) * Math.PI * 2 / total;
  156. rx = x * Math.cos(angle) - y * Math.sin(angle)
  157. ry = y * Math.cos(angle) + x * Math.sin(angle)
  158. rx += canvas.width / 2;
  159. ry += canvas.width / 2;
  160. if (i == 0){
  161. region.moveTo(rx, ry);
  162. initX = rx;
  163. initY = ry;
  164. }
  165. else{
  166. region.lineTo(rx, ry);
  167. }
  168. }
  169. region.lineTo(initX, initY);
  170. ctx_data.lineWidth = 2;
  171. ctx_data.strokeStyle = '#ff0000';
  172. ctx_data.stroke(region)
  173. ctx_data.fillStyle = '#ff000055';
  174. ctx_data.fill(region)
  175. }
  176. function diagramDropRuneStars(){
  177. var canvas = document.getElementById("diagram_rune_stars");
  178. var data = [
  179. <?=$page->drop_rune_stars["6"]?>,
  180. <?=$page->drop_rune_stars["5"]?>,
  181. <?=$page->drop_rune_stars["4"]?>,
  182. <?=$page->drop_rune_stars["3"]?>,
  183. <?=$page->drop_rune_stars["2"]?>,
  184. <?=$page->drop_rune_stars["1"]?>
  185. ];
  186. var total = 6;
  187. // Polarchart base
  188. var ctx_base = canvas.getContext("2d");
  189. ctx_base.lineWidth = 1;
  190. var lastend = Math.PI / total;
  191. for (var i = 0; i < total; i++) {
  192. radius = Math.round((canvas.width / 2) * ((i + 1) / total));
  193. ctx_base.moveTo(canvas.width / 2, canvas.height / 2);
  194. ctx_base.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 / total), false);
  195. ctx_base.lineTo(canvas.width / 2, canvas.height / 2);
  196. ctx_base.strokeStyle = '#333333';
  197. ctx_base.stroke();
  198. lastend += (Math.PI * 2 / total);
  199. }
  200. ctx_base.fillStyle = '#33333366';
  201. ctx_base.fill()
  202. // Polarchart content
  203. var ctx_data = canvas.getContext("2d");
  204. max = Math.max.apply(null, data) * 1.1;
  205. var initX = 0;
  206. var initY = 0;
  207. let region = new Path2D();
  208. for (var i = 0; i < total; i++) {
  209. var r = Math.round((canvas.width / 2) * data[i] / max);
  210. var x = Math.round(r * Math.sin(Math.PI * 2 / total));
  211. var y = Math.round(r * Math.cos(Math.PI * 2 / total));
  212. // Rotate the point
  213. angle = (i + 4) * Math.PI * 2 / total;
  214. rx = x * Math.cos(angle) - y * Math.sin(angle)
  215. ry = y * Math.cos(angle) + x * Math.sin(angle)
  216. rx += canvas.width / 2;
  217. ry += canvas.width / 2;
  218. if (i == 0){
  219. region.moveTo(rx, ry);
  220. initX = rx;
  221. initY = ry;
  222. }
  223. else{
  224. region.lineTo(rx, ry);
  225. }
  226. }
  227. region.lineTo(initX, initY);
  228. ctx_data.lineWidth = 2;
  229. ctx_data.strokeStyle = '#ff0000';
  230. ctx_data.stroke(region)
  231. ctx_data.fillStyle = '#ff000055';
  232. ctx_data.fill(region)
  233. }
  234. function diagramDropRuneQuality(){
  235. var canvas = document.getElementById("diagram_rune_quality");
  236. var data = [
  237. <?=$page->drop_rune_quality[strval(QUALITY_ID::LEGEND)]?>,
  238. <?=$page->drop_rune_quality[strval(QUALITY_ID::HERO)]?>,
  239. <?=$page->drop_rune_quality[strval(QUALITY_ID::RARE)]?>,
  240. <?=$page->drop_rune_quality[strval(QUALITY_ID::MAGIC)]?>,
  241. <?=$page->drop_rune_quality[strval(QUALITY_ID::NORMAL)]?>
  242. ];
  243. var total = 5;
  244. // Polarchart base
  245. var ctx_base = canvas.getContext("2d");
  246. ctx_base.lineWidth = 1;
  247. //var lastend = Math.PI * 2 / (0.5 * total / Math.PI);
  248. var lastend = 270 * Math.PI / 180;
  249. for (var i = 0; i < total; i++) {
  250. radius = Math.round((canvas.width / 2) * ((i + 1) / total));
  251. ctx_base.moveTo(canvas.width / 2, canvas.height / 2);
  252. ctx_base.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 / total), false);
  253. ctx_base.lineTo(canvas.width / 2, canvas.height / 2);
  254. ctx_base.strokeStyle = '#333333';
  255. ctx_base.stroke();
  256. lastend += (Math.PI * 2 / total);
  257. }
  258. ctx_base.fillStyle = '#33333366';
  259. ctx_base.fill()
  260. // Polarchart content
  261. var ctx_data = canvas.getContext("2d");
  262. max = Math.max.apply(null, data) * 1.1;
  263. var initX = 0;
  264. var initY = 0;
  265. let region = new Path2D();
  266. for (var i = 0; i < total; i++) {
  267. var r = Math.round((canvas.width / 2) * data[i] / max);
  268. var x = Math.round(r * Math.sin(Math.PI * 2 / total));
  269. var y = Math.round(r * Math.cos(Math.PI * 2 / total));
  270. // Rotate the point
  271. // TOTALLY experimental, not reliable for a different number of sectors.
  272. angle = (i * Math.PI * 2 / total) + 2 * Math.PI / (2 * (total - 1)) + 270 * (4.6/6) * Math.PI / 180;
  273. rx = x * Math.cos(angle) - y * Math.sin(angle)
  274. ry = y * Math.cos(angle) + x * Math.sin(angle)
  275. rx += canvas.width / 2;
  276. ry += canvas.width / 2;
  277. if (i == 0){
  278. region.moveTo(rx, ry);
  279. initX = rx;
  280. initY = ry;
  281. }
  282. else{
  283. region.lineTo(rx, ry);
  284. }
  285. }
  286. region.lineTo(initX, initY);
  287. ctx_data.lineWidth = 2;
  288. ctx_data.strokeStyle = '#ff0000';
  289. ctx_data.stroke(region)
  290. ctx_data.fillStyle = '#ff000055';
  291. ctx_data.fill(region)
  292. }
  293. // TODO: Script to show/hide area selector
  294. </script>
  295. </head>
  296. <body onload='populateDiagrams();'>
  297. <?php
  298. include __DIR__ . "/inc/header.php";
  299. ?>
  300. <section class='filters'>
  301. <h2 id='filters_title' onClick='toggleFilters();'>
  302. <img id='filters_slid' id='filters_slid' alt=' ' src='<?=URL::IMG["ICON"]?>slid.png'/>
  303. Stat filters
  304. </h2>
  305. <article id='filters_content'>
  306. <?php
  307. $filters = $page->filters;
  308. include __DIR__ . "/inc/filter_stats.php";
  309. ?>
  310. </article>
  311. </section> <!-- #filters -->
  312. <section class='content'>
  313. <h2>
  314. Stats
  315. </h2>
  316. <article>
  317. <div id='win' class='diagram'>
  318. <h3>
  319. Victory rate
  320. </h3>
  321. <canvas id='diagram_win' width='200' height='200'></canvas>
  322. <table class='legend'>
  323. <tr class='color_1'>
  324. <td>
  325. Victories:
  326. </td>
  327. <td>
  328. <?=$page->win_lose[0]?>
  329. </td>
  330. <td>
  331. (<?=number_format(($page->win_lose[0] * 100) / ($page->win_lose[0] + $page->win_lose[1]), 2, ".", ",")?>%)
  332. </td>
  333. </tr>
  334. <tr class='color_2'>
  335. <td>
  336. Defeats:
  337. </td>
  338. <td>
  339. <?=$page->win_lose[1]?>
  340. </td>
  341. <td>
  342. (<?=number_format(($page->win_lose[1] * 100) / ($page->win_lose[0] + $page->win_lose[1]), 2, ".", ",")?>%)
  343. </td>
  344. </tr>
  345. <tr class='color_0'>
  346. <td>
  347. Total:
  348. </td>
  349. <td colspan='2'>
  350. <?=($page->win_lose[0] + $page->win_lose[1])?>
  351. </td>
  352. </tr>
  353. </table>
  354. </div>
  355. <div id='drop_type' class='diagram'>
  356. <h3>
  357. Drop rate
  358. </h3>
  359. <canvas id='diagram_drop_type' width='200' height='200'></canvas>
  360. <table class='legend'>
  361. <?php
  362. // Do some calculations
  363. $rune = $page->drop_type["rune"];
  364. $rucr = $page->drop_type["rune_craft"];
  365. $item = $page->drop_type["item"];
  366. $sedu = $page->drop_type["sd"];
  367. $shap = $page->drop_type["shapeshifting"];
  368. $unit = $page->drop_type["unit"];
  369. $total = $rune + $rucr + $item + $sedu + $shap + $unit;
  370. ?>
  371. <tr class='color_1'>
  372. <td>
  373. Rune:
  374. </td>
  375. <td>
  376. <?=$rune?>
  377. </td>
  378. <td>
  379. (<?=number_format(($rune * 100) / $total, 2, ".", ",")?>%)
  380. </td>
  381. </tr>
  382. <tr class='color_2'>
  383. <td>
  384. Rune craft item:
  385. </td>
  386. <td>
  387. <?=$rucr?>
  388. </td>
  389. <td>
  390. (<?=number_format(($rucr * 100) / $total, 2, ".", ",")?>%)
  391. </td>
  392. </tr>
  393. <tr class='color_3'>
  394. <td>
  395. Item:
  396. </td>
  397. <td>
  398. <?=$item?>
  399. </td>
  400. <td>
  401. (<?=number_format(($item * 100) / $total, 2, ".", ",")?>%)
  402. </td>
  403. </tr>
  404. <tr class='color_4'>
  405. <td>
  406. Secret Dungeon:
  407. </td>
  408. <td>
  409. <?=$sedu?>
  410. </td>
  411. <td>
  412. (<?=number_format(($sedu * 100) / $total, 2, ".", ",")?>%)
  413. </td>
  414. </tr>
  415. <tr class='color_5'>
  416. <td>
  417. Transmog Stone:
  418. </td>
  419. <td>
  420. <?=$shap?>
  421. </td>
  422. <td>
  423. (<?=number_format(($shap * 100) / $total, 2, ".", ",")?>%)
  424. </td>
  425. </tr>
  426. <tr class='color_6'>
  427. <td>
  428. Unit:
  429. </td>
  430. <td>
  431. <?=$unit?>
  432. </td>
  433. <td>
  434. (<?=number_format(($unit * 100) / $total, 2, ".", ",")?>%)
  435. </td>
  436. </tr>
  437. </table>
  438. </div>
  439. <div id='drop_rune_slot' class='diagram'>
  440. <h3>
  441. Rune drops by slot
  442. </h3>
  443. <canvas id='diagram_rune_slot' width='200' height='200'></canvas>
  444. <table class='legend'>
  445. <?php
  446. $total = array_sum($page->drop_rune_slot);
  447. for ($i = 1; $i <= 6; $i ++){
  448. $val = $page->drop_rune_slot[strval($i)]
  449. ?>
  450. <tr class='color_0'>
  451. <td>
  452. Slot <?=$i?>:
  453. </td>
  454. <td>
  455. <?=$val?>
  456. </td>
  457. <td>
  458. (<?=number_format(($val * 100) / $total, 2, ".", ",")?>%)
  459. </td>
  460. </tr>
  461. <?php
  462. }
  463. ?>
  464. </table>
  465. </div>
  466. <div id='drop_rune_stars' class='diagram'>
  467. <h3>
  468. Rune drops by stars
  469. </h3>
  470. <canvas id='diagram_rune_stars' width='200' height='200'></canvas>
  471. <table class='legend'>
  472. <?php
  473. $total = array_sum($page->drop_rune_stars);
  474. for ($i = 6; $i >= 1; $i --){
  475. $val = $page->drop_rune_stars[strval($i)]
  476. ?>
  477. <tr class='color_0'>
  478. <td>
  479. <?php
  480. for ($j = 1; $j <= $i; $j ++){
  481. ?>
  482. <img class='star star_gold' src='<?=URL::IMG["ICON"]?>star.png'/>
  483. <?php
  484. }
  485. ?>
  486. </td>
  487. <td>
  488. <?=$val?>
  489. </td>
  490. <td>
  491. (<?=number_format(($val * 100) / $total, 2, ".", ",")?>%)
  492. </td>
  493. </tr>
  494. <?php
  495. }
  496. ?>
  497. </table>
  498. </div>
  499. <div id='drop_rune_quality' class='diagram'>
  500. <h3>
  501. Rune drops by quality
  502. </h3>
  503. <canvas id='diagram_rune_quality' width='200' height='200'></canvas>
  504. <table class='legend'>
  505. <?php
  506. $total = array_sum($page->drop_rune_quality);
  507. ?>
  508. <tr class='color_legend'>
  509. <td>
  510. Legend:
  511. </td>
  512. <td>
  513. <?=$page->drop_rune_quality[QUALITY_ID::LEGEND]?>
  514. </td>
  515. <td>
  516. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::LEGEND] * 100) / $total, 2, ".", ",")?>%)
  517. </td>
  518. </tr>
  519. <tr class='color_hero'>
  520. <td>
  521. Hero:
  522. </td>
  523. <td>
  524. <?=$page->drop_rune_quality[QUALITY_ID::HERO]?>
  525. </td>
  526. <td>
  527. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::HERO] * 100) / $total, 2, ".", ",")?>%)
  528. </td>
  529. </tr>
  530. <tr class='color_rare'>
  531. <td>
  532. Rare:
  533. </td>
  534. <td>
  535. <?=$page->drop_rune_quality[QUALITY_ID::RARE]?>
  536. </td>
  537. <td>
  538. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::RARE] * 100) / $total, 2, ".", ",")?>%)
  539. </td>
  540. </tr>
  541. <tr class='color_magic'>
  542. <td>
  543. Magic:
  544. </td>
  545. <td>
  546. <?=$page->drop_rune_quality[QUALITY_ID::MAGIC]?>
  547. </td>
  548. <td>
  549. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::MAGIC] * 100) / $total, 2, ".", ",")?>%)
  550. </td>
  551. </tr>
  552. <tr class='color_normal'>
  553. <td>
  554. Normal:
  555. </td>
  556. <td>
  557. <?=$page->drop_rune_quality[QUALITY_ID::NORMAL]?>
  558. </td>
  559. <td>
  560. (<?=number_format(($page->drop_rune_quality[QUALITY_ID::NORMAL] * 100) / $total, 2, ".", ",")?>%)
  561. </td>
  562. </tr>
  563. </table>
  564. </div>
  565. </article>
  566. </section>
  567. <?php
  568. include __DIR__ . "/inc/footer.php";
  569. ?>
  570. </body>
  571. </html>