function execute($request) { $path_parts = $request['path_parts']; $category_key = $path_parts[1]; $thread_id = intval($path_parts[2]); $page_id = 0; // returns null for admin-only threads if not an admin $thread_info = api_forum_get_thread_info($request['user_id'], $request['is_admin'], $thread_id, true); if ($thread_info == null || $thread_info['category_info']['key'] != $category_key) { return build_response_not_found("Thread not found."); } $total_posts = $thread_info['post_count']; if (count($path_parts) > 3 && substr($path_parts[3], 0, strlen('page')) == 'page') { $page_id = intval(substr($path_parts[3], strlen('page'))) - 1; if ($page_id < 0) { $page_id = 0; } } else { if ($path_parts[3] == 'new') { // TODO: per-user new post tracking } } $current_page = $page_id + 1; $total_pages = intval(($total_posts - 1) / 25) + 1; // List of integers including 1-indexed page numbers or -1 for ellipses. // Links to first 3 pages and last 3 pages should always be available, along with pages within 2 of the current page. $paginator_links = array(); $first_range = 3; $end_range = $total_pages - 2; $mid_begin_range = $current_page - 2; $mid_end_range = $current_page + 2; $last_item_is_ellipsis = false; for ($i = 1; $i <= $total_pages; ++$i) { if ($i <= $first_range || $i >= $end_range || $i >= $mid_begin_range && $i <= $mid_end_range) { array_push($paginator_links, $i); $last_item_is_ellipses = false; } else { if (!$last_item_is_ellipses) { array_push($paginator_links, -1); $last_item_is_ellipses = true; } } } $starting_post_index = $page_id * 25; if ($starting_post_index >= $total_posts) { } $forum_posts = api_forum_fetch_posts_for_thread($request['user_id'], $category_key, $thread_id, $page_id); $post_ids = $forum_posts['ordered_post_ids']; $thread_info = $forum_posts['thread_' . $thread_id]; $category_info = $forum_posts['category_' . $thread_info['category_id']]; if ($category_info == null) { return build_response_not_found("Thread not found."); } $output = array(); array_push($output, '<h1 style="font-size:16px;">', '<a href="/forum">Forum</a> > ', '<a href="/forum/' . $category_key . '">' . htmlspecialchars($category_info['name']) . '</a> > ', htmlspecialchars($thread_info['title']), '</h1>'); $paginator_html = array(); if ($total_pages > 1) { array_push($paginator_html, '<div style="text-align:right;">'); if ($current_page > 1) { array_push($paginator_html, '<a href="/forum/' . $category_key . '/' . $thread_id . '/page' . ($current_page - 1) . '">Prev</a> '); } foreach ($paginator_links as $page) { if ($page === -1) { array_push($paginator_html, ' ... '); } else { if ($page == $current_page) { array_push($paginator_html, '[' . $current_page . ']'); } else { array_push($paginator_html, '<a href="/forum/' . $category_key . '/' . $thread_id . '/page' . $page . '">' . $page . '</a>'); } } } if ($current_page < $total_pages) { array_push($paginator_html, '<a href="/forum/' . $category_key . '/' . $thread_id . '/page' . ($current_page + 1) . '">Next</a> '); } array_push($paginator_html, '</div>'); } $paginator_html = implode("\n", $paginator_html); array_push($output, $paginator_html); if (count($post_ids) == 0) { return build_response_not_found("No posts found."); } array_push($output, '</div>'); //array_push($output, '<div style="margin-bottom:20px;">'); foreach ($post_ids as $post_id) { $post = $forum_posts['post_' . $post_id]; $user = $forum_posts['user_' . $post['user_id']]; array_push($output, '<div style="clear:both; padding-top:20px;">', '<div class="block" style="float:left; width:120px; margin-right:20px;">', '<div style="text-align:center;">', strlen($user['image_id']) > 0 ? '<img src="/uploads/avatars/' . $user['image_id'] . '" />' : ":'(", '</div>', '</div>', '<div style="float:left; width:780px; background-color:#fff;">', '<div style="background-color:#ddd;font-weight:bold; padding:8px; font-size:12px;">', '<div title="' . date("M j, Y g:i:s A", $post['time']) . '" style="float:right;width:300px;text-align:right;font-weight:normal;color:#555;">', unix_to_scaling_time($post['time']), '</div>', '<a href="/profiles/' . $user['login_id'] . '">' . htmlspecialchars($user['name']) . '</a>', '</div>', '<div style="clear:right;padding:20px;">', nl2br(htmlspecialchars($post['content_raw'])), '</div>', '</div>', '</div>'); } //array_push($output, '</div>'); array_push($output, '<div class="fullblock" style="clear:both;margin-top:20px;">'); array_push($output, $paginator_html); array_push($output, '<div><a href="/forum/' . $category_key . '/' . $thread_id . '/reply">Reply</a></div>'); return build_response_ok("Forum thread", implode("\n", $output)); }
function execute($request) { $output = array('<h1>Code Golf</h1>', "<p><a href=\"https://en.wikipedia.org/wiki/Code_golf\">Code Golf</a> is a competition to see who can solve a programming problem using the fewest [key] \"strokes\".</p>", '</div>'); $now = time(); // TODO: migrate to api layer $current_challenge = api_autograder_canonicalize_problem(sql_query_item("SELECT * FROM `code_problems` WHERE `type` = 'golf' AND `golf_start_time` <= {$now} AND `golf_end_time` > {$now} LIMIT 1")); array_push($output, '<div style="padding-top:20px; margin-bottom:20px;">', '<div class="block" style="float:left; width:460px;">', '<p>' . "A new problem is posted every <s>2 weeks</s> once in a while. " . "During that time you can submit solutions. " . "Once time is up, the highest ranking (shortest) solutions will be awarded points. " . "You may still submit solutions after time is up for practice, but they won't be recorded for scores." . '</p>', '<p>Points are granted as follows on a per-language basis:</p>', '<ul>', '<li>First place: 3 points</li>', '<li>Second place: 2 points</li>', '<li>Third through fifth: 1 point</li>', '</ul>', '<p>Preference is given to earlier solutions in the event of ties. The maximum points you can receive is 3 × {number of languages}.</p>', '<p>More about <a href="/about#points">NP points</a>.</p>', '<p>Want a reminder every 2 weeks? New Golf questions will be announced via <a href="https://twitter.com/nerdparadise">twitter</a>.</p>', '</div>', '<div class="block" style="float:left; margin-left:20px; width:400px;">'); if ($current_challenge == null) { array_push($output, '<h2>Current Challenge: None</h2>', '<div>Check back soon or poke <a href="/profiles/blake">Blake</a></div>'); } else { array_push($output, '<h2>Current Challenge: <a href="/golf/' . $current_challenge['problem_id'] . '">' . htmlspecialchars($current_challenge['title']) . '</a></h2>', '<div><span style="color:#048; font-weight:bold;">' . seconds_to_duration($current_challenge['golf_end_time'] - time()) . '</span> Remain.</div>', ''); // TODO: migrate to api $ranked_entries = sql_query("\r\n\t\t\t\tSELECT\r\n\t\t\t\t\tr.`user_id`,\r\n\t\t\t\t\tr.`integer_rank`,\r\n\t\t\t\t\tr.`code_size`,\r\n\t\t\t\t\tr.`language_id`,\r\n\t\t\t\t\tlang.`name` AS 'lang_name',\r\n\t\t\t\t\tlang.`key` AS 'lang_key'\r\n\t\t\t\tFROM `code_solutions` r\r\n\t\t\t\tINNER JOIN `languages` lang ON (lang.`language_id` = r.`language_id`)\r\n\t\t\t\tWHERE\r\n\t\t\t\t\tr.`problem_id` = " . $current_challenge['problem_id'] . " AND\r\n\t\t\t\t\tr.`integer_rank` <= 3\r\n\t\t\t\tORDER BY r.`integer_rank`"); if ($ranked_entries->num_rows == 0) { array_push($output, '<p>Currently there are no submissions.</p>', '<p><a href="/golf/' . $current_challenge['problem_id'] . '">Be the first!</a></p>'); } else { array_push($output, '<h2 style="padding-top:20px; padding-bottom:10px;">Rankings</h2>'); $user_ids = array(); $languages = array(); $language_keys = array(); $language_names = array(); for ($i = 0; $i < $ranked_entries->num_rows; ++$i) { $entry = $ranked_entries->fetch_assoc(); array_push($user_ids, $entry['user_id']); $language_key = $entry['lang_key']; if (!isset($languages[$language_key])) { $languages[$language_key] = array(); array_push($language_keys, $language_key); $language_names[$language_key] = $entry['lang_name']; } array_push($languages[$language_key], $entry); } sort($language_keys); $user_infos = api_account_fetch_mini_profiles($user_ids); foreach ($language_keys as $language_key) { array_push($output, '<h3>', '<img src="/images/languages/' . $language_key . '_small.png" valign="middle" />', htmlspecialchars($language_names[$language_key]), '</h3>', '<table style="width:100%">'); $rank = 1; foreach ($languages[$language_key] as $entry) { $user_info = $user_infos['user_' . $entry['user_id']]; array_push($output, '<tr>', '<td>#' . $rank . '</td>', '<td><a href="/profiles/' . $user_info['login_id'] . '">' . htmlspecialchars($user_info['name']) . '</a></td>', '<td>' . $entry['code_size'] . ' byte' . ($entry['code_size'] == 1 ? '' : 's') . '</td>', '</tr>'); ++$rank; } array_push($output, '</table>'); } } } array_push($output, '</div>', '</div>'); array_push($output, '<div style="clear:left; padding-top:20px;">', '<div class="fullblock">', '<h2>All Challenges</h2>'); $languages = api_autograder_get_language_infos(true); $problems_and_scores = api_autograder_menu_get_problems($request['user_id'], $request['is_admin'], 'golf', 0, true); $ordered_problem_ids = $problems_and_scores['ordered_problem_ids']; array_push($output, '<table cellspacing="0" cellpadding="4"><tr style="font-size:14px; font-weight:bold;"><td></td><td></td>'); foreach ($languages as $language) { array_push($output, '<td style="padding-right:30px;">'); array_push($output, '<img src="/images/languages/' . htmlspecialchars($language['key']) . '_small.png" valign="middle" />'); array_push($output, htmlspecialchars($language['name'])); array_push($output, '</td>'); } array_push($output, '</tr>'); $now = time(); $alt = true; foreach ($ordered_problem_ids as $problem_id) { $problem_info = $problems_and_scores['problem_' . $problem_id]; $is_active = $now < $problem_info['golf_end_time']; $alt = !$alt; $bg_color = $is_active ? 'cde' : ($alt ? 'fff' : 'eee'); array_push($output, '<tr style="' . ($is_active ? 'font-weight:bold;' : '') . 'text-align:center;background-color:#' . $bg_color . ';">', '<td style="text-align:left;"><a href="/golf/' . $problem_id . '">', htmlspecialchars($problem_info['title']), '</a></td>', '<td>'); if ($is_active) { array_push($output, "Ends: " . unix_to_scaling_time($problem_info['golf_end_time'])); } else { array_push($output, "Ended: " . unix_to_scaling_time($problem_info['golf_start_time'])); } array_push($output, '</td>'); foreach ($languages as $language) { $score = $problems_and_scores['score_' . $problem_id . '_' . $language['language_id']]; if (intval($score['code_size']) > 0) { array_push($output, '<td>'); array_push($output, $score['code_size']); array_push($output, ' (#' . $score['integer_rank'] . ')'); // TODO: little trophy images. } else { array_push($output, '<td style="color:#888;">'); array_push($output, 'N/A'); } array_push($output, '</td>'); } array_push($output, '</tr>'); } array_push($output, '</table>'); array_push($output, '</div>'); return build_response_ok("Code Golf", implode("\n", $output)); }