/[james]/t2matchlog/t2matchlog
ViewVC logotype

Annotation of /t2matchlog/t2matchlog

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (hide annotations) (download)
Sun Dec 21 00:09:48 2003 UTC (20 years, 5 months ago) by james
File size: 23965 byte(s)
Flag tracking and better stats.

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

  ViewVC Help
Powered by ViewVC 1.1.26