Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/course/configuration/nbgrader.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Checkbox } from "@cocalc/frontend/antd-bootstrap";6import {7CSS,8redux,9useActions,10useRedux,11} from "@cocalc/frontend/app-framework";12import { A, Icon } from "@cocalc/frontend/components";13import { InputNumber } from "antd";14import { SelectProject } from "@cocalc/frontend/projects/select-project";15import { Card, Radio } from "antd";16import { CourseActions } from "../actions";17import {18NBGRADER_CELL_TIMEOUT_MS,19NBGRADER_MAX_OUTPUT,20NBGRADER_MAX_OUTPUT_PER_CELL,21NBGRADER_TIMEOUT_MS,22} from "../assignments/consts";2324const radioStyle: CSS = {25display: "block",26whiteSpace: "normal",27fontWeight: "inherit",28};2930interface Props {31name: string;32}3334export function Nbgrader({ name }: Props) {35const settings = useRedux([name, "settings"]);36const course_project_id = useRedux([name, "course_project_id"]);37const actions: CourseActions = useActions({ name });38if (actions == null) {39throw Error("bug");40}4142function render_grade_project(): JSX.Element {43const location = settings?.get("nbgrader_grade_project")44? "project"45: "student";46return (47<div48style={{49border: "1px solid lightgrey",50padding: "10px",51borderRadius: "5px",52}}53>54<h6>55Where to autograde assignments:{" "}56{location == "student"57? "in each student's project"58: "specific project"}59</h6>60<Radio.Group61onChange={(e) => {62if (e.target.value == "student") {63actions.configuration.set_nbgrader_grade_project("");64} else {65actions.configuration.set_nbgrader_grade_project(66course_project_id,67);68}69}}70value={location}71>72<Radio value={"student"} key={"student"} style={radioStyle}>73Grade assignments in each student's own project74</Radio>75<Radio value={"project"} key={"project"} style={radioStyle}>76Grade assignments in a project of your choice77</Radio>78</Radio.Group>79<br />80{location == "project" && (81<div>82<SelectProject83style={{ width: "100%", padding: "5px 25px" }}84onChange={actions.configuration.set_nbgrader_grade_project}85value={settings?.get("nbgrader_grade_project")}86/>87{settings?.get("nbgrader_grade_project") &&88settings?.get("nbgrader_grade_project") != course_project_id && (89<a90style={{ marginLeft: "25px" }}91onClick={() =>92redux.getActions("projects").open_project({93project_id: settings?.get("nbgrader_grade_project"),94switch_to: true,95})96}97>98Open grading project...99</a>100)}101</div>102)}103<hr />104<i>Where to grade:</i> choose the project in which to run autograding.105You can create a new project dedicated to running nbgrader, upgrade or106license it appropriately, and copy any files to it that student work107depends on. This new project will be shared will all collaborators of108this instructorproject.109<br />110You can also grade all student work in the student's own project, which111is good because the code runs in the same environment as the student112work (and won't harm any files you have), but can be slower since each113student project has to start running.114</div>115);116}117118function render_include_hidden_tests(): JSX.Element {119return (120<div121style={{122border: "1px solid lightgrey",123padding: "10px",124borderRadius: "5px",125}}126>127<h6>128Nbgrader hidden tests:{" "}129{settings?.get("nbgrader_include_hidden_tests")130? "Included"131: "NOT included"}132</h6>133<Checkbox134checked={settings?.get("nbgrader_include_hidden_tests")}135onChange={(e) =>136actions.configuration.set_nbgrader_include_hidden_tests(137(e.target as any).checked,138)139}140>141<i>Include the hidden tests:</i> Select this if you want the notebook142to contain why answers failed your hidden tests. The drawback is that143if you return assignments to your students, then you will reveal all144the hidden tests to the students.145</Checkbox>146</div>147);148}149150function render_timeouts(): JSX.Element {151const timeout = Math.round(152settings.get("nbgrader_timeout_ms", NBGRADER_TIMEOUT_MS) / 1000,153);154const cell_timeout = Math.round(155settings.get("nbgrader_cell_timeout_ms", NBGRADER_CELL_TIMEOUT_MS) / 1000,156);157return (158<div159style={{160border: "1px solid lightgrey",161padding: "10px",162borderRadius: "5px",163}}164>165<h6>Nbgrader timeouts: {timeout} seconds</h6>166<i>Grading timeout in seconds:</i> if grading a student notebook takes167longer than <i>{timeout} seconds</i>, then it is terminated with a168timeout error.169<InputNumber170onChange={(n) =>171actions.configuration.set_nbgrader_timeout_ms(172n ? n * 1000 : undefined,173)174}175min={30}176max={3600}177value={timeout}178/>179<br />180<i>Cell grading timeout in seconds:</i> if grading a cell in a student181notebook takes longer than <i>{cell_timeout} seconds</i>, then that cell182is terminated with a timeout error.183<InputNumber184onChange={(n) =>185actions.configuration.set_nbgrader_cell_timeout_ms(186n ? Math.min(n * 1000, timeout * 1000) : undefined,187)188}189min={5}190max={3600}191value={cell_timeout}192/>193</div>194);195}196197function render_limits(): JSX.Element {198const max_output = Math.round(199settings.get("nbgrader_max_output", NBGRADER_MAX_OUTPUT),200);201const max_output_per_cell = Math.round(202settings.get(203"nbgrader_max_output_per_cell",204NBGRADER_MAX_OUTPUT_PER_CELL,205),206);207return (208<div209style={{210border: "1px solid lightgrey",211padding: "10px",212borderRadius: "5px",213}}214>215<h6>Nbgrader output limits: {Math.round(max_output / 1000)} KB</h6>216<i>Max output:</i> if total output from all cells exceeds{" "}217{Math.round(max_output / 1000)} KB, then further output is truncated.218<InputNumber219onChange={(n) =>220actions.configuration.set_nbgrader_max_output(221n ? n * 1000 : undefined,222)223}224min={1}225max={10000}226value={Math.round(max_output / 1000)}227/>228<br />229<i>Max output per cell:</i> if output from a cell exceeds{" "}230{Math.round(max_output_per_cell / 1000)} KB, then further output is231truncated.232<InputNumber233onChange={(n) =>234actions.configuration.set_nbgrader_max_output_per_cell(235n ? n * 1000 : undefined,236)237}238min={1}239max={10000}240value={Math.round(max_output_per_cell / 1000)}241/>242</div>243);244}245246function render_parallel(): JSX.Element {247const parallel = Math.round(248settings.get("nbgrader_parallel") ??249actions.get_store().get_nbgrader_parallel(),250);251return (252<div253style={{254border: "1px solid lightgrey",255padding: "10px",256borderRadius: "5px",257}}258>259<h6>260Nbgrader parallel limit:{" "}261{parallel > 1262? `grade ${parallel} students at once`263: "one student a time"}264</h6>265<i>Max number of students</i> to grade in parallel. What is optimal266could depend on where grading is happening (see "Where to autograde267assignments" above), and compute resources you or your students have268bought.269<InputNumber270onChange={(n) =>271actions.configuration.set_nbgrader_parallel(n ? n : undefined)272}273min={1}274max={50}275value={parallel}276/>277</div>278);279}280281return (282<Card283title={284<A href="https://doc.cocalc.com/teaching-nbgrader.html">285<Icon name="graduation-cap" /> Nbgrader286</A>287}288>289{render_grade_project()}290<br />291{render_include_hidden_tests()}292<br />293{render_timeouts()}294<br />295{render_limits()}296<br />297{render_parallel()}298</Card>299);300}301302303