<?php
/**
 *    This file is part of "Liberty Gaming NQ Stats Analyzer".
 *
 *    "Liberty Gaming NQ Stats Analyzer" 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 3 of the License, or
 *    (at your option) any later version.
 *
 *    "Liberty Gaming NQ Stats Analyzer" 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, see <http://www.gnu.org/licenses/>.
 */

/**
 * Class PCPIN_PlayerData
 * Manage player (client) data
 * @author Konstantin Reznichak <k.reznichak@pcpin.com>
 * @copyright Copyright &copy; 2007, Konstantin Reznichak
 */
class PCPIN_PlayerData {

  /**
   * GUID
   * @var string
   */
  var $guid='';

  /**
   * Net name
   * @var string
   */
  var $name='';

  /**
   * Disguised name
   * @var string
   */
  var $disguise_name='';

  /**
   * Current team
   *    1: Axis
   *    2: Allies
   *    3: Spectator
   * @var int
   */
  var $team=-1;

  /**
   * Current class
   *    0: Soldier
   *    1: Medic
   *    2: Engineer
   *    3: Field ops
   *    4: Covert ops
   * @var int
   */
  var $class=-1;

  /**
   * Current class timer
   * @var int
   */
  var $class_timer=0;

  /**
   * Total time spent playing different classes in a different teams
   * @var array
   */
  var $team_class_timers=array();

  /**
   * Used names
   * @var array
   */
  var $used_names=array();

  /**
   * Killed enemies
   *  array ( <team> => array ( <class> => array ( <victim_guid> => array ( <mod> => <kills_count> ) ) ) )
   * @var array
   */
  var $killed_enemies=array();

  /**
   * Killed teammates
   *  array ( <team> => array ( <class> => array ( <victim_guid> => array ( <mod> => <kills_count> ) ) ) )
   * @var array
   */
  var $killed_teammates=array();

  /**
   * Killed by enemies
   *  array ( <team> => array ( <killer_guid> => array ( <mod> => <kills_count> ) ) )
   * @var array
   */
  var $killed_by_enemies=array();

  /**
   * Killed by teammates
   *  array ( <team> => array ( <killer_guid> => array ( <mod> => <kills_count> ) ) )
   * @var array
   */
  var $killed_by_teammates=array();

  /**
   * Deaths received from the world (for example, player was crushed)
   *  array ( <team> => array ( <mod> => <deaths_count> ) )
   * @var array
   */
  var $world_deaths=array();

  /**
   * Suicides
   *  array ( <team> => array ( <mod> => <suicides_count> ) )
   * @var array
   */
  var $suicides=array();

  /**
   * Revives made by player
   *  array ( <team> => array ( <guid> => <revives_count> ) )
   * @var array
   */
  var $revives=array();

  /**
   * Health packs given
   *  array ( <team> => array ( <guid> => <packs_count> ) )
   * @var array
   */
  var $health_given=array();

  /**
   * Ammo packs given
   *  array ( <team> => array ( <guid> => <packs_count> ) )
   * @var array
   */
  var $ammo_given=array();

  /**
   * Health packs taken count
   * @var int
   */
  var $health_taken_count=0;

  /**
   * Ammo packs taken count
   * @var int
   */
  var $ammo_taken_count=0;

  /**
   * Dynamite plants
   *  array ( <team> => <count> )
   * @var array
   */
  var $dynamite_plant=array();

  /**
   * Dynamite diffuses
   *  array ( <team> => <count> )
   * @var array
   */
  var $dynamite_diffuse=array();

  /**
   * Repair
   *  array ( <team> => <count> )
   * @var array
   */
  var $repairs=array();

  /**
   * Disguises
   *  array ( <team> => <count> )
   * @var array
   */
  var $disguises=array();

  /**
   * Taken objectives
   *  array ( <team> => <count> )
   * @var array
   */
  var $objectives_taken=array();

  /**
   * Score (XP)
   * @var int
   */
  var $score=0;

  /**
   * Ping (ms)
   * @var int
   */
  var $ping=0;

  /**
   * Flag: "y" if player did first kill in match, "n" otherwize
   * @var string
   */
  var $first_kill='n';

  /**
   * Flag: "y" if player had first dead in match, "n" otherwize
   * @var string
   */
  var $first_death='n';

  /**
   * Kill sprees count (5 or more kills)
   * @var int
   */
  var $kill_sprees=0;

  /**
   * Longest kill spree
   * @var int
   */
  var $longest_kill_spree=0;

  /**
   * Death sprees count (10 or more deaths)
   * @var int
   */
  var $death_sprees=0;

  /**
   * Longest death spree
   * @var int
   */
  var $longest_death_spree=0;

