<?

// 22.11.2006

class logparser {
   public $procid;
   public $round;
   public $warmup;
   public $running;
   public $readyplayers;
   public $starttime;
   public $connected;
   public $recording;
   public $recorddir;
   public $statusmode = false;
   public $queuestatus = 0;
   public $laststatus = 0;
   public $viewers;
   public $lastbanner = 0;
   public $gamename = "Unknown";
   public $pausetime = 0;
   public $numplayers = -1;
   public $playerstartnum = -1;
   public $lasterror = "Unknown";
   public $source = "";
   public $reportsocket = false;
   public $defunct = false;

   function checknick($id, $nick) {
      if(strtolower($nick) == "etplayer") {
         $this->send("qsay \"Kicked '$nick' (Slot $id) - Nickname not allowed\"");
         $this->send("clientkick $id");
         debug("Kicked ETPlayer");
         return false;
      }
      elseif(strtolower($nick) == "unnamedplayer") {
         $this->send("qsay \"Kicked '$nick' (Slot $id) - Nickname not allowed\"");
         $this->send("clientkick $id");
         debug("Kicked UnnamedPlayer");
         return false;
      }
      elseif(strtolower($nick) == "default") {
         $this->send("qsay \"Kicked '$nick' (Slot $id) - Nickname not allowed\"");
         $this->send("clientkick $id");
         debug("Kicked default");
         return false;
      }
      else {
         return true;
      }
   }

   function status() {
      $status = proc_get_status($this->proc);
      return $status['running'];
   }

   function queuebanner($text, $pos = "") {
      if(time() - $this->lastbanner < 2) {
         $this->lastbanner += 2;
         addtimer($this->lastbanner, "if(\$procs[$this->procid]) \$procs[$this->procid]->sendbanner('".addslashes($text)."', '$pos');");
      }
      else {
         $this->sendbanner($text, $pos);
         $this->lastbanner = time();
      }
   }

   function sendbanner($text, $pos) {
      global $pipes;
      if($pos == "left") {
         $pieces = explode("\n", $text);
         $text = "";
         foreach($pieces as $line) {
            $text .= str_pad($line, 81) . str_repeat(" ",substr_count($line, "^") * 2);
         }
      }
      elseif($pos == "right") {
         $pieces = explode("\n", $text);
         $text = "";
         foreach($pieces as $line) {
            $colourspace = strlen($line) - strlen(ereg_replace("\^[^\^]", "", $line));
            $text .= " ^7" . str_repeat(" ", $colourspace) . str_pad($line, 80, " ", STR_PAD_LEFT);
         }
      }
      fwrite($pipes['stdin'][$this->procid], "bp \"$text\"\n");
   }

   function send($txt) {
      global $pipes;
      $txt = trim($txt);
      fwrite($pipes['stdin'][$this->procid], "$txt\n");
   }

   function sendat($txt, $time) {
      addtimer($time, "if(\$procs[$this->procid]) \$procs[$this->procid]->send('".addslashes($txt)."');");
   }

   function unmute($uid) {
      $vid = -1;
      foreach($this->viewers AS $id => $viewer) {
         if($viewer['uid'] == $uid) {
            $vid = $id;
            break;
         }
      }
      if($vid > -1) {
         $this->send("unmute $vid");
         debug("Unmuted ".$this->viewers[$vid]['nick']."\n");
      }
   }

