/[james]/t2matchlog/t2matchlog
ViewVC logotype

Annotation of /t2matchlog/t2matchlog

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (hide 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 james 36 #!/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