  /**
   * Current kill spree (reseted if client dies)
   * @var int
   */
  var $current_kill_spree=0;

  /**
   * Current death spree (reseted if client kill someone)
   * @var int
   */
  var $current_death_spree=0;

  /**
   * Total bounties count
   * @var int
   */
  var $bounties=0;

  /**
   * Killed with engineer-only weapons enemies count
   * @var int
   */
  var $engineer_kills=0;

  /**
   * Killed with fieldops-only weapons enemies count
   * @var int
   */
  var $fieldops_kills=0;

  /**
   * Killed with covertops-only weapons enemies count
   * @var int
   */
  var $covertops_kills=0;



  /**
   * Constructor
   */
  function PCPIN_PlayerData() { }


  /**
   * Reset stats
   * @param   int   $time   Current game timer
   */
  function resetStats($time) {
    // Team/class timers
    $team=$this->team;
    $class=$this->class;
    $this->team=-1;
    $this->class=-1;
    $this->class_timer=0;
    $this->team_class_timers=array();
    $this->toggleTeamClassTimer($team, $class, $time);

    // Reset kill/death stats
    $this->killed_enemies=array();
    $this->killed_teammates=array();
    $this->killed_by_enemies=array();
    $this->killed_by_teammates=array();
    $this->world_deaths=array();
    $this->suicides=array();
    $this->engineer_kills=0;
    $this->fieldops_kills=0;
    $this->covertops_kills=0;

    // Revives stats
    $this->revives=array();

    // Health/Ammo pack stats
    $this->health_given=array();
    $this->ammo_given=array();
    $this->health_taken_count=0;
    $this->ammo_taken_count=0;

    // Dynamite plant/diffuse and repair stats
    $this->dynamite_plant=array();
    $this->dynamite_diffuse=array();
    $this->repairs=array();

    // Disguises
    $this->disguises=array();
    $this->disguise_name='';

    // Objectives taken
    $this->objectives_taken=array();

    // Score (XP)
    $this->score=0;

    // Ping in ms
    $this->ping=0;

    // First kill/victim
    $this->first_kill='n';
    $this->first_death='n';

    // Kill/death sprees
    $this->kill_sprees=0;
    $this->longest_kill_spree=0;
    $this->death_sprees=0;
    $this->longest_death_spree=0;
    $this->current_kill_spree=0;
    $this->current_death_spree=0;

    // Bounties
    $this->bounties=0;

  }


  /**
   * Parse ClientUserinfoChanged record
   * @param   string    $guid     GUID
   * @param   string    $ui       ClientUserinfoChanged record
   * @param   int       $time     Current game time
   */
  function ClientUserinfoChanged($guid, $ui, $time) {
    $this->guid=$guid;
    $parts=explode('\\', $ui);
    $parts_num=count($parts);

    $new_team=3;
    $new_class=0;
    for ($i=0; $i<$parts_num; $i+=2) {
      switch ($parts[$i]) {

        case 'n':
          // Net name
          $this->name=$parts[$i+1];
          if (!in_array($this->name, $this->used_names)) {
            $this->used_names[]=$this->name;
          }
        break;

        case 't':
          $new_team=$parts[$i+1];
        break;

        case 'c':
          $new_class=$parts[$i+1];
        break;

        case 'dn':
          if ($this->disguise_name!=$parts[$i+1]) {
            $this->disguise_name=$parts[$i+1];
            if ($this->disguise_name!='') {
              if (!isset($this->disguises[$this->team])) {
                $this->disguises[$this->team]=0;
              }
              $this->disguises[$this->team]++;
            }
          }
        break;

      }
    }
    $this->toggleTeamClassTimer($new_team, $new_class, $time);
    return true;
  }


  /**
   * Start/stop team/class timer
   * @param   int   $team     Team
   * @param   int   $class    Class
   * @param   int   $time     Current game time
   */
  function toggleTeamClassTimer($team, $class, $time) {
    // Store old team/class timer
    if (isset($this->team_class_timers[$this->team][$this->class])) {
      $this->team_class_timers[$this->team][$this->class]+=$time-$this->class_timer;
    }
    // Create new team/class timer
    if ($team>=0 && $class>=0) {
      if (!isset($this->team_class_timers[$team][$class])) {
        $this->team_class_timers[$team][$class]=0;
      }
      // Start new timer
      $this->class_timer=$time;
      // Set new team and class
      $this->team=$team;
      $this->class=$class;
    }
  }