   function log($line) {
      fputs($this->logfile, $line . "\n");
      $line = trim(preg_replace('/\s\s+/', ' ', $line));
      @list($first, $second, $third) = $pieces = explode(" ", $line);
      @list($last, $secondlast, $thirdlast) = $backpieces = array_reverse($pieces);
      @list($fract, $chatid) = explode(":", $first);
      if($first == "ettv_CL_InitTVGame:") {
         $this->gameinit();
      }
      elseif("$first $second $third" == "Opening IP socket:") {
         list($ip, $port) = explode(":", $pieces[3]);
         $this->socketbind($ip, $port);
      }
      elseif("$pieces[0] $pieces[1] $pieces[2] $pieces[3] $pieces[4] $pieces[5] " == "broadcast: print \"Server: timelimit changed to ") {
         list($time) = explode('\n', $pieces[6]);
         $this->timelimit($time);
      }
      elseif($first == "Server:") {
         $this->mapchange($second);
      }
      elseif($first == "cpm") {
         if($last == "connected") {
            if($this->numplayers != -1) {
               $this->numplayers++;
               $this->playercount();
            }
         }
         elseif($last == "disconnected") {
            if($this->numplayers != -1) {
               $this->numplayers--;
               $this->playercount();
            }
         }
         elseif(substr($line, -1, 1) == '"' && strpos($line, "PunkBuster") === false) {
            list(,$event) = explode("\"", $line);
            $event = ereg_replace("\^.", "", $event);
            $this->mapevent($event);
         }
      }
      elseif("$pieces[0] $pieces[1] $pieces[2] $pieces[3]" == "------- Game Initialization -------") {
         $this->mapstart();
      }
      elseif($first == "broadcast:") {
         if($last == 'ready!\n"') {
            if($secondlast == "NOT") {
               $this->oneunready();
            }
            else {
               $this->oneready();
            }
         }
         elseif("$pieces[1] $pieces[2] $pieces[3]" == 'print "^3Match is') {
            $this->pausestart();
         }
         elseif("$pieces[1] $pieces[2] $pieces[3]" == 'print "^3Referee ^1PAUSED^3') {
            $this->pausestart();
         }
         elseif("$pieces[1] $pieces[2] $pieces[3]" == 'print "\n^3Match ^5UNPAUSED^3') {
            $this->pauseend();
         }
         elseif("$pieces[1] $pieces[2] $pieces[3]" == 'print "\n^3Referee ^5UNPAUSES^3') {
            $this->pauseend();
         }
      }
      elseif($fract == "ETTV" && isset($chatid)) {
         list(,,$nickchat) = explode(" ", $line, 3);
         list($nick, $chat) = explode(": ", $nickchat, 2);
         if(!$chat) {
            $nick = substr($nick, 0, -1);
         }
         $nick = trim($nick);
         $this->ettvchat($chatid, $nick, $chat);
      }
      elseif($line == "ettv: demo completed") {
         $this->demodone();
      }
      elseif($line == "ettv: Need an <ettv_password>") {
         $this->lasterror = "Missing ettvpass";
         debug("[$this->type$this->num] $this->lasterror");
      }
      elseif($line == "master must set an ettv_password.") {
         $this->lasterror = "Master has to set ettv_password";
         debug("[$this->type$this->num] $this->lasterror");
      }
      elseif($line == "Invalid master password") {
         $this->lasterror = "Invalid ettvpw";
      }
      elseif($line == "Invalid password") {
         $this->lasterror = "Invalid gpw";
      }
      elseif($line == "ettv: Bad master server address") {
         $this->lasterror = "invalid server ip";
      }
      elseif($line == "Server is full.") {
         $this->lasterror = $line;
      }
      elseif("$pieces[0] $pieces[1]" == "Need paks:") {
         $this->lasterror = "Missing: $pieces[2]";
         debug("[$this->type$this->num] $this->lasterror");
      }
      elseif("$pieces[0] $pieces[1] $pieces[2]" == "ettv: recording to") {
         $this->werecord(substr(end(explode("/",$pieces[3])), 0, -7));
      }
      elseif("$pieces[0] $pieces[1] $pieces[2] $pieces[3] $pieces[4]" == "Idle Server with no map") {
         $this->watchdog();
      }
      elseif("$pieces[0] $pieces[1] $pieces[2] $pieces[3]" == "WARNING: watchdog will trigger") {
         $this->prewatchdog();
      }
      elseif($first == "ClientConnect:") {
         $this->viewerconnect($second);
      }
      elseif($first == "ClientDisconnect:") {
         if(isset($this->viewers[$second])) {
            $this->viewerquit($second);
            unset($this->viewers[$second]);
         }
      }
      elseif("$second $third" == "total players") {
         $this->numplayers = intval($first);
         $this->playercount();
      }
      elseif("$pieces[0] $pieces[1] $pieces[2] $pieces[3]" == "num score ping name") {
         $this->statusstart();
      }
      elseif("$pieces[0] $pieces[1] $pieces[2] $pieces[3]" == "--- ----- ---- ---------------") {
         // ignore
      }
      elseif($this->statusmode && strpos($thirdlast, ":") !== false) {
         $id   = $first;
         $xp   = $second;
         $ping = $third;
         list($ip) = explode(":", $thirdlast);
         $spcnt = substr_count($line, ' ') - 7;
         $nick = "";
         for($prt = 3; $prt <= 3 + $spcnt; $prt++) {
            $nick .= $pieces[$prt]." ";
         }
         $nick = trim($nick);
         if($nick != "" && is_numeric($ping)) {
            if(!isset($this->viewers[$id])) {
               $this->viewers[$id] = array("nick" => $nick, "ip" => $ip);
               $this->viewerconnectinfo($id);
            }
            else {
               if($nick != $this->viewers[$id]['nick']) {
                  $this->updatenicks($id, $nick);
               }
            }
         }
      }
      else {
         if($this->statusmode) {
            $this->statusmode = false;
            $this->laststatus = time();
            $this->queuestatus = false;
         }
         // debug(":> $line\n");
      }
   }

