/[james]/t2matchlog/t2matchlog
ViewVC logotype

Annotation of /t2matchlog/t2matchlog

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (hide annotations) (download)
Thu Jan 22 23:53:16 2004 UTC (20 years, 3 months ago) by james
File size: 24287 byte(s)
Bug fixes and configurable html extension.

1 james 36 #!/bin/perl -W
2    
3 james 37 use strict;
4 james 36 use GD;
5    
6 james 38 die "Usage: perl $0 logfile outputdir" unless @ARGV == 2;
7 james 37 open LOG, $ARGV[0] or die "Failed to open $ARGV[0]: $!";
8     my $outdir = $ARGV[1];
9     mkdir $outdir or die "Failed to create output directory $outdir: $!";
10 james 38 my $dir = $0;
11 james 46 $dir =~ s#(^|/)[^/]+$#$1#;
12 james 38 (system "cp ${dir}t2matchlog.css $outdir/") == 0 or die "Failed to copy stylesheet: $!";
13 james 37
14 james 36 $/ = "\r\n";
15 james 37 $| = 1;
16 james 36
17 james 37 my $near0 = 70;
18     my $near1 = 200;
19     my $thumbsize = 400;
20 james 47 my $html_extension = '';
21 james 36
22     # from damageTypes.cs
23 james 37 my @DamageTypeText;
24 james 36 $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 james 38 my $icon_player = load_image("${dir}icons/com_player_grey_24x.png");
64 james 37 my %icon;
65 james 38 $icon{'flag'} = load_image("${dir}icons/com_icon_flag_outside.png");
66     $icon{'gen'} = load_image("${dir}icons/com_icon_generator.png");
67     $icon{'turret'} = load_image("${dir}icons/com_icon_turretbase.png");
68     $icon{'inv'} = load_image("${dir}icons/com_icon_inventory.png");
69     $icon{'sensor'} = load_image("${dir}icons/com_icon_sensor.png");
70     $icon{'vpad'} = load_image("${dir}icons/com_icon_vehicle_inventory.png");
71     $icon{'solar'} = load_image("${dir}icons/com_icon_solar_gen.png");
72 james 36
73 james 37 my %colour = ('S' => 0xffff00, 'A' => 0xff8000, 'KK' => 0x00ff00, 'K' => 0xff0000,
74 james 46 'KS' => 0xff0000,
75 james 37 'L' => 0xff8000, 'F+' => 0x00ffff, 'F-' => 0xff00ff, 'P' => 0xff8000,
76     'V' => 0xffff00, 'W' => 0xff0000, 'G' => 0x0080ff, 'J' => 0x00ff80,
77 james 46 'GG' => 0x0080ff, 'JJ' => 0x00ff80,
78     'C' => 0x00ff00, 'R' => 0x00ff00);
79 james 37 my $colour_me = 0xffffff;
80     my %desc = ('S' => 'spawned on team $team_name[$p1]',
81     'A' => '$p1 armour',
82     'KK' => 'killed $enemy using $DamageTypeText[$p2]',
83     'K' => 'killed by $DamageTypeText[$p2] $enemy',
84 james 46 'KS' => 'killed himself using $DamageTypeText[$p2]',
85 james 37 'L' => 'left the game',
86 james 46 'F+' => '${melink}took the $team_name[$p1] flag',
87     'F-' => '${melink}dropped the $team_name[$p1] flag',
88 james 37 'P' => '$p1',
89     'V' => 'vehicle created',
90     'W' => 'vehicle destroyed',
91     'G' => 'entered " . vehicle_link($p1) . " as ${seat{$p2}}',
92     'J' => 'ejected from vehicle',
93 james 47 'GG' => '<a href=\'" . safe_name($p1) . $html_extension . "#t$time\'>$p1</a> entered as ${seat{$p2}}',
94     'JJ' => '<a href=\'" . safe_name($p1) . $html_extension . "#t$time\'>$p1</a> ejected',
95 james 46 'C' => '<strong>${melink}captured the $team_name[$p1] flag!</strong>',
96     'R' => '${melink}returned the $team_name[$p1] flag',);
97 james 37 my @teamcol = (0xffffff, 0x0000ff, 0xff00ff);
98     my %seat = ('' => 'a passenger', 'p' => 'pilot', 'w' => 'gunner');
99 james 47 my %veh_name = ('bomberflyer' => 'Bomber',
100     'hapcflyer' => 'Havoc',
101     'mobilebasevehicle' => 'MPB',
102     'scoutflyer' => 'Shrike',
103     'assaultvehicle' => 'Tank',
104     'scoutvehicle' => 'Wildcat');
105 james 37
106     my ($mission, $mission_type, $mission_name, $mission_type_name, $x0, $y0, $width, $height);
107     my (@landmarks, @waypoints);
108    
109     print "reading data";
110     read_header();
111    
112     my @events = ();
113     my @coords = ();
114     my %score = ();
115     my %kills = ();
116     my %deaths = ();
117 james 46 my %grabs = ();
118     my %caps = ();
119     my %returns = ();
120 james 37 my %player = ();
121     my %vehicle = ();
122     my %team = ();
123     my $end_time;
124     my (@final_score, @team_name);
125 james 46 my %flag = ();
126     my @flag_coords = ();
127 james 37
128     read_data();
129     print ".\n";
130    
131     my $imall = create_image();
132    
133     my $player;
134     foreach $player (keys %player) {
135     print "$player";
136     write_player_report($player);
137     print ".\n";
138 james 36 }
139 james 37 my $vehicle;
140     foreach $vehicle (keys %vehicle) {
141     my ($team, $name) = split / /, $vehicle, 2;
142     print "$team_name[$team] $veh_name{$name}s";
143     write_vehicle_report($name, $team);
144     print ".\n";
145     }
146 james 46 my $team;
147     foreach $team (keys %flag) {
148     print "$team_name[$team] flag";
149     write_flag_report($team);
150     print ".\n";
151     }
152 james 37 write_summary_report();
153 james 36
154 james 37 exit;
155 james 36
156 james 37 ####################################################################################################
157 james 36
158 james 37 sub read_header {
159     $mission = <LOG>; chomp $mission;
160     $mission_type = <LOG>; chomp $mission_type;
161     $mission_name = <LOG>; chomp $mission_name;
162     $mission_type_name = <LOG>; chomp $mission_type_name;
163     my $area = <LOG>; chomp $area; ($x0, $y0, $width, $height) = split / /, $area;
164    
165     while (($_ = <LOG>) ne $/) {
166     chomp;
167     my ($team, $type, $block, $name, $x, $y, $z, $desc) = split / /, $_, 8;
168     $x -= $x0; $y = $height - $y + $y0;
169     if ($type eq 'StaticShape' and $block eq 'GeneratorLarge') {
170     push @landmarks, "$z gen $team $x $y";
171     } elsif ($type eq 'Turret' and $block eq 'TurretBaseLarge') {
172     push @landmarks, "$z turret $team $x $y";
173     } elsif ($type eq 'StaticShape' and $block eq 'ExteriorFlagStand') {
174     push @landmarks, "$z flag $team $x $y";
175     } elsif ($type eq 'StaticShape' and $block eq 'StationVehicle') {
176     push @landmarks, "$z vpad $team $x $y";
177     } elsif ($type eq 'StaticShape' and $block eq 'StationInventory') {
178     push @landmarks, "$z inv $team $x $y";
179     } elsif ($type eq 'StaticShape' and $block eq 'SensorLargePulse') {
180     push @landmarks, "$z sensor $team $x $y";
181     } elsif ($type eq 'StaticShape' and $block eq 'SolarPanel') {
182     push @landmarks, "$z solar $team $x $y";
183     } elsif ($type eq 'WayPoint' and $block eq 'WayPointMarker') {
184     push @waypoints, "$team $x $y $z $desc";
185     }
186 james 36 }
187    
188 james 37 # sort by height for nicer plotting
189     @landmarks = sort { my ($az, $ra) = split / /, $a, 2; my ($bz, $rb) = split / /, $b, 2;
190     return $az <=> $bz; } @landmarks;
191     }
192 james 36
193 james 37 ####################################################################################################
194    
195     sub read_data {
196     my $time = 0;
197     my %name = ();
198     my @flag_carrier;
199     my %player_veh;
200 james 46 my %player_flag;
201 james 37
202     while (<LOG>) {
203     chomp;
204     if ($_ eq '') {
205     $time++;
206     next;
207 james 36 }
208 james 37
209     my ($cmd, $params) = split / /, $_, 2;
210    
211     if ($cmd eq 'S') { # player spawned
212     my ($id, $team, $name) = split / /, $params, 3;
213     $name{$id} = $name;
214     push @events, [$time, 'S', $name, $team];
215     $player{$name} = 1;
216     $team{$name} = $team;
217     $player_veh{$name} = 0;
218    
219     } elsif ($cmd eq 'K') { # player killed
220     my ($victim, $killer, $weapon) = split / /, $params;
221 james 46 next unless exists $name{$victim};
222 james 37 $deaths{$name{$victim}}++;
223     $kills{$name{$killer}}++ if exists $name{$killer};
224     push @events, [$time, 'K', $name{$victim}, $name{$killer}, $weapon];
225     push @events, [$time, 'KK', $name{$killer}, $name{$victim}, $weapon]
226 james 46 if exists $name{$killer} and $killer != $victim;
227 james 37 if (exists $name{$killer} and $player_veh{$name{$killer}}) {
228     push @events, [$time, 'KK', $name{$player_veh{$name{$killer}}},
229     $name{$victim}, $weapon];
230 james 36 }
231 james 47 delete $player_flag{$name{$victim}};
232 james 37 # if (defined $player_veh{$name}) TODO
233 james 46 # delete $name{$victim};
234 james 37
235     } elsif ($cmd eq 'L') { # player left
236     my ($id, $score) = split / /, $params;
237 james 46 next unless exists $name{$id};
238 james 37 push @events, [$time, 'L', $name{$id}];
239     $score{$name{$id}} += $score;
240     delete $name{$id};
241    
242     } elsif ($cmd eq 'A') { # armour changed
243     my ($id, $armour) = split / /, $params;
244     push @events, [$time, 'A', $name{$id}, $armour];
245    
246     } elsif ($cmd eq 'I') { # inventory changed
247     my ($id, $item, $count) = split / /, $params;
248 james 47 if ($item =~ m/(Pack|SatchelCharge|Deployable)$/ and $count == 1) {
249     $item =~ s/(Pack|Deployable)$/ pack/;
250 james 37 push @events, [$time, 'P', $name{$id}, $item];
251     }
252    
253     } elsif ($cmd eq 'D') { # player damaged
254     my ($victim, $attacker, $weapon) = split / /, $params;
255    
256     } elsif ($cmd eq 'V') { # new vehicle
257     my ($id, $team, $name) = split / /, $params, 3;
258 james 47 $name = lc $name;
259 james 37 $vehicle{"$team $name"}++;
260     $name{$id} = "$team $name " . $vehicle{"$team $name"};
261     $team{$name{$id}} = $team;
262     push @events, [$time, 'V', $name{$id}];
263    
264     } elsif ($cmd eq 'W') { # vehicle destroyed
265     my $id = $params;
266     push @events, [$time, 'W', $name{$id}];
267     #delete $name{$id};
268    
269     } elsif ($cmd eq 'Z') { # final score
270     my ($team, $score, $team_name) = split / /, $params, 3;
271     $final_score[$team] = $score;
272     $team_name[$team] = $team_name;
273    
274     } elsif ($cmd eq 'F') { # flag position
275     my ($team, @data) = split / /, $params;
276     my $carrier;
277 james 46 $flag{$team} = 1;
278     $team{"$team flag"} = $team;
279 james 37 $flag_carrier[$team] = 0 unless defined $flag_carrier[$team];
280     if (@data == 3) {
281     my ($x, $y, $z) = @data;
282     $x -= $x0; $y = $height - $y + $y0;
283 james 46 ${$coords[$time]}{"$team flag"} = "$x $y $z";
284 james 37 $carrier = 0;
285     } else {
286     $carrier = $name{$data[0]};
287     }
288     if ($carrier ne $flag_carrier[$team]) {
289     if ($flag_carrier[$team]) {
290     push @events, [$time, 'F-', $flag_carrier[$team], $team];
291 james 46 delete $player_flag{$flag_carrier[$team]};
292 james 37 }
293     if ($carrier) {
294     push @events, [$time, 'F+', $carrier, $team];
295 james 46 $grabs{$carrier}++;
296     $player_flag{$carrier} = $team;
297 james 37 }
298     $flag_carrier[$team] = $carrier;
299     }
300    
301 james 46 } elsif ($cmd eq 'C') { # flag captured (CTF)
302     my ($team, $id) = split / /, $params;
303     push @events, [$time, 'C', $name{$id}, $team];
304     $flag_carrier[$team] = 0;
305     $caps{$name{$id}}++;
306    
307     } elsif ($cmd eq 'R') { # flag returned (CTF)
308     my ($team, $id) = split / /, $params;
309     push @events, [$time, 'R', exists $name{$id} ? $name{$id} : '', $team];
310 james 47 $returns{$name{$id}}++ if exists $name{$id};
311 james 46
312 james 37 } else { # player / vehicle position
313     my $id = $cmd;
314     next unless exists $name{$id};
315     my $name = $name{$id};
316     my ($x, $y, $z, $vehicle, $seat) = split / /, $params;
317     $x -= $x0; $y = $height - $y + $y0;
318     ${$coords[$time]}{$name} = "$x $y $z";
319     next unless defined $player{$name};
320     if ($player_veh{$name} != $vehicle) {
321     if ($player_veh{$name}) {
322     push @events, [$time, 'J', $name];
323     push @events, [$time, 'JJ',
324     $name{$player_veh{$name}}, $name];
325     }
326     if ($vehicle != 0) {
327     push @events, [$time, 'G', $name,
328     $name{$vehicle}, $seat];
329     push @events, [$time, 'GG', $name{$vehicle},
330     $name, $seat];
331     }
332     $player_veh{$name} = $vehicle;
333     }
334 james 46 if (exists $player_flag{$name}) {
335     ${$coords[$time]}{$player_flag{$name} . " flag"} = "$x $y $z";
336     }
337 james 36 }
338 james 37 }
339     $end_time = $time + 1;
340     }
341    
342     ####################################################################################################
343    
344     sub write_player_report {
345     my $player = shift;
346    
347     my $score = exists $score{$player} ? $score{$player} : 0;
348     my $deaths = exists $deaths{$player} ? $deaths{$player} : 0;
349     my $kills = exists $kills{$player} ? $kills{$player} : 0;
350     my $sname = safe_name($player);
351     my $html = create_html($player);
352    
353     $html .= <<END;
354     <p>Total score $score, deaths $deaths, kills $kills. <a href="./">Match summary.</a></p>
355 james 36 END
356    
357 james 37 # find spawn / death times
358     my @spawn = map $$_[0], (grep {$$_[2] eq $player and $$_[1] eq 'S'} @events);
359     my @death = map $$_[0], (grep {$$_[2] eq $player and
360     ($$_[1] eq 'K' or $$_[1] eq 'L')} @events);
361     push @spawn, $end_time;
362 james 36
363 james 37 for (my $life = 0; $life != @spawn - 1; $life++) {
364     my $nicetime = nice_time($spawn[$life]);
365     my $nicedtime = nice_time($death[$life]);
366     my $life1 = $life + 1;
367     $html .= <<END;
368     <div><h2 id="life$life1">Life $life1 ($nicetime - $nicedtime)</h2>
369     <div><a href="${sname}_$life1.png"><img src="s${sname}_$life1.png"
370     alt="" title="Map of life $life1"></a></div>
371     END
372     $html .= player_life($player, "${sname}_$life1.png",
373     $spawn[$life], $spawn[$life1] - 1);
374     $html .= '</div>';
375     }
376 james 36
377 james 47 save_html(safe_name($player) . $html_extension, $html);
378 james 37 }
379 james 36
380 james 37 ####################################################################################################
381 james 36
382 james 37 sub player_life {
383     my $player = shift;
384     my $imname = shift;
385     my $time0 = shift;
386     my $time1 = shift;
387    
388     my $im = create_image();
389     plot_route($im, $player, $time0, $time1);
390    
391     my @evs = grep {$$_[2] eq $player and $time0 <= $$_[0] and $$_[0] <= $time1} @events;
392 james 46 my $html = write_events($player, \@evs, $im);
393 james 37
394 james 46 save_image($im, $imname);
395 james 47 undef $im;
396 james 46
397     return $html;
398     }
399    
400     ####################################################################################################
401    
402     sub write_events {
403     my $player = shift;
404     my $evs = shift;
405     my $im = shift;
406    
407     my $prev_time = -1;
408     my $html = "<table>\n";
409    
410 james 37 my $event;
411 james 46 foreach $event (@$evs) {
412 james 37 my ($time, $ev, $me, $p1, $p2) = @$event;
413    
414     my $nicetime = nice_time($time);
415     if ($time == $prev_time) {
416     $html .= '<tr><td></td>';
417     } else {
418     $html .= "<tr id='t$time'><td class='time'>$nicetime</td>";
419 james 36 }
420    
421 james 46 my $melink = '';
422 james 37 my $enemy = '';
423 james 46 $ev = 'KS' if ($ev eq 'K' and defined $p1 and $p1 eq $player);
424     if (defined $me and $me ne $player) {
425     my $sname_me = safe_name($me);
426 james 47 $melink = "<a href='$sname_me$html_extension#t$time'>$me</a> ";
427 james 46 }
428     if (defined $p1) {
429 james 37 my $sname_en = safe_name($p1);
430 james 47 $enemy = "<a href='$sname_en$html_extension#t$time'>$p1</a>";
431 james 36 }
432 james 37 my $desc = eval '"' . $desc{$ev} . '"';
433     my $hexcol = sprintf "%.6lx", $colour{$ev};
434     $html .= "<td style='color: #$hexcol'>$desc</td></tr>\n";
435 james 36
436 james 37 if (exists ${$coords[$time]}{$player}) {
437     my ($x, $y, $z) = split / /, ${$coords[$time]}{$player};
438     square($im, $x, $y, 8, $colour{$ev});
439     } elsif (exists ${$coords[$time - 1]}{$player}) {
440     my ($x, $y, $z) = split / /, ${$coords[$time - 1]}{$player};
441     square($im, $x, $y, 8, $colour{$ev});
442 james 36 }
443 james 37 $prev_time = $time;
444     }
445 james 36
446 james 37 $html .= "</table>\n";
447 james 36
448 james 37 return $html;
449     }
450 james 36
451 james 37 ####################################################################################################
452    
453     sub plot_route {
454     my $image = shift;
455     my $name = shift;
456     my $t0 = shift;
457     my $t1 = shift;
458     my %near = ();
459     for (my $t = $t0; $t != $t1; $t++) {
460     my $s = ($t % 10) == 0 ? 2 : 1;
461     if (exists ${$coords[$t]}{$name}) {
462     my ($x0, $y0, $z0) = split / /, ${$coords[$t]}{$name};
463     my $near;
464     foreach $near (keys %near) {
465     if (exists ${$coords[$t]}{$near}) {
466     my ($xn, $yn, $zn) = split / /, ${$coords[$t]}{$near};
467     delete $near{$near} if $near1 < distance($x0, $y0, $z0,
468     $xn, $yn, $zn);
469     } else {
470     delete $near{$near};
471     }
472     }
473     foreach $near (keys %player) {
474     next if $near eq $name;
475     next if exists $near{$near};
476     if (exists ${$coords[$t]}{$near}) {
477     my ($xn, $yn, $zn) = split / /, ${$coords[$t]}{$near};
478     if (distance($x0, $y0, $z0, $xn, $yn, $zn) < $near0) {
479     $near{$near} = 1;
480     line($image, $x0, $y0, $xn, $yn, 0x444444);
481     text($image, $xn, $yn, $near);
482     }
483     }
484     }
485     foreach $near (keys %near) {
486     my ($xn0, $yn0, $zn0) = split / /, ${$coords[$t]}{$near};
487     my $colour = $team{$name} == $team{$near} ? 0x00ff00 : 0xff0000;
488     line($image, $x0, $y0, $xn0, $yn0, 0x444444) if $s == 2;
489     if (exists ${$coords[$t + 1]}{$near}) {
490     my ($xn1, $yn1, $zn1) = split / /,
491     ${$coords[$t + 1]}{$near};
492     line($image, $xn0, $yn0, $xn1, $yn1, $colour);
493     }
494     square($image, $xn0, $yn0, $s, $colour);
495     }
496     if (exists ${$coords[$t + 1]}{$name}) {
497     my ($x1, $y1, $z1) = split / /, ${$coords[$t + 1]}{$name};
498     line($image, $x0, $y0, $x1, $y1, $colour_me);
499     line($imall, $x0, $y0, $x1, $y1, $teamcol[$team{$name}]);
500     }
501     square($image, $x0, $y0, $s, $colour_me);
502     text($image, $x0, $y0, nice_time($t)) if $s == 2;
503 james 36 }
504     }
505     }
506    
507 james 37 ####################################################################################################
508    
509     sub write_vehicle_report {
510     my $name = shift;
511     my $team = shift;
512    
513     my $sname = safe_name($name);
514     my $html = create_html($team_name[$team] . ' ' . $veh_name{$name} . 's');
515     $html .= '<p><a href="./">Match summary.</a></p>';
516    
517     my $run;
518     for ($run = 1; $run != $vehicle{"$team $name"} + 1; $run++) {
519     my @ev = grep {$$_[2] eq "$team $name $run"} @events;
520     my $time0 = ${$ev[0]}[0];
521     my $time1 = ${$ev[-1]}[1] eq 'W' ? ${$ev[-1]}[0] : $end_time;
522     my $nicetime = nice_time($time0);
523     my $nicedtime = nice_time($time1);
524    
525     $html .= <<END;
526     <div><h2 id="life$run">$veh_name{$name} $run ($nicetime - $nicedtime)</h2>
527     <div><a href="${team}_${sname}_$run.png"><img src="s${team}_${sname}_$run.png"
528     alt="" title="Map of $veh_name{$name} $run"></a></div>
529     END
530     $html .= player_life("$team $name $run", "${team}_${sname}_$run.png",
531     $time0, $time1);
532     $html .= '</div>';
533 james 36 }
534 james 37
535 james 47 save_html("${team}_$sname$html_extension", $html);
536 james 36 }
537    
538 james 37 ####################################################################################################
539    
540     sub vehicle_link {
541     my $s = shift;
542     my ($team, $name, $run) = split / /, $s;
543 james 47 return "<a href='${team}_$name$html_extension#life$run'>$team_name[$team] $veh_name{$name} $run</a>";
544 james 37 }
545    
546     ####################################################################################################
547    
548 james 46 sub write_flag_report {
549     my $team = shift;
550    
551     my $html = create_html($team_name[$team] . ' flag');
552    
553     my @grab;
554     my @return;
555    
556     my @fevs = grep {($$_[1] eq 'F+' or $$_[1] eq 'F-' or $$_[1] eq 'C' or $$_[1] eq 'R') and
557     $$_[3] == $team} @events;
558     my $event;
559     my $at_stand = 1;
560     foreach $event (@fevs) {
561     if ($at_stand and $$event[1] eq 'F+') {
562     push @grab, $$event[0];
563     $at_stand = 0;
564     } elsif (!$at_stand and ($$event[1] eq 'C' or $$event[1] eq 'R')) {
565     push @return, $$event[0];
566     $at_stand = 1;
567     }
568     }
569 james 47 push @return, $end_time;
570 james 46
571     for (my $grab = 0; $grab != @grab; $grab++) {
572     my $nicetime = nice_time($grab[$grab]);
573     my $nicedtime = nice_time($return[$grab]);
574     my $grab1 = $grab + 1;
575     $html .= <<END;
576     <div><h2 id="grab$grab1">Grab $grab1 ($nicetime - $nicedtime)</h2>
577     <div><a href="${team}_flag_$grab1.png"><img src="s${team}_flag_$grab1.png"
578     alt="" title="Map of ${team_name[$team]} flag grab $grab1"></a></div>
579     END
580    
581     my $im = create_image();
582     plot_route($im, "$team flag", $grab[$grab], $return[$grab] - 1);
583    
584     my @fevs;
585     my $carrier = '';
586     foreach $event (grep {$grab[$grab] <= $$_[0] and $$_[0] <= $return[$grab]} @events) {
587     if ($$event[1] eq 'F+' and $$event[3] == $team) {
588     $carrier = $$event[2];
589     } elsif (($$event[1] eq 'F-' or $$event[1] eq 'C' or $$event[1] eq 'R')
590     and $$event[3] == $team) {
591     $carrier = '';
592     } elsif ($$event[1] eq 'K' and $$event[2] eq $carrier) {
593     ;
594     } else {
595     next;
596     }
597     push @fevs, $event;
598     }
599     $html .= write_events("$team flag", \@fevs, $im);
600     $html .= '</div>';
601    
602     save_image($im, "${team}_flag_$grab1.png");
603 james 47 undef $im;
604 james 46 }
605    
606 james 47 save_html("${team}_flag$html_extension", $html);
607 james 46 }
608    
609     ####################################################################################################
610    
611 james 37 sub write_summary_report {
612     my $html = create_html("Match Summary");
613     my $name;
614     my $nicetime = nice_time($end_time);
615     my $i;
616    
617     $html .= <<END;
618 james 36 <div><a href="Overview.png"><img src="sOverview.png"
619     alt="" title="Overview map"></a></div>
620 james 37 <p>Playing time $nicetime</p>
621     <table><tr><th>Final scores</th></tr>
622     END
623     for ($i = 1; $i != @team_name; $i++) {
624     $html .= "<tr><td>${team_name[$i]}</td><td>${final_score[$i]}</td></tr>\n";
625     }
626 james 46 $html .= "</table>\n";
627 james 37
628 james 46 my $team;
629     foreach $team (keys %flag) {
630 james 47 $html .= "<p><a href=\"${team}_flag$html_extension\">${team_name[$team]} flag</a></p>\n";
631 james 46 }
632    
633 james 37 $html .= <<END;
634 james 46 <h2>Players and Vehicles</h2>
635 james 36 <table>
636 james 46 <tr><th>Player</th><th>Team</th><th>Score</th><th>Deaths</th><th>Kills</th><th>Grabs</th><th>Caps</th><th>Returns</th></tr>
637 james 36 END
638 james 37
639 james 46 sub lookup {
640     my $hash = shift;
641     my $name = shift;
642     my $max = 0; grep { $max = $_ if $max < $_ } values %$hash;
643     my $n = exists $$hash{$name} ? $$hash{$name} : 0;
644     return $n == $max ? "<td><strong class=\"max\">$n</strong></td>" : "<td>$n</td>";
645     }
646    
647 james 37 foreach $name (sort keys %player) {
648     my $sname = safe_name($name);
649 james 47 $html .= "<tr><td><a href=\"$sname$html_extension\">$name</a></td>" .
650 james 46 "<td>$team_name[$team{$name}]</td>" .
651     lookup(\%score, $name) .
652     lookup(\%deaths, $name) .
653     lookup(\%kills, $name) .
654     lookup(\%grabs, $name) .
655     lookup(\%caps, $name) .
656     lookup(\%returns, $name) .
657     "</tr>\n";
658 james 36 }
659    
660 james 37 $html .= "</table>\n";
661 james 36
662 james 46 if (keys %vehicle) {
663     $html .= "<table><tr><th>Vehicles</th><th>Total used</th></tr>\n";
664 james 47 foreach my $vehicle (sort keys %vehicle) {
665 james 46 my ($team, $name) = split / /, $vehicle, 2;
666     my $sname = safe_name($name);
667     $html .= <<END;
668 james 47 <tr><td><a href="${team}_$sname$html_extension">$team_name[$team] $veh_name{$name}s</a></td><td>${vehicle{"$team $name"}}</td></tr>
669 james 37 END
670 james 46 }
671     $html .= "</table>\n";
672 james 37 }
673 james 36
674 james 47 save_html("index$html_extension", $html);
675 james 37 save_image($imall, 'Overview.png');
676 james 47 undef $imall;
677 james 36 }
678    
679 james 37 ####################################################################################################
680 james 36
681     sub create_image {
682     my $image = GD::Image->newTrueColor($width, $height);
683 james 37 my ($lm, $g);
684 james 36 foreach $lm (@landmarks) {
685     my ($z, $type, $team, $x, $y) = split / /, $lm;
686     icon($image, $icon{$type}, $x, $y);
687     }
688     foreach $g (@waypoints) {
689     my ($team, $x, $y, $z, $desc) = split / /, $g, 5;
690     text($image, $x, $y, $desc);
691     }
692     return $image;
693     }
694    
695     sub save_image {
696     my $image = shift;
697     my $file = shift;
698     my $png = $image->png;
699 james 37 open PNG, ">$outdir/$file" or die "failed to open $outdir/$file: $!";
700 james 36 binmode PNG;
701     print PNG $png;
702     close PNG;
703    
704     my $max = $width < $height ? $height : $width;
705     my $thumb = GD::Image->newTrueColor($thumbsize * $width / $max,
706     $thumbsize * $height / $max);
707     $thumb->copyResampled($image, 0, 0, 0, 0, $thumbsize * $width / $max,
708     $thumbsize * $height / $max, $width, $height);
709     $png = $thumb->png;
710 james 37 open PNG, ">$outdir/s$file" or die "failed to open $outdir/s$file: $!";
711 james 36 binmode PNG;
712     print PNG $png;
713     close PNG;
714     }
715    
716     sub square {
717     my $image = shift;
718     return unless defined $image;
719     my $x = shift;
720     my $y = shift;
721     my $s = shift;
722     my $colour = shift;
723     $image->filledRectangle($x - $s, $y - $s, $x + $s, $y + $s, $colour);
724     }
725    
726     sub line {
727     my $image = shift;
728     return unless defined $image;
729     my $x0 = shift;
730     my $y0 = shift;
731     my $x1 = shift;
732     my $y1 = shift;
733     my $colour = shift;
734     $image->line($x0, $y0, $x1, $y1, $colour);
735     }
736    
737     sub load_image {
738     my $file = shift;
739     open PNG, $file or die "failed to open $file: $!";
740     my $im = GD::Image->newFromPng(\*PNG) or die "PNG load of $file failed";
741     close PNG;
742     $im->transparent(0);
743     return $im;
744     }
745    
746     sub icon {
747     my $image = shift;
748     my $icon = shift;
749     my $x = shift;
750     my $y = shift;
751     $image->setBrush($icon);
752     $image->setPixel($x, $y, gdBrushed);
753     }
754    
755     sub text {
756     my $image = shift;
757     my $x = shift;
758     my $y = shift;
759     my $text = shift;
760 james 37 $image->string(gdSmallFont, $x, $y, $text, 0xffffff);
761 james 36 }
762    
763 james 37 ####################################################################################################
764    
765 james 36 sub create_html {
766     my $title = shift;
767     my $html = <<END;
768     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
769     "http://www.w3.org/TR/html4/strict.dtd">
770     <html>
771     <head>
772     <link rel="stylesheet" type="text/css" href="t2matchlog.css">
773     <title>$title ($mission_name / $mission_type_name)</title>
774     </head>
775    
776     <body>
777     <h1>$title <em class="mission">($mission_name / $mission_type_name)</em></h1>
778    
779     END
780     return $html;
781     }
782    
783     sub save_html {
784     my $file = shift;
785     my $html = shift;
786     $html .= "</body></html>\n";
787 james 37 open HTML, ">$outdir/$file" or die "failed to open $outdir/$file: $!";
788 james 36 print HTML $html;
789     close HTML;
790     }
791    
792 james 37 ####################################################################################################
793    
794 james 36 sub safe_name {
795     my $s = shift;
796 james 47 $s =~ tr/a-zA-Z0-9/_/cs;
797 james 36 return $s;
798     }
799    
800 james 37 sub nice_time {
801     my $time = shift;
802     my $secs = $time % 60;
803     return int($time / 60) . ':' . (($secs < 10) ? "0$secs" : $secs);
804 james 36 }
805    
806 james 37 sub distance {
807     return sqrt (($_[0] - $_[3]) ** 2 + ($_[1] - $_[4]) ** 2 + ($_[2] - $_[5]) ** 2);
808 james 36 }
809    
810 james 37 ####################################################################################################
811    

  ViewVC Help
Powered by ViewVC 1.1.26