  /**
   * Client killed someone
   * @param   int     $victim_guid    Victim GUID
   * @param   int     $victim_team    Victim team
   * @param   string  $mod            Mean of death
   */
  function madeKill($victim_guid, $victim_team, $mod) {
    if ($this->team!=$victim_team) {
      // Enemy
      if (!isset($this->killed_enemies[$this->team])) {
        $this->killed_enemies[$this->team]=array();
      }
      if (!isset($this->killed_enemies[$this->team][$this->class])) {
        $this->killed_enemies[$this->team][$this->class]=array();
      }
      if (!isset($this->killed_enemies[$this->team][$this->class][$victim_guid])) {
        $this->killed_enemies[$this->team][$this->class][$victim_guid]=array();
      }
      if (!isset($this->killed_enemies[$this->team][$this->class][$victim_guid][$mod])) {
        $this->killed_enemies[$this->team][$this->class][$victim_guid][$mod]=0;
      }
      $this->killed_enemies[$this->team][$this->class][$victim_guid][$mod]++;
      $this->deathSpreeEnded();
      $this->current_kill_spree++;
      if (   $this->class==2 &&
             $mod=='MOD_CRUSH_CONSTRUCTION'
          || $mod=='MOD_CRUSH_CONSTRUCTIONDEATH'
          || $mod=='MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER'
          || $mod=='MOD_CARBINE'
          || $mod=='MOD_M7'
          || $mod=='MOD_DYNAMITE'
          || $mod=='MOD_LANDMINE'
          || $mod=='MOD_TRIPMINE'
          ) {
        // Engineer kill
        $this->engineer_kills++;
      } elseif (   $this->class==3 &&
                   $mod=='MOD_SMOKEBOMB'
                || $mod=='MOD_ARTY'
                || $mod=='MOD_AIRSTRIKE'
                ) {
        // Field op kill
        $this->fieldops_kills++;
      } elseif (   $this->class==4 &&
                   $mod=='MOD_SATCHEL'
                || $mod=='MOD_FG42'
                || $mod=='MOD_FG42_SCOPE'
                || $mod=='MOD_GARAND'
                || $mod=='MOD_GARAND_SCOPE'
                || $mod=='MOD_K43'
                || $mod=='MOD_K43_SCOPE'
                || $mod=='MOD_STEN'
                || $mod=='MOD_STEN_MKII'
                ) {
        // Covert op kill
        $this->covertops_kills++;
      }
    } else {
      // Teammate
      if (!isset($this->killed_teammates[$this->team])) {
        $this->killed_teammates[$this->team]=array();
      }
      if (!isset($this->killed_teammates[$this->team][$this->class])) {
        $this->killed_teammates[$this->team][$this->class]=array();
      }
      if (!isset($this->killed_teammates[$this->team][$this->class][$victim_guid])) {
        $this->killed_teammates[$this->team][$this->class][$victim_guid]=array();
      }
      if (!isset($this->killed_teammates[$this->team][$this->class][$victim_guid][$mod])) {
        $this->killed_teammates[$this->team][$this->class][$victim_guid][$mod]=0;
      }
      $this->killed_teammates[$this->team][$this->class][$victim_guid][$mod]++;
    }
  }


  /**
   * Client was killed by enemy or teammate
   * @param   int     $killer_guid    Killer GUID
   * @param   int     $killer_team    Killer team
   * @param   string  $mod            Mean of death
   */
  function gotKilled($killer_guid, $killer_team, $mod) {
    if ($this->team!=$killer_team) {
      // Enemy
      if (!isset($this->killed_by_enemies[$this->team])) {
        $this->killed_by_enemies[$this->team]=array();
      }
      if (!isset($this->killed_by_enemies[$this->team][$killer_guid])) {
        $this->killed_by_enemies[$this->team][$killer_guid]=array();
      }
      if (!isset($this->killed_by_enemies[$this->team][$killer_guid][$mod])) {
        $this->killed_by_enemies[$this->team][$killer_guid][$mod]=0;
      }
      $this->killed_by_enemies[$this->team][$killer_guid][$mod]++;
    } else {
      // Teammate
      if (!isset($this->killed_by_teammates[$this->team])) {
        $this->killed_by_teammates[$this->team]=array();
      }
      if (!isset($this->killed_by_teammates[$this->team][$killer_guid])) {
        $this->killed_by_teammates[$this->team][$killer_guid]=array();
      }
      if (!isset($this->killed_by_teammates[$this->team][$killer_guid][$mod])) {
        $this->killed_by_teammates[$this->team][$killer_guid][$mod]=0;
      }
      $this->killed_by_teammates[$this->team][$killer_guid][$mod]++;
    }
    $this->killSpreeEnded();
    $this->current_death_spree++;
  }