   function gameinit() {
      debug("[$this->type$this->num] Game init complete\n");
      $this->connected = true;
      if($this->reportsocket) {
         if($this->type == "recorder") {
            fputs($this->reportsocket, "123 $this->num - Recorder $this->num connected successfully\n\r");
         }
         elseif($this->type == "replayer") {
            fputs($this->reportsocket, "124 $this->num - Replayer $this->num started at $this->ip:$this->port\n\r");
         }
         $this->reportsocket = false;
      }
   }
   function socketbind($ip, $port) {
      debug("[$this->type$this->num] Server started at port $port\n");
      $this->port = $port;
      $this->ip = $ip;
   }
   function timelimit($time) {
      debug("[$this->type$this->num] Timelimit is now $time\n");
      if(strpos($time, ".") !== false) {
         debug("[$this->type$this->num] Second round started\n");
         $this->round = 2;
      }
      else {
         debug("[$this->type$this->num] We're in a first round\n");
         $this->round = 1;
      }
   }
   function mapchange($map) {
      debug("[$this->type$this->num] Map changed to $map\n");
      $this->round = 1;
      $this->warmup = 0;
      $this->starttime = 0;
      $this->pausetime = 0;
      $this->numplayers = -1;
      $this->send("players");
      $this->connected = true;
   }
   function mapevent($event) {
      // debug("[$this->type$this->num] Objective reached: $event\n");
   }
   function mapstart() {
      debug("[$this->type$this->num] Map started\n");
      if($this->warmup == 1) {
         $this->warmup = 0;
         $this->roundstart();
         if($this->round == 1) {
            $this->events = array();  // <-- unsauber
         }
         $this->starttime = time();
         $this->pausetime = 0;
      }
      $this->readyplayers = 0;
   }
   function oneready() {
      if($this->warmup == 0) {
         $this->warmupstart();
      }
      $this->readyplayers++;
      debug("[$this->type$this->num] $this->readyplayers players ready\n");
   }

   function warmupstart() {
      debug("[$this->type$this->num] We're in warmup\n");
      $this->warmup = 1;
      $this->starttime = 0;
   }

   function oneunready() {
      $this->readyplayers--;
      debug("[$this->type$this->num] $this->readyplayers players ready\n");
   }
   function ettvchat($id, $nick, $chat) {
      if($this->viewers[$id]['nick'] != $nick && strpos($chat, ": ") === false && isset($this->viewers[$id])) {
         $this->updatenicks($id, $nick);
      }
   }
   function demodone() {
      debug("[$this->type$this->num] demo finished\n");
   }
   function werecord($demo) {
      debug("[$this->type$this->num] Recording started to $demo in $this->recorddir\n");
      $this->recording = true;
   }
   function watchdog() {
      debug("[$this->type$this->num] Watchdog triggered\n");
      $this->numplayers = -1;
      $this->connected = false;
      $this->playercount();
   }
   function prewatchdog() {
      if($this->reportsocket) {  // If watchdog triggers right after starting the server its not good, kill it
         if($this->type == "recorder") {
            fputs($this->reportsocket, "423 $this->num - Recorder $this->num could not start - Error: $this->lasterror\n\r");
         }
         elseif($this->type == "replayer") {
            fputs($this->reportsocket, "424 $this->num - Replayer $this->num could not start - Error: $this->lasterror\n\r");
         }
         $this->reportsocket = false;
         $this->shutdown();
      }
   }
   function viewerconnect($slot) {
      // debug("[$this->type$this->num] A viewer connected on slot $slot\n");
   }
   function statusstart() {
      $this->statusmode = true;
   }
   function viewerquit($id) {
      debug("[$this->type$this->num] Quit ".$this->viewers[$id]['nick']." Slot: $id\n");
   }

   function pausestart() {
      $this->pausestart = time();
      debug("[$this->type$this->num] The match is paused\n");
   }
   function pauseend() {
      $this->pausetime += (time() - $this->pausestart) + 10;
      $this->pausestart = 0;
      debug("[$this->type$this->num] The match is resumed, total pausetime: $this->pausetime\n");
   }
   function playercount() {
      // debug("[$this->type$this->num] Now $this->numplayers Players");
   }
   function roundstart() {
      $this->playerstartnum = $this->numplayers;
      debug("[$this->type$this->num] Round has started with $this->playerstartnum Players\n");
   }

}