?>
<dt>Players:</dt>
    <dd><?php 
        echo $game->players;
        ?>
<br /></dd>
    
    <dt>Score:</dt>
    <dd><?php 
        echo $game->score;
        ?>
<br /></dd>
    
<?php 
        if ($game->waves > 0) {
            list($bonus_rounds, $set_reached, $round_reached, $wave_reached) = ODSTGame::wave_position($game->waves);
            ?>
    <dt>Total Waves:</dt>
    <dd><?php 
            echo $game->waves;
            ?>
<br /></dd>
    
    <dt>Bonus Rounds:</dt>
    <dd><?php 
            echo $bonus_rounds;
            ?>
<br /></dd>
    
    <dt>Set Reached:</dt>
    <dd><?php 
 function load_game()
 {
     // Grab the GameDetail Result for simplexml
     if (is_null($this->xml_data->getElementsByTagName('GetGameDetailResult')->item(0))) {
         // Couldn't find response
         $this->error_details[0] = -1;
         $this->error_details[1] = 'Internal Parser Error';
         $this->error = true;
         return;
     }
     $xml = simplexml_import_dom($this->xml_data->getElementsByTagName('GetGameDetailResult')->item(0));
     // Error Handling
     $this->error_details[0] = (int) $xml->status;
     $this->error_details[1] = (string) $xml->reason;
     if ($this->error_details[0] != 7777) {
         $this->error = true;
         return;
     }
     // Get game data
     $game_data = $xml->children('a', true)->children('b', true);
     // General Information
     $this->difficulty = (int) $game_data->Difficulty;
     $this->duration = (int) $game_data->Duration;
     $this->map = (string) $game_data->MapName;
     $this->time_bonus = (double) $game_data->TimeBonus;
     // Date/Time
     $this->datetime = new DateTime($game_data->GameDate, new DateTimeZone('America/Los_Angeles'));
     // Scoring
     if ($game_data->IsScoreEnabled == 'true') {
         $this->scoring_enabled = true;
     }
     // Players
     foreach ($game_data->GamePlayers->children('b', true) as $player) {
         $player_info = new ODSTPlayer();
         $player_info->id = (int) $player->DataIndex;
         $player_info->ghost = false;
         // Player was given to us
         $player_info->gamertag = rtrim((string) $player->Gamertag);
         $player_info->service_tag = (string) $player->ServiceTag;
         $player_info->armor_flags = unpack('C*', base64_decode((string) $player->ArmorFlags));
         $player_info->armor_type = (int) $player->ArmorType;
         $player_info->emblem_colors = unpack('C*', base64_decode((string) $player->EmblemColors));
         $player_info->emblem_flags = unpack('C*', base64_decode((string) $player->EmblemFlags));
         if ($this->scoring_enabled === true) {
             $player_info->score = 0;
         }
         $this->players[$player_info->id] = $player_info;
     }
     // Skulls
     if ($game_data->InitialPrimarySkulls != '') {
         $this->skulls_primary_start = explode(' ', $game_data->InitialPrimarySkulls);
     }
     if ($game_data->InitialSecondarySkulls != '') {
         $this->skulls_secondary_start = explode(' ', $game_data->InitialSecondarySkulls);
     }
     // Firefight
     if ($game_data->IsSurvival == 'true') {
         $this->firefight = true;
         // Calculate Set, Round, Wave reached and number of Bonus Rounds
         $this->total_waves = (int) $game_data->Waves;
         list($this->bonus_rounds, $this->set_reached, $this->round_reached, $this->wave_reached) = ODSTGame::wave_position((int) $game_data->Waves);
         // Initialize Wave Stats
         $a = 1;
         foreach ($game_data->GameWaves->children('b', true) as $wave) {
             $this->wave_stats[$a] = new ODSTFirefightWave();
             $this->wave_stats[$a]->id = $a;
             if ($this->scoring_enabled) {
                 $this->wave_stats[$a]->score = 0;
             }
             $this->wave_stats[$a]->start = $wave->STR;
             if ($a > 1) {
                 $this->wave_stats[$a - 1]->length = $wave->STR - $this->wave_stats[$a - 1]->start;
                 $this->wave_stats[$a - 1]->end = $this->wave_stats[$a - 1]->start + $this->wave_stats[$a - 1]->length;
             }
             ++$a;
         }
         $this->wave_stats[$a - 1]->end = $this->duration;
         $this->wave_stats[$a - 1]->length = $this->wave_stats[$a - 1]->end - $this->wave_stats[$a - 1]->start;
     } else {
         // Reset revert count
         $this->reverts = 0;
     }
     // Process game events
     //
     // Score is calculated per player, then the score from the players is
     // added up and returned as the total score. This is done to properly
     // track the scores (players' scores start at 0 and can't be negative,
     // hence why they are tracked individually).
     //
     // Event variable keys:
     // ET  - Event Type
     // PC  - Player that caused the event.
     //       -1 means it wasn't caused by a player
     // PE  - Player affected by the event.
     // S   - How much to change the score (up or down depending on the event type).
     // ST  - String information on the event.
     //       For MEDAL events: Stores the medal name.
     //       For KILL/DEATH events: Stores the enemy class.
     // ST2 - Second string information on the event.
     //       For KILL/DEATH events: Stores the enemy name.
     // T   - Time the event occurred.
     // WEP - The weapon involved in the event (if any).
     //
     // PC and PE's different meanings only apply in cases where the
     // distinction between the causing player and the affected player exists
     // (eg Betrayals). Otherwise, PC should be used, and PE if PC is
     // negative.
     foreach ($game_data->GameEvents->children('b', true) as $event) {
         // Start of game event loop
         // Event currently being processed is at $event
         if ($this->firefight) {
             // Find the wave
             foreach ($this->wave_stats as $wave) {
                 if ($event->T < $wave->end) {
                     $current_wave = $wave;
                     break;
                 }
             }
             // Since the wave obviously had an event, mark it as such.
             $current_wave->activity = true;
         }
         // Handle Event depending on the type of event
         switch ($event->ET) {
             case 'REVERT':
                 // The campaign game has been reverted to an
                 // earlier part of the current game.
                 $this->event_revert($event);
                 break;
             case 'DEATH':
                 // A player died
                 if ($this->firefight) {
                     $this->event_death($event, $wave = $current_wave);
                 } else {
                     $this->event_death($event);
                 }
                 break;
             case 'SUICIDE':
                 // A player committed suicide
                 if ($this->firefight) {
                     $this->event_suicide($event, $current_wave);
                 } else {
                     $this->event_suicide($event);
                 }
                 break;
             case 'BETRAYAL':
                 // A player betrayed an ally
                 if ($this->firefight) {
                     $this->event_betrayal($event, false, $current_wave);
                 } else {
                     $this->event_betrayal($event, false);
                 }
                 break;
             case 'AIBETRAYAL':
                 // A player betrayed an AI ally
                 if ($this->firefight) {
                     $this->event_betrayal($event, true, $current_wave);
                 } else {
                     $this->event_betrayal($event, true);
                 }
                 break;
             case 'KILL':
                 // A player killed an enemy
                 if ($this->firefight) {
                     $this->event_kill($event, $current_wave);
                 } else {
                     $this->event_kill($event);
                 }
                 break;
             case 'MEDAL':
                 // A medal was earned
                 if ($this->firefight) {
                     $this->event_medal($event, $current_wave);
                 } else {
                     $this->event_medal($event);
                 }
                 break;
         }
         if ($this->scoring_enabled) {
             // If the score pegs into the negative, set it to zero.
             foreach ($this->players as $player) {
                 if ($player->score < 0) {
                     $player->score = 0;
                 }
             }
         }
         // End of event loop
     }
     // Post event processing score calculations
     if ($this->scoring_enabled) {
         // Handle time bonus
         if ($this->time_bonus > 1.0) {
             foreach ($this->players as $player) {
                 $player->raw_score = (int) $player->score;
                 $player->score = $player->score * $this->time_bonus;
             }
         } else {
             foreach ($this->players as $player) {
                 $player->raw_score = (int) $player->score;
             }
         }
         // Convert scores to integers
         foreach ($this->players as $player) {
             $player->score = (int) $player->score;
         }
         foreach ($this->wave_stats as $wave) {
             $wave->score = (int) $wave->score;
             $wave->raw_score = $wave->score;
         }
         // Calculate the main score
         $this->score = 0;
         $this->raw_score = 0;
         foreach ($this->players as $player) {
             $this->score += $player->score;
             $this->raw_score += $player->raw_score;
         }
     }
     // Calculate medal counts
     foreach ($this->medals as $medal) {
         $this->medal_count += $medal;
     }
     foreach ($this->players as $player) {
         foreach ($player->medals as $medal) {
             $player->medal_count += $medal;
         }
     }
     // Calculate player count
     $this->player_count = count($this->players);
 }
  </div>
  
  <p>Processing...<tt><?php 
$use_metadata = false;
if ($_GET['gameid'] == '') {
    trigger_error('No Game ID given', E_USER_ERROR);
}
if (array_key_exists('use_metadata', $_GET) and $_GET['use_metadata'] == 'true') {
    if (is_readable(METADATA_FILE)) {
        $use_metadata = true;
        $metadata = unserialize(file_get_contents(METADATA_FILE));
    } else {
        trigger_error('Error, could not read the metadata file. Please <a href="metadata.php" title="Generate local metadata copy">generate the local copy</a>.', E_USER_WARNING);
    }
}
$game = new ODSTGame();
$game->get_game($_GET['gameid']);
$game->load_game();
?>
</tt> Done.</p>

  <h3>Error</h3>
  <dl>
    <dt>Error:</dt>
    <dd><?php 
echo btt($game->error);
?>
<br /></dd>
    
    <dt>Status Code:</dt>
    <dd><?php 
    echo "Error: No mode given.";
    trigger_error("No mode given", E_USER_ERROR);
}
switch ($_GET['mode']) {
    case 'odst_game':
        // Check for a Game ID
        if ($_GET['gameid'] == '') {
            echo "Error: No Game ID given. Aborting...";
            trigger_error("No Game ID given", E_USER_ERROR);
        }
        $gameid = $_GET['gameid'];
        // Set the HTTP headers
        header('Content-Type: text/xml; charset=utf-8');
        header("Content-Disposition: attachment; filename=\"game_{$gameid}.xml\"");
        // Download and return the game XML
        $odst_game = new ODSTGame();
        $odst_game->get_game($gameid);
        echo $odst_game->dump_xml();
        break;
    case 'odst_metadata':
        // Set the HTTP headers
        header('Content-Type: text/xml; charset=utf-8');
        header('Content-Disposition: attachment; filename="game_metadata.xml"');
        // Download and return the metadata XML
        $metadata = new ODSTMetadata();
        $metadata->get_metadata();
        echo $metadata->dump_xml();
        break;
    default:
        // Given nothing to do.
        echo 'No operation selected.';