6 # Reads a GS-compliant log file from STDIN, writes processed logs
9 # Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 # Enable this line for debugging
31 # Read mapname-mapping from file
33 open (MAPNAMES,"mapnames.txt") or die "Could not open mapnames.txt: $!\n";
35 # Log file for skill calculation
36 open (SKILLOG, ">skill.log") or die "Could not open skill.log: $!\n";
38 while ($line=<MAPNAMES>) {
40 ($handle,$mapname) = split (":",$line);
42 $handle{$mapname} = $handle;
47 while ($gslog_line = shift(@gslog)) {
49 ($killer,$victim,$action,$weapon,$fragdiff,$timestamp,$ping) =
50 split("\t",$gslog_line);
52 unless (defined($action)) {
56 if ($action eq "Kill") {
57 $pl_kills{"##global"}{$killer}++;
58 $pl_kills{$actual_map}{$killer}++;
59 $pl_victims{"##global"}{$victim}++;
60 $pl_victims{$actual_map}{$victim}++;
61 if (defined($pl_count_map{$killer})) {
62 $pl_maps_played{"##global"}{$killer}++;
63 $pl_maps_played{$actual_map}{$killer}++;
64 print "Map count for $killer increased to $pl_maps_played{\"##global\"}{$killer}\n" if $debug;
65 undef $pl_count_map{$killer};
67 if (defined($pl_count_map{$victim})) {
68 $pl_maps_played{"##global"}{$victim}++;
69 $pl_maps_played{$actual_map}{$victim}++;
70 print "Map count for $victim increased to $pl_maps_played{\"##global\"}{$victim}\n" if $debug;
71 undef $pl_count_map{$victim};
73 $sys_kills{"##global"}++;
74 $sys_kills{$actual_map}++;
75 $pl_kills_local{$killer}++;
78 print SKILLOG "K:$killer:$victim\n";
81 if ($action eq "Suicide") {
82 $pl_suicides{"##global"}{$killer}++;
83 $pl_suicides{$actual_map}{$killer}++;
84 if (defined($pl_count_map{$killer})) {
85 $pl_maps_played{"##global"}{$killer}++;
86 $pl_maps_played{$actual_map}{$killer}++;
87 print "Map count for $killer increased to $pl_maps_played{\"##global\"}{$killer}\n" if $debug;
88 undef $pl_count_map{$killer};
90 $sys_suicides{"##global"}++;
91 $sys_suicides{$actual_map}++;
92 $pl_kills_local{$killer}--;
95 print SKILLOG "S:$killer\n";
98 # Check if a new map has been started.
99 # $weapon holds the map name
101 if ($action eq "Map") {
104 $actual_map = $handle{$weapon};
105 unless (defined($actual_map)) {
106 $actual_map = "##undefined";
108 $sys_maps_played{"##global"}++;
109 $sys_maps_played{$actual_map}++;
110 print "Map started: $actual_map\n" if $debug;
113 # Check for a newly started game.
115 if ($action eq "GameStart") {
120 # Check for the end of a map. Calculate map winner.
121 # Log out all players
123 if ($action eq "GameEnd") {
124 print "Map ends: $actual_map\n" if $debug;
125 $sys_connect_total{"##global"} += $timestamp;
126 $sys_connect_total{$actual_map} += $timestamp;
129 if (defined(%pl_kills_local)) {
130 foreach $nick (keys %pl_kills_local) {
131 if ($pl_kills_local{$nick} > $pl_best_frags) {
132 $pl_best_frags = $pl_kills_local{$nick};
133 $pl_best_nick = $nick;
136 if (defined($pl_best_nick)) {
137 $pl_maps_won{"##global"}{$pl_best_nick}++;
138 $pl_maps_won{$actual_map}{$pl_best_nick}++;
139 print "$pl_best_nick wins $actual_map with $pl_best_frags\n" if $debug;
144 # Print out skill log
145 if (defined($pl_best_nick)) { # If no one won the map, why bother?
146 print SKILLOG "W:$pl_best_nick\n";
151 # Check for a newly connecting player. Initialize all fields, if necessary.
152 # $weapon holds player name.
154 if ($action eq "PlayerConnect") {
161 # If a player disconnects, log his online time.
162 # $weapon holds the player name.
164 if ($action eq "PlayerLeft") {
166 pl_disconnect($weapon);
171 # If a player renames himself, consider this a disconnect and immediate
173 # $weapon holds the old name, $fragdiff the new one.
174 # Preserve frags in the local map! Important for winning caclulations
175 # WARNING! We might get into trouble here. If a player wins a map,
176 # and renames during the ending music, the "new" player will win the
177 # map (since he inherits the kills), but the map will not count as
178 # played (since he was neither fragged, nor fragged another player).
179 # PS: this is not theoretical ;)
181 if ($action eq "PlayerRename") {
183 $tmp = $pl_kills_local{$weapon};
184 print "$weapon renamed to $fragdiff, inheriting $tmp\n" if $debug;
185 # If the map counts for the "leaving" player, decrease
186 # his mapcount, and increase the count of the "connecting" player.
187 unless(defined($pl_count_map{$weapon})) {
188 $pl_maps_played{"##global"}{$weapon}--;
189 $pl_maps_played{$actual_map}{$weapon}--;
190 print "Map count for $weapon decreased to $pl_maps_played{\"##global\"}{$weapon}\n" if $debug;
192 pl_disconnect($weapon);
193 pl_connect($fragdiff);
194 unless(defined($pl_count_map{$weapon})) {
195 $pl_maps_played{"##global"}{$fragdiff}++;
196 $pl_maps_played{$actual_map}{$fragdiff}++;
197 print "Map count for $fragdiff increased to $pl_maps_played{\"##global\"}{$fragdiff}\n" if $debug;
199 $pl_kills_local{$fragdiff} = $tmp;
204 # Just to be sure....
208 # Write out all results. Phew.
210 foreach $mapkey (keys %pl_kills) {
212 if ($mapkey eq "##global") {
213 $filename = "big.res";
215 $filename = $mapkey . ".res";
219 open(LOGFILE, ">$filename") or die "Could not open $filename: $!\n";
223 # Print final results. First line holds overall system statistics.
226 print "$sys_kills{$mapkey}:";
228 print "$sys_suicides{$mapkey}:";
229 print "$sys_maps_played{$mapkey}:";
231 print "$sys_connect_total{$mapkey}:";
234 foreach $nick (keys %{ $pl_kills{$mapkey} }) {
237 print "$pl_kills{$mapkey}{$nick}:";
238 print "$pl_victims{$mapkey}{$nick}:";
239 print "$pl_suicides{$mapkey}{$nick}:";
240 print "$pl_maps_played{$mapkey}{$nick}:";
241 print "$pl_maps_won{$mapkey}{$nick}:";
242 print "$pl_connect_total{$mapkey}{$nick}:";
259 return unless defined($pl_name);
261 # Reduce the player name to the first 15 characters. You want that.
264 $pl_name = substr($pl_name, 0, 15);
266 print "Player connected: $pl_name\n" if $debug;
268 $pl_kills{"##global"}{$pl_name} = 0 unless defined($pl_kills{"##global"}{$pl_name});
269 $pl_kills{$actual_map}{$pl_name} = 0 unless defined($pl_kills{$actual_map}{$pl_name});
271 $pl_victims{"##global"}{$pl_name} = 0 unless defined($pl_victims{"##global"}{$pl_name});
272 $pl_victims{$actual_map}{$pl_name} = 0 unless defined($pl_victims{$actual_map}{$pl_name});
274 $pl_suicides{"##global"}{$pl_name} = 0 unless defined($pl_suicides{"##global"}{$pl_name});
275 $pl_suicides{$actual_map}{$pl_name} = 0 unless defined($pl_suicides{$actual_map}{$pl_name});
277 $pl_maps_played{"##global"}{$pl_name} = 0 unless defined($pl_maps_played{"##global"}{$pl_name});
278 $pl_maps_played{$actual_map}{$pl_name} = 0 unless defined($pl_maps_played{$actual_map}{$pl_name});
280 $pl_maps_won{"##global"}{$pl_name} = 0 unless defined($pl_maps_won{"##global"}{$pl_name});
281 $pl_maps_won{$actual_map}{$pl_name} = 0 unless defined($pl_maps_won{$actual_map}{$pl_name});
285 # If the player reconnects before a map change, don't count as
287 # This flag is reset by pl_disconnect_all().
289 unless (defined($pl_connect{$pl_name})) {
290 $pl_count_map{$pl_name} = 1;
293 $pl_connect{$pl_name} = 1;
294 $pl_kills_local{$pl_name} = 0;
295 $pl_connect_start{"##global"}{$pl_name} = $timestamp;
296 $pl_connect_start{$actual_map}{$pl_name} = $timestamp;
299 # ----------------------
304 return unless defined($pl_name);
306 print "Player left: $pl_name with $pl_maps_played{\"##global\"}{$pl_name} maps played, $pl_maps_won{\"##global\"}{$pl_name} maps won\n" if $debug;
308 $pl_connect_total{"##global"}{$pl_name} += ($timestamp - $pl_connect_start{"##global"}{$pl_name});
309 $pl_connect_total{$actual_map}{$pl_name} += ($timestamp - $pl_connect_start{$actual_map}{$pl_name});
310 $pl_connect_start{"##global"}{$pl_name} = -1;
311 delete $pl_kills_local{$pl_name};
314 # ----------------------
316 sub pl_disconnect_all {
318 foreach $name (keys %pl_connect) {
320 undef $pl_connect{$name};
321 undef $pl_count_map{$name};
322 if ($pl_connect_start{"##global"}{$name} >= 0) {
323 pl_disconnect($name);
325 undef %pl_kills_local;