Unsupported PHP app for analysing and displaying stats for Team Fortress 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

deathmap.php 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?PHP
  2. require_once('inc/config.php');
  3. require_once('inc/deathmap.php');
  4. require_once(STATS_DIR . '/inc/database.php');
  5. if (!isset($_GET['map'])) {
  6. require_once('404.php');
  7. return;
  8. }
  9. $sql = 'SELECT map_id, map_name, MAX(UNIX_TIMESTAMP(game_endtime)) AS time FROM maps ';
  10. $sql .= 'NATURAL JOIN games WHERE map_name = \'' . s($_GET['map']) . '\' GROUP BY map_name';
  11. $res = mysql_query($sql);
  12. if (mysql_num_rows($res) == 0) {
  13. require_once('404.php');
  14. return;
  15. }
  16. $row = mysql_fetch_assoc($res);
  17. define('MAP_NAME', $row['map_name']);
  18. define('MAP_ID', $row['map_id']);
  19. define('MAP_FILE', sprintf(OVERVIEW_IMAGE, MAP_NAME));
  20. if (!file_exists(MAP_FILE) || !isset($coords[MAP_NAME])) {
  21. require_once('404.php');
  22. return;
  23. }
  24. if (isset($_GET['killer'])) {
  25. define('WHAT', 'killer');
  26. } else if (isset($_GET['sentries'])) {
  27. define('WHAT', 'sentry');
  28. } else {
  29. define('WHAT', 'victim');
  30. }
  31. if (isset($_GET['noteams'])) {
  32. define('NOTEAMS', true);
  33. }
  34. define('PALE', isset($_GET['pale']) ? (max(1, (int) $_GET['pale'])) : 3);
  35. define('ALPHA', isset($_GET['alpha']) ? min(max((int) $_GET['alpha'], 0), 127) : 0);
  36. define('RADIUS', isset($_GET['radius']) ? max(1, (int) $_GET['radius']) : 15);
  37. define('FILE_NAME', DM_CACHE . MAP_NAME . '.pale-' . PALE . '.radius-' . RADIUS . '.alpha-' . ALPHA . '.target-' . WHAT . (defined('NOTEAMS') ? '.noteams' : '') . '.jpg');
  38. if (file_exists(FILE_NAME) && filemtime(FILE_NAME) > (int) $row['time']) {
  39. // Cached version
  40. header('Content-type: image/jpeg');
  41. readfile(FILE_NAME);
  42. exit;
  43. }
  44. // Our map co-ords, for convenience
  45. list($x1,$y1,$i1,$j1,$x2,$y2,$i2,$j2,$x3,$y3,$i3,$j3) = $coords[MAP_NAME];
  46. /* Simultaneous equestions for translation co-ordinates:
  47. *
  48. * x1 = a * i1 + b * j1 + c
  49. * x2 = a * i2 + b * j2 + c
  50. * x3 = a * i3 + b * j3 + c
  51. *
  52. * y1 = d * i1 + e * j1 + f ...
  53. *
  54. * x1 - x2 = a * (i1 - i2) + b * (j1 - j2)
  55. * x2 - x3 = a * (i2 - i3) + b * (j2 - j3)
  56. * a = (x1 - x2 - b * (j1 - j2)) / (i1 - i2)
  57. * = (x2 - x3 - b * (j2 - j3)) / (i2 - i3)
  58. *
  59. * (i2 - i3) (x1 - x2 - b * (j1 - j2)) = (i1 - i2) (x2 - x3 - b * (j2 - j3))
  60. * (i2 - i3) (x1 - x2) - b * (j1 - j2) (i2 - i3) = (i1 - i2) (x2 - x3) - b * (j2 - j3) (i1 - i2)
  61. * b (((j2 - j3) (i1 - i2)) - ((j1 - j2) (i2 - i3))) = (i1 - i2) (x2 - x3) - (i2 - i3) (x1 - x2)
  62. * b = ((i1 - i2) (x2 - x3) - (i2 - i3) (x1 - x2)) / ((j2 - j3) (i1 - i2) - (j1 - j2) (i2 - i3))
  63. */
  64. $i12 = $i1 - $i2;
  65. $i23 = $i2 - $i3;
  66. $j12 = $j1 - $j2;
  67. $j23 = $j2 - $j3;
  68. $b = ($i12 * ($x2 - $x3) - $i23 * ($x1 - $x2)) / ($j23 * $i12 - $j12 * $i23);
  69. $a = (($x1 - $x2) - $b * $j12) / $i12;
  70. $c = $x1 - $a * $i1 - $b * $j1;
  71. if (abs($c - ($x3 - $a * $i3 - $b * $j3)) > 0.1) {
  72. die('Inconsistency between x co-ord translations for 1 and 3');
  73. } else if (abs($c - ($x2 - $a * $i2 - $b * $j2)) > 0.1) {
  74. die('Inconsistency between x co-ord tranlsations for 1 and 2');
  75. }
  76. $e = ($i12 * ($y2 - $y3) - $i23 * ($y1 - $y2)) / ($j23 * $i12 - $j12 * $i23);
  77. $d = (($y1 - $y2) - $e * $j12) / $i12;
  78. $f = $y1 - $d * $i1 - $e * $j1;
  79. if (abs($f - ($y3 - $d * $i3 - $e * $j3)) > 0.1) {
  80. die('Inconsistency between y co-ord translations for 1 and 3');
  81. } else if (abs($f - ($y2 - $d * $i2 - $e * $j2)) > 0.1) {
  82. die('Inconsistency between y co-ord translations for 1 and 2');
  83. }
  84. function getScreenX($gameX, $gameY) {
  85. global $a, $b, $c;
  86. $res = ($a * $gameX + $b * $gameY + $c);
  87. return (int) $res;
  88. }
  89. function getScreenY($gameX, $gameY) {
  90. global $d, $e, $f;
  91. $res = ($d * $gameX + $e * $gameY + $f);
  92. return (int) $res;
  93. }
  94. function checkCoords($set, $i1, $j1, $x1, $y1) {
  95. global $a, $b, $c, $d, $e, $f;
  96. if (abs(getScreenX($i1, $j1) - $x1) > 1 || abs(getScreenY($i1, $j1) - $y1) > 1) {
  97. die("Co-ordinate mapping failed for set $set.<br>(i,j) = ($i1,$j1)<br>(x,y) = ($x1,$y1)<br>(ix,iy) = (" . getScreenX($i1, $j1) . "," . getScreenY($i1, $j1) . ")<br>a, b, c = $a, $b, $c<br>d, e, f = $d, $e, $f");
  98. }
  99. }
  100. checkCoords(1, $i1, $j1, $x1, $y1);
  101. checkCoords(2, $i2, $j2, $x2, $y2);
  102. checkCoords(3, $i3, $j3, $x3, $y3);
  103. $pixels = array();
  104. $max = 0;
  105. $im = imagecreatefrompng(MAP_FILE);
  106. imagefill($im, 1, 1, imagecolorallocate($im, 0, 0, 0));
  107. imagefill($im, imagesx($im) - 2, imagesy($im) - 2, imagecolorallocate($im, 0, 0, 0));
  108. if (WHAT == 'killer' || WHAT == 'victim') {
  109. $sql = 'SELECT kill_id, kill_killer_position, kill_victim_position, roleperiod_team FROM games NATURAL JOIN sessions NATURAL JOIN roleperiods INNER JOIN kills ON kill_killer = roleperiod_id WHERE map_id = ' . MAP_ID;
  110. $loc = 'kill_' . WHAT . '_position';
  111. } else {
  112. $sql = 'SELECT roleperiod_team, event_location FROM games NATURAL JOIN sessions NATURAL JOIN roleperiods NATURAL JOIN events WHERE map_id = ' . MAP_ID;
  113. $loc = 'event_location';
  114. }
  115. $res = mysql_query($sql);
  116. while ($row = mysql_fetch_assoc($res)) {
  117. list($x, $y, $z) = explode(' ', $row[$loc]);
  118. $i = getScreenX($x, $y); $j = getScreenY($x, $y);
  119. for ($n = max(0, $i - RADIUS); $n < min(imagesx($im), $i + RADIUS); $n++) {
  120. for ($m = max(0, $j - RADIUS); $m < min(imagesy($im), $j + RADIUS); $m++) {
  121. $distance = sqrt(pow($n - $i, 2) + pow($m - $j, 2));
  122. if ($distance < RADIUS) {
  123. $pixels[$n][$m][$row['roleperiod_team']] += RADIUS - $distance;
  124. $max = max($max, ((int) $pixels[$n][$m][1]) + ((int) $pixels[$n][$m][2]));
  125. }
  126. }
  127. }
  128. }
  129. $x = imagesx($im);
  130. for($i = 0; $i < imagesy($im); $i++) {
  131. for($j = 0; $j < imagesx($im); $j++) {
  132. $pos = imagecolorat($im, $j, $i);
  133. $f = imagecolorsforindex($im, $pos);
  134. $gst = $f['red']*0.3 + $f['green']*0.3 + $f['blue']*0.3;
  135. $col = imagecolorresolve($im, ((PALE-1)*$gst + $f['red']) / PALE, ((PALE-1)*$gst + $f['green']) / PALE, ((PALE-1)*$gst + $f['blue']) / PALE);
  136. imagesetpixel($im, $j, $i, $col);
  137. }
  138. }
  139. foreach ($pixels as $x => $dat) {
  140. foreach ($dat as $y => $count) {
  141. $red = (int) $count[1];
  142. $blue = (int) $count[2];
  143. // Not sure why they'd exist in this case, but meh
  144. if ($red + $blue == 0) { continue; }
  145. if (defined('NOTEAMS')) {
  146. $ratio = ($red + $blue) / $max;
  147. $c = imagecolorallocatealpha($im,
  148. max(0, min(255, 255 * sin(pi() * ($ratio - 0.5)))), // Red
  149. max(0, 255 * sin($ratio * pi())), // Green
  150. max(0, 128 * cos($ratio * pi())), ALPHA - ALPHA * 0.5 * $ratio); // Blue
  151. $count = 1;
  152. } else {
  153. $c = imagecolorallocatealpha($im, 255 * $red/($red + $blue), 0, 255 * $blue/($red + $blue), ALPHA);
  154. $count = RADIUS * ($red + $blue)/$max;
  155. }
  156. imagefilledellipse($im, $x, $y, $count, $count, $c);
  157. }
  158. }
  159. $im2 = imagecreatetruecolor(imagesx($im), imagesy($im) + 43);
  160. $im3 = imagecreatefrompng('res/dmheader.png');
  161. imagecopy($im2, $im3, 0, 0, 0, 0, imagesx($im), 43);
  162. imagecopy($im2, $im, 0, 43, 0, 0, imagesx($im), imagesy($im));
  163. $c = imagecolorallocate($im2, 157, 83, 33);
  164. imagestring($im2, 1, imagesx($im) - 310, 30, str_pad('Map of ' . WHAT . ' locations on ' . MAP_NAME, 60, ' ', STR_PAD_LEFT), $c);
  165. imageline($im2, 0, 42, imagesx($im), 42, $c);
  166. imageinterlace($im2, 1);
  167. header('Content-type: image/jpeg');
  168. imagejpeg($im2, null, 100);
  169. imagefilledrectangle($im2, 1, imagesy($im2) - 5, 4, imagesy($im2) - 2, imagecolorallocate($im2, 157, 83, 33));
  170. imagejpeg($im2, FILE_NAME, 100);
  171. ?>