/[james]/t2matchlog/t2matchlog
ViewVC logotype

Contents of /t2matchlog/t2matchlog

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (show annotations) (download)
Mon Nov 24 23:57:14 2003 UTC (20 years, 5 months ago) by james
File size: 13157 byte(s)
Initial import.

1 #!/bin/perl -W
2
3 use GD;
4
5 $/ = "\r\n";
6
7 $near0 = 70;
8 $near1 = 200;
9 $thumbsize = 400;
10
11 $black = 0x000000;
12 $white = 0xffffff;
13 $red = 0xff0000;
14 $green = 0x00ff00;
15 $blue = 0x0000ff;
16 $magenta = 0xff00ff;
17 $yellow = 0xffff00;
18 $orange = 0xff8000;
19 $grey = 0x404040;
20 $teamcol[1] = $blue;
21 $teamcol[2] = $magenta;
22
23 # from damageTypes.cs
24 $DamageTypeText[0] = 'default';
25 $DamageTypeText[1] = 'blaster';
26 $DamageTypeText[2] = 'plasma';
27 $DamageTypeText[3] = 'chaingun';
28 $DamageTypeText[4] = 'disc';
29 $DamageTypeText[5] = 'grenade';
30 $DamageTypeText[6] = 'laser';
31 $DamageTypeText[7] = 'ELF';
32 $DamageTypeText[8] = 'mortar';
33 $DamageTypeText[9] = 'missile';
34 $DamageTypeText[10] = 'shocklance';
35 $DamageTypeText[11] = 'mine';
36 $DamageTypeText[12] = 'explosion';
37 $DamageTypeText[13] = 'impact';
38 $DamageTypeText[14] = 'ground';
39 $DamageTypeText[15] = 'turret';
40 $DamageTypeText[16] = 'plasma turret';
41 $DamageTypeText[17] = 'AA turret';
42 $DamageTypeText[18] = 'ELF turret';
43 $DamageTypeText[19] = 'mortar turret';
44 $DamageTypeText[20] = 'missile turret';
45 $DamageTypeText[21] = 'clamp turret';
46 $DamageTypeText[22] = 'spike turret';
47 $DamageTypeText[23] = 'sentry turret';
48 $DamageTypeText[24] = 'out of bounds';
49 $DamageTypeText[25] = 'lava';
50 $DamageTypeText[26] = 'shrike blaster';
51 $DamageTypeText[27] = 'belly turret';
52 $DamageTypeText[28] = 'bomber bomb';
53 $DamageTypeText[29] = 'tank chaingun';
54 $DamageTypeText[30] = 'tank mortar';
55 $DamageTypeText[31] = 'satchel charge';
56 $DamageTypeText[32] = 'MPB missile';
57 $DamageTypeText[33] = 'lighting';
58 $DamageTypeText[35] = 'ForceField';
59 $DamageTypeText[36] = 'Crash';
60 $DamageTypeText[98] = 'nexus camping';
61 $DamageTypeText[99] = 'suicide';
62
63 $icon_player = load_image("icons/com_player_grey_24x.png");
64 $icon{'flag'} = load_image("icons/com_icon_flag_outside.png");
65 $icon{'gen'} = load_image("icons/com_icon_generator.png");
66 $icon{'turret'} = load_image("icons/com_icon_turretbase.png");
67 $icon{'inv'} = load_image("icons/com_icon_inventory.png");
68 $icon{'sensor'} = load_image("icons/com_icon_sensor.png");
69 $icon{'vpad'} = load_image("icons/com_icon_vehicle_inventory.png");
70
71 # read header
72 $mission = <>; chomp $mission;
73 $mission_type = <>; chomp $mission_type;
74 $mission_name = <>; chomp $mission_name;
75 $mission_type_name = <>; chomp $mission_type_name;
76 $area = <>; chomp $area; ($x0, $y0, $width, $height) = split / /, $area;
77 while (($_ = <>) ne $/) {
78 chomp;
79 ($team, $type, $block, $name, $x, $y, $z, $desc) = split / /, $_, 8;
80 $x -= $x0; $y = $height - $y + $y0;
81 if ($type eq 'StaticShape' and $block eq 'GeneratorLarge') {
82 push @landmarks, "$z gen $team $x $y";
83 } elsif ($type eq 'Turret' and $block eq 'TurretBaseLarge') {
84 push @landmarks, "$z turret $team $x $y";
85 } elsif ($type eq 'StaticShape' and $block eq 'ExteriorFlagStand') {
86 push @landmarks, "$z flag $team $x $y";
87 } elsif ($type eq 'StaticShape' and $block eq 'StationVehicle') {
88 push @landmarks, "$z vpad $team $x $y";
89 } elsif ($type eq 'StaticShape' and $block eq 'StationInventory') {
90 push @landmarks, "$z inv $team $x $y";
91 } elsif ($type eq 'StaticShape' and $block eq 'SensorLargePulse') {
92 push @landmarks, "$z sensor $team $x $y";
93 } elsif ($type eq 'WayPoint' and $block eq 'WayPointMarker') {
94 push @waypoints, "$team $x $y $z $desc";
95 }
96 }
97 @landmarks = sort { my ($az, $ra) = split / /, $a, 2; my ($bz, $rb) = split / /, $b, 2;
98 return $az <=> $bz; } @landmarks;
99
100 $html_index = create_html('Match Summary');
101
102 $time = 0;
103 $nicetime = "0:00";
104 $imall = create_image();
105 %alive = ();
106 @allevents = ();
107
108 while (<>) {
109 chomp;
110 if ($_ eq '') {
111 plot_frame();
112 $time++;
113 $secs = $time % 60;
114 $nicetime = int($time / 60) . ':' . (($secs < 10) ? "0$secs" : $secs);
115 next;
116 }
117
118 ($cmd, $params) = split / /, $_, 2;
119
120 if ($cmd eq 'S' or $cmd eq 'V') { # player spawned / new vehicle
121 ($id, $team, $name) = split / /, $params, 3;
122 if ($cmd eq 'V') {
123 $vname{$id} = $name;
124 $name = $id;
125 }
126 $name{$id} = $name;
127 $life{$name}++;
128 $type{$name} = $cmd eq 'S' ? 'player' : 'vehicle';
129 $team{$name} = $team;
130 $im{$name} = create_image();
131 delete $last_pos{$name};
132 delete $pos{$name};
133 $alive{$name} = 1;
134 $near{$name} = {};
135 $events{$name} = [];
136 if (!exists $html{$name}) {
137 $html{$name} = create_html($name);
138 unless ($type{$name} eq 'vehicle') {
139 $html{$name} .= <<END;
140 <p>Total score FINALSCORE, deaths FINALDEATHS, kills FINALKILLS.</p>
141 END
142 }
143 $score{$name} = 0;
144 $deaths{$name} = 0;
145 $kills{$name} = 0;
146 } else {
147 $html{$name} .= "</table></div>\n";
148 }
149 $sname = safe_name($name);
150 $html{$name} .= <<END;
151 <div><h2 id="life$life{$name}">Life $life{$name} ($nicetime - ENDTIME)</h2>
152 <div><a href="${sname}_$life{$name}.png"><img src="s${sname}_$life{$name}.png"
153 alt="" title="Map of life $life{$name}"></a></div>
154 <table>
155 END
156 event($name, "spawned on team $team", $yellow);
157
158 } elsif ($cmd eq 'F') { # flag position
159
160 } elsif ($cmd eq 'D') { # player damaged
161 ($victim, $attacker, $weapon) = split / /, $params;
162
163 } elsif ($cmd eq 'K' or $cmd eq 'L' or $cmd eq 'W') { # player killed / left / vehicle destroyed
164 if ($cmd eq 'K') {
165 ($victim, $killer, $weapon) = split / /, $params;
166 $victim = $name{$victim};
167 $killer = $name{$killer};
168 event($victim, "killed by $DamageTypeText[$weapon]", $red, $killer);
169 if (defined $killer) {
170 event($killer, "killed ($DamageTypeText[$weapon])", $green, $victim);
171 $kills{$killer}++;
172 }
173 $deaths{$victim}++;
174
175 } elsif ($cmd eq 'L') {
176 ($victim, $score) = split / /, $params;
177 $victim = $name{$victim};
178 undef $killer;
179 event($victim, "left the game, score $score", $red);
180 $score{$victim} += $score;
181
182 } elsif ($cmd eq 'W') {
183 $victim = $name{$params};
184 }
185
186 foreach $name (keys %near) {
187 delete ${$near{$name}}{$victim} if exists ${$near{$name}}{$victim};
188 }
189
190 if ($im{$victim}) {
191 plot_events($victim);
192 $sname = safe_name($victim);
193 save_image($im{$victim}, "${sname}_$life{$victim}.png");
194 }
195 delete $alive{$victim};
196 $html{$victim} =~ s/ENDTIME/$nicetime/;
197
198 } elsif ($cmd eq 'A') { # armour changed
199 ($id, $armour) = split / /, $params;
200 $name = $name{$id};
201 $armour{$name} = $armour;
202 event($name, "$armour armour", $orange);
203
204 } elsif ($cmd eq 'Z') { # final score
205
206 } else { # player / vehicle position
207 $id = $cmd;
208 $name = $name{$id};
209 next unless (exists $name{$id} and exists $im{$name});
210 ($x, $y, $z, $vehicle, $seat) = split / /, $params;
211 $x -= $x0; $y = $height - $y + $y0;
212 $pos{$name} = "$x $y $z";
213 if (exists $pending{$name}) {
214 push @{$events{$name}}, "$x $y $z $pending{$name}";
215 delete $pending{$name};
216 }
217
218 }
219 }
220
221 foreach $victim (keys %alive) {
222 if ($im{$victim}) {
223 plot_events($victim);
224 $sname = safe_name($victim);
225 save_image($im{$victim}, "${sname}_$life{$victim}.png");
226 }
227 }
228
229 $html_index .= <<END;
230 <div><a href="Overview.png"><img src="sOverview.png"
231 alt="" title="Overview map"></a></div>
232 <p>Playing time: $nicetime</p>
233 <table>
234 <tr><th>Player</th><th>Team</th><th>Score</th><th>Deaths</th><th>Kills</th></tr>
235 END
236 while (($name, $html) = each %html) {
237 $html .= "</table></div>\n";
238 $html =~ s/FINALSCORE/$score{$name}/;
239 $html =~ s/FINALDEATHS/$deaths{$name}/;
240 $html =~ s/FINALKILLS/$kills{$name}/;
241 $sname = safe_name($name);
242 save_html("$sname.html", $html);
243 if ($type{$name} eq 'player') {
244 $html_index .= <<END;
245 <tr><td><a href="$sname.html">$name</a></td><td>$team{$name}</td><td>$score{$name}</td><td>$deaths{$name}</td><td>$kills{$name}</td></tr>
246 END
247 }
248 }
249
250 $html_index .= "</table>\n";
251
252
253 #$html_index .= "<h2>Timeline<h2>\n<table class='timeline'>\n";
254 $header = "<tr><td></td>";
255 foreach $n (keys %type) {
256 $header .= "<th>$n</th>";
257 }
258 $header .= "</tr>\n";
259 #$html_index .= $header;
260 $time = 0;
261 %event = ();
262 foreach $e (@allevents) {
263 ($t, $colour, $name) = split / /, $e, 3;
264 while ($time < $t) {
265 $secs = $time % 60;
266 $nicetime = int($time / 60) . ':' . (($secs < 10) ? "0$secs" : $secs);
267 # $html_index .= "<tr><td>$nicetime</td>";
268 foreach $n (keys %type) {
269 if (exists $event{$n}) {
270 $hexcol = sprintf "%.6lx", $event{$n};
271 # $html_index .= "<td style='background-color: #$hexcol'>&nbsp;</td>";
272 } else {
273 # $html_index .= "<td>&nbsp;</td>";
274 }
275 }
276 %event = ();
277 # $html_index .= "</tr>\n";
278 $time++;
279 # $html_index .= $header if (($time % 30) == 0);
280 }
281 $event{$name} = $colour;
282 }
283
284 save_image($imall, "Overview.png");
285 #$html_index .= "</table>\n";
286 save_html("index.html", $html_index);
287
288
289 sub plot_frame {
290 $s = 1;
291 $s = 2 if ($time % 10) == 0;
292 foreach $name (keys %alive) {
293 next unless exists $pos{$name};
294 ($x, $y, $z) = split / /, $pos{$name};
295 %near0 = %{$near{$name}};
296 foreach $name1 (keys %alive) {
297 next if $name1 eq $name;
298 ($x1, $y1, $z1) = split / /, $pos{$name1};
299 my $dist = distance($x, $y, $z, $x1, $y1, $z1);
300 if (exists ${$near{$name}}{$name1}) {
301 delete ${$near{$name}}{$name1} if $near1 < $dist;
302 } elsif ($dist < $near0) {
303 ($x1, $y1, $z1) = split / /, $pos{$name1};
304 text($im{$name}, $x1 + 4, $y1, $name1);
305 ${$near{$name}}{$name1} = 1;
306 }
307 }
308 foreach $name1 (keys %{$near{$name}}) {
309 ($x1, $y1, $z1) = split / /, $pos{$name1};
310 my $colour = $team{$name1} == $team{$name} ? $green : $red;
311 if ($last_pos{$name1}) {
312 ($xp, $yp, $zp) = split / /, $last_pos{$name1};
313 line($im{$name}, $xp, $yp, $x1, $y1, $colour);
314 }
315 square($im{$name}, $x1, $y1, $s, $colour);
316 line($im{$name}, $x, $y, $x1, $y1, $grey) if $s == 2;
317 }
318 text($im{$name}, $x, $y, $nicetime) if $s == 2;
319 if (exists $last_pos{$name}) {
320 ($xp, $yp, $zp) = split / /, $last_pos{$name};
321 line($im{$name}, $xp, $yp, $x, $y, $white);
322 line($imall, $xp, $yp, $x, $y, $teamcol[$team{$name}]);
323 }
324 square($im{$name}, $x, $y, $s, $white);
325
326 }
327 %last_pos = %pos;
328 %pos = ();
329 }
330
331 sub create_image {
332 my $image = GD::Image->newTrueColor($width, $height);
333 my $lm;
334 foreach $lm (@landmarks) {
335 my ($z, $type, $team, $x, $y) = split / /, $lm;
336 icon($image, $icon{$type}, $x, $y);
337 }
338 foreach $g (@waypoints) {
339 my ($team, $x, $y, $z, $desc) = split / /, $g, 5;
340 text($image, $x, $y, $desc);
341 }
342 return $image;
343 }
344
345 sub save_image {
346 my $image = shift;
347 my $file = shift;
348 my $png = $image->png;
349 open PNG, ">$file" or die "failed to open $file: $!";
350 binmode PNG;
351 print PNG $png;
352 close PNG;
353
354 my $max = $width < $height ? $height : $width;
355 my $thumb = GD::Image->newTrueColor($thumbsize * $width / $max,
356 $thumbsize * $height / $max);
357 $thumb->copyResampled($image, 0, 0, 0, 0, $thumbsize * $width / $max,
358 $thumbsize * $height / $max, $width, $height);
359 $png = $thumb->png;
360 open PNG, ">s$file" or die "failed to open s$file: $!";
361 binmode PNG;
362 print PNG $png;
363 close PNG;
364 }
365
366 sub square {
367 my $image = shift;
368 return unless defined $image;
369 my $x = shift;
370 my $y = shift;
371 my $s = shift;
372 my $colour = shift;
373 $image->filledRectangle($x - $s, $y - $s, $x + $s, $y + $s, $colour);
374 }
375
376 sub line {
377 my $image = shift;
378 return unless defined $image;
379 my $x0 = shift;
380 my $y0 = shift;
381 my $x1 = shift;
382 my $y1 = shift;
383 my $colour = shift;
384 $image->line($x0, $y0, $x1, $y1, $colour);
385 }
386
387 sub distance {
388 return sqrt (($_[0] - $_[3]) ** 2 + ($_[1] - $_[4]) ** 2 + ($_[2] - $_[5]) ** 2);
389 }
390
391 sub load_image {
392 my $file = shift;
393 open PNG, $file or die "failed to open $file: $!";
394 my $im = GD::Image->newFromPng(\*PNG) or die "PNG load of $file failed";
395 close PNG;
396 $im->transparent(0);
397 return $im;
398 }
399
400 sub icon {
401 my $image = shift;
402 my $icon = shift;
403 my $x = shift;
404 my $y = shift;
405 $image->setBrush($icon);
406 $image->setPixel($x, $y, gdBrushed);
407 }
408
409 sub text {
410 my $image = shift;
411 my $x = shift;
412 my $y = shift;
413 my $text = shift;
414 $image->string(gdSmallFont, $x, $y, $text, $white);
415 }
416
417 sub create_html {
418 my $title = shift;
419 my $html = <<END;
420 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
421 "http://www.w3.org/TR/html4/strict.dtd">
422 <html>
423 <head>
424 <link rel="stylesheet" type="text/css" href="t2matchlog.css">
425 <title>$title ($mission_name / $mission_type_name)</title>
426 </head>
427
428 <body>
429 <h1>$title <em class="mission">($mission_name / $mission_type_name)</em></h1>
430
431 END
432 return $html;
433 }
434
435 sub save_html {
436 my $file = shift;
437 my $html = shift;
438 $html .= "</body></html>\n";
439 open HTML, ">$file" or die "failed to open $file: $!";
440 print HTML $html;
441 close HTML;
442 }
443
444 sub safe_name {
445 my $s = shift;
446 $s =~ tr/[a-zA-Z0-9]/_/cs;
447 return $s;
448 }
449
450 sub event {
451 my $name = shift;
452 return unless exists $html{$name};
453 my $desc = shift;
454 my $colour = shift;
455 my $name2 = shift;
456 print "$nicetime\t$name $desc";
457 my $hexcol = sprintf "%.6lx", $colour;
458 my $line = "<tr id='t$time'><td class='time'>$nicetime</td><td style='color: #$hexcol'>$desc";
459 if (defined $name2 and exists $html{$name2}) {
460 print " $name2";
461 $sname = safe_name($name2);
462 $line .= " <a href='$sname.html#t$time'>$name2</a>";
463 }
464 print "\n";
465 $line .= "</td></tr>\n";
466 $html{$name} .= $line;
467 if (exists $last_pos{$name}) {
468 push @{$events{$name}}, "$last_pos{$name} $colour $desc";
469 } else {
470 $pending{$name} = "$colour $desc";
471 }
472 push @allevents, "$time $colour $name";
473 }
474
475 sub plot_events {
476 my $name = shift;
477 foreach $e (@{$events{$name}}) {
478 my ($x, $y, $z, $colour, $desc) = split / /, $e, 5;
479 square($im{$name}, $x, $y, 8, $colour);
480 }
481 }
482

  ViewVC Help
Powered by ViewVC 1.1.26