function cscircles_students_page() { echo "<div class='wrap'>\n<h2>Manage CS Circles Students</h2>"; if (isSoft($_REQUEST, 'submitted', 'true')) { $d = 0; $h = 0; $newhide = ""; $newnicks = array(); $newgroups = array(); foreach ($_REQUEST as $key => $val) { if (substr($key, 0, 1) == 's' && is_numeric(substr($key, 1))) { $id = substr($key, 1); if ($val == 'hide') { if ($newhide != '') { $newhide .= ","; } $newhide .= substr($key, 1); $h++; } else { if ($val == 'remove') { if (strtolower(get_user_meta(substr($key, 1), 'pbguru', true)) == strtolower(wp_get_current_user()->user_login)) { update_user_meta(substr($key, 1), 'pbguru', ''); } $d++; } } } if (substr($key, 0, 1) == 'n' && is_numeric(substr($key, 1))) { $id = substr($key, 1); $nick = $val; $nick = preg_replace('_[<>&\\"\\\\]_', "", trim($nick)); if ($nick != '') { $newnicks[$id] = $nick; } } if (substr($key, 0, 1) == 'g' && is_numeric(substr($key, 1))) { $id = substr($key, 1); $group = $val; $group = preg_replace('_[<>&\\"\\\\]_', "", trim($group)); if ($group != '') { $newgroups[$id] = $group; } } } update_user_meta(wp_get_current_user()->ID, 'pb_hidestudents', $newhide); update_user_meta(wp_get_current_user()->ID, 'pb_studentnicks', json_encode($newnicks)); update_user_meta(wp_get_current_user()->ID, 'pb_studentgroups', json_encode($newgroups)); echo "<div class='updated'>Deleted {$d} students. You have {$h} hidden students.</div>"; } echo "<script type='text/javascript'>classlist = function() {\n var classes={};\n jQuery('.grouplabel').each(function(i, elt) {classes[elt.value] = true;});\n var keys = [];\n for(var key in classes) {\n if (classes.hasOwnProperty(key)) {\n keys.push(key);\n }\n }\n keys.sort();\n jQuery('#classlist-select').html('');\n jQuery('#classlist-select').append(new Option('', ''));\n jQuery('#classlist-select').append(new Option('<show all students>', '<show all students>'));\n for (var i = 0; i < keys.length; i++) {\n if (keys[i] != '')\n jQuery('#classlist-select').append(new Option(keys[i], keys[i]));\n } \n}\nselectClass = function() {\n theclass = jQuery('#classlist-select')[0].value;\n jQuery('.student-row').each(function(i, row){\n if (jQuery(row).find('.grouplabel')[0].value == theclass || theclass == '<show all students>')\n jQuery(jQuery(row).find('.unhide')[0]).prop('checked',true);\n else\n jQuery(jQuery(row).find('.hide')[0]).prop('checked',true);\n });\n}\njQuery(classlist); // call once on load\n</script>"; echo "<p>Students who are hidden or removed won't show up\non the Progress page. You still have access to \nmessages between you and them in the Mail page histories.</p>\n\n<p>If you hide a student, you can unhide them later.</p>\n<p>If you remove a student, their guru is cleared. They would have to re-add you if you want them back.</p>\n<p>Students are listed in order of registration on CS Circles (earliest first).</p>\n<!--<p>Nicknames are optional. Otherwise, students appear by their e-mail and/or userid.</p>-->\n"; if (count(getStudents(true)) == 0) { echo "<div class='error'>You have no students. This page will disappear, and reappear if you get more students.</div>"; } else { echo "<form method='get' action='users.php'>\n <input type='hidden' name='page' value='cscircles-students'>\n <input type='hidden' name='submitted' value='true'>\n<table style='text-align:center'><tr><th>Unhidden</th><th>Hidden</th><th>Remove</th><th>Username</th><th>Name</th><th>E-mail</th><th>Optional nickname <br>(appears just to you, throughout site)</th><th>Optional class/section label</th></tr>"; $hidden = get_user_meta(wp_get_current_user()->ID, 'pb_hidestudents', true); $nicks = json_decode(get_user_meta(wp_get_current_user()->ID, 'pb_studentnicks', true), true); $groups = json_decode(get_user_meta(wp_get_current_user()->ID, 'pb_studentgroups', true), true); if (!is_array($nicks)) { $nicks = array(); } if (!is_array($groups)) { $groups = array(); } if ($hidden == '') { $hidden = ''; } $hidden = explode(",", $hidden); foreach (getStudents(true) as $index => $id) { $user = get_userdata($id); $hid = in_array($id, $hidden); $c1 = $hid ? "" : "checked='true'"; $c2 = $hid ? "checked='true'" : ""; $nick = getSoft($nicks, $id, ''); $group = getSoft($groups, $id, ''); echo "<tr class='student-row'>\n<td><input type='radio' class='unhide' name='s{$id}' {$c1} value='unhide'/></td>\n<td><input type='radio' class='hide' name='s{$id}' {$c2} value='hide'/></td>\n<td><input type='radio' name='s{$id}' value='remove'/></td>\n<td>{$user->user_login}</td>\n<td>{$user->user_firstname} {$user->user_lastname}</td>\n<td>{$user->user_email}</td>\n<td><input style='width:100%' type='text' name = 'n{$id}' value=\"{$nick}\"></td>\n<td><input style='width:100%' type='text' class = 'grouplabel' name = 'g{$id}' value=\"{$group}\" onkeyup=\"javascript:classlist()\" onchange=\"javascript:classlist()\"></td>\n</tr>"; } echo "<tr id='classlist-tr'>\n <td colspan='7' style='text-align:right'>\n <div id='classlist-label'>Show a class and hide all other students? (Select and press <b>Submit</b> to activate.)</div>\n </td>\n <td style='text-align:left'><select id='classlist-select' onchange='javascript:selectClass()'></select></td></tr>"; echo "</table>\n <button class='button-primary' id='submit'>Submit</button></form>"; echo "</div>"; } }
if ($problem_info === NULL) { header('HTTP/1.1 404 Not Found'); return; } $message = stripcslashes($_POST["message"]); $noreply = getSoft($_POST, 'noreply', 'false'); if ($source == 1) { //inline help form $guru_login = get_the_author_meta('pbguru', get_current_user_id()); // '' if does not exist $guru = get_user_by('login', $guru_login); // FALSE if does not exist $code = stripcslashes($_POST["code"]); $message .= "\n===\n" . __t("The user sent this code with the message:") . "\n===\n" . $code; echo send($problem_info, getUserID(), isSoft($_POST, 'recipient', '1') ? $guru->ID : 0, getUserID(), $slug, $message, $noreply); } elseif ($source == 2) { //mail page $id = $_POST['id']; $guru_login = get_the_author_meta('pbguru', $id); // '' if does not exist $guru = get_user_by('login', $guru_login); // FALSE if does not exist if (userIsAdmin() || userIsAssistant() || getUserID() == $guru->ID) { // from {guru or CSC Asst.} to student echo send($problem_info, userIsAdmin() ? 0 : getUserID(), $id, $id, $slug, $message, $noreply); } elseif ($id == getUserID()) { // from student to {guru or CSC Asst.} echo send($problem_info, $id, isSoft($_POST, 'recipient', '1') ? $guru->ID : 0, $id, $slug, $message, $noreply); } } // end of file!
$cached_result = NULL; $basehash = md5($_REQUEST['user_script'] . "\t\t\t" . $_REQUEST['raw_input_json']) . '-viz'; $versionedhash = $basehash . VIZ_VERSION; $dontCache = strstr($_REQUEST['user_script'], 'random') !== FALSE; if (!$dontCache) { // don't cache if randomized $the_count = $wpdb->get_var($wpdb->prepare("SELECT count(1) FROM {$wpdb->prefix}pb_submissions\nWHERE hash LIKE %s LIMIT 4", $basehash . '%')); $cached_result = $wpdb->get_var($wpdb->prepare("SELECT result FROM {$wpdb->prefix}pb_submissions\nWHERE hash = %s AND result is NOT NULL LIMIT 1", $versionedhash)); // if cached_result is NULL, we still have to compute it anyway } /************* do logging *************/ // save things to build up the cache count // save things sent to the real visualizer (not the iframe) // but once something is iframed 5 times we don't need to log it any more if ($cached_result === NULL || !isSoft($_REQUEST, "iframe_mode", "Y")) { $logRow = array('beginstamp' => date('Y-m-d H:i:s', time()), 'usercode' => $_REQUEST['user_script'], 'userinput' => $_REQUEST['raw_input_json'], 'hash' => $versionedhash, 'problem' => isSoft($_REQUEST, "iframe_mode", "Y") ? 'visualizer-iframe' : 'visualizer', 'ipaddress' => $_SERVER['REMOTE_ADDR'], 'referer' => $_SERVER['HTTP_REFERER'], 'userid' => is_user_logged_in() ? wp_get_current_user()->ID : -1); $table_name = $wpdb->prefix . "pb_submissions"; $wpdb->insert($table_name, $logRow); $logid = $wpdb->insert_id; } /************* actually execute the visualizer if necessary *************/ if ($cached_result !== NULL) { echo $cached_result; exit; } $descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w")); $command = PSAFEEXEC . " --env_vars PY --gid 1000 --uidplus 10000 --cpu 5 --mem 100000 --clock 7 --chroot_dir " . PJAIL . " --exec_dir /static/OnlinePythonTutor3-cemc/ --exec /bin/python3 -S -u csc_exec.py -"; $process = proc_open($command, $descriptorspec, $pipes); if (is_resource($process)) { fwrite($pipes[0], json_encode($_REQUEST)); fclose($pipes[0]);
function list_pybox_pages($options, $content) { $out = get_pages(array('parent' => 0, 'status' => 'publish')); $links = array(); global $polylang; foreach ($out as $page) { if ($polylang->model->get_translation('post', $page->ID, 'en') == $page->ID) { //english only $links[] = array("url" => get_page_link($page->ID), "title" => $page->post_title); if (isSoft($_GET, 'export', 'Y')) { $p = get_page($page->ID); $slug = $p->post_name; $f = fopen(PEXPORT . $slug . ".txt", 'w'); fwrite($f, 'Title: ' . $p->post_title . "\n\nContent:\n\n"); fwrite($f, translator_template($p->post_content)); fclose($f); } elseif (isSoft($_GET, 'export', 'raw')) { $p = get_page($page->ID); $slug = $p->post_name; $f = fopen(PEXPORT . $slug . ".txt", 'w'); fwrite($f, 'Title: ' . $p->post_title . "\n\nContent:\n\n"); fwrite($f, $p->post_content); fclose($f); } } } $user_id = get_current_user_id(); $current_user = wp_get_current_user(); $profile_url = get_edit_profile_url($user_id); if ($user_id) { $links[] = array("url" => $profile_url, "title" => __t('Edit my profile')); $links[] = array("url" => wp_logout_url(), 'title' => __t('Log out now')); } else { $links[] = array("url" => wp_logout_url(), 'title' => __t('Log in or create a new account')); } foreach ($links as $i => $page) { $s = $page['title']; $m = preg_match('/^([0-9]+)([A-Z])?\\: (.*)$/', $s, $matches); if ($m <= 0) { $k = '9999---' . $s; } else { $sub = $matches[2]; if ($sub == "") { $sub = "-"; } $k = sprintf("%04d", $matches[1]) . '-' . $sub . '-' . $matches[3]; } $links[$i]['key'] = $k; } // print_r($links); function cmp($p1, $p2) { return strcmp($p1['key'], $p2['key']); } usort($links, 'cmp'); echo '<ul>'; foreach ($links as $page) { echo "<li><a class='open-same-window' href='" . $page['url'] . "'>" . $page['title'] . "</a></li>"; } echo '</ul>'; }
function run_submission($post) { /************************************************** part 0 : initialization and checking that a valid problem is selected ************************************************/ global $logRow, $beginstamp, $userid, $userinput, $meta, $wpdb, $inputInUse, $facultative, $usertni, $mainProfilingID, $slug, $log_it, $appendix; $beginstamp = time(); $logRow = FALSE; $meta = array(); if ($log_it) { $mainProfilingID = beginProfilingEntry(array("activity" => "submit-code")); } /*if ($_SERVER['REQUEST_METHOD'] != 'POST') return merror('', 'HTTP mangling: method "' . $_SERVER['REQUEST_METHOD'] . '" was requested instead of "POST"', 'suppress');*/ if (count($post) == 0) { return merror('', 'HTTP mangling: request contained no data', 'suppress'); } if (strlen(print_r($post, TRUE)) > POSTLIMIT) { pyboxlog("submit.php got too many bytes of data:" . strlen(print_r($post, TRUE))); return mfail(sprintf(__t('Submitted data (program and/or test input) ' . 'too large. Reduce size or <a href = "%s">' . 'run at home</a>.'), cscurl('install'))); } $id = getSoft($post, "pyId", "EMPTY"); $usercode = tabs_to_spaces(3, getSoft($post, "usercode" . $id, -1)); if (!is_string($usercode)) { return merror("", "No usercode" . $id . "!" . print_r($post, TRUE)); } $usercode = preg_replace('|\\xc2\\xa0|', ' ', $usercode); // nbsp $userinput = getSoft($post, "userinput", ""); $userinput = preg_replace('|\\xc2\\xa0|', ' ', $userinput); //nbsp $hash = $post["hash"]; //$graderArgsString = safeDereference("@file:" . $hash, 'hashes'); //if (!is_string($graderArgsString)) // return merror("", "PyBox error: problem hash " . $hash . " not found."); /************************************************** part 1 : set global variables, build skeleton log row; quit upon justsave. ************************************************/ //$problemArgs = multilineToAssociative($graderArgsString); // foreach ($problemArgs as $key=>$value) // $problemArgs[$key] = stripcslashes($value); $problemArgs = $wpdb->get_var($wpdb->prepare("\nSELECT graderArgs from " . $wpdb->prefix . "pb_problems WHERE hash = %s", $hash)); if ($problemArgs === NULL) { return merror("", sprintf(__t("Pybox error: problem hash %s not found. " . "Try reloading the page."), $hash)); } $problemArgs = json_decode($problemArgs, TRUE); // if ($problemArgs != $problemArgsNew) // pyboxlog("different: " . var_export($problemArgs, TRUE) // . var_export($problemArgsNew, TRUE)); //else // pyboxlog("same", TRUE); $re = '/^(' . implode("|", array_keys(optionsAndDefaults())) . ')([0-9]*)$/'; $problemOptions = optionsAndDefaults(); $subproblemOptions = array(); foreach ($problemArgs as $key => $value) { $match = preg_match($re, $key, $matches); if ($match == 0) { return merror("", "PyBox error: unknown option " . $key); } if ($matches[2] == "") { $problemOptions[$matches[1]] = $value; } else { if (!array_key_exists($matches[2], $subproblemOptions)) { $subproblemOptions[$matches[2]] = array(); } $subproblemOptions[$matches[2]][$matches[1]] = $value; } } foreach ($subproblemOptions as $index => $spo) { foreach ($problemOptions as $option => $value) { if (!array_key_exists($option, $spo)) { $subproblemOptions[$index][$option] = $value; } } } $inputInUse = isSoft($post, "inputInUse", "Y"); /* var_dump( $post, TRUE); echo "eq: " .(($post["inputInUse"] === "Y") ? "T":"F"); echo "inputinuse: " . ($inputInUse ? "T":"F");*/ if ($inputInUse && !isSoft($problemOptions, "allowinput", "Y")) { return merror("", "Pybox error: input not actually allowed"); } $facultative = isSoft($problemOptions, "facultative", "Y") || $inputInUse; $usertni = isSoft($problemOptions, "usertni", "Y"); $userid = is_user_logged_in() ? wp_get_current_user()->ID : -1; $meta['userid'] = $userid; $meta['problem'] = getSoft($problemArgs, 'slug', $hash); $slug = getSoft($problemArgs, 'slug', NULL); //most of submit logging preparation. quitting earlier => not logged in DB if ($log_it and !isSoft($problemOptions, "nolog", "Y")) { $postmisc = $post; unset($postmisc['usercode' . $id]); unset($postmisc['userinput']); unset($postmisc['hash']); $logRow = array('beginstamp' => date('Y-m-d H:i:s', $beginstamp), 'usercode' => $usercode, 'hash' => $hash, 'postmisc' => print_r($postmisc, TRUE), 'problem' => $slug, 'ipaddress' => $_SERVER['REMOTE_ADDR'], 'referer' => $_SERVER['HTTP_REFERER']); if ($inputInUse) { $logRow['userinput'] = $userinput; } $logRow['userid'] = $userid; //if ($logRow['problem']===NULL) //pyboxlog('nameless problem that is not read-only!', TRUE); } // old feature: // $justsave = array_key_exists('justsave', $post); //if ($justsave) // return msave(); /************************************************** part 2 : grading ************************************************/ if ($problemOptions['taboo'] != FALSE) { $taboo = explode(",", $problemOptions['taboo']); foreach ($taboo as $t) { $p = strpos($t, "|"); if ($p === FALSE) { $regex = $t; $display = $t; } else { $display = substr($t, 0, $p); $regex = substr($t, $p + 1); } $match = preg_match("#.*" . trim($regex) . ".*#", $usercode); if ($match != 0) { return mfail(sprintf(__t("You cannot use %s in this exercise."), "<code>" . trim($display) . "</code>")); } } } if ($problemOptions["maxeditdistance"] != FALSE) { $k = $problemOptions["maxeditdistance"]; $S = preg_replace('/\\s+/', '', $usercode); $T = preg_replace('/\\s+/', '', $problemOptions["originalcode"]); $s = strlen($S); $t = strlen($T); $msg = sprintf(__t("You are only allowed to change at most %s " . "characters compared to the original version " . "of the code."), $k); if (abs($s - $t) > 2 * $k + 5) { return mfail($msg) . " " . sprintf(__t("You changed %s or more."), 2 * $k + 5); } else { $DP = array_fill(0, $s + 1, NULL); for ($i = 0; $i <= $s; $i++) { $DP[$i] = array_fill(0, $t + 1, NULL); } for ($i = 0; $i <= $s; $i++) { for ($j = 0; $j <= $t; $j++) { if ($i == 0 || $j == 0) { $DP[$i][$j] = $i + $j; } else { $DP[$i][$j] = $DP[$i - 1][$j - 1]; if ($S[$i - 1] != $T[$j - 1]) { $DP[$i][$j]++; } $DP[$i][$j] = min($DP[$i][$j], 1 + min($DP[$i][$j - 1], $DP[$i - 1][$j])); } } } if ($DP[$s][$t] > 0 + $k) { return mfail($msg . " " . sprintf(__t("You changed %s."), $DP[$s][$t])); } } } /*************** done preprocessing source code, time to execute some things ************************/ if ($inputInUse && $slug != 'console') { global $usertni; $appendix = '<div class="testing-warning">'; if ($usertni) { $appendix .= __t('Note: ran with user tests.'); } else { $appendix .= __t('Note: ran with user inputs.'); } if (!isSoft($problemOptions, "facultative", "Y")) { $appendix .= ' ' . __t(' Click "Go back to grading" to switch back.'); } else { $appendix .= ' ' . __t(' Click "Hide input box" to switch back.'); } } else { $appendix = ''; } if (count($subproblemOptions) == 0) { // if ($problemOptions['grader'] == '*nograder*') $subproblemOptions["1"] = $problemOptions; //else //return merror("", "No test cases found!"); } // $spo: subproblemOptions for the current subproblem $tcTotal = 0; foreach ($subproblemOptions as $N => $spo) { $tcTotal += $spo["repeats"]; } $m = ''; //the result string, built a bit at a time. ksort($subproblemOptions); //test case 1, then 2, ... $tcCurrent = 0; $allCorrect = TRUE; ///*********************************************** main grading loop ***/ foreach ($subproblemOptions as $N => $spo) { // spo: subproblemOptions for current subproblem for ($i = 0; $i < $spo["repeats"]; $i++) { $tcCurrent++; if (!$inputInUse && $tcTotal > 1) { $m .= "<b>" . sprintf(__t('Results for test case %1$s out of %2$s'), $tcCurrent, $tcTotal) . "</b><br/>"; } try { $GLOBALS['pb_translation'] = getSoft($spo, 'translate', NULL); $tcOutcome = doGrading($usercode, $spo); $GLOBALS['pb_translation'] = NULL; $m .= $tcOutcome["message"]; if ($tcOutcome["result"] == "error") { return merror($m, $tcOutcome["errmsg"]); } if ($tcOutcome["result"] == "fail" && $spo["haltonwrong"] == "Y") { return mfail($m); } if ($tcOutcome["result"] == "fail") { $allCorrect = FALSE; } } catch (PyboxException $e) { return merror($m, $e->getMessage()); } if ($inputInUse) { break; } } if ($inputInUse) { break; } } return $allCorrect ? mpass($m) : mfail($m); }
$r .= '['; if ($row['type'] == 'short answer') { $codename = 'pyShort'; } else { if ($row['type'] == 'multiple choice') { $codename = 'pyMulti'; } else { if ($row['type'] == 'multichoice scramble') { $codename = 'pyMultiScramble'; } else { if ($row['type'] == 'scramble') { $codename = 'pyScramble'; unset($args['scramble']); } else { if ($row['type'] == 'code') { if (isSoft($args, 'pyexample', 'Y')) { $codename = 'pyExample'; unset($args['pyexample']); } else { $codename = 'pyBox'; } } else { $codename = 'py??' . $row['type'] . '??'; } } } } } $r .= $codename; foreach ($args as $field => $value) { $r .= "\n";
} //$errnorm = normalize($errmsg); global $hintage; foreach ($hintage as $patt => $repl) { if (preg_match("" . $patt . "", $errmsg, $matches)) { return preg_replace("" . $patt . "", $repl, $errmsg); } } return NULL; } function hintable($errmsg) { $hintables = array("RuntimeError", "ValueError", "ZeroDivisionError", "AttributeError", "TabError", "IndentationError", "IndexError", "SyntaxError", "UnboundLocalError", "ImportError", "OverflowError", "TypeError", "NameError", "EOFError"); $t = substr($errmsg, 0, strpos($errmsg, ":")); return in_array($t, $hintables); } function normalize($errmsg) { $errmsg = preg_replace("_ '.*'( |\$)_", " '' ", $errmsg); $errmsg = preg_replace("_\".*\"_", "\"\"", $errmsg); $errmsg = preg_replace("_\\d+_", "0", $errmsg); $errmsg = preg_replace("_\\b\\w+\\(\\)_", "func()", $errmsg); $errmsg = preg_replace("_^TypeError: unsupported operand type\\(s\\) .+\$_", "TypeError: unsupported operand type(s)", $errmsg); return $errmsg; } // only called from ajax to action-submit, so has $REQUEST["lang"] if (isSoft($_REQUEST, "lang", "lt_LT")) { require_once "plugin-errorhint-lt_LT.php"; } else { require_once "plugin-errorhint-en_US.php"; }
function pyUser($options, $content) { if (!is_user_logged_in()) { return __t("You must login to view your user page."); } global $wpdb; $user = wp_get_current_user(); $uid = $user->ID; $students = getStudents(); $cstudents = count($students); $problem_table = $wpdb->prefix . "pb_problems"; $problems = $wpdb->get_results("SELECT * FROM {$problem_table} WHERE facultative = 0 AND lang = '" . currLang2() . "' AND lesson IS NOT NULL ORDER BY lesson ASC, boxid ASC", ARRAY_A); $problemsByNumber = array(); foreach ($problems as $prow) { $problemsByNumber[$prow['slug']] = $prow; } $gp = getSoft($_GET, "problem", ""); if ($gp != "" && $gp != "console" && !array_key_exists($gp, $problemsByNumber)) { echo sprintf(__t("Problem %s not found (at least in current language)"), $gp); return; } if (userIsAdmin() || userIsAssistant() || $cstudents > 0) { $preamble = "<div class='progress-selector'>\n <form method='get'><table style='border:none'><tr><td>" . sprintf(__t("View one of your students? (you have %s)"), $cstudents) . '</td><td>'; $options = array(); $options[''] = __t('Show only me'); $options['all'] = __t('Summary of all my students'); if (!userIsAdmin()) { foreach ($students as $student) { $info = get_userdata($student); $options[$info->ID] = userString($info->ID); } } if (userIsAdmin()) { $preamble .= 'blank: you; "all": all; id#: user (<a href="' . cscurl('allusers') . '">list</a>) <input style = "padding:0px;width:60px" type="text" name="user" value="' . getSoft($_REQUEST, 'user', '') . '">'; } else { $preamble .= optionsHelper($options, 'user'); } $preamble .= '</td></tr><tr><td>'; $preamble .= __t("Just show submissions for one problem?"); $options = array(); $options[''] = __t('Show all'); $options['console'] = __t('Console'); foreach ($problems as $problem) { if ($problem['type'] == 'code') { $options[$problem['slug']] = $problem['publicname']; } } $preamble .= '</td><td>'; $preamble .= optionsHelper($options, 'problem'); $preamble .= "</td></tr><tr><td colspan='2' style='text-align:center'><input style='width: 25%' type='submit' value='" . __t('Submit') . "'/></tr></td></table></form></div>"; echo $preamble; } $allStudents = isSoft($_GET, 'user', 'all'); $viewingAsStudent = '' == getSoft($_GET, 'user', ''); $allProblems = $gp == ""; if (!$viewingAsStudent) { if ($allProblems) { $problem_html = "all problems"; } else { if ($gp == 'console') { $problem_html = "Console"; } else { $problem_html = "<a href='" . $problemsByNumber[$gp]['url'] . "'>" . $problemsByNumber[$gp]['publicname'] . "</a>"; } } } if (!$allStudents && array_key_exists('user', $_GET) && $_GET['user'] != '') { if (!is_numeric($_GET['user'])) { return __t("User id must be numeric."); } $getuid = (int) $_GET['user']; if (userIsAdmin() || userIsAssistant()) { if (get_userdata($getuid) === FALSE) { return __t("Invalid user id."); } } else { if (!in_array($getuid, $students)) { return __t("Invalid user id."); } } $uid = $getuid; $user = get_userdata($uid); echo "<div class='history-prenote'>" . sprintf(__t("Now viewing %s for "), $problem_html) . userString($uid) . '</div>'; } if ($allStudents) { echo "<div class='history-prenote'>" . sprintf(__t("Now viewing %s for all of your students"), $problem_html) . "</div>"; } /***************** end of header ***************/ $flexigrids = ""; $completed_table = $wpdb->prefix . "pb_completed"; if ($allStudents && !$allProblems && $gp != "console") { $flexigrids .= niceFlex('perstudent', sprintf(__t("Solutions by my students for %s"), $problemsByNumber[$_GET['problem']]['publicname']), 'problem-summary', 'dbProblemSummary', array('p' => $_GET['problem'])); } $dbparams = array(); if (getSoft($_GET, 'user', '') != '') { $dbparams['user'] = $_GET['user']; } if (getSoft($_GET, 'problem', '') != '') { $dbparams['problemhash'] = $_GET['problem']; } $flexigrids .= niceFlex('submittedcode', $allProblems ? __t("Submitted code") : sprintf(__t("Submitted code for %s"), $_GET['problem'] == 'console' ? 'Console' : $problemsByNumber[$_GET['problem']]['publicname']), 'entire-history', 'dbEntireHistory', $dbparams); $recent = ""; if (!$allStudents) { // queries more than 6 in order to fill out progress table of all problems $completed = $wpdb->get_results("SELECT * FROM {$completed_table} WHERE userid = {$uid} ORDER BY time DESC", ARRAY_A); $recent .= '<div class="recent"><span class="latest-title">' . __t("Latest problems completed") . ":</span>"; // but for now we only use 6 entries for "most recently completed" section for ($i = 0; $i < count($completed) && $i < 6; $i++) { $p = getSoft($problemsByNumber, $completed[$i]['problem'], FALSE); if ($p !== FALSE) { if (getSoft($_GET, 'user', '') != '') { if ($problemsByNumber[$p['slug']]['type'] == 'code') { $url = '.?user='******'user'] . '&problem=' . $p['slug']; } else { $url = null; } } else { $url = $p['url']; } $recent .= ' <a class="open-same-window problem-completed" '; if ($url != null) { $recent .= ' href="' . $url . '" '; } $recent .= ' title="' . $completed[$i]['time'] . '">' . $p['publicname'] . '</a>'; } else { $recent .= '[' . $completed[$i]['problem'] . ']'; } } $recent .= '</div>'; } $submissions_table = $wpdb->prefix . "pb_submissions"; $studentTable = ''; if ($allStudents && !userIsAdmin()) { $studentList = getStudentList(); $where = "WHERE userid in {$studentList}"; if (!$allProblems) { $where .= $wpdb->prepare("and problem LIKE %s", $gp); } // show number of problems each student completed $scompleted = $wpdb->get_results("SELECT userid, count(1) as comps from {$completed_table} {$where} GROUP BY userid", OBJECT_K); // show number of submissions by each student for this problem $ssubmissions = $wpdb->get_results("SELECT userid, count(1) as subs from {$submissions_table} {$where} GROUP BY userid", OBJECT_K); $studentTable .= '<div class="history-note">Student listing (click name to drill down)</div>'; $studentTable .= '<table>'; foreach (getStudents() as $stu) { $studentTable .= '<tr>'; $studentTable .= '<td>'; $studentTable .= '<a class="open-same-window" href="?user='******'&problem=' . $gp . '">'; $studentTable .= userString($stu); $studentTable .= '</a></td>'; $studentTable .= '<td>'; if ($allProblems) { $studentTable .= (array_key_exists($stu, $scompleted) ? $scompleted[$stu]->comps : 0) . ' completed'; } else { $studentTable .= '<img src="' . UFILES . (array_key_exists($stu, $scompleted) ? 'checked' : 'icon') . '.png"/>'; } $studentTable .= '</td>'; $studentTable .= '<td>'; $studentTable .= (array_key_exists($stu, $ssubmissions) ? $ssubmissions[$stu]->subs : 0) . ' submissions'; $studentTable .= '</td>'; $studentTable .= '</tr>'; } $studentTable .= '</table>'; } $lessons_table = $wpdb->prefix . "pb_lessons"; $lessons = $wpdb->get_results("SELECT * FROM {$lessons_table} WHERE lang = '" . currLang2() . "'", ARRAY_A); $lessonsByNumber = array(); foreach ($lessons as $lrow) { $lessonsByNumber[$lrow['ordering']] = $lrow; } $overview = ''; if ($allProblems || !$allStudents) { $overview = '<h2 style="margin-top:5px;text-align:center">' . __t('List of all problems') . ' ' . ($allStudents ? __t('(with #completed)') : __t('(with #submissions)')) . '</h2>'; if (!$viewingAsStudent) { $overview .= "<div style='text-align:center'>Click on the <img style='height:1em,width:1em' src='" . UFILES . "/icon.png'> to drill down.</div>"; } $checkIt = array(); //array from slug to boolean, whether to check the icon $showNum = array(); //array from slug to number, number to display beside each if ($allStudents) { if (userIsAdmin() || userIsAssistant()) { $completed = $wpdb->get_results("SELECT count(userid), problem from {$completed_table} GROUP BY problem", ARRAY_A); } else { $studentList = getStudentList(); $completed = $wpdb->get_results("SELECT count(userid), problem from {$completed_table} WHERE userid in {$studentList} GROUP BY problem", ARRAY_A); } foreach ($completed as $crow) { $showNum[$crow['problem']] = $crow['count(userid)']; } } else { $submissions = $wpdb->get_results("SELECT count(1), problem from {$submissions_table} WHERE userid = {$uid} GROUP BY problem", ARRAY_A); foreach ($submissions as $srow) { $showNum[$srow['problem']] = $srow['count(1)']; } foreach ($completed as $crow) { // this was queried earlier $checkIt[$crow['problem']] = TRUE; } } $overview .= '<table style="width:auto;border:none;margin:0px auto;">'; $lesson = -1; $lrow = NULL; $llink = ""; $firstloop = true; foreach ($problems as $prow) { if ($prow['lesson'] != $lesson) { if (!$firstloop) { $overview .= "</td></tr>\n"; } $firstloop = false; $overview .= "<tr><td class='lessoninfo'>"; $lesson = $prow['lesson']; $lrow = $lessonsByNumber[$lesson]; $overview .= '<a class="open-same-window" href="'; $llink = get_page_link($lrow['id']); $overview .= $llink; $overview .= '">'; $overview .= $lrow['number'] . ": " . $lrow['title']; $overview .= '</a></td><td>'; } if (!$viewingAsStudent) { // drill-down link $url = '.?user='******'user'] . '&problem=' . $prow['slug']; } else { $url = $prow['url']; } $overview .= '<a class="open-same-window" '; if ($url != null) { $overview .= ' href="' . $url . '" '; } $overview .= '>'; $overview .= '<table class="history-tablette" ><tr class="history-tablette-top"><td>'; $overview .= '<img style="margin:-10px 0px" title="' . $prow['publicname'] . '" src="' . UFILES . (isSoft($checkIt, $prow['slug'], TRUE) ? 'checked' : 'icon') . '.png"/>'; $overview .= '</a></td></tr><tr class="history-tablette-bottom"><td>'; /* $overview .= '<a class="open-same-window" '; if ($url != null) $overview .= ' href="' . $url . '" '; $overview .= '>';*/ $overview .= array_key_exists($prow['slug'], $showNum) ? $showNum[$prow['slug']] : ' '; $overview .= '</td></tr></table></a>'; } $overview .= '</table>'; } return "<div class='userpage'>{$flexigrids} {$recent} {$studentTable} {$overview}</div>"; }