  /**
   * Client commited suicide
   * @param   string  $mod            Mean of death
   */
  function madeSuicide($mod) {
    if (!isset($this->suicides[$this->team])) {
      $this->suicides[$this->team]=array();
    }
    if (!isset($this->suicides[$this->team][$mod])) {
      $this->suicides[$this->team][$mod]=0;
    }
    $this->suicides[$this->team][$mod]++;
    $this->killSpreeEnded();
    $this->current_death_spree++;
  }


  /**
   * Client was killed by world (for example, was crushed)
   * @param   string  $mod            Mean of death
   */
  function worldDeath($mod) {
    if (!isset($this->world_deaths[$this->team])) {
      $this->world_deaths[$this->team]=array();
    }
    if (!isset($this->world_deaths[$this->team][$mod])) {
      $this->world_deaths[$this->team][$mod]=0;
    }
    $this->world_deaths[$this->team][$mod]++;
    $this->killSpreeEnded();
    $this->current_death_spree++;
  }


  /**
   * Player revived someone
   * @param   string    $guid   GUID of revived player
   */
  function didRevive($guid) {
    if (!isset($this->revives[$this->team])) {
      $this->revives[$this->team]=array();
    }
    if (!isset($this->revives[$this->team][$guid])) {
      $this->revives[$this->team][$guid]=0;
    }
    $this->revives[$this->team][$guid]++;
  }


  /**
   * Player gave health pack to someone
   * @param   string    $guid   GUID of health pack receiver
   */
  function gaveHealthPack($guid) {
    if (!isset($this->health_given[$this->team])) {
      $this->health_given[$this->team]=array();
    }
    if (!isset($this->health_given[$this->team][$guid])) {
      $this->health_given[$this->team][$guid]=0;
    }
    $this->health_given[$this->team][$guid]++;
  }


  /**
   * Player gave ammo pack to someone
   * @param   string    $guid   GUID of health pack receiver
   */
  function gaveAmmoPack($guid) {
    if (!isset($this->ammo_given[$this->team])) {
      $this->ammo_given[$this->team]=array();
    }
    if (!isset($this->ammo_given[$this->team][$guid])) {
      $this->ammo_given[$this->team][$guid]=0;
    }
    $this->ammo_given[$this->team][$guid]++;
  }


  /**
   * Player planted a dynamite
   */
  function dynamitePlant() {
    if (!isset($this->dynamite_plant[$this->team])) {
      $this->dynamite_plant[$this->team]=0;
    }
    $this->dynamite_plant[$this->team]++;
  }


  /**
   * Player diffused a dynamite
   */
  function dynamiteDifuse() {
    if (!isset($this->dynamite_diffuse[$this->team])) {
      $this->dynamite_diffuse[$this->team]=0;
    }
    $this->dynamite_diffuse[$this->team]++;
  }


  /**
   * Player repaired something
   */
  function madeRepair() {
    if (!isset($this->repairs[$this->team])) {
      $this->repairs[$this->team]=0;
    }
    $this->repairs[$this->team]++;
  }


  /**
   * Player have taken objectives
   */
  function tookObjectives() {
    if (!isset($this->objectives_taken[$this->team])) {
      $this->objectives_taken[$this->team]=0;
    }
    $this->objectives_taken[$this->team]++;
  }


  /**
   * Player have taken health pack
   */
  function tookHealth() {
    $this->health_taken_count++;
  }


  /**
   * Player have taken ammo pack
   */
  function tookAmmo() {
    $this->ammo_taken_count++;
  }


  /**
   * Set score (XP)
   * @param   int   $score    Score
   */
  function setScore($score) {
    $this->score=$score;
  }


  /**
   * Set ping
   * @param   int   $ping   Ping in ms
   */
  function setPing($ping) {
    $this->ping=$ping;
  }


  /**
   * Set "first kill" award
   */
  function setFirstKillAward() {
    $this->first_kill='y';
  }


  /**
   * Set "first death" award
   */
  function setFirstDeathAward() {
    $this->first_death='y';
  }


  /**
   * Stop "kill spree" counter
   */
  function killSpreeEnded() {
    if ($this->current_kill_spree>=5) {
      $this->kill_sprees++;
      if ($this->current_kill_spree>$this->longest_kill_spree) {
        $this->longest_kill_spree=$this->current_kill_spree;
      }
    }
    $this->current_kill_spree=0;
  }


  /**
   * Stop "death spree" counter
   */
  function deathSpreeEnded() {
    if ($this->current_death_spree>=10) {
      $this->death_sprees++;
      if ($this->current_death_spree>$this->longest_death_spree) {
        $this->longest_death_spree=$this->current_death_spree;
      }
    }
    $this->current_death_spree=0;
  }


  /**
   * Increase bounties counter
   * @param   int   $increment    Increment
   */
  function addBounties($increment) {
    if ($increment>0) {
      $this->bounties+=$increment;
    }
  }


}
?>