if (!is_dir(UPLOAD_DIR) || !is_writeable(UPLOAD_DIR)) { throw new Exception(sprintf("UPLOAD_DIR (%s) is not writeable", UPLOAD_DIR)); } if (!is_dir(LOG_DIR) || !is_writeable(LOG_DIR)) { throw new Exception(sprintf("LOG_DIR (%s) is not writeable", LOG_DIR)); } }); $StatTracker->error(function (Exception $e, $code) { // Eventually, have a custom error page }); // Default handler. Will match any alphnumeric string. If the page doesn't exist, // 404 $StatTracker->get('/{page}', function ($page) use($StatTracker) { if ($page == "dashboard" || $page == "leaderboards" || $page == "submit-stats" || $page == "settings" || $page == "trends" || $page == "terms") { $StatTracker['session']->set("page_after_login", $page); return $StatTracker['twig']->render("index.twig", array("agent" => $StatTracker->getAgent(), "constants" => array("ga_id" => StatTracker::getConstant("GOOGLE_ANALYTICS_ID"), "admin_agent" => StatTracker::getConstant("ADMIN_AGENT"), "contributors" => $StatTracker->getContributors(), "debug" => StatTracker::getConstant("DEBUG", false), "group_name" => StatTracker::getConstant("GROUP_NAME"), "version" => StatTracker::getConstant("VERSION", "bleeding edge")), "stats" => $StatTracker->getStats(), "page" => $page)); } else { if ($page == "logout") { $StatTracker->getAuthenticationProvider()->logout($StatTracker); return $StatTracker->redirect("./"); } else { if ($page == "authenticate") { switch ($_REQUEST['action']) { case "login": $authResponse = $StatTracker->getAuthenticationProvider()->login($StatTracker); if ($authResponse->status == "registration_required") { $StatTracker->sendRegistrationEmail($authResponse->email); } return $StatTracker->json($authResponse); break; case "callback":
$data->timestamp = $agent->getUpdateTimestamp(); break; } $response = JsonResponse::create(); $response->setEncodingOptions($response->getEncodingOptions() | JSON_NUMERIC_CHECK); $response->setData($data); return $response; })->before($validateRequest)->assert("view", "breakdown|leaderboard|prediction|trend|graph")->value("stat", "ap")->value("view", "raw")->value("when", "most-recent")->value("format", "json"); // Allow agents to submit stats $StatTracker->post("/api/{token}/submit", function (Request $request, $token) use($StatTracker) { $agent = Agent::lookupAgentByToken($token); if (!$agent->isValid()) { return $StatTracker->abort(403); } // Filter out keys that do not represent stats $data = array_intersect_key($_POST, array_merge(StatTracker::getStats(), array("date" => ""))); $response = new stdClass(); $response->error = false; $allow_lower_values = filter_var($request->query->get("allow_lower_values", false), FILTER_VALIDATE_BOOLEAN); try { $result = $agent->updateStats($data, $allow_lower_values); if ($result === true) { $response->message = sprintf("Your stats for %s have been received.", date("l, F j", strtotime($data['date']))); if (!$agent->hasSubmitted()) { $response->message .= " Since this was your first submission, predictions are not available. Submit again tomorrow to see your predictions."; } $StatTracker['session']->set("agent", Agent::lookupAgentByToken($token)); } else { $response->error = true; $response->message = $result; }
/** * Updates the agent's stats. * * @param array $data associative array where key is stat and value is the value for the stat. */ public function updateStats($data, $allow_lower) { // Get lowest submission date $stmt = StatTracker::db()->prepare("SELECT COALESCE(MIN(date), CAST(NOW() AS Date)) `min_date` FROM Data WHERE agent = ?"); try { $stmt->execute(array($this->name)); extract($stmt->fetch()); $ts = date("Y-m-d 00:00:00"); $dt = $data['date'] == null ? date("Y-m-d") : $data['date']; $select_stmt = StatTracker::db()->prepare("SELECT value `current_value` FROM Data WHERE agent = ? AND date = ? AND stat = ?"); $insert_stmt = StatTracker::db()->prepare("INSERT INTO Data (agent, date, timepoint, stat, value) VALUES (?, ?, DATEDIFF(?, ?) + 1, ?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value);"); StatTracker::db()->beginTransaction(); foreach ($data as $stat => $value) { if ($stat == "date") { continue; } $value = filter_var($data[$stat], FILTER_SANITIZE_NUMBER_INT); $value = !is_numeric($value) ? 0 : $value; if ($allow_lower) { $insert_stmt->execute(array($this->name, $dt, $dt, $min_date, $stat, $value)); } else { $select_stmt->execute(array($this->name, $dt, $stat)); extract($select_stmt->fetch()); $select_stmt->closeCursor(); if ($current_value <= $value) { $insert_stmt->execute(array($this->name, $dt, $dt, $min_date, $stat, $value)); } else { StatTracker::db()->rollback(); return sprintf("Stats cannot be updated. %s is lower than %s for %s.", number_format($value), number_format($current_value), StatTracker::getStats()[$stat]->name); } } } StatTracker::db()->commit(); return true; } catch (Exception $e) { throw $e; } finally { $select_stmt->closeCursor(); $insert_stmt->closeCursor(); } }