/**
  * Stats of a problem
  *
  * @param Request $r
  * @return array
  * @throws ForbiddenAccessException
  * @throws InvalidDatabaseOperationException
  */
 public static function apiStats(Request $r)
 {
     // Get user
     self::authenticateRequest($r);
     // Validate request
     self::validateRuns($r);
     // We need to check that the user has priviledges on the problem
     if (!Authorization::CanEditProblem($r['current_user_id'], $r['problem'])) {
         throw new ForbiddenAccessException();
     }
     try {
         // Array of GUIDs of pending runs
         $pendingRunsGuids = RunsDAO::GetPendingRunsOfProblem($r['problem']->getProblemId());
         // Count of pending runs (int)
         $totalRunsCount = RunsDAO::CountTotalRunsOfProblem($r['problem']->getProblemId());
         // List of verdicts
         $verdict_counts = array();
         foreach (self::$verdicts as $verdict) {
             $verdict_counts[$verdict] = RunsDAO::CountTotalRunsOfProblemByVerdict($r['problem']->getProblemId(), $verdict);
         }
         // Array to count AC stats per case.
         // Let's try to get the last snapshot from cache.
         $problemStatsCache = new Cache(Cache::PROBLEM_STATS, $r['problem']->getAlias());
         $cases_stats = $problemStatsCache->get();
         if (is_null($cases_stats)) {
             // Initialize the array at counts = 0
             $cases_stats = array();
             $cases_stats['counts'] = array();
             // We need to save the last_id that we processed, so next time we do not repeat this
             $cases_stats['last_id'] = 0;
             // Build problem dir
             $problem_dir = PROBLEMS_PATH . '/' . $r['problem']->getAlias() . '/cases/';
             // Get list of cases
             $dir = opendir($problem_dir);
             if (is_dir($problem_dir)) {
                 while (($file = readdir($dir)) !== false) {
                     // If we have an input
                     if (strstr($file, '.in')) {
                         // Initialize it to 0
                         $cases_stats['counts'][str_replace('.in', '', $file)] = 0;
                     }
                 }
                 closedir($dir);
             }
         }
         // Get all runs of this problem after the last id we had
         $runs = RunsDAO::searchRunIdGreaterThan(new Runs(array('problem_id' => $r['problem']->getProblemId())), $cases_stats['last_id'], 'run_id');
         // For each run we got
         foreach ($runs as $run) {
             // Build grade dir
             $grade_dir = RunController::getGradePath($run);
             // Skip it if it failed to compile.
             if (file_exists("{$grade_dir}/compile_error.log")) {
                 continue;
             }
             // Try to open the details file.
             if (file_exists("{$grade_dir}/details.json")) {
                 $details = json_decode(file_get_contents("{$grade_dir}/details.json"));
                 foreach ($details as $group) {
                     foreach ($group->cases as $case) {
                         if ($case->score > 0) {
                             $cases_stats['counts'][$case->name]++;
                         }
                     }
                 }
             }
         }
     } catch (Exception $e) {
         throw new InvalidDatabaseOperationException($e);
     }
     // Save the last id we saw in case we saw something
     if (!is_null($runs) && count($runs) > 0) {
         $cases_stats['last_id'] = $runs[count($runs) - 1]->getRunId();
     }
     // Save in cache what we got
     $problemStatsCache->set($cases_stats, APC_USER_CACHE_PROBLEM_STATS_TIMEOUT);
     return array('total_runs' => $totalRunsCount, 'pending_runs' => $pendingRunsGuids, 'verdict_counts' => $verdict_counts, 'cases_stats' => $cases_stats['counts'], 'status' => 'ok');
 }