1 |
#!@PERL@ |
2 |
# scores.pl |
3 |
# (c) Pertti Karppinen a.k.a roWer <pjka@iki.fi> |
4 |
# |
5 |
# thanks for Sami Ylönen a.k.a klux for some cleaning up |
6 |
# |
7 |
# This program is free software; you can redistribute it |
8 |
# and/or modify it under the terms of the GNU General Public |
9 |
# License as published by the Free Software Foundation; |
10 |
# either version 2 of the License, or (at your option) any |
11 |
# later version. |
12 |
# This program is distributed in the hope that it will be |
13 |
# useful, but WITHOUT ANY WARRANTY; without even the implied |
14 |
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
15 |
# PURPOSE. See the GNU General Public License for more |
16 |
# details. |
17 |
|
18 |
# This should get run out of cron like: |
19 |
# 0,5,10,15,20,25,30,35,40,45,50,55 * * * * $HOME/crossfire/var/www/bin/scores.pl > /dev/null 2>&1 |
20 |
# As a note, if you have a lot of players, you may want to run this less often. This |
21 |
# reads through all the player files on the server to generate this information. |
22 |
# |
23 |
|
24 |
use File::Basename; |
25 |
|
26 |
|
27 |
#the name of the server admin |
28 |
my $admin_name="Some Admin"; |
29 |
|
30 |
#the email of the server admin |
31 |
my $admin_email="Some.Admin@Some.Where"; |
32 |
|
33 |
#html output file |
34 |
my $outfile="/var/www/html/cscores.html"; |
35 |
|
36 |
#complete url to the output |
37 |
my $scoreurl="/cscores.html"; |
38 |
|
39 |
my $timezone=`date +%Z`; |
40 |
|
41 |
#Your Crossfire folder |
42 |
my $crossfire_home="@prefix@"; |
43 |
|
44 |
#background color of the webpage |
45 |
my $bgcolor="#eeeeee"; |
46 |
|
47 |
#background color of the outer table |
48 |
my $outertablebgcolor="#dddddd"; |
49 |
|
50 |
#background color of the inner table |
51 |
my $innertablebgcolor="#dddddd"; |
52 |
|
53 |
#background color for <tr> |
54 |
my $tabletrcolor="#a9b4f2"; |
55 |
|
56 |
#the title of your score webpage |
57 |
my $title="Crossfire scores"; |
58 |
|
59 |
|
60 |
#the levels =) |
61 |
# MSW Note - we should really be clever and read the exp_table |
62 |
# file to dynamically generate this. |
63 |
|
64 |
my @levels=(0,2000,4000, 8000, |
65 |
16000,32000,64000,125000,250000, |
66 |
500000,900000,1400000,2000000,2600000, |
67 |
3300000,4100000,4900000,5700000,6600000, |
68 |
7500000,8400000,9300000,10300000,11300000, |
69 |
12300000,13300000,14400000,15500000,16600000, |
70 |
17700000,18800000,19900000,21100000,22300000, |
71 |
23500000,24700000,25900000,27100000,28300000, |
72 |
29500000,30800000,32100000,33400000,34700000, |
73 |
36000000,37300000,38600000,39900000,41200000, |
74 |
42600000,44000000,45400000,46800000,48200000, |
75 |
49600000,51000000,52400000,53800000,55200000, |
76 |
56600000,58000000,59400000,60800000,62200000, |
77 |
63700000,65200000,66700000,68200000,69700000, |
78 |
71200000,72700000,74200000,75700000,77200000, |
79 |
78700000,80200000,81700000,83200000,84700000, |
80 |
86200000,87700000,89300000,90900000,92500000, |
81 |
94100000,95700000,97300000,98900000,100500000, |
82 |
102100000,103700000,105300000,106900000,108500000, |
83 |
110100000,111700000,113300000,114900000,116500000, |
84 |
118100000,119700000,121300000,122900000,124500000, |
85 |
126100000,127700000,129300000,130900000,785400000, |
86 |
1570800000); |
87 |
|
88 |
|
89 |
my $DEBUG=0; |
90 |
|
91 |
#prototypes |
92 |
sub parse_file($); |
93 |
sub html_print_player($@); |
94 |
sub html_print_table_header(); |
95 |
sub html_print_header(); |
96 |
sub html_print_footer(); |
97 |
sub read_dms(); |
98 |
|
99 |
my @files= glob("$crossfire_home/var/crossfire/players/*/*.pl"); |
100 |
foreach(sort @files) { |
101 |
print "$_\n" if $DEBUG; |
102 |
parse_file($_); |
103 |
} |
104 |
for($i=0;$i<$#scores+1;$i++) { |
105 |
my $exp=$scores[$i][6]; |
106 |
my $name=$scores[$i][0]; |
107 |
$score_hash{$name}=$exp; |
108 |
$ranking{$name}=$i; |
109 |
} |
110 |
my %dms; |
111 |
read_dms(); |
112 |
|
113 |
my $rank=1; |
114 |
$saved_exp=-1; |
115 |
$saved_rank=-1; |
116 |
open(OUT,">$outfile") or die("Couldn't open outputfile $outfile: $!\n"); |
117 |
my $ofh=select(OUT); |
118 |
$|=1; |
119 |
html_print_header(); |
120 |
html_print_table_header(); |
121 |
foreach(sort {$score_hash{$b} <=> $score_hash{$a}} keys %ranking) { |
122 |
my $i=$ranking{$_}; |
123 |
my @tmp; |
124 |
print "$scores[$i][0]\t$scores[$i][6]\n" if $DEBUG; |
125 |
for($j=0;$j<12;$j++) { |
126 |
$tmp[$j]=$scores[$i][$j]; |
127 |
} |
128 |
html_print_player($rank++,@tmp); |
129 |
} |
130 |
print "</table>\n"; |
131 |
html_print_footer(); |
132 |
close(OUT); |
133 |
select($ofh); |
134 |
exit 0; |
135 |
|
136 |
sub parse_file($) { |
137 |
my $player_file=shift; |
138 |
my($name,$title,$race,$class,$killer,$exp,$map,$maxhp,$maxsp,$maxgrace,$level,$god); |
139 |
my $state=0; |
140 |
my $count=0; |
141 |
my $no_class=0; |
142 |
$killer="left"; |
143 |
$god=" "; |
144 |
open(PLAYER_FILE,"$player_file") or die("autch $!"); |
145 |
while(<PLAYER_FILE>) { |
146 |
if(/no_class_face_change/) { |
147 |
$no_class=1; |
148 |
} |
149 |
if($state==0) { |
150 |
if(/^title/) { |
151 |
/^title\s*(.*)$/; |
152 |
$title=$1; |
153 |
$count++; |
154 |
next; |
155 |
} elsif(/^map/) { |
156 |
chomp; |
157 |
$map=basename($_); |
158 |
$count++; |
159 |
next; |
160 |
} |
161 |
$state=2 if($count==2); |
162 |
$state=2 if(/^arch.*_player/ || /^arch.*pl_.*/); |
163 |
next unless($state==2); |
164 |
} |
165 |
if($state==2||$state==3) { |
166 |
next unless($state==3||/^arch.*_player/ || /^arch.*pl_.*/); |
167 |
next if(/^name_pl/); |
168 |
if($state==2&&/^arch.*_player/) { |
169 |
/^arch\s*(.*?)_player/; |
170 |
$race=$1; |
171 |
$count++; |
172 |
$state=3; |
173 |
next; |
174 |
} |
175 |
if($state==2&&/^arch.*pl_.*/) { |
176 |
/^arch.*pl_(\S*)/; |
177 |
$race=$1; |
178 |
$race =~ s/_/ /g; |
179 |
$count++; |
180 |
$state=3; |
181 |
next; |
182 |
} |
183 |
if(/^title/) { |
184 |
/^title\s*(.*)$/; |
185 |
$title=$1; |
186 |
$count++; |
187 |
next; |
188 |
} |
189 |
if(/^name/) { |
190 |
/^name\s*(.*)$/; |
191 |
$name=$1; |
192 |
$count++; |
193 |
next; |
194 |
} |
195 |
if(/^face/) { |
196 |
/^face\s*([^_]*).*\.\d+/; |
197 |
$class=$1; |
198 |
$count++; |
199 |
next; |
200 |
} |
201 |
if(/^maxhp/) { |
202 |
/^maxhp\s*(\d*)/; |
203 |
$maxhp=$1; |
204 |
$count++; |
205 |
next; |
206 |
} |
207 |
if(/^maxsp/) { |
208 |
/^maxsp\s*(\d*)/; |
209 |
$maxsp=$1; |
210 |
$count++; |
211 |
next; |
212 |
} |
213 |
if(/^maxgrace/) { |
214 |
/^maxgrace\s*(\d*)/; |
215 |
$maxgrace=$1; |
216 |
$count++; |
217 |
next; |
218 |
} |
219 |
if(/^exp/) { |
220 |
/^exp\s*(\d*)/; |
221 |
$exp=$1; |
222 |
$count++; |
223 |
next; |
224 |
} |
225 |
if(/^level/) { |
226 |
/^level\s*(\d*)/; |
227 |
$level=$1; |
228 |
$count++; |
229 |
next; |
230 |
} |
231 |
# $state=4 if($count==8); |
232 |
$state=4 if(/^arch/ || /^end/); |
233 |
next; |
234 |
} elsif($state==4) { |
235 |
next unless(/^arch skill_praying/); |
236 |
$state=5; |
237 |
next; |
238 |
} elsif($state==5) { |
239 |
$state=6 if(/^end/); |
240 |
next unless(/^title/); |
241 |
/^title\s*(.*)/; |
242 |
$god=$1; |
243 |
$state=6; |
244 |
} |
245 |
} |
246 |
close(PLAYER_FILE); |
247 |
$class=$race if($no_class); |
248 |
$title=$class unless defined $title; |
249 |
if(!defined $level) { |
250 |
for($level=0;$level<$#levels;$level++) { |
251 |
last if($exp<$levels[$level]); |
252 |
} |
253 |
} |
254 |
if(defined $exp) { |
255 |
my @tmp= ($name, $title ,$race,$class,$killer,$map,$exp,$level,$maxhp,$maxsp,$maxgrace,$god); |
256 |
push(@scores,\@tmp); |
257 |
print STDERR "$name the $title ($race $class) $killer the game on map $map with $exp points (level $level)" if $DEBUG; |
258 |
print STDERR " and maxhp of $maxhp, maxsp of $maxsp and maxgrace" if $DEBUG; |
259 |
print STDERR " (from $god)" if (defined $god && $DEBUG); |
260 |
print STDERR " of $maxgrace.\n" if $DEBUG; |
261 |
} |
262 |
|
263 |
} |
264 |
|
265 |
sub html_print_player($@) { |
266 |
my($rank,@table)=@_; |
267 |
my $name = $table[0]; |
268 |
my $title = $table[1]; |
269 |
my $race = $table[2]; |
270 |
my $class = $table[3]; |
271 |
my $killer = $table[4]; |
272 |
my $map = $table[5]; |
273 |
my $exp = $table[6]; |
274 |
my $level = $table[7]; |
275 |
my $maxhp = $table[8]; |
276 |
my $maxsp = $table[9]; |
277 |
my $maxgrace = $table[10]; |
278 |
my $god = $table[11]; |
279 |
print "<tr bgcolor=\"$tabletrcolor\">\n"; |
280 |
if ($saved_exp!=$exp) { |
281 |
$saved_exp=$exp; |
282 |
$saved_rank=$rank; |
283 |
} |
284 |
if ($saved_rank<11) { |
285 |
print " <td align=right><b>$saved_rank.</b></td>\n"; |
286 |
} else { |
287 |
print " <td align=right>$saved_rank.</td>\n"; |
288 |
} |
289 |
if ($dms{$name}) { |
290 |
print " <td>$name the $title <font color=red size=-3>DM</font></td>\n"; |
291 |
} else { |
292 |
print " <td>$name the $title</td>\n"; |
293 |
} |
294 |
print " <td>$race</td>\n"; |
295 |
print " <td align=right>$exp</td>\n" unless($exp>=785400000); |
296 |
print " <td align=right><font color=red>$exp</font></td>\n" if($exp>=785400000); |
297 |
print " <td align=right>$level</td>\n"; |
298 |
print " <td align=right>$maxhp</td>\n"; |
299 |
print " <td align=right>$maxsp</td>\n"; |
300 |
print " <td align=right>$maxgrace</td>\n"; |
301 |
print " <td>$god</td>\n"; |
302 |
print " <td>$map</td>\n"; |
303 |
print "</tr>\n"; |
304 |
} |
305 |
|
306 |
sub html_print_table_header() { |
307 |
print "<table border=0 cellpadding=2 cellspacing=1 class=\"inner_table\">\n"; |
308 |
print "<tr bgcolor=\"$tabletrcolor\">\n"; |
309 |
print " <td align=\"center\">Rank</td>\n"; |
310 |
print " <td align=\"center\">Character</td>\n"; |
311 |
print " <td align=\"center\">Race</td>\n"; |
312 |
print " <td align=\"center\">Score</td>\n"; |
313 |
print " <td align=\"center\">Level</td>\n"; |
314 |
print " <td align=\"center\">MaxHP</td>\n"; |
315 |
print " <td align=\"center\">MaxSP</td>\n"; |
316 |
print " <td align=\"center\">MaxGP</td>\n"; |
317 |
print " <td align=\"center\">God</td>\n"; |
318 |
print " <td align=\"center\">Location</td>\n"; |
319 |
print "</tr>\n"; |
320 |
} |
321 |
sub html_print_header() { |
322 |
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"; |
323 |
print "<html><head><title>$title</title>\n"; |
324 |
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n"; |
325 |
print "<meta http-equiv=\"refresh\" content=\"300; url=$scoreurl\">\n"; |
326 |
print << "EOF"; |
327 |
|
328 |
<STYLE TYPE="text/css"> |
329 |
<!-- |
330 |
.outer_table { |
331 |
background-color: $outertablebgcolor; |
332 |
border: 1px #4350b0 solid; |
333 |
} |
334 |
.inner_table { |
335 |
background-color: $innertablebgcolor; |
336 |
border: 2px #4350b0 solid; |
337 |
} |
338 |
--> |
339 |
</STYLE> |
340 |
|
341 |
EOF |
342 |
|
343 |
print "</head>\n"; |
344 |
print "<body bgcolor=\"$bgcolor\"><center>\n"; |
345 |
print "<table border=0 class=\"outer_table\" align=\"center\"><tr><td align=\"center\">\n"; |
346 |
print "<h1>$title</h1>\n"; |
347 |
} |
348 |
sub html_print_footer() |
349 |
{ |
350 |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = |
351 |
localtime(time); |
352 |
$year+=1900; |
353 |
my @months=("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"); |
354 |
my @days=("Sun","Mon","Tue","Wed","Thu","Fri","Sat"); |
355 |
print "<a href=\"/\">Back</a>\n</center>\n"; |
356 |
print "<hr>\n<address><a href=\"mailto:$admin_email\">$admin_name</a></address>\n"; |
357 |
printf ("Last modified: $days[$wday] $months[$mon] $mday %2.2d:%2.2d:%2.2d $timezone $year\n",$hour,$min,$sec); |
358 |
print "</td></tr></table>\n"; |
359 |
print "</body></html>\n"; |
360 |
} |
361 |
|
362 |
sub read_dms() |
363 |
{ |
364 |
open(DMLIST, "$crossfire_home/etc/crossfire/dm_file"); |
365 |
while(<DMLIST>) { |
366 |
next if(/^\s*#/); |
367 |
chomp; |
368 |
/\s*([^\s:]+):/; |
369 |
$dms{$1}=1; |
370 |
} |
371 |
close(DMLIST); |
372 |
} |