--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+README - NDC Code
+=================
+
+Dies ist die README fuer die GPL-Release des NDC (Northcore Deathmatch
+Clan) Codes fuer Quakeserver-Administration und -Auswertung (oder
+ganz kurz: NDC Code).
+
+Die in diesem Paket gesammelten Werke sind ueber die Jahre aus
+eigenem Beduerfnis bei der Verwaltung unserer Quakeserver und
+der Homepage entstanden.
+Meisterwerke sind nach unserer Meinung nicht dabei, aber da es
+genug Leute gegeben hat, die Interesse an dem Code gezeigt
+haben: nun, hier ist er.
+Erwartet bitte keinen wunderschoenen und akurat durchkommentierten
+Code. Ich habe versucht, die groessten Knaller rauszufeilen
+(ich habe Perl und SQL gelernt, waehrend dieser Code entstand,
+und das sieht man), aber teilweise sind da noch Stellen
+drin, die ich selber nicht mehr verstehe.
+Der gesamte Code steht von der ersten bis zur letzten Zeile
+unter der GPL (GNU Public License), in voller Laenge und
+Schoenheit nachzulesen in der Datei COPYING.
+
+Was heisst das fuer Euch und uns?
+(Note: Dieser Absatz ist meine Interpretation der GPL. Er ist
+_keine_ Rechtsgrundlage. Gueltig ist der Wortlaut der GPL,
+zu entnehmen der Datei COPYING, oder bei der FSF)
+Fuer uns heisst es: was auch immer dieser Code bei Euch anrichten
+mag, es ist einzig und allein Euer Problem. Wir uebernehmen keinerlei
+Garantie fuer die Funktionalitaet, Sicherheit oder Brauchbarkeit
+des Codes fuer irgendwelche Zwecke.
+Fuer Euch heisst es: Macht damit, was ihr wollt. Veraendert ihn,
+erweitert ihn, benutzt, was Euch gefaellt, und werft den Rest weg.
+Dies alles unter einer Bedingung: der Code, der aus unserem oder
+mit Hilfe unseres Codes entsteht, muss wieder unter der GPL stehen.
+Man koennte sagen, GPL ist ansteckend. Und Heilmittel gibts keins :)
+Dass abgeleiteter Code wieder unter der GPL steht, impliziert
+automatisch, daß er wieder frei verfügbar sein muss. Das heisst
+_nicht_, dass ihr damit kein Geld verdienen duerft. Ihr duerft
+Programme verfassen, und dafuer Geld verlangen. Aber ihr muesst
+(spaetestens auf Anfrage) den Code rausruecken.
+
+
+INHALT
+======
+
+Was verbirgt sich nun in den einzelnen Verzeichnissen? Eine kurze
+Auflistung:
+
+gs_analyze Ein Perl-Script, dass die von Lithium (und anderen
+ MODs) erzeugten GS-Logfiles auswertet, und in eine
+ Form bringt, die die Datenbankscripte leichter ver-
+ arbeiten koennen.
+ Das Script erzeugt eine Gesamtstatistik, und
+ Statistiken fuer einzelne Maps.
+
+stats Die Teile des Codes, die auf der Website im Vordergrund
+ (dailystats, foreverstats, playerstats) und im Hintergrund
+ (makedb, makerank) die Statistiken verwalten.
+
+server Das quakec5-Skript, das den Echtzeit-Status eines
+ Quake2-Servers auswertet.
+
+
+VORAUSSETZUNGEN
+===============
+
+Was braucht man fuer all das hier? Von den technischen Voraussetzungen
+her:
+perl (mindestens 5.002)
+MySQL 3.22
+apache 1.3
+
+Es gibt keinen wirklichen Grund, warum das alles hier nicht auch mit
+IIS und Oracle laufen sollte, aber die obige Liste stellt die laufende
+Konfiguration dar, und ist als solche geprueft.
+
+Noch etwas: die Skripte sind zwar "aus dem Leben" gegriffen, aber
+natuerlich steht da auch etwas drin, was Euch nix angeht. Passworte,
+Serverpfade, so ein Zeug. Das ist in diesem Release entfernt.
+Das bringt es mit sich, dass moeglicherweise (oder eher: ziemlich
+sicher) dieser Sourcetree nicht aus der Tuete laufen wird. Wer also
+Angst vor dreckigen Fingern und anderer Leute Code hat, ist hiermit
+wohl auf dem falschen Dampfer. Aber solche Personen lesen fuer gewoehnlich
+auch keine READMEs :)
+
+
+VERSIONIERUNG
+=============
+
+Versionsnummern? Was ist das?
+Bei den fuer NDC erstellten Scripts war das nie ein grosses Thema.
+Neuere Versionen wurden einfach gnadenlos in den alten Code
+reingeschoben. Bei guter Laune des Autors wurde dem Dateinamen
+eine sich (eventuell sogar nachvollziehbar erhoehende) angehaengte
+Nummer verpasst. Diese Nummern haben sie hier auch.
+Aus diesem Chaos heraus deklarieren wir alle hier mitgelieferten
+Programme als Version NDC Code Release 1. Also bitte nicht wundern,
+wenn es eine foreverstats3.pl gibt, aber keine Spur der vorigen
+zu finden ist. Das ist dann eben so :)
+
+
+KONTAKT
+=======
+
+Bei Fragen, Anregungen, Bugfixes:
+http://www.ndc.sh/ndccode
+
+oder
+ndccode@ndc.sh
--- /dev/null
+README - gs_analyze2.pl
+=======================
+
+Eines der Kernstuecke des Statistiksystems. Dieses Script
+laeuft bevorzugt auf dem Quake-Server selbst, wo es
+Logfiles im GS-Format liest, und in ein kuerzeres Logfile
+umwandelt, das von den Datenbankscripten weiterverarbeitet
+werden kann.
+
+Das Script liest seine Daten von STDIN. Die Ausgabe erfolgt
+zu einen in eine Datei (big.res), die die gesamte Statistik
+fuer das Logfile enthaelt.
+Zum anderen liest das Script, falls vorhanden, eine Datei namens
+mapnames.txt ein. Da GS-Logfiles aus nicht bekannten Gruenden
+nicht den BSP-Namen der gespielten Maps, sondern den vollen Namen
+(also nicht q2dm1 sondern "The Edge") enthalten, wird der Inhalt
+dieser Datei zur Uebersetzung genutzt.
+Fuer Maps, deren BSP-Namen das Script auf diese Weise ermitteln
+kann, werden separate Logdateien mit dem Namen des BSP (also
+q2dm1.res...) geschrieben.
+
+Jede .res-Datei enthaelt in einer Zeile Daten fuer je einen
+Spieler. Die einzelnen Felder sind durch ":" getrennt (nein,
+wir machen uns keine Gedanken um : in Spielernamen). Die einzelnen
+Felder:
+
+Name
+Kills
+Victims
+Suicides
+gespielte Maps
+gewonnene Maps
+Spielzeit (Sekunden)
+
+Die jeweils erste Zeile (ohne Spielernamen, beginnend mit einem :)
+enthaelt die jeweiligen Summen aller Felder.
--- /dev/null
+#!/usr/bin/perl -w
+
+# gs_analyze2.pl
+# NDC Code Release 1
+#
+# Reads a GS-compliant log file from STDIN, writes processed logs
+# to various files.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+@gslog=<STDIN>;
+
+# Enable this line for debugging
+
+# $debug = 1;
+
+# Read mapname-mapping from file
+
+open (MAPNAMES,"mapnames.txt") or die "Could not open mapnames.txt: $!\n";
+
+# Log file for skill calculation
+open (SKILLOG, ">skill.log") or die "Could not open skill.log: $!\n";
+
+while ($line=<MAPNAMES>) {
+
+ ($handle,$mapname) = split (":",$line);
+ chop($mapname);
+ $handle{$mapname} = $handle;
+}
+
+close (MAPNAMES);
+
+while ($gslog_line = shift(@gslog)) {
+
+ ($killer,$victim,$action,$weapon,$fragdiff,$timestamp,$ping) =
+ split("\t",$gslog_line);
+
+ unless (defined($action)) {
+ next;
+ }
+
+ if ($action eq "Kill") {
+ $pl_kills{"##global"}{$killer}++;
+ $pl_kills{$actual_map}{$killer}++;
+ $pl_victims{"##global"}{$victim}++;
+ $pl_victims{$actual_map}{$victim}++;
+ if (defined($pl_count_map{$killer})) {
+ $pl_maps_played{"##global"}{$killer}++;
+ $pl_maps_played{$actual_map}{$killer}++;
+ print "Map count for $killer increased to $pl_maps_played{\"##global\"}{$killer}\n" if $debug;
+ undef $pl_count_map{$killer};
+ }
+ if (defined($pl_count_map{$victim})) {
+ $pl_maps_played{"##global"}{$victim}++;
+ $pl_maps_played{$actual_map}{$victim}++;
+ print "Map count for $victim increased to $pl_maps_played{\"##global\"}{$victim}\n" if $debug;
+ undef $pl_count_map{$victim};
+ }
+ $sys_kills{"##global"}++;
+ $sys_kills{$actual_map}++;
+ $pl_kills_local{$killer}++;
+
+ # Print out skill log
+ print SKILLOG "K:$killer:$victim\n";
+ }
+
+ if ($action eq "Suicide") {
+ $pl_suicides{"##global"}{$killer}++;
+ $pl_suicides{$actual_map}{$killer}++;
+ if (defined($pl_count_map{$killer})) {
+ $pl_maps_played{"##global"}{$killer}++;
+ $pl_maps_played{$actual_map}{$killer}++;
+ print "Map count for $killer increased to $pl_maps_played{\"##global\"}{$killer}\n" if $debug;
+ undef $pl_count_map{$killer};
+ }
+ $sys_suicides{"##global"}++;
+ $sys_suicides{$actual_map}++;
+ $pl_kills_local{$killer}--;
+
+ # Print out skill log
+ print SKILLOG "S:$killer\n";
+ }
+
+ # Check if a new map has been started.
+ # $weapon holds the map name
+
+ if ($action eq "Map") {
+ chop ($weapon);
+ chop ($weapon);
+ $actual_map = $handle{$weapon};
+ unless (defined($actual_map)) {
+ $actual_map = "##undefined";
+ }
+ $sys_maps_played{"##global"}++;
+ $sys_maps_played{$actual_map}++;
+ print "Map started: $actual_map\n" if $debug;
+ }
+
+ # Check for a newly started game.
+
+ if ($action eq "GameStart") {
+ pl_disconnect_all();
+ }
+
+
+ # Check for the end of a map. Calculate map winner.
+ # Log out all players
+
+ if ($action eq "GameEnd") {
+ print "Map ends: $actual_map\n" if $debug;
+ $sys_connect_total{"##global"} += $timestamp;
+ $sys_connect_total{$actual_map} += $timestamp;
+ $pl_best_frags = 0;
+ undef $pl_best_nick;
+ if (defined(%pl_kills_local)) {
+ foreach $nick (keys %pl_kills_local) {
+ if ($pl_kills_local{$nick} > $pl_best_frags) {
+ $pl_best_frags = $pl_kills_local{$nick};
+ $pl_best_nick = $nick;
+ }
+ }
+ if (defined($pl_best_nick)) {
+ $pl_maps_won{"##global"}{$pl_best_nick}++;
+ $pl_maps_won{$actual_map}{$pl_best_nick}++;
+ print "$pl_best_nick wins $actual_map with $pl_best_frags\n" if $debug;
+ }
+ }
+ pl_disconnect_all();
+
+ # Print out skill log
+ if (defined($pl_best_nick)) { # If no one won the map, why bother?
+ print SKILLOG "W:$pl_best_nick\n";
+ }
+ }
+
+
+ # Check for a newly connecting player. Initialize all fields, if necessary.
+ # $weapon holds player name.
+
+ if ($action eq "PlayerConnect") {
+
+ pl_connect($weapon);
+
+ }
+
+
+ # If a player disconnects, log his online time.
+ # $weapon holds the player name.
+
+ if ($action eq "PlayerLeft") {
+
+ pl_disconnect($weapon);
+
+ }
+
+
+ # If a player renames himself, consider this a disconnect and immediate
+ # reconnect.
+ # $weapon holds the old name, $fragdiff the new one.
+ # Preserve frags in the local map! Important for winning caclulations
+ # WARNING! We might get into trouble here. If a player wins a map,
+ # and renames during the ending music, the "new" player will win the
+ # map (since he inherits the kills), but the map will not count as
+ # played (since he was neither fragged, nor fragged another player).
+ # PS: this is not theoretical ;)
+
+ if ($action eq "PlayerRename") {
+
+ $tmp = $pl_kills_local{$weapon};
+ print "$weapon renamed to $fragdiff, inheriting $tmp\n" if $debug;
+ # If the map counts for the "leaving" player, decrease
+ # his mapcount, and increase the count of the "connecting" player.
+ unless(defined($pl_count_map{$weapon})) {
+ $pl_maps_played{"##global"}{$weapon}--;
+ $pl_maps_played{$actual_map}{$weapon}--;
+ print "Map count for $weapon decreased to $pl_maps_played{\"##global\"}{$weapon}\n" if $debug;
+ }
+ pl_disconnect($weapon);
+ pl_connect($fragdiff);
+ unless(defined($pl_count_map{$weapon})) {
+ $pl_maps_played{"##global"}{$fragdiff}++;
+ $pl_maps_played{$actual_map}{$fragdiff}++;
+ print "Map count for $fragdiff increased to $pl_maps_played{\"##global\"}{$fragdiff}\n" if $debug;
+ }
+ $pl_kills_local{$fragdiff} = $tmp;
+ }
+
+}
+
+# Just to be sure....
+
+pl_disconnect_all();
+
+# Write out all results. Phew.
+
+foreach $mapkey (keys %pl_kills) {
+
+ if ($mapkey eq "##global") {
+ $filename = "big.res";
+ } else {
+ $filename = $mapkey . ".res";
+ }
+
+
+ open(LOGFILE, ">$filename") or die "Could not open $filename: $!\n";
+
+ select LOGFILE;
+
+ # Print final results. First line holds overall system statistics.
+
+ print ":";
+ print "$sys_kills{$mapkey}:";
+ print ":";
+ print "$sys_suicides{$mapkey}:";
+ print "$sys_maps_played{$mapkey}:";
+ print ":";
+ print "$sys_connect_total{$mapkey}:";
+ print "\n";
+
+ foreach $nick (keys %{ $pl_kills{$mapkey} }) {
+
+ print "$nick:";
+ print "$pl_kills{$mapkey}{$nick}:";
+ print "$pl_victims{$mapkey}{$nick}:";
+ print "$pl_suicides{$mapkey}{$nick}:";
+ print "$pl_maps_played{$mapkey}{$nick}:";
+ print "$pl_maps_won{$mapkey}{$nick}:";
+ print "$pl_connect_total{$mapkey}{$nick}:";
+ print "\n";
+
+ }
+
+ select STDOUT;
+
+ close (LOGFILE);
+
+}
+
+
+###### - Subroutines
+
+sub pl_connect() {
+
+ $pl_name = shift;
+ return unless defined($pl_name);
+
+ # Reduce the player name to the first 15 characters. You want that.
+ # Believe me.
+
+ $pl_name = substr($pl_name, 0, 15);
+
+ print "Player connected: $pl_name\n" if $debug;
+
+ $pl_kills{"##global"}{$pl_name} = 0 unless defined($pl_kills{"##global"}{$pl_name});
+ $pl_kills{$actual_map}{$pl_name} = 0 unless defined($pl_kills{$actual_map}{$pl_name});
+
+ $pl_victims{"##global"}{$pl_name} = 0 unless defined($pl_victims{"##global"}{$pl_name});
+ $pl_victims{$actual_map}{$pl_name} = 0 unless defined($pl_victims{$actual_map}{$pl_name});
+
+ $pl_suicides{"##global"}{$pl_name} = 0 unless defined($pl_suicides{"##global"}{$pl_name});
+ $pl_suicides{$actual_map}{$pl_name} = 0 unless defined($pl_suicides{$actual_map}{$pl_name});
+
+ $pl_maps_played{"##global"}{$pl_name} = 0 unless defined($pl_maps_played{"##global"}{$pl_name});
+ $pl_maps_played{$actual_map}{$pl_name} = 0 unless defined($pl_maps_played{$actual_map}{$pl_name});
+
+ $pl_maps_won{"##global"}{$pl_name} = 0 unless defined($pl_maps_won{"##global"}{$pl_name});
+ $pl_maps_won{$actual_map}{$pl_name} = 0 unless defined($pl_maps_won{$actual_map}{$pl_name});
+
+
+
+ # If the player reconnects before a map change, don't count as
+ # a played map
+ # This flag is reset by pl_disconnect_all().
+
+ unless (defined($pl_connect{$pl_name})) {
+ $pl_count_map{$pl_name} = 1;
+ }
+
+ $pl_connect{$pl_name} = 1;
+ $pl_kills_local{$pl_name} = 0;
+ $pl_connect_start{"##global"}{$pl_name} = $timestamp;
+ $pl_connect_start{$actual_map}{$pl_name} = $timestamp;
+}
+
+# ----------------------
+
+sub pl_disconnect {
+
+ $pl_name = shift;
+ return unless defined($pl_name);
+
+ 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;
+
+ $pl_connect_total{"##global"}{$pl_name} += ($timestamp - $pl_connect_start{"##global"}{$pl_name});
+ $pl_connect_total{$actual_map}{$pl_name} += ($timestamp - $pl_connect_start{$actual_map}{$pl_name});
+ $pl_connect_start{"##global"}{$pl_name} = -1;
+ delete $pl_kills_local{$pl_name};
+}
+
+# ----------------------
+
+sub pl_disconnect_all {
+
+ foreach $name (keys %pl_connect) {
+
+ undef $pl_connect{$name};
+ undef $pl_count_map{$name};
+ if ($pl_connect_start{"##global"}{$name} >= 0) {
+ pl_disconnect($name);
+ }
+ undef %pl_kills_local;
+ }
+}
--- /dev/null
+q2dm1:The Edge
+q2dm2:Tokay's Towers
+q2dm3:The Frag Pipe
+q2dm4:Lost Hallways
+q2dm5:The Pits
+q2dm6:Lava Tomb
+q2dm7:The Slimy Place
+q2dm8:WareHouse
+match1:Reckless Abandon
+nexus2:Rusted \85 by Shadowdane
+trdm01a:Sepulchre -by Trebz-
--- /dev/null
+README quakec5.pl
+=================
+
+Ein Perl-Skript, das
--- /dev/null
+<STYLE type=text/css>
+ A:link
+ {
+ COLOR: #000066; TEXT-DECORATION: none
+ }
+ A:visited
+ {
+ COLOR: #000066; TEXT-DECORATION: none
+ }
+ A:active
+ {
+ COLOR: #0033FF; TEXT-DECORATION: none
+ }
+ A:hover
+ {
+ COLOR: #336699; CURSOR: hand; TEXT-DECORATION: none
+ }
+ A
+ {
+ COLOR: #000000; TEXT-DECORATION: line-through
+ }
+ P
+ {
+ COLOR: #336699
+ }
+ </STYLE>
+ <BODY background="../pic/gitter_w.gif" TOPMARGIN=2 LEFTMARGIN=2 MARGINWIDTH=2 MARGINHEIGHT=2
+ TEXT="000000" BGCOLOR="FFFFFF" LINK="0000FF" VLINK="0000FF">
+
+ <H1 align="center">Serverstatus</H1>
+ <center>
+ <font size="+1"><b>Letztes Update: <i><!--$server_date--></i></font></b><br><br>
+ <font size="-1">(-<a href="http://141.57.8.35:6666/cgi-bin/sstatus.pl?server=141.57.8.35&port=27910" target="_self">aktualisieren</a>-)</font><br>
+ <hr width="50%"><br>
+ <table border="0" align="center">
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Server </td>
+ <td bgcolor="e0e0e0" align="left"> <font color="#0000FF"><!--$server_hostname--></font> </td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Map </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_map--></td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Game Mod </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_gamename--></td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Game Dir </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_gamedir--></td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Features </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_features--></td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Fraglimit </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_fraglimit--></td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Timelimit </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_timelimit--></td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> DMFlags </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_dmflags--></td>
+ </tr>
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><b> Version </td>
+ <td bgcolor="e0e0e0" align="left"><!--$server_version--></td>
+ </tr>
+ </table>
+ <br><hr width="50%"><center>
+<!--if clients-->
+ <b>Diese Spieler sind zurzeit auf dem Server:</b><br><br>
+ <table border="0" align="center">
+ <tr>
+ <th bgcolor="a0a0a0" align="left"> Playername </th>
+ <th bgcolor="a0a0a0" align="left"> Frags </th>
+ <th bgcolor="a0a0a0" align="left"> Ping </th>
+ </tr>
+<!--loop clients-->
+ <tr>
+ <td bgcolor="a0a0a0" align="left"><!--$parser_clientname--></td>
+ <td bgcolor="e0e0e0" align="left"><!--$parser_clientfrags--></td>
+ <td bgcolor="e0e0e0" align="left"><!--$parser_clientping--></td>
+ </tr>
+<!--endloop clients-->
+ </table>
+<!--endif clients-->
+<!--if noclients-->
+ <b>Derzeit keine Spieler auf dem Server</b>
+<!--endif noclients-->
+ <br><hr width="50%"><br><br>
+ <font size="-1">(Script wurde erstellt mit freundlicher Hilfe von [NDC]Maria)<br>
+ - <a href="http://www.ndc.sh" target="NDCWin">www.ndc.sh</a> -</font>
+
+</BODY></HTML>
--- /dev/null
+q2dm1:The Edge
+q2dm2:Tokay's Towers
+q2dm3:The Frag Pipe
+q2dm4:Lost Hallways
+q2dm5:The Pits
+q2dm6:Lava Tomb
+q2dm7:The Slimy Place
+q2dm8:WareHouse
+match1:Reckless Abandon
+nexus2:Rusted \85 by Shadowdane
+trdm01a:Sepulchre -by Trebz-
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+
+<!--$parser_selfinfo-->
+
+<HTML>
+<HEAD>
+ <TITLE>NDC Serverstatus</TITLE>
+ <META NAME="Author" CONTENT="Andreas Ulbrich">
+ <META NAME="Author" CONTENT="Ralf Ertzinger">
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF">
+ <CENTER>
+ <img SRC="http://www.ndc.sh/graphics/aktuell_logo.jpg" WIDTH="300" HEIGHT="90" BORDER="0" ALT="[SERVER Status]">
+ </CENTER>
+ <P STYLE="margin-left=1cm">
+ <table BORDER="0">
+ <tr>
+ <td WIDTH="270" ALIGN="CENTER" BGCOLOR="#FFFFCC">
+ <b>Serverstatus</b> <!--$server_date-->
+ </td>
+ </tr>
+ </TABLE><BR>
+ <table BORDER="0">
+ <tr>
+ <td>
+ Adresse:
+ </td>
+ <td>
+ <!--$server_address--> Port: <!--$server_port-->
+ </td>
+ <td ROWSPAN="10" VALIGN="BOTTOM">
+ <img src="<!--$map_thumbnail-->" WIDTH="160" HEIGHT="120" BORDER="0" ALT="Map Thumbnail">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Server-Name:
+ </td>
+ <td>
+ <b><!--$server_hostname--></b>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Systemlast:
+ </td>
+ <td>
+ <!--$server_load_color-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Server-Mod:
+ </td>
+ <td>
+ <!--$server_gamename-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Features:
+ </td>
+ <td>
+ <!--$server_features-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ dmflags:
+ </td>
+ <td>
+ <!--$server_dmflags-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Timelimit:
+ </td>
+ <td>
+ <!--$server_timelimit-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Fraglimit:
+ </td>
+ <td>
+ <!--$server_fraglimit-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Spieleranzahl:
+ </td>
+ <td>
+ <!--$server_actclients-->/<!--$server_maxclients-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Momentan gespielte Map:
+ </td>
+ <td>
+ <!--$server_map-->
+ </td>
+ </tr>
+ </TABLE>
+ <BR>
+<!--if clients-->
+ <b><!--$parser_sortmode--></b>
+ <table BORDER="0">
+ <tr>
+ <td WIDTH="50" ALIGN="CENTER" BGCOLOR="#FFFFCC">
+ <b>Rank</b>
+ </td>
+ <td WIDTH="170" ALIGN="CENTER" BGCOLOR="#FFFFCC">
+ <b>
+ <a href="<!--$parser_selfsortname-->">Name</a>
+ </b>
+ </td>
+ <td WIDTH="130" ALIGN="CENTER" BGCOLOR="#FFFFCC">
+ <b>
+ <a href="<!--$parser_selfsortfrags-->">Frags</a>
+ </b>
+ </td>
+ <td WIDTH="130" ALIGN="CENTER" BGCOLOR="#FFFFCC">
+ <b>
+ <a href="<!--$parser_selfsortping-->">Ping</a>
+ </b>
+ </td>
+ </tr>
+<!--loop clients-->
+ <tr>
+ <td ALIGN="CENTER" BGCOLOR="#EEEEEE">
+ <!--$parser_clientrank-->
+ </td>
+ <td ALIGN="CENTER" BGCOLOR="#CCCCCC">
+ <!--$parser_clientlink_color-->
+ </td>
+ <td ALIGN="CENTER" BGCOLOR="#EEEEEE">
+ <!--$parser_clientfrags-->
+ </td>
+ <td ALIGN="CENTER" BGCOLOR="#EEEEEE">
+ <!--$parser_clientping-->
+ </td>
+ </tr>
+<!--endloop clients-->
+ </table>
+<!--endif clients-->
+<!--if noclients-->
+ <table BORDER="0">
+ <tr>
+ <td WIDTH="350" ALIGN="CENTER" BGCOLOR="#FFFFCC">
+ <b>Zur Zeit sind keine Spieler auf dem Server</b>
+ </td>
+ </tr>
+ </table>
+<!--endif noclients-->
+ <P align="right">
+ <FONT SIZE="-2">
+ Skripting by ADDIX<BR>
+ <A href="http://www.addix.de" target="_top">www.addix.de</A>
+ </FONT>
+</BODY>
+</HTML>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<HTML>
+
+<HEAD>
+ <TITLE>NDC Serverstatus</TITLE>
+ <META NAME="Author" CONTENT="Andreas Ulbrich">
+ <META NAME="Author" CONTENT="Ralf Ertzinger">
+ <link rel="stylesheet" href="http://www.ndc.sh/css/ndcstrict.css" media="screen">
+</HEAD>
+
+
+<BODY>
+ <p class="image">
+ <img SRC="http://www.ndc.sh/graphics/aktuell_logo.jpg" WIDTH="300" HEIGHT="90" ALT="[SERVER Status]">
+ </p>
+ <div class="serverstatus">
+ <p>
+ <b>Serverstatus</b> <!--$server_date-->
+ </p>
+ </div>
+ <p>
+ <table BORDER="0">
+ <tr>
+ <td>
+ Adresse:
+ </td>
+ <td>
+ <!--$server_address--> Port: <!--$server_port-->
+ </td>
+ <td ROWSPAN="10" VALIGN="BOTTOM">
+ <img src="<!--$map_thumbnail-->" WIDTH="160" HEIGHT="120" ALT="Map Thumbnail">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Server-Name:
+ </td>
+ <td>
+ <b><!--$server_hostname--></b>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Systemlast:
+ </td>
+ <td>
+ <!--$server_load-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Server-Mod:
+ </td>
+ <td>
+ <!--$server_gamename-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Features:
+ </td>
+ <td>
+ <!--$server_features-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ dmflags:
+ </td>
+ <td>
+ <!--$server_dmflags-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Timelimit:
+ </td>
+ <td>
+ <!--$server_timelimit-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Fraglimit:
+ </td>
+ <td>
+ <!--$server_fraglimit-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Spieleranzahl:
+ </td>
+ <td>
+ <!--$server_actclients-->/<!--$server_maxclients-->
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Momentan gespielte Map:
+ </td>
+ <td>
+ <!--$server_map-->
+ </td>
+ </tr>
+ </TABLE>
+<!--if clients-->
+ <p>
+ <b><!--$parser_sortmode--></b>
+ </p>
+ <table class="player">
+ <tr class="playerheader">
+ <td class="rankheader">
+ <b>Rank</b>
+ </td>
+ <td class="nameheader">
+ <b>
+ <a href="<!--$parser_selfsortname-->">Name</a>
+ </b>
+ </td>
+ <td class="fragheader">
+ <b>
+ <a href="<!--$parser_selfsortfrags-->">Frags</a>
+ </b>
+ </td>
+ <td class="pingheader">
+ <b>
+ <a href="<!--$parser_selfsortping-->">Ping</a>
+ </b>
+ </td>
+ </tr>
+<!--loop clients-->
+ <tr>
+ <td class="rankbody">
+ <!--$parser_clientrank-->
+ </td>
+ <td>
+ <!--$parser_clientlink-->
+ </td>
+ <td>
+ <!--$parser_clientfrags-->
+ </td>
+ <td>
+ <!--$parser_clientping-->
+ </td>
+ </tr>
+<!--endloop clients-->
+ </table>
+<!--endif clients-->
+<!--if noclients-->
+ <div class="serverstatus">
+ <p>
+ <b>Zur Zeit sind keine Spieler auf dem Server</b>
+ </p>
+ </div>
+<!--endif noclients-->
+ <p class="credits">
+ Skripting by ADDIX<BR>
+ <A href="http://www.addix.de">www.addix.de</A>
+ </p>
+</BODY>
+</HTML>
--- /dev/null
+#!/usr/bin/perl
+
+# quakec5.pl
+# NDC Code Release 1
+#
+# Connects to a Quake2 server, queries current map, players, mod
+# and various other stuff, and builds a web page from that.
+# Templates are supported.
+# CGI-Parameters:
+# server: IP or FQDN of server. Defaults to 194.64.167.5
+# port: Port. Defaults to 27910
+# template: Template file. Defaults to ndc
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#use strict;
+require 5.002;
+use Socket;
+use Sys::Hostname;
+use DBI;
+use CGI;
+
+# Define some variables
+my %eingabe;
+my %variables;
+my %mapnames;
+my $mappath = "/maparchiv"; # Path to map thumbnails
+my $template_path = "."; # Path to templates.
+my $mapnamefile = "mapnames.txt";
+my $scriptpath = "http://www.ndc.sh/cgi-bin/quake/quakec5.pl"; # The script itself when called by HTTP
+my $quakeresponse;
+my $template;
+my $template_file;
+my $CGIquery;
+
+# Info about the script
+$variables{parser_selfinfo} = "<!--\nThis is the [NDC] serverinfo script, Release 5.\n" .
+ "Featuring support for Quake2, HTML templatefiles and SQL-Queries.\n" .
+ "Parsing-Engine: Lilith, Version 1.1.\n" .
+ "Output is HTML 4.01 strict compliant.\n\n" .
+ "Original Release by [NDC]Maria.\n" .
+ "Quake connection code by [NDC]Maria and [NDC]Sundancer.\n" .
+ "Lilith by [NDC]Sundancer.\n" .
+ "Source code is available. Contact ndccode\@ndc.sh or see http://www.ndc.sh/ndccode.\n" .
+ "//-->";
+
+### Var def ###
+$CGIquery = new CGI;
+$variables{server_address} = ($CGIquery->param("server")?$CGIquery->param("server"):"194.64.167.5");
+$variables{server_port} = ($CGIquery->param("port")?$CGIquery->param("port"):"27910");
+$sort = ($CGIquery->param("sort")?$CGIquery->param("sort"):0);
+$template = ($CGIquery->param("template")?$CGIquery->param("template"):"ndc");
+
+# Load map names
+if (-e $mapnamefile) {
+ open(MAPNAMES,$mapnamefile);
+ while ($line=<MAPNAMES>) {
+ ($maphandle,$mapn) = split(":",$line);
+ chomp($mapn);
+ $mapname{$maphandle} = $mapn;
+ }
+ close(MAPNAMES);
+}
+
+$quakeresponse = QueryQuakeServer("status");
+
+### Ausgabeformatierung ###
+## Abtrennen der ersten Zeile mit den Systeminformationen ###
+@ausg = split (/\n/,$quakeresponse);
+
+## Zuweisen der Ausgabevariablen zu $variable{wasausgegebenwerdensoll} ##
+@config = split (/\\/,$ausg[1]);
+for ( $i = 1; $i < $#config; $i= $i + 2) {
+ $var = $config[$i];
+ $variables{"server_${var}"} = $config[$i + 1];
+}
+
+## Zaehlen der Onlinespieler ##
+$anzplayer = scalar(@ausg) - 2;
+$variables{server_actclients} = $anzplayer;
+
+#### Umfomartieren der Spielernamen
+foreach $i (2..($#ausg))
+{
+
+ @playerdata = ($ausg[$i] =~ /^(\d+)\s(\d+)\s"(.+)"$/);
+ $name = $playerdata[2];
+ $pings{$name} = $playerdata[1];
+ $frags{$name} = $playerdata[0];
+ $nicks{$name} = $name;
+ $nicks{$name} =~ s/&/&/g;
+ $nicks{$name} =~ s/</</g;
+ $nicks{$name} =~ s/>/>/g;
+ $nicks{$name} =~ s/"/"/g;
+}
+
+
+## Mapnamen auf vollen Namen erweitern (wenn möglich)
+if (defined($mapname{$variables{server_mapname}})) {
+ $variables{server_map} = $mapname{$variables{server_mapname}} . " (". $variables{server_mapname} . ")";
+} else {
+ $variables{server_map} = $variables{server_mapname};
+}
+
+#### Ermittlung der Load falls moeglich #####
+$load = "N/A";
+
+$variables{server_load} = $load;
+$variables{server_load_color} = "<FONT color=\"#000000\">" . $load. "</FONT>";
+if ($load <= 0.7) {
+ $variables{server_load_color} = "<FONT color=\"#00CC00\">$load</FONT>";
+}
+if (($load > 0.7) && ($load < 1)) {
+ $variables{server_load_color} = "<FONT color=\"#CCCC00\">$load</FONT>";
+}
+if ($load >= 1) {
+ $variables{server_load_color} = "<FONT color=\"#CC0000\">$load</FONT>";
+}
+
+
+###### Sortieren #####
+
+# By default, sort by frags.
+@sortkey = sort { $frags{$b} <=> $frags{$a} } (keys %frags);
+$sortname = "Frags";
+
+if ($sort eq "0") {
+ @sortkey = sort { $frags{$b} <=> $frags{$a} } (keys %frags);
+ $sortname = "Frags";
+}
+
+if ($sort eq "1") {
+ @sortkey = sort { $pings{$a} <=> $pings{$b} } (keys %pings);
+ $sortname = "Pings";
+}
+
+if ($sort eq "2") {
+ @sortkey = sort { $nicks{$a} cmp $nicks{$b} } (keys %nicks);
+ $sortname = "Nick";
+}
+
+$variables{parser_sortmode} = "Sortiert nach $sortname";
+
+#### Ermittlung und formatierung des Datums #####
+$date_command = "/bin/date";
+$date = `$date_command +"%T Uhr \ \; %d.%m.%Y"`;
+chop($date);
+$variables{server_date} = $date;
+
+#### Bild von Map? #####
+
+if (-e "$mappath/$variables{server_mapname}/$variables{server_mapname}_1_thumb.jpg") {
+ $variables{map_thumbnail} = "http://www.ndc.sh/maparchiv/$variables{server_mapname}/$variables{server_mapname}_1_thumb.jpg";
+} else {
+ $variables{map_thumbnail} = "http://www.ndc.sh/maparchiv/blank.gif";
+}
+
+## Variables for different sorting
+$variables{parser_selfsortname} = $scriptpath . "?server=" . $variables{server_address} . "&port=" . $variables{server_port} . "&sort=2";
+$variables{parser_selfsortfrags} = $scriptpath . "?server=" . $variables{server_address} . "&port=" . $variables{server_port} . "&sort=0";
+$variables{parser_selfsortping} = $scriptpath . "?server=" . $variables{server_address} . "&port=" . $variables{server_port} . "&sort=1";
+
+
+## Ausgabe ##
+
+# Define variables used by if and loop statements
+$in_if_clients = 0;
+$in_if_noclients = 0;
+$in_loop_players = 0;
+
+# Check template file
+if ($eingabe{template} =~ /\W/) {
+ # template file contains illegal characters
+ $template_file = $template_path . "/ndc.template";
+} else {
+ $template_file = $template_path . "/" . $eingabe{template} . ".template";
+}
+
+if ( ! -e $template_file ) {
+ $template_file = $template_path . "/ndc.template";
+}
+
+# Start by printing content type
+print "Content-Type: text/html\n\n";
+
+open (TEMPLATE, $template_file) or die "Could not open template file: $!\n";
+@main_source=<TEMPLATE>;
+close(TEMPLATE);
+parse(@main_source);
+##### Subroutines ######
+
+
+sub cantconnect {
+
+# Start by printing content type
+print "Content-Type: text/html\n\n";
+print "<HTML><BODY>Can\'t connect to $server:$port\n<BR>$!\n</BODY></HTML>";
+exit;
+}
+
+sub dmflag {
+@dmflags_name = ("Health" , "Powerups" , "Weapon Stay" , "Falling Damage" , "Instant Powerups" , "Same Map" , "Teams by Skin" , "Teams by Model" , "Friendly Fire" , "Spawn Farthest" , "Force Respawn" , "Armor" , "Allow Exit" , "Infinite Ammo" , "Quad Drop" , "Fixed FOV");
+@dmflags_neg = (1 , 2 , 0 , 8 , 0 , 0 , 0 , 0 , 256 , 0 , 0 , 2048 , 0 , 0 , 0 , 0);
+
+
+print "<P>\ \;<P><UL><a name=\"dmflags\"><b>DMFLAGS f\ü\;r DUMMIES<\/b><\/a><BR>\n";
+print "<TABLE BORDER = \"0\">\n";
+print "<TR><td WIDTH=\"150\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b>Flag<\/B><\/td>\n";
+print "<td WIDTH=\"60\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b>On<\/B><\/td>\n";
+print "<td WIDTH=\"60\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b>Off<\/b><\/td><\/TR>\n";
+foreach $i (0..($#dmflags_name)) {
+ if ( (($text{dmflags} & (2**$i)) ^ $dmflags_neg[$i]) == (2**$i)) {
+ print "<TR><TD ALIGN=\"LEFT\" BGCOLOR=\"\#CCCCCC\">$dmflags_name[$i]<\/TD>\n";
+ print "<TD ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><img src=\"http\:\/\/www.ndc.sh\/graphics\/haken.gif\"><\/TD>\n";
+ print "<TD ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\">\ \;<\/TD><\/TR>\n";
+ } else {
+ print "<TR><TD ALIGN=\"LEFT\" BGCOLOR=\"\#CCCCCC\">$dmflags_name[$i]<\/TD>\n";
+ print "<TD ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\">\ \;<\/TD>\n";
+ print "<TD ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><img src=\"http\:\/\/www.ndc.sh\/graphics\/haken.gif\"><\/TD><\/TR>\n";
+ }
+}
+
+print "<\/TABLE><\/UL>\n";
+
+}
+
+
+sub GetDBURL {
+
+# Takes a player name from subroutine call, returns a URL if player is in
+# database, undef else.
+
+ $pl_sql_nick = shift;
+ $pl_sql_nick_old = $pl_sql_nick;
+
+ $pl_sql_nick =~ s/(\\)/\\$1/g;
+ $pl_sql_nick =~ s/(')/\\$1/g;
+
+ # SQL-Variables
+
+ $sql_database = "stats";
+ $sql_db_table = "PlayerStats";
+ $sql_datasource = "DBI:mysql:$sql_database";
+ $sql_username = "";
+ $sql_password = "";
+ $sql_db_handle = DBI->connect($sql_datasource, $sql_username, $sql_password) or return undef;
+
+ $sql_query = $sql_db_handle->prepare("SELECT nick FROM $sql_db_table WHERE nick='$pl_sql_nick'");
+ $sql_query->execute;
+ $sql_result = $sql_query->fetchrow_hashref;
+ $sql_query->finish;
+
+ if (defined($sql_result)) {
+ $returnvalue = "\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/playerstats.pl\?nick\=" . make_compatible($pl_sql_nick_old) . "\"";
+ } else {
+ $returnvalue = undef;
+ }
+
+ $sql_db_handle->disconnect;
+ return $returnvalue;
+}
+
+sub parse {
+# This routine takes an array as input, and parses it line by line,
+# echoing results to the screen.
+# BEWARE:
+# Switches like if and loop are GLOBAL!
+
+my $template_line;
+my $if_variable;
+my $loop_variable;
+my @parser_comment;
+my $comment;
+my $fullcomment;
+my $replacement;
+my @looparray;
+my $clients;
+my $i;
+my $dbURL;
+
+LOOP: while ($template_line = shift) {
+ # Catch special requests
+ if ($template_line =~ /^\s*\<!--if [\w_]+--\>/) {
+ ($if_variable) = $template_line =~ /\<!--if ([\w_]+)--\>/;
+ if ($if_variable eq "clients") {
+ $in_if_clients = 1;
+ }
+ if ($if_variable eq "noclients") {
+ $in_if_noclients = 1;
+ }
+ next LOOP;
+ }
+ if ($template_line =~ /^\s*\<!--endif [\w_]+--\>/) {
+ ($if_variable) = ($template_line =~ /\<!--endif ([\w_]+)--\>/);
+ if ($if_variable eq "clients") {
+ $in_if_clients = 0;
+ }
+ if ($if_variable eq "noclients") {
+ $in_if_noclients = 0;
+ }
+ next LOOP;
+ }
+
+ if ($template_line =~ /^\s*\<!--loop [\w_]+--\>/) {
+ ($loop_variable) = ($template_line =~ /\<!--loop ([\w_]+)--\>/);
+ if ($if_variable eq "clients") {
+ $in_loop_clients = 1;
+ }
+ next LOOP;
+ }
+
+ if ($template_line =~ /^\s*\<!--endloop [\w_]+--\>/) {
+ ($loop_variable) = ($template_line =~ /\<!--endloop ([\w_]+)--\>/);
+ if ($if_variable eq "clients") {
+ $in_loop_clients = 0;
+ # Now, loop through all clients and parse
+ # the saved loop once for each.
+ $i = 0;
+ foreach $clients ( @sortkey) {
+ $dbURL = GetDBURL($clients);
+ $variables{parser_clientrank} = ++$i;
+ $variables{parser_clientname} = $nicks{$clients};
+ if (defined($dbURL)) {
+ $variables{parser_clientlink} = "<a href=$dbURL>" . $nicks{$clients} . "</a>";
+ $variables{parser_clientlink_color} = "<a href=$dbURL><font color=\"#000000\">" . $nicks{$clients} . "</font></a>";
+ } else {
+ $variables{parser_clientlink} = $nicks{$clients};
+ $variables{parser_clientlink_color} = $nicks{$clients};
+ }
+ $variables{parser_clientping} = $pings{$clients};
+ $variables{parser_clientfrags} = $frags{$clients};
+ parse(@looparray);
+ }
+
+ }
+ next LOOP;
+ }
+
+ # Check if we are to ignore these lines
+ if (($in_if_clients == 1) && ($variables{server_actclients} == 0)) {
+ next LOOP;
+ }
+ if (($in_if_noclients == 1) && ($variables{server_actclients} != 0)) {
+ next LOOP;
+ }
+
+ # If we are in loop mode, copy lines into an array for
+ # later parsing
+ if ($in_loop_clients == 1) {
+ push @looparray, $template_line;
+ next LOOP;
+ }
+
+ @parser_comment = ($template_line =~ /\<!--\$([\w_]+)--\>/g);
+ foreach $comment ( @parser_comment) {
+ if (defined($variables{$comment})) {
+ $fullcomment = "\\<!--\\\$" . $comment . "--\\>";
+ $replacement = $variables{$comment};
+ $template_line =~ s/$fullcomment/$replacement/g;
+ }
+ }
+ print $template_line;
+}
+} # end of sub
+
+sub make_compatible {
+
+ $input = shift;
+ $input =~ s/%/%25/g;
+ $input =~ s/\+/%2B/g;
+ $input =~ s/ /+/g;
+ $input =~ s/,/%2C/g;
+ $input =~ s/</%3C/g;
+ $input =~ s/>/%3E/g;
+ $input =~ s/#/%23/g;
+ $input =~ s/\[/%5B/g;
+ $input =~ s/\]/%5D/g;
+ $input =~ s/\//%2F/g;
+ $input =~ s/\|/%7C/g;
+ $input =~ s/\?/%3F/g;
+ $input =~ s/\x1c/%1C/g;
+
+ return $input;
+}
+
+sub QueryQuakeServer {
+
+# Takes a command from caller. Executes the command on the server defined by the
+# global variables $variables{server_address} and $variables{server_port}
+# Returns a literal containing the server's response.
+
+my ($count, $hisiaddr, $host, $iaddr,$paddr, $port ,$proto, $hispaddr, $command, $query, $response);
+
+$command = shift;
+
+$iaddr = gethostbyname(hostname());
+$proto = getprotobyname('udp');
+$paddr =sockaddr_in(0 ,$iaddr);
+
+
+### Netzwerk und auslesen der Daten ###
+
+socket (SOCKET, PF_INET, SOCK_DGRAM, $proto) or &cantconnect;
+bind(SOCKET, $paddr) or die "bind: $!";
+$| = 1;
+
+
+$hisiaddr = inet_aton($variables{server_address}) or &cantconnect;
+$hispaddr = sockaddr_in($variables{server_port}, $hisiaddr);
+$query = "\xff\xff\xff\xff$command\x00";
+defined(send(SOCKET, $query, 0, $hispaddr)) or &cantconnect;
+
+## Timeout nach 5 sec ##
+$rin = "";
+vec($rin, fileno(SOCKET), 1) = 1;
+while (($response eq "" ) && select($rout = $rin, undef ,undef ,5.0))
+{
+ ($hispaddr = recv(SOCKET, $response, 1000, 0)) || &cantconnect;
+}
+
+if ($response eq "")
+{
+ &cantconnect;
+}
+
+close(SOCKET);
+
+return $response;
+
+}
--- /dev/null
+README - stats
+==============
+
+Diese Skripte bilden das Herzstueck des Statistiksystems.
+Sie _sind_ das Statistiksystem.
+foreverstats - Die ewigen Statistiken
+ Version 2, die aktuell laeuft
+ Version 3, die neue (schoenerbesserbunter), mit
+ Suchfunktion in der Datenbank und Template-
+ Unterstuetzung (wer hat da "PHP" gerufen?)
+ WAP-Version.
+dailystats - Die Tagesstatistiken
+ HTML und WAP.
+playerstats - Statistiken fuer einzelne Spieler.
+ Von den dailystats und foreverstats
+ gelinkt.
+
+makedb Macht aus gs_analyze-Ausgaben SQL
+makerank Berechnet die Raenge in der ewigen Bestenliste
+databasectrl Ein Shellscript, das makedb und makerank aufruft.
+
+Der Lauf der Daten vom Quake-Server zur Webseite laeuft
+ueber verschiedene Stufen.
+
+Die vom Server erzeugten Logs werden von gs_analyze in
+ein Zwischenformat gewandelt, und dann per FTP-Upload
+auf den Webserver geschoben.
+Hier kommt ein Synchronisationsproblem ans Licht. Der
+Quakeserver rotiert (in unserem Fall) taeglich um 6
+seine Stats, und wertet sie danach mit gs_analyze aus.
+Dann kommen die Zwischenlogs auf den Webserver.
+Nun weiss der Webserver leider nicht, wann es beim Quake-
+server 6 Uhr ist. Da wir uns Konstukte wie rsh gerne ersparen
+wollten, haben wir einen anderen Weg gewählt.
+Der Quakeserver uebertraegt neben dem Logfile noch eine Datei
+namens first.run. Diese enthaelt nur eine 1. Jedesmal wenn
+entweder foreverstat oder dailystats aufgerufen wird, wird
+der Inhalt dieser Datei ueberprueft. Ist er 1, so wird
+databasectrl.sh aufgerufen, das wiederum das Logfile in die
+Datenbank ueberfuerht. Dann wird der Inhalt von first.run
+auf 0 gesetzt. Solange, bis ein neues Logfile vom Quakeserver
+kommt.
+
+In allen Skripten, die auf die Datenbanken zugreifen, gibt es
+Variablen, die den Benutzernamen und das Passwort setzen, mit
+denen auf die Datenbank zugegriffen wird. Im Moment sind diese
+beiden Felder leer.
+Der Name der Datenbank wird mit "stats" angenommen.
+Die Datei "stats.sql" enthaelt die SQL-Aufrufe, die die von den
+Skripten benoetigten Tables erstellen.
+
+In allen Skripten, die auf die Datenbanken zugreifen, gibt es
+
+In allen Skripten, die auf die Datenbanken zugreifen, gibt es
+Variablen, die den Benutzernamen und das Passwort setzen, mit
+denen auf die Datenbank zugegriffen wird. Im Moment sind diese
+beiden Felder leer.
+Der Name der Datenbank wird mit "stats" angenommen.
+Die Datei "stats.sql" enthaelt die SQL-Aufrufe, die die von den
+Skripten benoetigten Tables erstellen.
+Variablen, die den Benutzernamen und das Passwort setzen, mit
+denen auf die Datenbank zugegriffen wird. Im Moment sind diese
+beiden Felder leer.
+Der Name der Datenbank wird mit "stats" angenommen.
+Die Datei "stats.sql" enthaelt die SQL-Aufrufe, die die von den
+Skripten benoetigten Tables erstellen.
--- /dev/null
+#!/usr/bin/perl
+
+# dailystats.pl
+# NDC Code Release 1
+#
+# Connects to the database holding the stats, and builds the web page
+# for the previous day.
+# CGI-Parameters:
+# start: First entry displayed
+# limit: Number of entries. Defaults to 20.
+# sort: Sort mode.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#use strict;
+require 5.002;
+use DBI;
+use CGI;
+
+my $CGIquery;
+
+### Var def ###
+$CGIquery = new CGI;
+$sort = ($CGIquery->param("sort")?$CGIquery->param("sort"):0);
+$limit = ($CGIquery->param("limit")?$CGIquery->param("limit"):20);
+$back = ($CGIquery->param("back")?$CGIquery->param("back"):0);
+$sort = ($back==1?0:($CGIquery->param("sort")?$CGIquery->param("sort"):0));
+
+# Rebuild database, if necessary
+open (FIRST, "< first.run") || die "Can't open first.run\n";
+while (<FIRST>) {
+ if ($_ == 1) {
+ close (FIRST);
+ open (FIRST, "> first.run") || die "Can't open first.run\n";
+ print FIRST "0\n";
+ close (FIRST);
+ {$update = `databasectrl.sh`}
+ }
+}
+close (FIRST);
+
+$database = "stats";
+$data_source = "DBI:mysql:$database";
+$username = "";
+$password = "";
+$dbh = DBI->connect( $data_source, $username, $password) or die "Can't connect to $data_source\n"; #: $dbh->errstr\n";
+
+$query = $dbh->prepare("SELECT nick FROM PlayerStats WHERE mapsplayed > 0");
+$query->execute;
+$rows = $query->rows;
+$query->finish;
+
+$query = $dbh->prepare("SELECT nick ,skill, kills, victims, suicides, mapsplayed, mapswon, time, fph FROM PlayerStats WHERE mapsplayed > 0 ORDER by skill DESC LIMIT $start,$limit");
+$query->execute;
+
+while ($row_hash = $query->fetchrow_hashref) {
+ $name = $row_hash->{nick};
+ $nick{$name} = $name;
+ $skill{$name} = $row_hash->{skill};
+ $kills{$name} = $row_hash->{kills};
+ $victims{$name} = $row_hash->{victims};
+ $suicides{$name} = $row_hash->{suicides};
+ $maps{$name} = $row_hash->{mapsplayed};
+ $wonmaps{$name} = $row_hash->{mapswon};
+ $time{$name} = $row_hash->{time};
+ $fph{$name} = $row_hash->{fph};
+}
+$query->finish;
+$dbh->disconnect;
+
+
+
+
+
+print "Content-Type: text/html\n\n\n";
+
+
+###### Sortieren #####
+
+# By default, sort by rank
+
+if ($sort eq "0") {
+ @sortkey = sort { $skill{$b} <=> $skill{$a} } (keys %nick);
+ $sortname = "Skill";
+ $darstellung = "<IMG SRC=\"\/graphics\/formel.gif\" ALT=\"Formel\">";
+}
+
+
+
+if ($sort eq "1") {
+ @sortkey = sort { $nick{$a} cmp $nick{$b} } (keys %nick);
+ $sortname = "Nick";
+ $darstellung = "";
+}
+
+if ($sort eq "2") {
+ @sortkey = sort { $maps{$b} <=> $maps{$a} } (keys %maps);
+ $sortname = "gespielten Maps";
+ $darstellung = "";
+}
+
+if ($sort eq "3") {
+ @sortkey = sort { $kills{$b} <=> $kills{$a} } (keys %kills);
+ $sortname = "Kills";
+ $darstellung = "";
+}
+
+if ($sort eq "4") {
+ @sortkey = sort { $victims{$b} <=> $victims{$a} } (keys %victims);
+ $sortname = "Victims";
+ $darstellung = "";
+}
+
+if ($sort eq "5") {
+ @sortkey = sort { $suicides{$b} <=> $suicides{$a} } (keys %suicides);
+ $sortname = "Suicides";
+ $darstellung = "";
+}
+
+if ($sort eq "6") {
+ @sortkey = sort { $fph{$b} <=> $fph{$a} } (keys %fph);
+ $sortname = "FPH";
+ $darstellung = "\= Kills \/ \(Sec \/ 3600 \)";
+}
+
+if ($sort eq "7") {
+ @sortkey = sort { $time{$b} <=> $time{$a} } (keys %nick);
+ $sortname = "Zeit";
+ $darstellung = "";
+}
+
+if ($sort eq "8") {
+ @sortkey = sort { $wonmaps{$b} <=> $wonmaps{$a} } (keys %nick);
+ $sortname = "gewonnenen Maps";
+ $darstellung = "";
+}
+## Ausgabe ##
+### Header ###
+print '<HTML><HEAD><TITLE>Cardassia - Hall of Fame</TITLE>';
+print '<META NAME="Andreas Ulbrich \+ Ralf Ertzinger">';
+print '</HEAD><BODY BGCOLOR="#FFFFFF">';
+print "\n<CENTER><img SRC=\"http\:\/\/www.ndc.sh\/graphics\/dailystatic_logo.jpg\" WIDTH=\"500\" HEIGHT=\"90\" BORDER=\"0\"ALT=\"\[SERVER Daily Static\]\"><\/CENTER>\n";
+
+print "<CENTER><b>Anzahl der Spieler: $rows<\/B><BR>\n";
+if ($back == 0) {
+ print "<b><a href =\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=0\&limit\=$rows\&back\=1\">Alle Spieler anzeigen<\/A><\/B><\/CENTER><\/BR>\n";
+}
+else {
+ print "<b><a href =\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=0\&limit\=20\&back\=0\">Die ersten 20 anzeigen<\/A><\/B><\/CENTER><\/BR>\n";
+}
+
+
+##### Sortiert nach sortkey ########
+
+print "<P>\ \;<P><UL><b>Sortiert nach $sortname $darstellung<\/b>\n";
+print "<table BORDER=\"0\">\n";
+print "<tr>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b>Rang<\/b><\/td>
+\n";
+print "<td WIDTH=\"120\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=1\&limit=$limit\&back=$back\">Name<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=0\&limit=$limit\&back=$back\">Skill<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=6\&limit=$limit\&back=$back\">FPH<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=2\&limit=$limit\&back=$back\">Maps gespielt<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=8\&limit=$limit\&back=$back\">Maps gewonnen<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=3\&limit=$limit\&back=$back\">Kills<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=4\&limit=$limit\&back=$back\">Victims<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=5\&limit=$limit\&back=$back\">Suicides<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort\=7\&limit=$limit\&back=$back\">Zeit (Min)<\/a><\/b><\/td>\n";
+print "<\/tr>\n";
+
+$count = $start;
+foreach $name (@sortkey)
+{
+
+ $count ++;
+ print "<tr>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"+0\">$count<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#CCCCCC\"><font size =\"+0\">";
+ print "<a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/playerstats.pl\?nick\=";
+ print make_compatible($nick{$name});
+ print "\">";
+ print "<font color=\"#000000\">";
+ print make_html($nick{$name});
+ print "<\/font>";
+ print "<\/a><\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$skill{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$fph{$name}<\/font><\/td>\n";
+
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$maps{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$wonmaps{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$kills{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$victims{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$suicides{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$time{$name}<\/font><\/td>\n";
+ print "<\/tr>\n";
+}
+
+print "<\/TABLE><\/UL><P>\n";
+
+if ($back == 0) {
+ print "<CENTER><TABLE BORDER=\"0\">\n";
+ print "<tr>\n";
+ print "<td WIDTH=\"200\" ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\">";
+ if ($start != 0) {
+ $start_prev = $start - $limit;
+ if ($start_prev < 0) {$start_prev = 0;}
+ print "<a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort=$sort&start=$start_prev&limit=$limit&back=0\">";
+ print "Zurück";
+ print "<\/a>\n";
+ } else {
+ print "Zurück";
+ }
+ print "<\/td>\n";
+ print "<td WIDTH=\"200\" ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\">";
+ if ($start + $limit < $rows) {
+ $start_next = $start + $limit;
+ print "<a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/dailystats.pl\?sort=$sort&start=$start_next&limit=$limit&back=0\">";
+ print "Weiter";
+ print "<\/a>\n";
+ } else {
+ print "Weiter";
+ }
+ print "<\/td>\n";
+ print "<\/tr>\n";
+ print "<\/TABLE><\/CENTER>\n";
+}
+
+print "<P><FONT SIZE=\"-2\"><DIV ALIGN=right>Skripting by NDC Code<BR><A href=\"http://www.ndc.sh\" target=\"_top\">www.ndc.sh</A></DIV></FONT><BR>\n";
+print '</BODY></HTML>';
+
+
+############### Subroutines ###########
+
+sub make_html {
+
+ $input = shift;
+# $input =~ s/&/und/g;
+ $input =~ s/</<\;/g;
+ $input =~ s/>/>\;/g;
+ $input =~ s/"/"\;/g;
+ $input =~ s/\x1c/·/g;
+# $input =~ s/\|/pipe/g;
+ return $input;
+}
+
+sub make_compatible {
+
+ $input = shift;
+ $input =~ s/%/%25/g;
+ $input =~ s/\+/%2B/g;
+ $input =~ s/ /+/g;
+ $input =~ s/,/%2C/g;
+ $input =~ s/</%3C/g;
+ $input =~ s/>/%3E/g;
+ $input =~ s/#/%23/g;
+ $input =~ s/\[/%5B/g;
+ $input =~ s/\]/%5D/g;
+ $input =~ s/\//%2F/g;
+ $input =~ s/\|/%7C/g;
+ $input =~ s/\?/%3F/g;
+ $input =~ s/\x1c/%1C/g;
+
+ return $input;
+}
--- /dev/null
+#!/usr/bin/perl
+
+# dailystats_wap3.pl
+# NDC Code Release 1
+#
+# Connects to the server holding the stats, and builds a web page
+# of yesterdays players
+# CGI-Parameters:
+# start: First entry displayed
+# limit: Number of entries. Defaults to 10.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#use strict;
+require 5.002;
+use DBI;
+use CGI;
+
+my $CGIquery;
+
+### Var def ###
+$CGIquery = new CGI;
+$start = ($CGIquery->param("start")?$CGIquery->param("start"):0);
+$limit = ($CGIquery->param("limit")?$CGIquery->param("limit"):10);
+
+# Rebuild database, if necessary
+
+$database = "stats";
+$data_source = "DBI:mysql:$database";
+$username = "";
+$password = "";
+$dbh = DBI->connect( $data_source, $username, $password) or die "Can't connect to $data_source\n"; #: $dbh->errstr\n";
+
+$query = $dbh->prepare("SELECT nick FROM PlayerStats WHERE mapsplayed > 0");
+$query->execute;
+$rows = $query->rows;
+$query->finish;
+
+$query = $dbh->prepare("SELECT nick ,skill FROM PlayerStats WHERE mapsplayed > 0 ORDER by skill DESC LIMIT $start,$limit");
+$query->execute;
+
+while ($row_hash = $query->fetchrow_hashref) {
+ $name = $row_hash->{nick};
+ $nick{$name} = $name;
+ $skill{$name} = $row_hash->{skill};
+}
+$query->finish;
+$dbh->disconnect;
+
+# Sort
+@sortkey = sort { $skill{$b} <=> $skill{$a} } (keys %nick);
+
+print "Content-Type: text/vnd.wap.wml\n\n";
+
+## Ausgabe ##
+### Header ###
+print '<?xml version="1.0"?>' . "\n";
+print '<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">' . "\n\n";
+
+print "<wml>\n";
+print "<card id=\"card1\" title=\"Gestern\">\n";
+
+if (($start + 10) < $rows) {
+ $start_next=$start + 10;
+ print "<do type=\"accept\" label=\"Weiter\">\n";
+ print "<go href=\"\/cgi-bin\/quake\/dailystats_wap.pl\?start=$start_next\"\/>\n";
+ print "<\/do>\n";
+}
+
+print "<p>\n";
+
+print "<small>\n";
+print "<table columns=\"3\">\n";
+print "<tr><td>P.<\/td><td>Name<\/td><td>Skill<\/td><\/tr>\n";
+
+$count = $start;
+foreach $name (@sortkey)
+{
+ $count ++;
+ print "<tr>\n";
+ print "<td>$count<\/td>\n";
+ print "<td>";
+ print make_html($nick{$name});
+ print "<\/td>\n";
+ print "<td>$skill{$name}<\/td>\n";
+ print "<\/tr>\n";
+}
+
+print "<\/table></small>\n";
+print "<\/p>\n";
+print "</card>\n";
+print '</wml>';
+
+
+############### Subroutines ###########
+
+sub make_html {
+
+ $input = shift;
+# $input =~ s/&/und/g;
+ $input =~ s/</<\;/g;
+ $input =~ s/>/>\;/g;
+ $input =~ s/"/"\;/g;
+# $input =~ s/\|/pipe/g;
+ return $input;
+}
+
+sub make_compatible {
+
+ $input = shift;
+ $input =~ s/%/%25/g;
+ $input =~ s/\+/%2B/g;
+ $input =~ s/ /+/g;
+ $input =~ s/,/%2C/g;
+ $input =~ s/</%3C/g;
+ $input =~ s/>/%3E/g;
+ $input =~ s/#/%23/g;
+ $input =~ s/\[/%5B/g;
+ $input =~ s/\]/%5D/g;
+ $input =~ s/\//%2F/g;
+ $input =~ s/\|/%7C/g;
+ $input =~ s/\?/%3F/g;
+
+ return $input;
+}
--- /dev/null
+cat big.res | makedb.pl
+makerank.pl
--- /dev/null
+#!/usr/bin/perl
+
+# foreverstats2.pl
+# NDC Code Release 1
+#
+# Connects to the database holding the statistic data and builds
+# a web page from it.
+# This is old code. The HTML is inlined in it. Hard to read,
+# almost impossible to maintain.
+# CGI-Parameters:
+# start: First entry displayed
+# limit: Number of entries. Defaults to 20.
+# sort: Sort mode.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#use strict;
+require 5.002;
+use DBI;
+use CGI;
+
+my $CGIquery;
+
+### Var def ###
+$CGIquery = new CGI;
+$sort = ($CGIquery->param("sort")?$CGIquery->param("sort"):'0');
+$limit = ($CGIquery->param("limit")?$CGIquery->param("limit"):'20');
+$start = ($CGIquery->param("start")?$CGIquery->param("start"):'0');
+$back = ($CGIquery->param("back")?$CGIquery->param("back"):'0');
+
+# Rebuild database, if necessary
+open (FIRST, "< first.run") || die "Can't open first.run\n";
+while (<FIRST>) {
+ if ($_ == 1) {
+ close (FIRST);
+ open (FIRST, "> first.run") || die "Can't open first.run\n";
+ print FIRST "0\n";
+ close (FIRST);
+ {$update = `databasectrl.sh`}
+ }
+}
+close (FIRST);
+
+$database = "stats";
+$data_source = "DBI:mysql:$database";
+$username = "";
+$password = "";
+$dbh = DBI->connect( $data_source, $username, $password) or die "Can't connect to $data_source\n"; #: $dbh->errstr\n";
+
+$query = $dbh->prepare("SELECT nick FROM PlayerStats WHERE fe_skill > 0");
+$query->execute;
+$rows = $query->rows;
+$query->finish;
+
+
+$query = $dbh->prepare("SELECT nick FROM PlayerStats");
+$query->execute;
+$rowsall = $query->rows;
+$query->finish;
+
+
+
+$query = $dbh->prepare("SELECT nick ,fe_skill, fe_kills, fe_victims, fe_suicides, fe_mapsplayed, fe_mapswon, fe_time, fe_fph, date_format(LastSeen, '%d.%m.%Y') as date_europe FROM PlayerStats WHERE fe_skill > 0 ORDER by fe_skill DESC LIMIT $start,$limit");
+$query->execute;
+
+while ($row_hash = $query->fetchrow_hashref) {
+ $name = $row_hash->{nick};
+ $nick{$name} = $name;
+ $skill{$name} = $row_hash->{fe_skill};
+ $kills{$name} = $row_hash->{fe_kills};
+ $victims{$name} = $row_hash->{fe_victims};
+ $suicides{$name} = $row_hash->{fe_suicides};
+ $maps{$name} = $row_hash->{fe_mapsplayed};
+ $wonmaps{$name} = $row_hash->{fe_mapswon};
+ $time{$name} = $row_hash->{fe_time};
+ $fph{$name} = $row_hash->{fe_fph};
+ $lastseen{$name} = $row_hash->{date_europe};
+ unless(defined($lastseen{$name})) { $lastseen{$name} = '--.--.--'; }
+}
+$query->finish;
+$dbh->disconnect;
+
+
+
+print "Content-Type: text/html\n\n\n";
+
+
+###### Sortieren #####
+
+# By default, sort by rank
+
+if ($sort eq "0") {
+ @sortkey = sort { $skill{$b} <=> $skill{$a} } (keys %nick);
+ $sortname = "Skill";
+ $darstellung = "\= Kills \/ \( 1 \+ Victims \+ Suicides \) \* \( 1 \+ \( Maps-won \/ Maps-played \)";
+}
+
+
+
+if ($sort eq "1") {
+ @sortkey = sort { $nick{$a} cmp $nick{$b} } (keys %nick);
+ $sortname = "Nick";
+ $darstellung = "";
+}
+
+if ($sort eq "2") {
+ @sortkey = sort { $maps{$b} <=> $maps{$a} } (keys %maps);
+ $sortname = "gespielten Maps";
+ $darstellung = "";
+}
+
+if ($sort eq "3") {
+ @sortkey = sort { $kills{$b} <=> $kills{$a} } (keys %kills);
+ $sortname = "Kills";
+ $darstellung = "";
+}
+
+if ($sort eq "4") {
+ @sortkey = sort { $victims{$b} <=> $victims{$a} } (keys %victims);
+ $sortname = "Victims";
+ $darstellung = "";
+}
+
+if ($sort eq "5") {
+ @sortkey = sort { $suicides{$b} <=> $suicides{$a} } (keys %suicides);
+ $sortname = "Suicides";
+ $darstellung = "";
+}
+
+if ($sort eq "6") {
+ @sortkey = sort { $fph{$b} <=> $fph{$a} } (keys %fph);
+ $sortname = "FPH";
+ $darstellung = "\= Kills \/ \(Sec \/ 3600 \)";
+}
+
+if ($sort eq "7") {
+ @sortkey = sort { $time{$b} <=> $time{$a} } (keys %nick);
+ $sortname = "Zeit";
+ $darstellung = "";
+}
+
+if ($sort eq "8") {
+ @sortkey = sort { $wonmaps{$b} <=> $wonmaps{$a} } (keys %nick);
+ $sortname = "gewonnenen Maps";
+ $darstellung = "";
+}
+## Ausgabe ##
+### Header ###
+print '<HTML><HEAD><TITLE>Cardassia - Hall of Fame</TITLE>';
+print '<META NAME="Andreas Ulbrich \+ Ralf Ertzinger">';
+print '</HEAD><BODY BGCOLOR="#FFFFFF">';
+print "\n<CENTER><img SRC=\"http\:\/\/www.ndc.sh\/graphics\/halloffame_logo.jpg\" WIDTH=\"500\" HEIGHT=\"90\" BORDER=\"0\"ALT=\"\[SERVER Hall of Fame\]\"><\/CENTER>\n";
+
+print "<CENTER><b>Erfasste Spieler gesamt: $rowsall <BR>Anzahl der Spieler mit mehr als 10 Maps: $rows<\/B><BR>\n";
+if ($back == 0) {
+ print "<b><a href =\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=0\&limit\=$rows\&back\=1\">$rows Spieler anzeigen<\/A><\/B><\/CENTER><\/BR>\n";
+}
+else {
+ print "<b><a href =\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=0\&limit\=20\&back\=0\">Die ersten 20 anzeigen<\/A><\/B><\/CENTER><\/BR>\n";
+}
+
+
+##### Sortiert nach sortkey ########
+
+print "<P>\ \;<P><UL><b>Sortiert nach $sortname $darstellung<\/b>\n";
+print "<table BORDER=\"0\">\n";
+print "<tr>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b>Rang<\/b><\/td>
+\n";
+print "<td WIDTH=\"120\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=1\&limit=$limit\&back=$back\">Name<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=0\&limit=$limit\&back=$back\">Skill<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=6\&limit=$limit\&back=$back\">FPH<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=2\&limit=$limit\&back=$back\">Maps gespielt<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=8\&limit=$limit\&back=$back\">Maps gewonnen<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=3\&limit=$limit\&back=$back\">Kills<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=4\&limit=$limit\&back=$back\">Victims<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=5\&limit=$limit\&back=$back\">Suicides<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"50\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b><a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort\=7\&limit=$limit\&back=$back\">Zeit (Min)<\/a><\/b><\/td>\n";
+print "<td WIDTH=\"100\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b>Zuletzt gespielt<\/b><\/td>\n";
+print "<\/tr>\n";
+
+$count = $start;
+foreach $name (@sortkey)
+{
+
+ $count ++;
+ print "<tr>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"+0\">$count<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#CCCCCC\"><font size =\"+0\">";
+ print "<a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/playerstats.pl\?nick\=";
+ print make_compatible($nick{$name});
+ print "\">";
+ print "<font color\=\"#000000\">";
+ print make_html($nick{$name});
+ print "<\/font>";
+ print "<\/a><\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$skill{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$fph{$name}<\/font><\/td>\n";
+
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$maps{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$wonmaps{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$kills{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$victims{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$suicides{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$time{$name}<\/font><\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\"><font size =\"-1\">$lastseen{$name}<\/font><\/td>\n";
+ print "<\/tr>\n";
+}
+
+print "<\/TABLE><\/UL><P>\n";
+
+if ($back == 0) {
+ print "<CENTER><TABLE BORDER=\"0\">\n";
+ print "<tr>\n";
+ print "<td WIDTH=\"200\" ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\">";
+ if ($start != 0) {
+ $start_prev = $start - $limit;
+ if ($start_prev < 0) {$start_prev = 0;}
+ print "<a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort=$sort&start=$start_prev&limit=$limit&back=0\">";
+ print "Zurück";
+ print "<\/a>\n";
+ } else {
+ print "Zurück";
+ }
+ print "<\/td>\n";
+ print "<td WIDTH=\"200\" ALIGN=\"CENTER\" BGCOLOR=\"\#EEEEEE\">";
+ if ($start + $limit < $rows) {
+ $start_next = $start + $limit;
+ print "<a href=\"http\:\/\/www.ndc.sh\/cgi-bin\/quake\/foreverstats2.pl\?sort=$sort&start=$start_next&limit=$limit&back=0\">";
+ print "Weiter";
+ print "<\/a>\n";
+ } else {
+ print "Weiter";
+ }
+ print "<\/td>\n";
+ print "<\/tr>\n";
+ print "<\/TABLE><\/CENTER>\n";
+}
+
+print "<P><FONT SIZE=\"-2\"><DIV ALIGN=right>Skripting by NDC Code<BR><A href=\"http://www.ndc.sh\" target=\"_top\">www.ndc.sh</A></DIV></FONT><BR>\n";
+print '</BODY></HTML>';
+
+
+############### Subroutines ###########
+
+sub make_html {
+
+ $input = shift;
+# $input =~ s/&/und/g;
+ $input =~ s/</<\;/g;
+ $input =~ s/>/>\;/g;
+ $input =~ s/"/"\;/g;
+ $input =~ s/\x1c/·/g;
+# $input =~ s/\|/pipe/g;
+ return $input;
+}
+
+sub make_compatible {
+
+ $input = shift;
+ $input =~ s/%/%25/g;
+ $input =~ s/\+/%2B/g;
+ $input =~ s/ /+/g;
+ $input =~ s/,/%2C/g;
+ $input =~ s/</%3C/g;
+ $input =~ s/>/%3E/g;
+ $input =~ s/#/%23/g;
+ $input =~ s/\[/%5B/g;
+ $input =~ s/\]/%5D/g;
+ $input =~ s/\//%2F/g;
+ $input =~ s/\|/%7C/g;
+ $input =~ s/\?/%3F/g;
+ $input =~ s/\x1c/%1C/g;
+
+ return $input;
+}
--- /dev/null
+#!/usr/bin/perl -w
+
+# foreverstats3.pl
+# NDC Code Release 1
+#
+# Connects to the database holding the statistic data. Builds a
+# web page based on a template file.
+# This script has limited functionality compared to foreverstats2,
+# bus has _much_ cleaner code.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+use strict;
+use CGI;
+use CGI::Debug (report => 'everything', on => 'warnings');
+use DBI;
+
+# Define some variables
+my $template_path = "templates";
+my $scriptpath = "http://www.ndc.sh/cgi-bin/quake/foreverstats3.pl";
+my $template_file;
+my @main_source;
+my %variables;
+my @playerdata;
+
+my $CGI_query;
+
+# Info about the script
+$variables{parser_selfinfo} = "<!--\nThis is the [NDC] foreverstats script, Release 3.0.\n" .
+ "Featuring support for selectable viewlimits and player highlighting.\n" .
+ "Parsing-Engine: Lilith, Version 1.1.\n" .
+ "Output is HTML 4.01 strict compliant.\n\n".
+ "Original Release by [NDC]Maria.\n" .
+ "Rewrite by [NDC]Sundancer.\n" .
+ "Lilith by [NDC]Sundancer.\n" .
+ "Source code is available. Contact ndccode\@ndc.sh or see http://www.ndc.sh/ndccode.\n" .
+ "//-->";
+$variables{scriptpath} = $ENV{REQUEST_URI};
+
+sub parse {
+
+ # This is Lilith. Takes an array on input, and parses it line by line,
+ # printing the result to STDOUT.
+
+ # Variables
+ my $template_line;
+ my @parser_comment;
+ my @looparray;
+ my $comment;
+ my $fullcomment;
+ my $replacement;
+ my $loop_variable;
+ my $in_loop_players = 0;
+
+ LOOP: while ($template_line = shift) {
+
+ if ($template_line =~ /^\s*\<!--loop [\w_]+--\>/) {
+ ($loop_variable) = ($template_line =~ /<!--loop ([\w_]+)--\>/);
+ if ($loop_variable eq "players") {
+ $in_loop_players = 1;
+ }
+ next LOOP;
+ }
+
+ if ($template_line =~ /^\s*\<!--endloop [\w_]+--\>/) {
+ ($loop_variable) = ($template_line =~ /<!--endloop ([\w_]+)--\>/);
+ if ($loop_variable eq "players") {
+ $in_loop_players = 0;
+
+ # Unroll the loop.
+ for (my $i=0;$i<scalar(@playerdata);$i++) {
+ $variables{'parser_playerrank'} = $i+1;
+ $variables{'parser_playername'} = make_compatible(@{$playerdata[$i]}->[0]);
+ $variables{'parser_playerskill'} = @{$playerdata[$i]}->[1];
+ $variables{'parser_playerfph'} = @{$playerdata[$i]}->[2];
+ $variables{'parser_playermapsplayed'} = @{$playerdata[$i]}->[3];
+ $variables{'parser_playermapswon'} = @{$playerdata[$i]}->[4];
+ $variables{'parser_playerkills'} = @{$playerdata[$i]}->[5];
+ $variables{'parser_playervictims'} = @{$playerdata[$i]}->[6];
+ $variables{'parser_playersuicides'} = @{$playerdata[$i]}->[7];
+ $variables{'parser_playertime'} = @{$playerdata[$i]}->[8];
+ $variables{'parser_playerlastseen'} = @{$playerdata[$i]}->[9];
+ parse(@looparray);
+ }
+ }
+ next LOOP;
+ }
+
+ # If we are in loopmode, copy lines into an array for later parsing.
+ if ($in_loop_players == 1) {
+ push @looparray, $template_line;
+ next LOOP;
+ }
+
+ @parser_comment = ($template_line =~ /\<!--\$([\w_]+)--\>/g);
+ foreach $comment ( @parser_comment) {
+ if(defined($variables{$comment})) {
+ $fullcomment = "\\<!--\\\$" . $comment . "--\\>";
+ $replacement = $variables{$comment};
+ $template_line =~ s/$fullcomment/$replacement/g;
+ }
+ }
+ print $template_line;
+ }
+}
+
+sub main {
+
+ # Main routine.
+
+ my $template;
+
+ $CGI_query = new CGI;
+ $template = ($CGI_query->param('template')?$CGI_query->param('template'):'/foreverstatsstrict.template');
+ $template_file = $template_path;
+ if ($template =~ /\W/) {
+ # template file name contains illegal characters
+ $template_file .= "/forerverstatsstrict.template";
+ } else {
+ $template_file .= $template . ".template";
+ }
+
+ if ( ! -e $template_file) {
+ $template_file = $template_path . "/foreverstatsstrict.template";
+ }
+
+ # Read the contents of the templatefile
+ open(TEMPLATE, $template_file) or die "Could not open template file: $!\n";
+ @main_source = <TEMPLATE>;
+ close(TEMPLATE);
+ GetPlayerData();
+ print "Content-Type: text/html\n\n";
+ parse(@main_source);
+}
+
+sub buildsqlquery {
+
+ # Evaluates the parameters and constructs a SQL-query.
+
+ my $operator;
+ my $field;
+ my $value;
+ my $sql_query;
+
+ my %operatormapping = ( 'mehrgleich' => '>=',
+ 'wenigergleich' => '<=',
+ 'gleich' => '=',
+ 'mehr' => '>',
+ 'weniger' => '<' );
+
+ my %fieldmapping = ( 'Mapsplayed' => 'fe_MapsPlayed',
+ 'Mapswon' => 'fe_MapsWon',
+ 'Kills' => 'fe_Kills',
+ 'Victims' => 'fe_Victims',
+ 'Suicides' => 'fe_Suicides' );
+
+ $operator = ($CGI_query->param('sel_operator')?$CGI_query->param('sel_operator'):'mehrgleich');
+ $field = ($CGI_query->param('sel_field')?$CGI_query->param('sel_field'):'50');
+ $value = ($CGI_query->param('sel_number')?$CGI_query->param('sel_number'):'mehrgleich');
+
+ if(defined($operatormapping{$operator})) {
+ $operator = $operatormapping{$operator};
+ } else {
+ $operator = $operatormapping{'mehrgleich'};
+ }
+
+ if(defined($fieldmapping{$field})) {
+ $field = $fieldmapping{$field};
+ } else {
+ $field = $fieldmapping{'Mapsplayed'};
+ }
+
+ unless($value=~/\d+/) {
+ $value = 50;
+ }
+
+ # Build the Query. Hiho.
+ $sql_query = 'SELECT nick, fe_skill, fe_fph, fe_mapsplayed, fe_mapswon, fe_kills, fe_victims, fe_suicides, fe_time, date_format(LastSeen, \'%d.%m.%Y\') as date_europe FROM PlayerStats WHERE (' . $field . $operator . $value . ') ORDER BY fe_skill DESC LIMIT 20';
+
+ return $sql_query;
+}
+
+sub GetPlayerData {
+
+ # Get the players from the database.
+
+ my $sql_handle;
+ my $sql_query;
+ my $sql_querystring;
+ my @row;
+ my $i=0;
+
+ my $sql_user = "";
+ my $sql_pass = "";
+
+ $sql_handle = DBI->connect("DBI:mysql:NDC",$sql_user,$sql_pass) or die;
+ $sql_querystring = buildsqlquery();
+ $sql_query = $sql_handle->prepare($sql_querystring);
+ $sql_query->execute or die;
+
+ while (@row = $sql_query->fetchrow_array) {
+ $playerdata[$i++] = [ @row ];
+ }
+ $sql_query->finish;
+ $sql_handle->disconnect;
+}
+
+sub make_compatible {
+
+ # Takes a string. Converts all suspicious characters into HTML.
+
+ my $input;
+
+ $input = shift;
+ $input =~ s/&/&/g;
+ $input =~ s/\x1c/·/g;
+ $input =~ s/</</g;
+ $input =~ s/>/>/g;
+ $input =~ s/"/"/g;
+ return $input;
+}
+
+
+# This is the main program.
+
+main();
--- /dev/null
+#!/usr/bin/perl
+
+# foreverstats_wap.pl
+# NDC Code Release 1
+#
+# Connects to the database holding the stats, and builds a WAP-Page
+# from it.
+# CGI-Parameters:
+# start: First entry displayed
+# limit: Number of entries. Defaults to 10.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#use strict;
+require 5.002;
+use DBI;
+use CGI;
+
+my $CGIquery;
+
+### Var def ###
+$CGIquery = new CGI;
+$start = ($CGIquery->param("start")?$CGIquery->param("start"):0);
+$limit = ($CGIquery->param("limit")?$CGIquery->param("limit"):10);
+
+# Rebuild database, if necessary
+
+$database = "stats";
+$data_source = "DBI:mysql:$database";
+$username = "";
+$password = "";
+$dbh = DBI->connect( $data_source, $username, $password) or die "Can't connect to $data_source\n"; #: $dbh->errstr\n";
+
+$query = $dbh->prepare("SELECT nick FROM PlayerStats WHERE fe_skill > 0");
+$query->execute;
+$rows = $query->rows;
+$query->finish;
+
+$query = $dbh->prepare("SELECT nick ,skill FROM PlayerStats WHERE fe_skill > 0 ORDER by fe_skill DESC LIMIT $start,$limit");
+$query->execute;
+
+while ($row_hash = $query->fetchrow_hashref) {
+ $name = $row_hash->{nick};
+ $nick{$name} = $name;
+ $skill{$name} = $row_hash->{skill};
+}
+$query->finish;
+$dbh->disconnect;
+
+# Sort
+@sortkey = sort { $skill{$b} <=> $skill{$a} } (keys %nick);
+
+print "Content-Type: text/vnd.wap.wml\n\n\n";
+
+
+
+## Ausgabe ##
+### Header ###
+print '<?xml version="1.0"?>' . "\n";
+print '<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">' . "\n";
+
+print "<wml>\n";
+print "<card id=\"card1\" title=\"Ewige Stats\">\n";
+if ($start!=0) {
+ $start_prev=$start - 10;
+ if ($start_prev<0) {$start_prev=0;}
+ print "<do type=\"accept\" label=\"Zurück\">\n";
+ print "<go href=\"\/cgi-bin\/quake\/foreverstats_wap.pl\?start=$start_prev\"\/>\n";
+ print "<\/do>\n";
+}
+
+if (($start + 10) < $rows) {
+ $start_next=$start + 10;
+ print "<do type=\"accept\" label=\"Weiter\">\n";
+ print "<go href=\"\/cgi-bin\/quake\/foreverstats_wap.pl\?start=$start_next\"\/>\n";
+ print "<\/do>\n";
+}
+
+print "<do type=\"accept\" label=\"Gestern\">\n";
+print "<go href=\"\/cgi-bin\/quake\/dailystats_wap.pl\"\/>\n";
+print "<\/do>\n";
+
+print "<do type=\"accept\" label=\"Navigation\">\n";
+print "<go href=\"\/nav.wml\"\/>\n";
+print "<\/do>\n";
+
+print "<do type=\"accept\" label=\"Hauptseite\">\n";
+print "<go href=\"\/\"\/>\n";
+print "<\/do>\n";
+
+print "<p>\n";
+
+print "<small>\n";
+print "<table columns=\"3\">\n";
+print "<tr><td>P.<\/td><td>Name<\/td><td>Skill<\/td><\/tr>\n";
+
+$count = $start;
+foreach $name (@sortkey)
+{
+ $count ++;
+ print "<tr>\n";
+ print "<td>$count<\/td>\n";
+ print "<td>";
+ print make_html($nick{$name});
+ print "<\/td>\n";
+ print "<td>$skill{$name}<\/td>\n";
+ print "<\/tr>\n";
+}
+
+print "<\/table></small>\n";
+print "<\/p>\n";
+print "<\/card>\n";
+print "<\/wml>";
+
+
+############### Subroutines ###########
+
+sub make_html {
+
+ $input = shift;
+# $input =~ s/&/und/g;
+ $input =~ s/</<\;/g;
+ $input =~ s/>/>\;/g;
+ $input =~ s/"/"\;/g;
+# $input =~ s/\|/pipe/g;
+ return $input;
+}
+
+sub make_compatible {
+
+ $input = shift;
+ $input =~ s/%/%25/g;
+ $input =~ s/\+/%2B/g;
+ $input =~ s/ /+/g;
+ $input =~ s/,/%2C/g;
+ $input =~ s/</%3C/g;
+ $input =~ s/>/%3E/g;
+ $input =~ s/#/%23/g;
+ $input =~ s/\[/%5B/g;
+ $input =~ s/\]/%5D/g;
+ $input =~ s/\//%2F/g;
+ $input =~ s/\|/%7C/g;
+ $input =~ s/\?/%3F/g;
+
+ return $input;
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<!--$parser_selfinfo-->
+
+<HTML>
+
+<HEAD>
+ <TITLE>NDC Foreverstats</TITLE>
+ <META NAME="Author" CONTENT="Andreas Ulbrich">
+ <META NAME="Author" CONTENT="Ralf Ertzinger">
+
+<link rel="stylesheet" href="/css/ndcstrict.css" media="screen" type="text/css">
+<style type="text/css">
+<!--
+.globalinfo { font-weight: bold; text-align: center}
+.tableheader { background-color: #FFFFCC; text-align: center}
+.namecolumn { font-size: smaller; background-color: #CCCCCC; width: 120px; text-align: center}
+.othercolumn { font-size: smaller; background-color: #EEEEEE; width: 50px; text-align: center}
+.sortedby { text-align: left; font-weight: bold}
+-->
+</style></HEAD>
+
+
+<BODY>
+
+<p class="image"> <img SRC="/graphics/halloffame_logo.jpg" WIDTH="500" HEIGHT="90" ALT="[Hall of Fame]">
+</p>
+<p class="globalinfo">Erfasste Spieler gesamt:<br>
+ Anzahl der Spieler mit mehr als xx Maps:</p>
+<form method="post" action="<!--$scriptpath-->">
+ <p class="globalinfo">
+ Zeige Spieler mit
+ <select name="sel_operator">
+ <option value="mehrgleich" selected>>=</option>
+ <option value="gleich">=</option>
+ <option value="wenigergleich"><=</option>
+ <option value="mehr">></option>
+ <option value="weniger"><</option>
+ </select>
+ <input type="text" name="sel_number" maxlength="20" value="50">
+ <select name="sel_field">
+ <option value="Mapsplayed" selected>gespielten Maps</option>
+ <option value="Mapswon">gewonnenen Maps</option>
+ <option value="Kills">Kills</option>
+ <option value="Victims">Victims</option>
+ <option value="Suicides">Suicides</option>
+ </select>
+ <input type="submit" name="Submit" value="Go go go">
+ </p>
+</form>
+<p class="globalinfo"> </p>
+<p class="sortedby">Sortiert nach Skill = Kills / ( 1 + Victims + Suicides ) *
+ ( 1 + ( Maps-won / Maps-played )</p>
+<table border="0">
+ <tr class="tableheader">
+ <td>Rang</td>
+ <td>Name</td>
+ <td>Skill</td>
+ <td>FPH</td>
+ <td>Maps gespielt</td>
+ <td>Maps gewonnen</td>
+ <td>Kills</td>
+ <td>Victims</td>
+ <td>Suicides</td>
+ <td>Zeit (Min)</td>
+ <td>Zuletzt gespielt</td>
+ </tr>
+<!--loop players-->
+ <tr>
+ <td class="othercolumn"><!--$parser_playerrank--></td>
+ <td class="namecolumn"><!--$parser_playername--></td>
+ <td class="othercolumn"><!--$parser_playerskill--></td>
+ <td class="othercolumn"><!--$parser_playerfph--></td>
+ <td class="othercolumn"><!--$parser_playermapsplayed--></td>
+ <td class="othercolumn"><!--$parser_playermapswon--></td>
+ <td class="othercolumn"><!--$parser_playerkills--></td>
+ <td class="othercolumn"><!--$parser_playervictims--></td>
+ <td class="othercolumn"><!--$parser_playersuicides--></td>
+ <td class="othercolumn"><!--$parser_playertime--></td>
+ <td class="othercolumn"><!--$parser_playerlastseen--></td>
+ </tr>
+<!--endloop players-->
+</table>
+<p class="globalinfo"> </p>
+<p class="credits">
+ Skripting by NDC Code<BR>
+ <A href="http://www.ndc.sh">www.ndc.sh</A>
+ </p>
+</BODY>
+</HTML>
--- /dev/null
+#!/bin/perl -w
+
+# makedb.pl
+# NDC Code Release 1
+#
+# Read preprocessed GS-Logs from STDIN, and flush them into a SQL-Database
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+use DBI;
+
+# Define SQL-Variables
+
+$sql_database = "stats";
+$sql_db_table = "PlayerStats";
+$sql_datasource = "DBI:mysql:$sql_database";
+$sql_username = "";
+$sql_password = "";
+$sql_db_handle = DBI->connect($sql_datasource, $sql_username, $sql_password) or die "Could not connect to database.\n";
+
+# Load player data
+
+@gslog = <STDIN>;
+
+# Load a list of players who are _not_ updated.
+if ( -r "noupdate") {
+ open(NOUPDATE,"noupdate") or die "Could not open noupdate: $!\n";
+ @noupdate = <NOUPDATE>;
+ close(NOUPDATE);
+ chomp(@noupdate);
+ print "List of players not being updated by specific request:\n";
+ print join("\n", @noupdate);
+ print "\n";
+ %noupdate = ();
+ foreach $nick (@noupdate) { $noupdate{$nick} = 1 }
+}
+
+# First, delete all players who didn't play within the last 100 days
+
+print "Deleting players...\n";
+
+$sql_query = $sql_db_handle->prepare("DELETE from $sql_db_table WHERE TO_DAYS(NOW()) - TO_DAYS(LastSeen) > 100");
+$sql_query->execute or die "Could not delete datasets.";
+$sql_query->finish;
+
+# Flush data from previous day (in fact, flush only 'mapsplayed'. The
+# DailyStats.pl script will ignore these datasets for table generation.
+
+print "Flushing datasets...\n";
+
+$sql_query = $sql_db_handle->prepare("UPDATE $sql_db_table SET MapsPlayed=0, fe_rank=0");
+$sql_query->execute or die "Could not flush database.\n";
+$sql_query->finish;
+
+# Process data
+
+print "Processing...\n";
+
+LOOP: while ($gslog_line = shift(@gslog)) {
+
+ ($pl_nick,$pl_kills,$pl_victims,$pl_suicides,$pl_maps_played,$pl_maps_won,$pl_time) = split(":",$gslog_line);
+
+ # Check if the player is on the "noupdate" list. Skip it then.
+ if (defined($noupdate{$pl_nick})) {
+ print "Skipping $pl_nick due to noupdate.";
+ shift @gslog;
+ next LOOP;
+ }
+
+ if (($pl_nick ne "") & ($pl_time > 60) & ($pl_maps_played != 0)) {
+
+ # Check if there is already a dataset for this player.
+ # If not, init all values, and create an entry.
+
+ $sql_query = $sql_db_handle->prepare("SELECT nick FROM $sql_db_table WHERE nick=?");
+ $sql_query->execute($pl_nick);
+ $sql_result = $sql_query->fetchrow_hashref;
+ $sql_query->finish;
+
+ unless (defined($sql_result)) {
+ $sql_query = $sql_db_handle->prepare("INSERT INTO $sql_db_table (Nick, Email, Picture, Homepage, Skill, Skill_top, Kills, Victims, Suicides, MapsPlayed, MapsWon, Time, FPH, fe_Skill, fe_Kills, fe_Victims, fe_Suicides, fe_MapsPlayed, fe_MapsWon, fe_Time, fe_FPH, LastSeen) VALUES (?, '', 'empty.jpg', '', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', NOW())");
+ $sql_query->execute($pl_nick) or die "Could not insert dataset for $pl_nick\n";
+ $sql_query->finish;
+ }
+
+ # Load the dataset
+
+ $sql_query = $sql_db_handle->prepare("SELECT Skill, Skill_top, Kills, Victims, Suicides, MapsPlayed, MapsWon, Time, FPH, fe_Skill, fe_Kills, fe_Victims, fe_Suicides, fe_MapsPlayed, fe_MapsWon, fe_Time, fe_FPH FROM $sql_db_table WHERE nick=?");
+ $sql_query->execute($pl_nick);
+ $sql_result = $sql_query->fetchrow_hashref;
+
+ $pl_sql_skill = $sql_result->{Skill};
+ $pl_sql_skill_top = $sql_result->{Skill_top};
+ $pl_sql_kills = $sql_result->{Kills};
+ $pl_sql_victims = $sql_result->{Victims};
+ $pl_sql_suicides = $sql_result->{Suicides};
+ $pl_sql_mapsplayed = $sql_result->{MapsPlayed};
+ $pl_sql_mapswon = $sql_result->{MapsWon};
+ $pl_sql_time = $sql_result->{"Time"};
+ $pl_sql_fph = $sql_result->{FPH};
+ $pl_sql_fe_skill = $sql_result->{fe_Skill};
+ $pl_sql_fe_kills = $sql_result->{fe_Kills};
+ $pl_sql_fe_victims = $sql_result->{fe_Victims};
+ $pl_sql_fe_suicides = $sql_result->{fe_Suicides};
+ $pl_sql_fe_mapsplayed = $sql_result->{fe_MapsPlayed};
+ $pl_sql_fe_mapswon = $sql_result->{fe_MapsWon};
+ $pl_sql_fe_time = $sql_result->{fe_Time};
+ $pl_sql_fe_fph = $sql_result->{fe_FPH};
+
+ $sql_query->finish;
+
+ $pl_skill = ($pl_kills / ($pl_victims + $pl_suicides + 1)) * (1 + ($pl_maps_won / $pl_maps_played));
+ $pl_fph = ($pl_kills * 3600) / $pl_time;
+ $pl_time = $pl_time / 60;
+
+ # Flush the data into the fields
+
+ $pl_sql_skill = $pl_skill;
+ $pl_sql_kills = $pl_kills;
+ $pl_sql_victims = $pl_victims;
+ $pl_sql_suicides = $pl_suicides;
+ $pl_sql_mapsplayed = $pl_maps_played;
+ $pl_sql_mapswon = $pl_maps_won;
+ $pl_sql_time = $pl_time;
+ $pl_sql_fph = $pl_fph;
+
+ $pl_sql_fe_kills += $pl_kills;
+ $pl_sql_fe_victims += $pl_victims;
+ $pl_sql_fe_suicides += $pl_suicides;
+ $pl_sql_fe_mapsplayed += $pl_maps_played;
+ $pl_sql_fe_mapswon += $pl_maps_won;
+ $pl_sql_fe_time += $pl_time;
+ $pl_sql_fe_fph = ($pl_sql_fe_kills * 60) / $pl_sql_fe_time;
+ $pl_sql_fe_skill = ($pl_sql_fe_kills / ($pl_sql_fe_victims + $pl_sql_fe_suicides + 1)) * (1 + ($pl_sql_fe_mapswon / $pl_sql_fe_mapsplayed));
+ if ($pl_sql_fe_mapsplayed < 10) {
+ $pl_sql_fe_skill = 0;
+ }
+ if ($pl_sql_fe_skill > $pl_sql_skill_top) {
+ $pl_sql_skill_top = $pl_sql_fe_skill;
+ }
+
+ $sql_query = $sql_db_handle->prepare("UPDATE $sql_db_table SET Skill='$pl_sql_skill', Skill_top='$pl_sql_skill_top', Kills='$pl_sql_kills', Victims='$pl_sql_victims', Suicides='$pl_sql_suicides', MapsPlayed='$pl_sql_mapsplayed', MapsWon='$pl_sql_mapswon', Time='$pl_sql_time', FPH='$pl_sql_fph', fe_Skill='$pl_sql_fe_skill', fe_kills='$pl_sql_fe_kills', fe_Victims='$pl_sql_fe_victims', fe_Suicides='$pl_sql_fe_suicides', fe_MapsPlayed='$pl_sql_fe_mapsplayed', fe_MapsWon='$pl_sql_fe_mapswon', fe_Time='$pl_sql_fe_time', fe_FPH='$pl_sql_fe_fph', LastSeen=NOW() WHERE nick=?");
+ $sql_query->execute($pl_nick) or die "Could not update entry: $pl_nick\n";
+ $sql_query->finish;
+ }
+
+ shift @gslog;
+
+}
+
+$sql_db_handle->disconnect;
+
+print "Finished.\n";
+
+exit(0);
+
--- /dev/null
+#!/usr/bin/perl
+
+# makerank.pl
+# NDC Code Release 1
+#
+# Updates the rank field in the stats database.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#use strict;
+require 5.002;
+use DBI;
+
+### Var def ###
+
+$database = "stats";
+$data_source = "DBI:mysql:$database";
+$username = "";
+$password = "";
+$dbh = DBI->connect( $data_source, $username, $password) or die "Can't connect to $data_source\n"; #: $dbh->errstr\n";
+
+
+$query = $dbh->prepare("SELECT nick FROM PlayerStats WHERE fe_skill > 0 ORDER by fe_skill DESC");
+$query->execute;
+
+$rank = 1;
+
+while ($row_hash = $query->fetchrow_hashref) {
+ $name = $row_hash->{nick};
+ $nick{$name} = $name;
+ $rank{$name} = $rank++;
+}
+
+$query->finish;
+
+foreach $name (%nick) {
+
+ $sql_query_string = "UPDATE PlayerStats SET fe_rank=? WHERE nick=?";
+ $sql_query=$dbh->prepare($sql_query_string);
+ $sql_query->execute($rank{$name},$nick{$name});
+ $sql_query->finish;
+}
+
+$dbh->disconnect;
+
--- /dev/null
+#!/usr/bin/perl
+
+# playerstats.pl
+# NDC Code Release 1
+# CGI-Parameters:
+# nick: Player name
+#
+# Displays a web page showing the stats for one player, displaying
+# a picture, mail address and web page.
+#
+# Copyright (C) 2001 Andreas Ulbrich, Ralf Ertzinger (ndccode@ndc.sh)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#use strict;
+require 5.002;
+use DBI;
+use CGI;
+
+my $CGIquery;
+
+### Var def ###
+$CGIquery = new CGI;
+$picturepath = 'http://www.ndc.sh/graphics/playerdb/';
+$nick = $CGIquery->param("nick");
+
+# Define SQL-Variables
+
+$sql_database = "stats";
+$sql_datasource = "DBI:mysql:$sql_database";
+$sql_username = "";
+$sql_password = "";
+$sql_db_handle = DBI->connect($sql_datasource, $sql_username, $sql_password) or die "Could not connect to database.\n";
+
+
+print "Content-Type: text/html\n\n\n";
+
+# Retrieve player data from SQL
+
+$sql_query_string = "SELECT nick, email, picture, homepage, kills, victims, suicides, mapsplayed, mapswon, FPH, skill, time, skill_top, fe_skill, fe_kills, fe_victims, fe_suicides, fe_mapsplayed, fe_mapswon, fe_fph, fe_time, fe_rank, date_format(LastSeen, '%d.%m.%Y') as date_europe FROM PlayerStats WHERE nick=?";
+$sql_query = $sql_db_handle->prepare($sql_query_string);
+$sql_query->execute($nick);
+
+$sql_row = $sql_query->fetchrow_hashref;
+
+$pl_name = $sql_row->{nick};
+$pl_email = $sql_row->{email};
+$pl_picture = $picturepath . $sql_row->{picture};
+$pl_homepage = $sql_row->{homepage};
+$pl_kills = $sql_row->{kills};
+$pl_victims = $sql_row->{victims};
+$pl_suicides = $sql_row->{suicides};
+$pl_fph = $sql_row->{FPH};
+$pl_skill = $sql_row->{skill};
+$pl_time = $sql_row->{time};
+$pl_maps_played = $sql_row->{mapsplayed};
+$pl_maps_won = $sql_row->{mapswon};
+$pl_fe_kills = $sql_row->{fe_kills};
+$pl_fe_victims = $sql_row->{fe_victims};
+$pl_fe_suicides = $sql_row->{fe_suicides};
+$pl_fe_maps_played= $sql_row->{fe_mapsplayed};
+$pl_fe_maps_won = $sql_row->{fe_mapswon};
+$pl_fe_skill = $sql_row->{fe_skill};
+$pl_fe_fph = $sql_row->{fe_fph};
+$pl_fe_time = $sql_row->{fe_time};
+$pl_skill_top = $sql_row->{skill_top};
+$pl_fe_rank = $sql_row->{fe_rank};
+$pl_lastseen = $sql_row->{date_europe};
+
+$sql_query->finish;
+
+$sql_db_handle->disconnect;
+
+## Ausgabe ##
+### Header ###
+print '<HTML><HEAD><TITLE>NDC Spielerdaten</TITLE>';
+print '<META NAME="Andreas Ulbrich">';
+print '</HEAD><BODY BGCOLOR="#FFFFFF">';
+print "\n<CENTER><img SRC=\"http:\/\/www.ndc.sh\/graphics\/aktuell_logo.jpg\" WIDTH=\"300\" HEIGHT=\"90\" BORDER=\"0\"ALT=\"\[SERVER Status\]\"><\/CENTER>\n";
+print "\ \;<P>\n";
+if (defined($eingabe{showquery})) {
+ print "<pre>\n";
+ print "SQL-Query:\n";
+ print "$sql_query_string\n";
+ print "</pre>";
+}
+print "<UL><table BORDER=\"0\">\n";
+print "<tr>\n";
+print "<td WIDTH=\"270\" ALIGN=\"CENTER\" BGCOLOR=\"\#FFFFCC\"><b>Spielerdaten<\/b><\/td>\n";
+print "<\/TABLE><\/UL>\n";
+
+if (defined($pl_name)) {
+ print "<UL><table BORDER=\"0\">\n";
+ print "<tr>\n";
+ print "<td ROWSPAN=\"10\" VALIGN=\"TOP\"><img src \=\"$pl_picture\" WIDTH=\"186\" HEIGHT=\"300\" BORDER=\"0\"><\/td>";
+ print "<td WIDTH=\"120\" BGCOLOR=\"\#CCCCCC\">Nickname:<\/td>";
+ print "<td WIDTH=\"200\" BGCOLOR=\"\#EEEEEE\"><b>" . make_html($pl_name) . "<\/b><\/td>\n";
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">email:<\/td>";
+ if ($pl_email ne "") {
+ print "<td BGCOLOR=\"#EEEEEE\"><b><a href=\"mailto:$pl_email\">$pl_email<\/a><\/b><\/td>\n";
+ } else {
+ print "<td BGCOLOR=\"#EEEEEE\"><b>-<\/b><\/td>\n";
+ }
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Homepage:<\/td>";
+ if ($pl_homepage ne "") {
+ print "<td BGCOLOR=\"#EEEEEE\"><b><a href=\"$pl_homepage\" TARGET=\"xxyyzz\">$pl_homepage<\/a><\/b><\/td>\n";
+ } else {
+ print "<td BGCOLOR=\"#EEEEEE\"><b>-<\/b><\/td>\n";
+ }
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Kills:<\/td>";
+ print "<td BGCOLOR=\"#EEEEEE\"><b>$pl_fe_kills<\/b><\/td>\n";
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Victims:<\/td>";
+ print "<td BGCOLOR=\"#EEEEEE\"><b>$pl_fe_victims<\/b><\/td>\n";
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Suicides:<\/td>";
+ print "<td BGCOLOR=\"#EEEEEE\"><b>$pl_fe_suicides<\/b><\/td>\n";
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Skill:<\/td>";
+ print "<td BGCOLOR=\"#EEEEEE\"><b>$pl_fe_skill<\/b><\/td>\n";
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Höchster Skill:<\/td>";
+ print "<td BGCOLOR=\"#EEEEEE\"><b>$pl_skill_top<\/b><\/td>\n";
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Rang:<\/td>";
+ if ($pl_fe_rank != 0) {
+ print "<td BGCOLOR=\"#EEEEEE\"><b>$pl_fe_rank<\/b><\/td>\n";
+ } else {
+ print "<td BGCOLOR=\"#EEEEEE\"><b>-<\/b><\/td>\n";
+ }
+ print "<\/tr>\n";
+
+ print "<tr>\n";
+ print "<td BGCOLOR=\"#CCCCCC\">Zuletzt gespielt:<\/td>";
+ print "<td BGCOLOR=\"#EEEEEE\"><b>$pl_lastseen<\/b><\/td>\n";
+ print "<\/tr>\n";
+
+ print "<\/TABLE><\/UL>\n";
+
+ print "<P> <P>\n";
+ print "<UL><b>Gestern<\/b><br>\n";
+ print "<TABLE border=\"0\">\n";
+ print "<tr>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"100\">Map<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Skill<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">FPH<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Maps gespielt<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Maps gewonnen<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Kills<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Victims<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Suicides<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Zeit (Min)<\/td>\n";
+ print "<\/tr>\n";
+
+ if ($pl_maps_played > 0) {
+
+ print "<tr>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#CCCCCC\">Total<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_skill<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fph<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_maps_played<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_maps_won<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_kills<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_victims<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_suicides<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_time<\/td>\n";
+ print "<\/tr>\n";
+
+ } else {
+
+ print "<tr>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#CCCCCC\">Total<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">-<\/td>\n";
+ print "<\/tr>\n";
+
+ }
+
+ print "<\/TABLE><\/UL>\n";
+
+
+ print "<P> <P>\n";
+ print "<UL><b>Gesamt<\/b><br>\n";
+ print "<TABLE border=\"0\">\n";
+ print "<tr>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"100\">Map<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Skill<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">FPH<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Maps gespielt<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Maps gewonnen<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Kills<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Victims<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Suicides<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#FFFFCC\" WIDTH=\"50\">Zeit (Min)<\/td>\n";
+ print "<\/tr>\n";
+
+
+ print "<tr>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#CCCCCC\">Total<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_skill<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_fph<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_maps_played<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_maps_won<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_kills<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_victims<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_suicides<\/td>\n";
+ print "<td ALIGN=\"CENTER\" BGCOLOR=\"#EEEEEE\">$pl_fe_time<\/td>\n";
+ print "<\/tr>\n";
+
+ print "<\/TABLE><\/UL>\n";
+
+ print "<P> <P>\n";
+ print "<UL>Suche bei <a href=\"http\:\/\/www.theclq.com\/asp\/find.asp\?name=";
+ print make_compatible($pl_name);
+ print "\" TARGET=\"_blank\">The CLQ<\/a><\/ul>\n";
+
+
+} else {
+
+ print "<ul>Es wurde kein Spieler dieses Namens in der Datenbank gefunden.</ul>\n";
+
+}
+
+print "<P><FONT SIZE=\"-2\"><DIV ALIGN=right>Skripting by NDC Code<BR><A href=\"http://www.ndc.sh\" target=\"_top\">www.ndc.sh</A></DIV></FONT><BR>\n";
+
+print '</BODY></HTML>';
+
+
+####### Subroutines #####
+
+sub make_html {
+
+ $input = shift;
+# $input =~ s/&/und/g;
+ $input =~ s/</<\;/g;
+ $input =~ s/>/>\;/g;
+ $input =~ s/"/"\;/g;
+ $input =~ s/\x1c/·/g;
+# $input =~ s/\|/pipe/g;
+ return $input;
+}
+
+sub make_compatible {
+
+ $input = shift;
+ $input =~ s/%/%25/g;
+ $input =~ s/\+/%2B/g;
+ $input =~ s/ /+/g;
+ $input =~ s/,/%2C/g;
+ $input =~ s/</%3C/g;
+ $input =~ s/>/%3E/g;
+ $input =~ s/#/%23/g;
+ $input =~ s/\[/%5B/g;
+ $input =~ s/\]/%5D/g;
+ $input =~ s/\//%2F/g;
+ $input =~ s/\|/%7C/g;
+ $input =~ s/\?/%3F/g;
+ $input =~ s/\x1c/%1C/g;
+
+ return $input;
+}
+
--- /dev/null
+# --------------------------------------------------------
+#
+# Table structure for table 'PlayerStats'
+# CREATE TABLE PlayerStats (
+ Nick varchar(30) NOT NULL,
+ Email varchar(60),
+ Picture varchar(50) NOT NULL,
+ Homepage varchar(100),
+ Skill float(10,3) DEFAULT '0.000' NOT NULL,
+ Skill_top float(10,3) DEFAULT '0.000' NOT NULL,
+ Kills int(11) DEFAULT '0' NOT NULL,
+ Victims int(11) DEFAULT '0' NOT NULL,
+ Suicides int(11) DEFAULT '0' NOT NULL,
+ MapsPlayed int(11) DEFAULT '0' NOT NULL,
+ MapsWon int(11) DEFAULT '0' NOT NULL,
+ Time int(11) DEFAULT '0' NOT NULL,
+ FPH float(10,2) DEFAULT '0.00' NOT NULL,
+ fe_Skill float(10,3) DEFAULT '0.000' NOT NULL,
+ fe_Kills int(11) DEFAULT '0' NOT NULL,
+ fe_Victims int(11) DEFAULT '0' NOT NULL,
+ fe_Suicides int(11) DEFAULT '0' NOT NULL,
+ fe_MapsPlayed int(11) DEFAULT '0' NOT NULL,
+ fe_MapsWon int(11) DEFAULT '0' NOT NULL,
+ fe_Time int(11) DEFAULT '0' NOT NULL,
+ fe_FPH float(10,2) DEFAULT '0.00' NOT NULL,
+ fe_rank int(11) DEFAULT '0' NOT NULL,
+ LastSeen date DEFAULT '0000-00-00' NOT NULL,
+ PRIMARY KEY (Nick)
+);