diff --git a/.gitignore b/.gitignore index 52b8674..735da4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,102 @@ -docker/build.log -scripts/container.txt +### https://github.com/github/gitignore/blob/697a1e236a3ebde2ae68456dc90988bc763c42ac/Java.gitignore + + + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + + +### https://github.com/github/gitignore/blob/697a1e236a3ebde2ae68456dc90988bc763c42ac/Global/Eclipse.gitignore + + + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + + + +### https://github.com/github/gitignore/blob/697a1e236a3ebde2ae68456dc90988bc763c42ac/Maven.gitignore + + + +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# Exclude maven wrapper +!/.mvn/wrapper/maven-wrapper.jar diff --git a/README.md b/README.md index 7017537..2551799 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,11 @@ -# JOE: Java Online Exercises +# nbgraderutils: Automatically graded Java web exercises -This repository provides scripts and information to offer web-based Java (and C++, Python) assignments. +This branch provides a Java/Maven template to create new assignments. -It uses *Jupyter Notebook* for web access and the extension *nbgrader* for automatically graded assignments. -Additionally, *JupyterHub* manages multiple users, *IJava* provides language support, and files are managed by *Docker*. +An assignment consists of several exercises. -If you haven't heard of *nbgrader* yet, you can watch the video [YouTube: nbgrader at SciPy 2017](https://www.youtube.com/watch?v=5WUm0QuJdFw). +With this template, you can provide: - -## Quick start - -1. **Install Docker** - [www.docker.com](https://www.docker.com/) -2. **Download and unpack JOE** - `wget https://github.com/dice-group/JavaOnlineExercises/archive/master.zip` - `unzip master.zip` -3. **Build Docker image** - `sudo docker build -t nbgjava:latest JavaOnlineExercises-master/docker/` - (This takes about 9 minutes.) -4. **Run Docker container** - `sudo docker run -t -d -p 8000:8000 --name nbgjava nbgjava:latest` -5. **Initialize the system** - `sudo ./JavaOnlineExercises-master/scripts/initialize.sh` - (This creates example student accounts *nbgtesta*, *nbgtestb*, and *nbgtestc*. - It also copies assignment templates.) -6. **Go ahead** - Open [https://localhost:8000/](https://localhost:8000/) - Ignore messages like 'Your connection is not private' for now. - You can use the teacher account *nbgadmin*, and the student test accounts *nbgtesta*, *nbgtestb*, *nbgtestc*, and *nbguser*. - All passwords are *nbgpsw*. You have to change the passwords for public installations. - -The [wiki](https://github.com/dice-group/JavaOnlineExercises/wiki) provides detailed descriptions. -There are scripts for an installation on a virtual machine. This variant provides a mounted directory to create backups. It is described on the [installation](https://github.com/dice-group/nbgraderutils/wiki/Installation) wiki page. - -## Info - -- Code - https://github.com/dice-group/JavaOnlineExercises -- Documentation - https://github.com/dice-group/JavaOnlineExercises/wiki -- Credits - Data Science Group (DICE) at Paderborn University - Adrian Wilke and Michael Röder - https://dice-research.org/ +- Exercises and solutions (src/main/java) +- Tests for auto-grading (src/test/java) +- Instructions for students (src/main/resources) \ No newline at end of file diff --git a/docker/1-build-image.sh b/docker/1-build-image.sh deleted file mode 100755 index fe8c339..0000000 --- a/docker/1-build-image.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# This file builds a docker image based on a dockerfile. -# The output is written to build.log - - - -# Uncomment for disabling script (as it has to be executed only one time) - -#echo "Script disabled." ; exit - - - -# Configuration - -IMAGE_NAME="nbgjava" -TAG_NAME="latest" - - - -# Ensure correct working directory - -cd "$(dirname "$0")" - - - -# Execution - -echo "Monitor the progress with: tail -f -n 20 build.log" -docker build -t $IMAGE_NAME:$TAG_NAME . >> build.log diff --git a/docker/2-run-container.sh b/docker/2-run-container.sh deleted file mode 100755 index b24db64..0000000 --- a/docker/2-run-container.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash - -# This file builds and runs a docker container based on a docker image. -# It publishes a nbgrader container port to a host port. -# It mounts the home directory for backups. - - - -# Uncomment for disabling script (as it has to be executed only one time) - -#echo "Script disabled." ; exit - - - -# Configuration - -CONTAINER_NAME="nbgjava" -PORT_HOST="8000" -MOUNT_DIR_HOST="/mnt/nbgjava" - -# Image source for the container to create -IMAGE_NAME="nbgjava" -TAG_NAME="latest" - -# Static Container configuration -MOUNT_DIR_CONTAINER="/home/nbgadmin" -PORT_CONTAINER="8000" - - - -# Ensure correct working directory - -cd "$(dirname "$0")" - - - -# Execution - -docker run \ --t -d \ --p $PORT_HOST:$PORT_CONTAINER \ --v $MOUNT_DIR_HOST:$MOUNT_DIR_CONTAINER \ ---name $CONTAINER_NAME \ -$IMAGE_NAME:$TAG_NAME - - - -# Create container info in scripts directory - -if [ -e ../scripts ] -then - echo $CONTAINER_NAME > ../scripts/container.txt -fi - - - -# Restore admin home - -docker exec $CONTAINER_NAME [ -d /home/nbgadmin ] || mkdir /home/nbgadmin -docker exec $CONTAINER_NAME cp -Rp /home/.nbgadmin/. /home/nbgadmin/ diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 4d84108..0000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,194 +0,0 @@ -# Dockerfile for Jupyter notebook + nbgrader + Java kernel -# https://github.com/dice-group/nbgraderutils - - - -# Based on -# Jupyterhub 1.0.0 -# which is based on -# Ubuntu 18.04 LTS -# https://jupyterhub.readthedocs.io/en/stable/quickstart-docker.html -# https://hub.docker.com/r/jupyterhub/jupyterhub/ -# https://hub.docker.com/r/library/ubuntu/ -# https://github.com/jupyterhub/jupyterhub/blob/0.9.4/Dockerfile - -FROM jupyterhub/jupyterhub:1.0.0 -LABEL maintainer="Adrian Wilke " - - - -# Update the system and install -# - APT utils - -RUN apt-get -y update && \ - apt-get -y install \ - apt-utils - - - -# Upgrade the system and install -# - nano editor -# - zip (including unzip) - -RUN apt-get -y upgrade && \ - apt-get -y install \ - nano \ - zip - - - -# Install Java -# - Java 11 JRE (OpenJDK) -# - Java 11 JDK (OpenJDK) -# https://wiki.ubuntuusers.de/Java/Installation/OpenJDK/ - -RUN apt-get -y install \ - openjdk-11-jre \ - openjdk-11-jdk \ - openjdk-11-demo \ - openjdk-11-doc \ - openjdk-11-jre-headless \ - openjdk-11-source \ - && \ - apt-get purge && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - - - -# Install Jupyter notebook -# https://hub.docker.com/r/jupyterhub/jupyterhub/#installation - -RUN python3 -m pip install notebook - - - -# Install Java kernel / iJava -# https://github.com/SpencerPark/IJava -RUN wget --quiet https://github.com/SpencerPark/IJava/releases/download/v1.3.0/ijava-1.3.0.zip && \ - unzip ijava-1.3.0.zip && \ - python3 install.py --sys-prefix - - - -# Create linux users (default admin and user for nbgrader) -# Set default password nbgpsw - -RUN useradd --create-home nbgadmin && \ - useradd --create-home nbguser && \ - usermod --password \$1\$xg4dbNmA\$ygNrKGsFBsu8hXoGieRSK0 nbgadmin && \ - usermod --password \$1\$xg4dbNmA\$ygNrKGsFBsu8hXoGieRSK0 nbguser - - - -# Install nbgrader -# Create directory for pushing/pulling assignments -# Disable extensions for non-admins -# https://conda-forge.org/docs/ -# https://anaconda.org/conda-forge/nbgrader/labels -# https://nbgrader.readthedocs.io/en/stable/user_guide/installation.html - -RUN conda update -n base conda && \ - conda install -c conda-forge nbgrader=0.6.1 && \ - jupyter nbextension disable --sys-prefix create_assignment/main && \ - jupyter nbextension disable --sys-prefix formgrader/main --section=tree && \ - runuser -l nbgadmin -c '/opt/conda/bin/jupyter nbextension enable --user create_assignment/main' && \ - runuser -l nbgadmin -c '/opt/conda/bin/jupyter nbextension enable --user formgrader/main --section=tree' - - - -# Create certificate for HTTPS - -RUN mkdir -p /opt/ssl && \ - cd /opt/ssl && \ - /usr/bin/openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=DE/ST=NRW/L=Paderborn/O=UPB/OU=DICE/CN=dice.cs.upb.de" - - - -# Configure JupyterHub -# https://jupyterhub.readthedocs.io/en/stable/getting-started/security-basics.html -# https://jupyterhub.readthedocs.io/en/stable/getting-started/authenticators-users-basics.html -# https://jupyterhub.readthedocs.io/en/stable/reference/config-user-env.html - -RUN cd /srv/jupyterhub/ && \ - jupyterhub --generate-config && \ - sed -i 's/^#c.JupyterHub.ssl_cert.*/c.JupyterHub.ssl_cert = "\/opt\/ssl\/cert.pem"/' /srv/jupyterhub/jupyterhub_config.py && \ - sed -i 's/^#c.JupyterHub.ssl_key.*/c.JupyterHub.ssl_key = "\/opt\/ssl\/key.pem"/' /srv/jupyterhub/jupyterhub_config.py && \ - sed -i 's/^#c.Authenticator.admin_users.*/c.Authenticator.admin_users = set(["nbgadmin"])/' /srv/jupyterhub/jupyterhub_config.py && \ - cd /mnt && \ - ln -s /srv/jupyterhub/jupyterhub_config.py - - - -# Configure Jupyter -# https://jupyterhub.readthedocs.io/en/stable/getting-started/config-basics.html -# https://jupyterhub.readthedocs.io/en/stable/reference/config-user-env.html -# https://jupyter-notebook.readthedocs.io/en/stable/config_overview.html -RUN jupyter notebook --generate-config && \ - sed -i 's/^#c.NotebookApp.shutdown_no_activity_timeout.*/c.NotebookApp.shutdown_no_activity_timeout = 60 * 60/' /root/.jupyter/jupyter_notebook_config.py && \ - sed -i 's/^#c.MappingKernelManager.cull_idle_timeout.*/c.MappingKernelManager.cull_idle_timeout = 20 * 60/' /root/.jupyter/jupyter_notebook_config.py && \ - sed -i 's/^#c.MappingKernelManager.cull_interval.*/c.MappingKernelManager.cull_interval = 2 * 60/' /root/.jupyter/jupyter_notebook_config.py \ - && \ - [ -d /etc/jupyter/ ] || mkdir -p /etc/jupyter/ && \ - mv /root/.jupyter/jupyter_notebook_config.py /etc/jupyter/ && \ - ln -s /etc/jupyter/jupyter_notebook_config.py /mnt/ - - - -# Configure nbgrader -# https://nbgrader.readthedocs.io/en/stable/configuration/config_options.html -# https://nbgrader.readthedocs.io/en/stable/user_guide/managing_assignment_files.html#id8 - -RUN mkdir -p /srv/nbgrader/exchange && \ - chmod ugo+rw /srv/nbgrader/exchange \ - && \ - printf "c = get_config()\n\ -c.CourseDirectory.course_id = \"default-course\"\n\ -c.Exchange.root = '/srv/nbgrader/exchange'\n\ -c.ExecutePreprocessor.timeout = 300\n\ -c.ClearSolutions.code_stub = {\n\ -'python': '# YOUR CODE HERE',\n\ -'java': '// YOUR CODE HERE',\n\ -}" \ -> /opt/conda/etc/jupyter/nbgrader_config.py \ - && \ - cd /mnt && \ - ln -s /opt/conda/etc/jupyter/nbgrader_config.py - - - -# Create nbgrader accounts for nbgadmin and nbguser -# (Avoids autograding errors, if these accounts submitted solution) - -RUN cd /home/nbgadmin/ && \ - nbgrader db student add nbgadmin && \ - nbgrader db student add nbguser - - - -# - Default filesystem permissions -# New homes not readable by others -# - Homes group is nbgadmin for providing feedback -# - Strict permissions for SSL and /mnt -# - Directory to distribute files - -RUN sed -i 's/^DIR_MODE=0755.*/DIR_MODE=0770/' /etc/adduser.conf && \ - chmod go-rwx /home/* && \ - chmod g+rwx /home/* \ - && \ - chgrp nbgadmin /home/* \ - && \ - chmod -R o-rwx /opt/ssl && \ - chmod o-rwx /mnt \ - && \ - mkdir /srv/distribution && \ - chown nbgadmin:nbgadmin /srv/distribution/ && \ - echo "hello world!" > /srv/distribution/hello-world.txt && \ - chmod 775 /srv/distribution/hello-world.txt - - - -# Create backup of admin users home - -RUN cp -Rp /home/nbgadmin/ /home/.nbgadmin/ && \ - chown nbgadmin:nbgadmin /home/.nbgadmin/ diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index a274f62..0000000 --- a/docker/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# nbgraderutils - -## Files -- `1-build-image.sh` and `Dockerfile` - Shell script and commands to build and assemble docker image -- `2-run-container.sh` - Shell script to build and run a docker container based on the docker image - -## Info - -- Code - https://github.com/dice-group/nbgraderutils -- Documentation - https://github.com/dice-group/nbgraderutils/wiki -- Credits - https://dice.cs.uni-paderborn.de/ \ No newline at end of file diff --git a/examples/AssignmentAdministration.ipynb b/examples/AssignmentAdministration.ipynb deleted file mode 100644 index 8843601..0000000 --- a/examples/AssignmentAdministration.ipynb +++ /dev/null @@ -1,306 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Assignment administration\n", - "\n", - "- Run the following cell.\n", - "- Follow the instructions below." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%maven commons-io:commons-io:2.6\n", - "import org.apache.commons.io.FileUtils;\n", - "import org.apache.commons.io.filefilter.TrueFileFilter;\n", - "\n", - "void createAssignment(String assignmentName, int numberOfExercises) throws Exception {\n", - " if(assignmentName == null || assignmentName.isEmpty()){\n", - " throw new Exception(\"No assignment name\");\n", - " }\n", - " \n", - " File templateDirectory = new File(\"/home/nbgadmin/templates/\");\n", - " File sourceDirectory = new File(\"/home/nbgadmin/source/\");\n", - " File assignmentDirectory = new File(sourceDirectory, assignmentName);\n", - " if (!templateDirectory.exists() || !templateDirectory.canRead()) {\n", - " throw new Exception(\"Can not read: \" + templateDirectory.getPath());\n", - " }\n", - " if (!sourceDirectory.exists()) {\n", - " sourceDirectory.mkdirs();\n", - " }\n", - " if (!sourceDirectory.canWrite()) {\n", - " throw new Exception(\"Can not write: \" + sourceDirectory.getPath());\n", - " }\n", - " if (assignmentDirectory.exists()) {\n", - " throw new Exception(\"Already existing: \" + assignmentDirectory.getPath());\n", - " }\n", - " \n", - " for (File file : templateDirectory.listFiles(new FilenameFilter() {\n", - " public boolean accept(File directory, String name) {\n", - " if (name.endsWith(\".ipynb\")) {\n", - " return true;\n", - " } else {\n", - " return false;\n", - " }\n", - " }\n", - " })) {\n", - " if (file.getName().equals(\"AssignmentTemplate.ipynb\")) {\n", - " for (int i = 1; i <= numberOfExercises; i++) {\n", - " File newFile = new File(assignmentDirectory, \"Exercise-\" + i + \".ipynb\");\n", - " FileUtils.copyFile(file, newFile);\n", - " System.out.println(\"Created file: \" + newFile.getPath());\n", - " }\n", - " }\n", - " File newFile = new File(assignmentDirectory, file.getName());\n", - " FileUtils.copyFile(file, newFile);\n", - " System.out.println(\"Created file: \" + newFile.getPath());\n", - " }\n", - "}\n", - "\n", - "void copyFeedback(String assignmentName) throws Exception {\n", - " if(assignmentName == null || assignmentName.isEmpty()){\n", - " throw new Exception(\"No assignment name\");\n", - " }\n", - " \n", - " File feedbackBaseDirectory = new File(\"/home/nbgadmin/feedback/\");\n", - " if (!feedbackBaseDirectory.exists() || !feedbackBaseDirectory.canRead()) {\n", - " throw new Exception(\"Can not read: \" + feedbackBaseDirectory.getPath());\n", - " }\n", - " \n", - " int copies = 0;\n", - " int directories = 0;\n", - " for (File feedbackUserDirectory : feedbackBaseDirectory.listFiles()) {\n", - " // Should only contain directories, just skip\n", - " if(!feedbackUserDirectory.isDirectory()) {\n", - " continue;\n", - " }\n", - " File feedbackAssignmentDirectory = new File(feedbackUserDirectory, assignmentName);\n", - " // User has not participated, just skip\n", - " if (!feedbackAssignmentDirectory.exists()) {\n", - " continue;\n", - " }\n", - " \n", - " directories++;\n", - " \n", - " if (!feedbackAssignmentDirectory.canRead()) {\n", - " System.err.println(\"Can not read feedback for user, skipping: \" + feedbackAssignmentDirectory.getPath());\n", - " continue;\n", - " }\n", - " File userHomeDirectory = new File(\"/home/\" + feedbackUserDirectory.getName());\n", - " if (!userHomeDirectory.exists()) {\n", - " System.err.println(\"User home not found, skipping: \" + userHomeDirectory.getPath());\n", - " continue;\n", - " }\n", - " if (!userHomeDirectory.canWrite()) {\n", - " System.err.println(\"Can not write user home, skipping: \" + userHomeDirectory.getPath());\n", - " continue;\n", - " }\n", - " File resultsDirectory = new File(userHomeDirectory, \"results\");\n", - " if (resultsDirectory.exists() && !resultsDirectory.canWrite()) {\n", - " System.err.println(\"Can not write results: \" + resultsDirectory.getPath());\n", - " continue;\n", - " }\n", - " File assignmentResultsDirectory = new File(resultsDirectory, assignmentName);\n", - "\n", - "\t\ttry {\n", - "\t\t\tFileUtils.copyDirectory(feedbackAssignmentDirectory, assignmentResultsDirectory);\n", - "\t\t} catch (IOException e) {\n", - " System.err.println(\"Error copying: \" + e.getMessage());\n", - " continue;\n", - "\t\t}\n", - " System.out.println(\"Provided feedback: \" + assignmentResultsDirectory);\n", - " copies++;\n", - " }\n", - " System.out.println(directories + \" feedback entries found.\");\n", - " System.out.println(copies + \" feedback entries copied.\");\n", - "}\n", - "\n", - "void printAutogradeCommands(String assignmentName) {\n", - " System.out.println(\"cd \\\"/home/nbgadmin\\\"\");\n", - " System.out.println(\"nbgrader autograde \\\"\" + assignmentName + \"\\\"\");\n", - "}\n", - "\n", - "void printFeedbackCommands(String assignmentName) {\n", - " System.out.println(\"cd \\\"/home/nbgadmin\\\"\");\n", - " System.out.println(\"nbgrader feedback \\\"\" + assignmentName + \"\\\"\");\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Configuration\n", - "\n", - "Specify an **assignment name** for the next steps.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "String assignmentName = \"Example\";" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create an assignment\n", - "\n", - "1. Specify the **number of exercise files to create** in the following cell.\n", - "2. Run the createAssignment cell. It will create the assignment directory and template files." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "int numberOfExercisesFilesToCreate = 3;" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Created file: /home/nbgadmin/source/Example/FilesystemExample.ipynb\n", - "Created file: /home/nbgadmin/source/Example/MultipleChoiceExample.ipynb\n", - "Created file: /home/nbgadmin/source/Example/Exercise-1.ipynb\n", - "Created file: /home/nbgadmin/source/Example/Exercise-2.ipynb\n", - "Created file: /home/nbgadmin/source/Example/Exercise-3.ipynb\n", - "Created file: /home/nbgadmin/source/Example/AssignmentTemplate.ipynb\n" - ] - } - ], - "source": [ - "createAssignment(assignmentName, numberOfExercisesFilesToCreate);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "3. Open the [source directory in the files view](/user/nbgadmin/tree/source). \n", - " * Edit the files. \n", - " * **Delete** unused files. \n", - " * Set the points of the **autograder test cells** or remove the cells." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Release the assignment\n", - "\n", - "Open [Formgrader](/user/nbgadmin/formgrader).\n", - "\n", - "1. Click on [**Generate**]. \n", - " (Generated files will be stored in the _release_ directory.)\n", - "2. Click on [**Preview**]. \n", - " Check the generated files. \n", - " If there are errors, edit the files and continue with step 1.\n", - "3. Click on [**Release**]. \n", - " If you want to test the release, you can login as _nbgtesta_, _nbgtestb_, and _nbgtestc_.\n", - "4. You may want to make a backup of the _source/[assignmentName]_ directory to save your solution.\n", - "5. **Inform your students** about the assignment and a **deadline**." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Finish the assignment\n", - "\n", - "Open [Formgrader](/user/nbgadmin/formgrader).\n", - "\n", - "1. Click on [**Collect**]. \n", - " (Collected files will be stored in the _submitted_ directory.)\n", - "2. Click on [**Release**] to to end the release.\n", - "3. You could stop all running servers at the [hub admin](/hub/admin) (which also will affect this notebook).\n", - "4. You may want to make a backup of the _submitted_ directory to save the student solutions." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Rate the assignment\n", - "\n", - "1. Open a [terminal](/user/nbgadmin/terminals/1) and use the lines printed in the following cell to **autograde** the assignment.\n", - "2. Open [Formgrader](/user/nbgadmin/formgrader) and click on **[Manual Grading]** and rate the answers.\n", - "3. You may want to make a backup of the nbgrader database _gradebook.db_ to save the students points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "printAutogradeCommands(assignmentName);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Provide feedback\n", - "\n", - "1. Open a [terminal](/user/nbgadmin/terminals/1) and use the lines printed in the following cell to create **feedback** of the assignment.\n", - "2. Run the cell afterwards to generate feedback in HTML format and to copy the generated feedback to the students filesystem directories." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "printFeedbackCommands(assignmentName);" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "copyFeedback(assignmentName);" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.4+11-post-Ubuntu-1ubuntu218.04.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/AssignmentTemplate.ipynb b/examples/AssignmentTemplate.ipynb deleted file mode 100644 index ed7a7a9..0000000 --- a/examples/AssignmentTemplate.ipynb +++ /dev/null @@ -1,336 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "source": [ - "# Exercise: Numeric ASCII representation\n", - "\n", - "(24 points)\n", - "\n", - "Implement a method which converts a String to the numeric ASCII representation of its single characters.\n", - "\n", - "#### Example\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "

Input

Output

Type

String

int array

Value

Hi

72, 105

\n", - "\n", - "#### Hints\n", - "\n", - "- The [String class](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#toCharArray()) provides methods for conversion.\n", - "- Please read the [notes](#Notes) at the end of this notebook." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-code", - "locked": false, - "schema_version": 3, - "solution": true - } - }, - "outputs": [], - "source": [ - "public class Exercise {\n", - "\n", - " /**\n", - " * Converts a String to the numeric ASCII representation of its single\n", - " * characters.\n", - " */\n", - " public int[] toNumericAscii(String string) {\n", - " int[] result = new int[string.length()];\n", - "\n", - " // BEGIN SOLUTION\n", - "\n", - " /*\n", - " * Notes for lecturers:\n", - " *\n", - " * Markdown examples for the cell above:\n", - " * https://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Working%20With%20Markdown%20Cells.html\n", - " * \n", - " * Insert your solution inside one or several marked solution blocks. These\n", - " * blocks will be removed for students.\n", - " *\n", - " * If possible, a return variable should be defined before this marked solution\n", - " * block. It avoids unnecessary error messages, if the solution block is removed\n", - " * for the students. A null value also works.\n", - " * \n", - " * You can remove this comment.\n", - " */\n", - "\n", - " char[] chars = string.toCharArray();\n", - " for (int i = 0; i < chars.length; i++) {\n", - " result[i] = chars[i];\n", - " }\n", - "\n", - " // END SOLUTION\n", - "\n", - " return result;\n", - " }\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-evaluation", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "source": [ - "# Evaluation\n", - "\n", - "- Run the following cell to test your implementation.\n", - "- You can ignore the empty cells afterwards." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible", - "locked": true, - "points": 0, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "import org.opentest4j.AssertionFailedError;\n", - "\n", - "void test(String inputString, int[] expectedResult, String testDescription) {\n", - " try {\n", - " long time = System.currentTimeMillis();\n", - "\n", - " Assertions.assertArrayEquals(expectedResult, new Exercise().toNumericAscii(inputString),\n", - " testDescription);\n", - "\n", - " time = System.currentTimeMillis() - time;\n", - " System.out.println(\"Test(s) successfully completed. Calculation took \" + time + \" ms.\");\n", - " } catch (AssertionFailedError e) {\n", - " System.err.println(\"Your solution returned an unexpected result. \");\n", - " throw e;\n", - " } catch (Throwable e) {\n", - " System.err.println(\"Your solution caused an unexpected error. \");\n", - " throw e;\n", - " }\n", - "}\n", - "\n", - "test(\"Hi\", new int[] { 72, 105 }, \"Testing 'Hi'\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-1", - "locked": true, - "points": 14, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "/* Notes for lecturers:\n", - " *\n", - " * For the cell above 'cell-autograde-visible', there should be no points.\n", - " * Use this cell instead to create a test case similar to the visible test.\n", - " * This avoids students to just return the exact solution of the visible test.\n", - " *\n", - " * Use the last parameter of assertions to provide meaningful test descriptions.\n", - " * A description \"Test no. X\" also helps in giving feedback.\n", - " *\n", - " * Feel free to change the parameters of the method test(...).\n", - " * \n", - " * Overview of Assertions:\n", - " * https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/Assertions.html\n", - " */\n", - "\n", - "test(\"Ho\", new int[] { 72, 111 }, \"Testing 'Ho'\");\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-2", - "locked": true, - "points": 10, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "test(\"HiHo\", new int[] { 72, 105, 72, 111 }, \"Testing 'HiHo'\");\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-3", - "locked": true, - "points": 0, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-4", - "locked": true, - "points": 0, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-5", - "locked": true, - "points": 0, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-notes", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "source": [ - "# Notes\n", - "\n", - "- You are free to use a different IDE to develop your solution. However, you have to copy the solution into this notebook to submit it.\n", - "- Do not add additional external libraries.\n", - "- Interface\n", - " - You can use _[TAB]_ for autocompletion and _[SHIFT]_+_[TAB]_ for code inspection.\n", - " - Use _Menu_ > _View_ > _Toggle Line Numbers_ for debugging.\n", - " - Check _Menu_ > _Help_ > _Keyboard Shortcuts_.\n", - "- Known issues\n", - " - All global variables will be set to void after an import.\n", - " - Missing spaces around `%` (modulo operator) can cause unexpected errors so please make sure that you have added spaces around every `%` character.\n", - "- Finish\n", - " - Save your solution by clicking on the _disk icon_.\n", - " - Make sure that all necessary imports are listed at the beginning of your cell.\n", - " - Run a final check of your solution by\n", - " - Click the _fast forward arrow_ in the tool bar (or _Menu_ > _Kernel_ > _Restart & Run All_). Wait fo the kernel to restart and execute all cells (all executable cells should have numbers in front of them instead of a `[*]`).\n", - " - Check all executed cells for errors. If an exception is thrown, please check your code. Note that although the error might look cryptic, until now we never encounter that an exception was caused without a valid reason inside of the submitted code. A good way to check the code is to copy the solution into a new class in your favorite IDE and check\n", - " - errors reported by the IDE\n", - " - imports the IDE adds to your code which might be missing in your submission, here\n", - " - Finally, choose _Menu_ > _File_ > _Close and Halt_.\n", - " - Do not forget to submit your solution in the _Assignments_ view." - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".java", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "10.0.2+13-Ubuntu-1ubuntu0.18.04.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/FilesystemExample.ipynb b/examples/FilesystemExample.ipynb deleted file mode 100644 index b37a0c9..0000000 --- a/examples/FilesystemExample.ipynb +++ /dev/null @@ -1,106 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Filesystem example\n", - "\n", - "- [Apache Commons IO FileUtils](https://commons.apache.org/proper/commons-io/javadocs/api-release/index.html?org/apache/commons/io/FileUtils.html)\n", - "- The directory for shared files is `/srv/distribution/`. \n", - " Students can read, but not write." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%maven commons-io:commons-io:2.6\n", - "import org.apache.commons.io.FileUtils;\n", - "import org.apache.commons.io.filefilter.TrueFileFilter;" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Read example\n", - "\n", - "Can be used in assignments." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "File file = new File(\"/srv/distribution/hello-world.txt\");\n", - "String helloWorld = FileUtils.readFileToString(file, \"UTF-8\");\n", - "System.out.println(helloWorld);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Write example\n", - "\n", - "Only possible for nbgadmin. \n", - "Code can be used to create files for assignments." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "File tmpFile = new File(\"/srv/distribution/tmp.txt\");\n", - "FileUtils.writeStringToFile(tmpFile, \"Test\", \"UTF-8\");\n", - "String tmpString = FileUtils.readFileToString(tmpFile, \"UTF-8\");\n", - "tmpFile.delete();\n", - "System.out.println(tmpString);" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## List files example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "File distributionDirectory = new File(\"/srv/distribution/\");\n", - "Collection files = FileUtils.listFiles(distributionDirectory, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);\n", - "for (File file : files) {\n", - "\tSystem.out.println(file);\n", - "}" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".java", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.1+13-LTS" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/MultipleChoiceExample.ipynb b/examples/MultipleChoiceExample.ipynb deleted file mode 100644 index c8c8a79..0000000 --- a/examples/MultipleChoiceExample.ipynb +++ /dev/null @@ -1,253 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "source": [ - "## Multiple choice\n", - "\n", - "# Which of the possible answers represent colors?\n", - "\n", - "Set the variables to **true**, if they represent a **correct** answer.\n", - "\n", - "#### Notes\n", - "\n", - "- **Do not change the names of the variables**.\n", - "- Finish\n", - " - Save your solution by clicking on the _disk icon_.\n", - " - Finally, choose _Menu_ -> _File_ -> _Close and Halt_.\n", - " - Do not forget to _Submit_ your solution in the _Assignments_ view." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-code", - "locked": false, - "schema_version": 3, - "solution": true - } - }, - "outputs": [], - "source": [ - "boolean cat = false;\n", - "boolean green = false;\n", - "boolean red = false;\n", - "boolean dog = false;\n", - "\n", - "// BEGIN SOLUTION\n", - "green = true;\n", - "red = true;\n", - "// END SOLUTION" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-evaluation", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "source": [ - "# Evaluation\n", - "\n", - "- You can ignore the following cells." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible", - "locked": true, - "points": 0, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "import org.opentest4j.AssertionFailedError;" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-all", - "locked": true, - "points": 3, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "/* Notes for lecturers:\n", - " *\n", - " * If you want to award points ONLY if ALL solutions are correct:\n", - " * - Set all points to this cell.\n", - " * - Set the points in other autograder-test-cells to 0.\n", - " * - Do NOT delete other autograder-test-cells.\n", - " * They will provide feedback to the students.\n", - " *\n", - " * If you want to award points ONLY for EACH single solution:\n", - " * - Set the points in this cell to 0.\n", - " * - Set the points in other autograder-test-cells to 1 (or greater, if a greater sum is needed).\n", - " * - You can remove the assertions in this cell.\n", - " *\n", - " * If you want to have a combination:\n", - " * - Set points for all autograder-test-cells.\n", - " *\n", - " * Example configuration:\n", - " * - 3+1+1+1+1 = 7 points for a perfect solution.\n", - " * - 0+1+1+1+0 = 3 points, if 'dog is a color' is the opinion of the student.\n", - " *\n", - " * Overview of Assertions:\n", - " * https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/Assertions.html\n", - " */\n", - "\n", - "Assertions.assertFalse(cat, \"general test\");\n", - "Assertions.assertTrue(green, \"general test\");\n", - "Assertions.assertTrue(red, \"general test\");\n", - "Assertions.assertFalse(dog, \"general test\");\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-1", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "Assertions.assertFalse(cat, \"cat\");\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-2", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "Assertions.assertTrue(green, \"green\");\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-3", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "Assertions.assertTrue(red, \"red\");\n", - "\n", - "// END HIDDEN TESTS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-4", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "// Ignore this cell\n", - "// BEGIN HIDDEN TESTS\n", - "\n", - "Assertions.assertFalse(dog, \"dog\");\n", - "\n", - "// END HIDDEN TESTS" - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".java", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.1+13-LTS" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/TestFilesystem.ipynb b/examples/TestFilesystem.ipynb deleted file mode 100644 index 9dc1bd5..0000000 --- a/examples/TestFilesystem.ipynb +++ /dev/null @@ -1,365 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Filesystem tests" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Filesystem methods" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "String execCommand(String command) throws Exception {\n", - " // https://www.mkyong.com/java/how-to-execute-shell-command-from-java/\n", - "\n", - " Process p = Runtime.getRuntime().exec(command);\n", - " p.waitFor();\n", - " BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));\n", - "\n", - " StringBuffer sb = new StringBuffer();\n", - " String l = \"\";\n", - " while ((l = r.readLine()) != null) {\n", - " sb.append(l + \"\\n\");\n", - " }\n", - " return sb.toString();\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "private static String readFile(String file) throws Exception {\n", - " // https://howtodoinjava.com/java/io/java-read-file-to-string-examples/\n", - "\n", - " StringBuilder sb = new StringBuilder();\n", - " BufferedReader br = new BufferedReader(new FileReader(file));\n", - " String l;\n", - " while ((l = br.readLine()) != null) {\n", - " sb.append(l).append(\"\\n\");\n", - " }\n", - " br.close();\n", - " return sb.toString();\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Config: Is current user an admin?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "boolean admin = false;\n", - "if(\"nbgadmin\".equals(execCommand(\"whoami\").trim())) {\n", - " admin = true;\n", - "}\n", - "System.out.println(\"You are\" + (admin ? \"\" : \" not\") + \" logged in as admin.\");" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tests" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Home directories" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "String user = execCommand(\"whoami\").trim();\n", - "\n", - "for (File f : new File(\"/home\").listFiles()) {\n", - " if(f.isDirectory()) {\n", - " if(f.getName().equals(user) || admin) {\n", - " Assertions.assertTrue(f.canRead(), \"canRead \" + f.getPath());\n", - " } else {\n", - " Assertions.assertFalse(f.canRead(), \"canRead \" + f.getPath());\n", - " }\n", - " }\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Distribution and exchange directory" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "// Read\n", - "Assertions.assertEquals(\"hello world!\".trim(), readFile(\"/srv/distribution/hello-world.txt\").trim());\n", - "\n", - "// Write\n", - "if(admin) {\n", - " Assertions.assertTrue(new File(\"/srv/distribution\").canWrite(), \"canWrite /srv/distribution\");\n", - "} else {\n", - " Assertions.assertFalse(new File(\"/srv/distribution\").canWrite(), \"canWrite /srv/distribution\");\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "// Read\n", - "Assertions.assertTrue(new File(\"/srv/nbgrader/exchange\").canRead(), \"canRead /srv/nbgrader/exchange\");\n", - "\n", - "// Write\n", - "if(admin) {\n", - " Assertions.assertTrue(new File(\"/srv/nbgrader/exchange\").canWrite(), \"canWrite /srv/nbgrader/exchange\");\n", - " Assertions.assertFalse(new File(\"/srv/nbgrader\").canWrite(), \"canWrite /srv/nbgrader\");\n", - "} else {\n", - " Assertions.assertTrue(new File(\"/srv/nbgrader/exchange\").canWrite(), \"canWrite /srv/nbgrader/exchange\");\n", - " Assertions.assertFalse(new File(\"/srv/nbgrader\").canWrite(), \"canWrite /srv/nbgrader\");\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Configuration directories" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Assertions.assertFalse(new File(\"/mnt\").canRead(), \"canWrite /mnt\");\n", - "Assertions.assertFalse(new File(\"/mnt\").canWrite(), \"canWrite /mnt\");\n", - "\n", - "File nCfg = new File(\"/opt/conda/etc/jupyter/nbgrader_config.py\");\n", - "Assertions.assertFalse(nCfg.canWrite(), \"canWrite \" + nCfg.getPath());\n", - "\n", - "File jCfg = new File(\"/srv/jupyterhub/jupyterhub_config.py\");\n", - "Assertions.assertFalse(jCfg.canWrite(), \"canWrite \" + jCfg.getPath());" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Installation directories" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for (File f : new File(\"/opt\").listFiles()) {\n", - " \n", - " // Read\n", - " if(f.getName().equals(\"Oracle_Java\") || f.getName().equals(\"conda\")) {\n", - " Assertions.assertTrue(f.canRead(), \"canRead \" + f.getPath());\n", - " } else {\n", - " Assertions.assertFalse(f.canRead(), \"canRead \" + f.getPath()); \n", - " }\n", - " \n", - " // Write\n", - " Assertions.assertFalse(f.canWrite(), \"canWrite \" + f.getPath());\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for (File f : new File(\"/srv\").listFiles()) {\n", - " \n", - " // Read\n", - " Assertions.assertTrue(f.canRead(), \"canRead \" + f.getPath());\n", - " \n", - " // Write\n", - " if(f.getName().equals(\"distribution\")) {\n", - " if(admin) {\n", - " Assertions.assertTrue(f.canWrite(), \"canWrite \" + f.getPath());\n", - " } else {\n", - " Assertions.assertFalse(f.canWrite(), \"canWrite \" + f.getPath());\n", - " }\n", - " } else {\n", - " Assertions.assertFalse(f.canWrite(), \"canWrite \" + f.getPath());\n", - " }\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Human tests" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "void printFilePermissions(String directory) throws Exception {\n", - " for (File f : new File(directory).listFiles()) {\n", - " System.out.print(f.isDirectory() ? \"d\" : \" \");\n", - " System.out.print(f.canRead() ? \"r\" : \" \");\n", - " System.out.print(f.canWrite() ? \"w\" : \" \");\n", - " System.out.print(f.canExecute() ? \"x\" : \" \");\n", - " System.out.println(\" \" + f.getCanonicalPath());\n", - " }\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "System.out.println(execCommand(\"whoami\"));" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "printFilePermissions(\"/home\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "// only if current user equals\n", - "printFilePermissions(\"/home/nbgadmin\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "// only if current user equals or as admin\n", - "printFilePermissions(\"/home/nbguser\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "readFile(\"/srv/distribution/hello-world.txt\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "// should not work\n", - "printFilePermissions(\"/mnt\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "printFilePermissions(\"/opt\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "printFilePermissions(\"/srv\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "printFilePermissions(\"/srv/nbgrader/\");" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".java", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.1+13-LTS" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/TestTime.ipynb b/examples/TestTime.ipynb deleted file mode 100644 index 6d2180d..0000000 --- a/examples/TestTime.ipynb +++ /dev/null @@ -1,114 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "source": [ - "# Time test\n", - "\n", - "This tests the maximum execution time. \n", - "It is defined by nbgrader option `ExecutePreprocessor.timeout`. \n", - "The test has to be executed as an assignment." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-code", - "locked": false, - "schema_version": 3, - "solution": true - } - }, - "outputs": [], - "source": [ - "// BEGIN SOLUTION\n", - "// END SOLUTION\n", - "int timeoutSeconds = 300;\n", - "boolean testShouldPass = false;" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-a74effbecac8c29b", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "boolean doSomething(int timeoutSeconds) throws java.lang.InterruptedException {\n", - " long time = System.currentTimeMillis();\n", - " long end = time + (timeoutSeconds * 1000);\n", - " while(System.currentTimeMillis() < end) {\n", - " Thread.sleep(490);\n", - " time = System.currentTimeMillis();\n", - " }\n", - " return true;\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "\n", - "if(testShouldPass) {\n", - " System.out.println(\"Waiting \" + (timeoutSeconds - 20) + \" seconds\");\n", - " Assertions.assertTrue(doSomething(timeoutSeconds - 20));\n", - "} else {\n", - " System.out.println(\"Waiting \" + (timeoutSeconds + 10) + \" seconds\");\n", - " Assertions.assertTrue(doSomething(timeoutSeconds + 10));\n", - "}\n", - "System.out.println(\"Test(s) successfully completed\");" - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.4+11-post-Ubuntu-1ubuntu218.04.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/TimeoutContinuationTest/TimeoutContinuationTest-A.ipynb b/examples/TimeoutContinuationTest/TimeoutContinuationTest-A.ipynb deleted file mode 100644 index 771791f..0000000 --- a/examples/TimeoutContinuationTest/TimeoutContinuationTest-A.ipynb +++ /dev/null @@ -1,69 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "source": [ - "# Timeout continuation test\n", - "\n", - "Tests, if the grading of all ngbrader-tests continue, even if there is a timeout during one single test. \n", - "The test has to be auto-graded. \n", - "\n", - "One test in one file should fail. \n", - "The overall grading should result in 40 points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible", - "locked": true, - "points": 10, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "\n", - "System.out.println(\"Testing A\");\n", - "\n", - "Assertions.assertTrue(true);" - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.4+11-post-Ubuntu-1ubuntu218.04.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} - diff --git a/examples/TimeoutContinuationTest/TimeoutContinuationTest-B.ipynb b/examples/TimeoutContinuationTest/TimeoutContinuationTest-B.ipynb deleted file mode 100644 index 89e4ea9..0000000 --- a/examples/TimeoutContinuationTest/TimeoutContinuationTest-B.ipynb +++ /dev/null @@ -1,69 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "source": [ - "# Timeout continuation test\n", - "\n", - "Tests, if the grading of all ngbrader-tests continue, even if there is a timeout during one single test. \n", - "The test has to be auto-graded. \n", - "\n", - "One test in one file should fail. \n", - "The overall grading should result in 40 points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible", - "locked": true, - "points": 10, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "\n", - "System.out.println(\"Testing B\");\n", - "\n", - "Assertions.assertTrue(true);" - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.4+11-post-Ubuntu-1ubuntu218.04.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} - diff --git a/examples/TimeoutContinuationTest/TimeoutContinuationTest-C-Fails.ipynb b/examples/TimeoutContinuationTest/TimeoutContinuationTest-C-Fails.ipynb deleted file mode 100644 index 92f5542..0000000 --- a/examples/TimeoutContinuationTest/TimeoutContinuationTest-C-Fails.ipynb +++ /dev/null @@ -1,201 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "source": [ - "# Timeout continuation test\n", - "\n", - "Tests, if the grading of all ngbrader-tests continue, even if there is a timeout during one single test. \n", - "The test has to be auto-graded. \n", - "\n", - "One test in one file should fail. \n", - "The overall grading should result in 40 points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-code", - "locked": false, - "schema_version": 3, - "solution": true - } - }, - "outputs": [], - "source": [ - "// BEGIN SOLUTION\n", - "// END SOLUTION\n", - "int timeoutSecondsPass = 1;\n", - "int timeoutSecondsFail = 400;" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-a74effbecac8c29b", - "locked": true, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "boolean doSomething(int timeoutSeconds) throws java.lang.InterruptedException {\n", - " long time = System.currentTimeMillis();\n", - " long end = time + (timeoutSeconds * 1000);\n", - " System.out.println(\"\");\n", - " while(System.currentTimeMillis() < end) {\n", - " System.out.print(((end-time)/1000) + \" \");\n", - " Thread.sleep(5000);\n", - " time = System.currentTimeMillis();\n", - " }\n", - " System.out.println(\"\");\n", - " return true;\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible-1", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "\n", - "System.out.println(\"Testing C\");\n", - "\n", - "System.out.println(\"Waiting \" + timeoutSecondsPass + \" seconds\");\n", - "Assertions.assertTrue(doSomething(timeoutSecondsPass));\n", - "System.out.println(\"Test 1 successfully completed\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible-2", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "System.out.println(\"Waiting \" + timeoutSecondsPass + \" seconds\");\n", - "Assertions.assertTrue(doSomething(timeoutSecondsPass));\n", - "System.out.println(\"Test 2 successfully completed\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible-3", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false - } - }, - "outputs": [], - "source": [ - "System.out.println(\"Waiting \" + timeoutSecondsFail + \" seconds\");\n", - "Assertions.assertTrue(doSomething(timeoutSecondsFail));\n", - "System.out.println(\"Test 3 successfully completed\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible-4", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "System.out.println(\"Waiting \" + timeoutSecondsPass + \" seconds\");\n", - "Assertions.assertTrue(doSomething(timeoutSecondsPass));\n", - "System.out.println(\"Test 4 successfully completed\");" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible-5", - "locked": true, - "points": 1, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "System.out.println(\"Waiting \" + timeoutSecondsPass + \" seconds\");\n", - "Assertions.assertTrue(doSomething(timeoutSecondsPass));\n", - "System.out.println(\"Test 5 successfully completed\");" - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.4+11-post-Ubuntu-1ubuntu218.04.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} - diff --git a/examples/TimeoutContinuationTest/TimeoutContinuationTest-D.ipynb b/examples/TimeoutContinuationTest/TimeoutContinuationTest-D.ipynb deleted file mode 100644 index 120d674..0000000 --- a/examples/TimeoutContinuationTest/TimeoutContinuationTest-D.ipynb +++ /dev/null @@ -1,69 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "source": [ - "# Timeout continuation test\n", - "\n", - "Tests, if the grading of all ngbrader-tests continue, even if there is a timeout during one single test. \n", - "The test has to be auto-graded. \n", - "\n", - "One test in one file should fail. \n", - "The overall grading should result in 40 points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible", - "locked": true, - "points": 10, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "\n", - "System.out.println(\"Testing D\");\n", - "\n", - "Assertions.assertTrue(true);" - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.4+11-post-Ubuntu-1ubuntu218.04.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} - diff --git a/examples/TimeoutContinuationTest/TimeoutContinuationTest-E.ipynb b/examples/TimeoutContinuationTest/TimeoutContinuationTest-E.ipynb deleted file mode 100644 index 7cd618f..0000000 --- a/examples/TimeoutContinuationTest/TimeoutContinuationTest-E.ipynb +++ /dev/null @@ -1,69 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "nbgrader": { - "grade": false, - "grade_id": "cell-markdown-task", - "locked": true, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "source": [ - "# Timeout continuation test\n", - "\n", - "Tests, if the grading of all ngbrader-tests continue, even if there is a timeout during one single test. \n", - "The test has to be auto-graded. \n", - "\n", - "One test in one file should fail. \n", - "The overall grading should result in 40 points." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbgrader": { - "grade": true, - "grade_id": "cell-autograde-visible", - "locked": true, - "points": 10, - "schema_version": 3, - "solution": false, - "task": false - } - }, - "outputs": [], - "source": [ - "%maven org.junit.jupiter:junit-jupiter-api:5.3.1\n", - "import org.junit.jupiter.api.Assertions;\n", - "\n", - "System.out.println(\"Testing E\");\n", - "\n", - "Assertions.assertTrue(true);" - ] - } - ], - "metadata": { - "celltoolbar": "Create Assignment", - "kernelspec": { - "display_name": "Java", - "language": "java", - "name": "java" - }, - "language_info": { - "codemirror_mode": "java", - "file_extension": ".jshell", - "mimetype": "text/x-java-source", - "name": "Java", - "pygments_lexer": "java", - "version": "11.0.4+11-post-Ubuntu-1ubuntu218.04.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} - diff --git a/examples/teststudents.ENCRYPTED.csv b/examples/teststudents.ENCRYPTED.csv deleted file mode 100644 index ef3945d..0000000 --- a/examples/teststudents.ENCRYPTED.csv +++ /dev/null @@ -1,3 +0,0 @@ -nbgtesta,$1$xg4dbNmA$ygNrKGsFBsu8hXoGieRSK0,Alice,Anderson,alice@example.com -nbgtestb,$1$xg4dbNmA$ygNrKGsFBsu8hXoGieRSK0,Bob,Brown,bob@example.com -nbgtestc,$1$xg4dbNmA$ygNrKGsFBsu8hXoGieRSK0,Carol,Clark,carol@example.com diff --git a/examples/teststudents.PASSWORDS.csv b/examples/teststudents.PASSWORDS.csv deleted file mode 100644 index 7b76999..0000000 --- a/examples/teststudents.PASSWORDS.csv +++ /dev/null @@ -1,3 +0,0 @@ -nbgtesta,nbgpsw,Alice,Anderson,alice@example.com -nbgtestb,nbgpsw,Bob,Brown,bob@example.com -nbgtestc,nbgpsw,Carol,Clark,carol@example.com diff --git a/examples/teststudents.csv b/examples/teststudents.csv deleted file mode 100644 index 7ffc6bd..0000000 --- a/examples/teststudents.csv +++ /dev/null @@ -1,3 +0,0 @@ -nbgtesta,Alice,Anderson,alice@example.com -nbgtestb,Bob,Brown,bob@example.com -nbgtestc,Carol,Clark,carol@example.com diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..debc048 --- /dev/null +++ b/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + org.dice-research + nbgraderutils-java-template + 0.0.1-SNAPSHOT + nbgraderutils-java-template + + 1.11 + 1.11 + + + + + + + + org.junit.jupiter + junit-jupiter-engine + 5.4.0 + test + + + + + org.junit.platform + junit-platform-runner + 1.4.0 + test + + + + \ No newline at end of file diff --git a/scripts/README.md b/scripts/README.md deleted file mode 100644 index 53f48de..0000000 --- a/scripts/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# nbgraderutils - -## Files - -- `bash.sh` - Accesses a bash -- `change-password.sh` - Sets a new password for a linux user -- `create-student.sh` - Creates a student account (linux user and nbgrader database) -- `create-students.sh` - Reads CSV file and adds student accounts -- `generate-passwords.sh` - Reads a CSV file and creates CSV files with (un-)encrypted passwords - -## Info - -- Code - https://github.com/dice-group/nbgraderutils -- Documentation - https://github.com/dice-group/nbgraderutils/wiki -- Credits - https://dice.cs.uni-paderborn.de/ \ No newline at end of file diff --git a/scripts/bash.sh b/scripts/bash.sh deleted file mode 100755 index 7731b17..0000000 --- a/scripts/bash.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# This file executes a command to access a bash inside a docker container. - - - -# Configuration - -CONTAINER_NAME="nbgjava" - - - -# Ensure correct working directory - -cd "$(dirname "$0")" - - - -# If container.txt exists, the including container name will be used. - -if [ -e container.txt ] -then - CONTAINER_NAME=`cat container.txt` -fi - - - -# Access bash - -docker exec --interactive --tty $CONTAINER_NAME /bin/bash diff --git a/scripts/change-password.sh b/scripts/change-password.sh deleted file mode 100755 index 3ca9b17..0000000 --- a/scripts/change-password.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - -# This file sets a new password for a linux user - - - -# Configuration - -CONTAINER_NAME="nbgjava" - - - -# Ensure correct working directory - -cd "$(dirname "$0")" - - - -# If container.txt exists, the including container name will be used. - -if [ -e container.txt ] -then - CONTAINER_NAME=`cat container.txt` -fi - - - -# Check input parameters - -if [ $# -ne 2 ]; then - echo "change-password.sh " - echo "Sets a new password for a linux user" - echo "Container: $CONTAINER_NAME" - exit 1 -fi - -ID=$1 -UNCRYPTED_PASSWORD=$2 - - - -# Execution - -ENCRYPTED_PASSWORD=$(openssl passwd -1 $UNCRYPTED_PASSWORD) -ESCAPED_PASSWORD="${ENCRYPTED_PASSWORD//\$/\\\$}" - -if [ ${#ENCRYPTED_PASSWORD} -ne 34 ]; then - echo "Error: The escaped pasword length is not 34." - exit 2 -fi - -docker exec $CONTAINER_NAME usermod --password $ENCRYPTED_PASSWORD $ID diff --git a/scripts/create-student.sh b/scripts/create-student.sh deleted file mode 100755 index b5f24a0..0000000 --- a/scripts/create-student.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# This file adds a student account to a docker container: -# - A linux user is added -# - The nbgrader gradebook database is updated -# -# Please ensure an encrypted password - - - -# Configuration - -CONTAINER_NAME="nbgjava" -COURSE_DIR="/home/nbgadmin/" - - - -# Ensure correct working directory - -cd "$(dirname "$0")" - - - -# If container.txt exists, the including container name will be used. - -if [ -e container.txt ] -then - CONTAINER_NAME=`cat container.txt` -fi - - - -# Check input parameters - -if [ $# -ne 5 ]; then - echo "create-student.sh " - echo "Creates a student account (linux user and nbgrader database)" - echo "Container: $CONTAINER_NAME" - echo "Course directory: $COURSE_DIR" - exit 1 -fi - -ID=$1 -ENCRYPTED_PASSWORD=$2 -FIRST_NAME=$3 -SURNAME=$4 -EMAIL=$5 - -if [ ${#ENCRYPTED_PASSWORD} -ne 34 ]; then - echo "Error: The pasword length is not 34. Use \"openssl passwd -1 \"." - exit 2 -fi - - - -# Execution - -docker exec $CONTAINER_NAME adduser --gecos "" --disabled-password "$ID" -docker exec $CONTAINER_NAME usermod --password "$ENCRYPTED_PASSWORD" "$ID" -docker exec $CONTAINER_NAME chgrp nbgadmin "/home/$ID" -docker exec $CONTAINER_NAME nbgrader db student add --course-dir="$COURSE_DIR" --first-name="$FIRST_NAME" --last-name="$SURNAME" --email="$EMAIL" "$ID" diff --git a/scripts/create-students.sh b/scripts/create-students.sh deleted file mode 100755 index 843ba77..0000000 --- a/scripts/create-students.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# This file reads a CSV file and adds student accounts to a docker container. -# It uses the script create-student.sh. -# -# CSV file line structure: -# studentId,encryptedPa$$word,first name(s),the surname(s),email@address - - - -# Ensure correct working directory - -cd "$(dirname "$0")" - - - -# Check input parameters - -if [ $# -ne 1 ]; then - echo "create-students.sh " - echo "Input file line structure: studentId,encryptedPa\$\$word,first name(s),the surname(s),email@address" - exit 1 -fi - -FILE=$1 - -if [ -r $FILE ];then - echo "Reading: $FILE" -else - echo "Error: Can not read: $FILE" - exit 2 -fi - - - -# Create students - -while IFS=',' read -r ID ENCRYPTED_PASSWORD FIRST_NAME SURNAME EMAIL ; do - ./create-student.sh "$ID" "$ENCRYPTED_PASSWORD" "$FIRST_NAME" "$SURNAME" "$EMAIL" -done < "$FILE" diff --git a/scripts/generate-passwords.sh b/scripts/generate-passwords.sh deleted file mode 100755 index fad1f44..0000000 --- a/scripts/generate-passwords.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# This file reads a CSV file and creates CSV files with (un-)encrypted passwords. -# -# CSV input file line structure: -# studentId,first name(s),the surname(s),email@address -# -# CSV output file line structure: -# studentId,password,first name(s),the surname(s),email@address - - - -# Check input parameters - -if [ $# -ne 1 ]; then - echo "generate-passwords.sh " - echo "Creates CSV files with passwords" - echo "Input file line structure: studentId,first name(s),the surname(s),email@address" - exit 1 -fi - -FILE=$1 - - - -# Create output file names - -FILE_ID=$(basename -- "$FILE") -FILE_EXTENSION="${FILE##*.}" -FILE_PASSWORDS="${FILE_ID%.*}.PASSWORDS.$FILE_EXTENSION" -FILE_ENCRYPTED="${FILE_ID%.*}.ENCRYPTED.$FILE_EXTENSION" - - - -# Create passwords and files - -while IFS=',' read -r ID FIRST_NAME SURNAME EMAIL ; do - - # Create password - PASSWORD="dice" - PASSWORD=$PASSWORD$(< /dev/urandom tr -dc 1-9 | head -c4) - PASSWORD=$PASSWORD$(< /dev/urandom tr -dc a-z | head -c4) - ENCRYPTED_PASSWORD=$(openssl passwd -1 $PASSWORD) - - # Write password file - echo $ID,$PASSWORD,$FIRST_NAME,$SURNAME,$EMAIL >> $FILE_PASSWORDS - echo $ID,$ENCRYPTED_PASSWORD,$FIRST_NAME,$SURNAME,$EMAIL >> $FILE_ENCRYPTED - -done < "$FILE" diff --git a/scripts/generate-users.sh b/scripts/generate-users.sh deleted file mode 100755 index 3e521f5..0000000 --- a/scripts/generate-users.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -# This file writes in a CSV file. -# -# CSV file line structure: -# user,user,user, -# -# representing: -# user-id,first-name,surname,email@address -# -# example: -# user1,user1,user1, - - - -# Check input parameters - -if [ $# -ne 3 ]; then - echo "generate-users.sh " - echo "Output file line structure: user,user,user," - exit 1 -fi - -FILE=$1 -BEGIN=$2 -END=$3 - - - -# Generate users - -for ((i=${BEGIN};i<=${END};i++)) -do - echo "user${i},user${i},user${i}," >> $FILE -done diff --git a/scripts/initialize.sh b/scripts/initialize.sh deleted file mode 100755 index e36b0ae..0000000 --- a/scripts/initialize.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# This file creates 3 example students and copies example notebooks - - - -# Configuration - -CONTAINER_NAME="nbgjava" - - - -# Ensure correct working directory - -cd "$(dirname "$0")" - - - -# If container.txt exists, the including container name will be used. - -if [ -e container.txt ] -then - CONTAINER_NAME=`cat container.txt` -fi - - - -# Create example students: nbgtesta, nbgtestb, nbgtestc - -./create-students.sh ../examples/teststudents.ENCRYPTED.csv - - - -# Create example notebooks - -docker cp ../examples/AssignmentAdministration.ipynb "$CONTAINER_NAME":/home/nbgadmin/ - -docker exec $CONTAINER_NAME mkdir /home/nbgadmin/templates -docker cp ../examples/AssignmentTemplate.ipynb "$CONTAINER_NAME":/home/nbgadmin/templates/ -docker cp ../examples/FilesystemExample.ipynb "$CONTAINER_NAME":/home/nbgadmin/templates/ -docker cp ../examples/MultipleChoiceExample.ipynb "$CONTAINER_NAME":/home/nbgadmin/templates/ - -docker exec $CONTAINER_NAME mkdir /home/nbgadmin/tests -docker cp ../examples/TestTime.ipynb "$CONTAINER_NAME":/home/nbgadmin/tests/ -docker cp ../examples/TestFilesystem.ipynb "$CONTAINER_NAME":/home/nbgadmin/tests/ - -docker exec $CONTAINER_NAME mkdir /home/nbguser/tests -docker cp ../examples/TestFilesystem.ipynb "$CONTAINER_NAME":/home/nbguser/tests/ - -docker exec $CONTAINER_NAME chown -R nbgadmin:nbgadmin /home/nbgadmin/ diff --git a/src/main/java/org/dice_research/nbraderutils/javatemplate/Exercise1.java b/src/main/java/org/dice_research/nbraderutils/javatemplate/Exercise1.java new file mode 100644 index 0000000..0bab420 --- /dev/null +++ b/src/main/java/org/dice_research/nbraderutils/javatemplate/Exercise1.java @@ -0,0 +1,48 @@ +package org.dice_research.nbraderutils.javatemplate; + +/** + * Exercise 1 - Numeric ASCII representation + * + * @author Adrian Wilke + */ +public class Exercise1 { + + /** + * Converts a String to the numeric ASCII representation of its single + * characters. + */ + public int[] toNumericAscii(String string) { + int[] result = new int[string.length()]; + + // BEGIN SOLUTION + + /* + * Notes for lecturers: + * + * Insert your solution inside one or several marked solution blocks. These + * blocks will be removed for students. + * + * If possible, a return variable should be defined before this marked solution + * block. It avoids unnecessary error messages, if the solution block is removed + * for the students. A null value also works. + * + * Please edit the JavaDoc class comment (exercise name, author) and method + * comment(s) as well. + * + * Additionally to this solution, provide a markdown file describing the + * exercise task and a test file for auto-grading. + * + * You can remove this comment. + */ + + char[] chars = string.toCharArray(); + for (int i = 0; i < chars.length; i++) { + result[i] = chars[i]; + } + + // END SOLUTION + + return result; + } + +} \ No newline at end of file diff --git a/src/main/resources/Exercise1.md b/src/main/resources/Exercise1.md new file mode 100644 index 0000000..00c904d --- /dev/null +++ b/src/main/resources/Exercise1.md @@ -0,0 +1,34 @@ +Note for lecturers: Markdown examples +https://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Working%20With%20Markdown%20Cells.html + + + +# Exercise 1 - Numeric ASCII representation + +(??? points) + +Implement a method which converts a String to the numeric ASCII representation of its single characters. + +#### Example + + + + + + + + + + + + + + + + + +

Input

Output

Type

String

int array

Value

Hi

72, 105

+ +#### Hints + +- The [String class](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#toCharArray()) provides methods for conversion. diff --git a/src/test/java/org/dice_research/nbraderutils/javatemplate/AllTestsSuite.java b/src/test/java/org/dice_research/nbraderutils/javatemplate/AllTestsSuite.java new file mode 100644 index 0000000..1516ad4 --- /dev/null +++ b/src/test/java/org/dice_research/nbraderutils/javatemplate/AllTestsSuite.java @@ -0,0 +1,17 @@ +package org.dice_research.nbraderutils.javatemplate; + +import org.junit.platform.runner.JUnitPlatform; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.runner.RunWith; + +// Alternative to set order of tests: +// import org.junit.platform.suite.api.SelectClasses; + +@RunWith(JUnitPlatform.class) +@SelectPackages({ "org.dice_research.nbraderutils.javatemplate" }) + +// Alternative to set order of tests: +// @SelectClasses({ Exercise1Test.class, OverallPointsTest.class }) + +public class AllTestsSuite { +} \ No newline at end of file diff --git a/src/test/java/org/dice_research/nbraderutils/javatemplate/Configuration.java b/src/test/java/org/dice_research/nbraderutils/javatemplate/Configuration.java new file mode 100644 index 0000000..ad7240c --- /dev/null +++ b/src/test/java/org/dice_research/nbraderutils/javatemplate/Configuration.java @@ -0,0 +1,11 @@ +package org.dice_research.nbraderutils.javatemplate; + +public abstract class Configuration { + + // If true, it is checked if exercise points sum up to assignment points. + public static final boolean EQUAL_POINTS_FOR_ASSIGNMENTS = true; + + // 12 or 24 overall points for an assignment are fine for equal points + // distribution of 1/2/3/4 exercises. + public static final int POINTS_PER_ASSIGNMENT = 24; +} \ No newline at end of file diff --git a/src/test/java/org/dice_research/nbraderutils/javatemplate/Exercise1Test.java b/src/test/java/org/dice_research/nbraderutils/javatemplate/Exercise1Test.java new file mode 100644 index 0000000..d55342b --- /dev/null +++ b/src/test/java/org/dice_research/nbraderutils/javatemplate/Exercise1Test.java @@ -0,0 +1,68 @@ +package org.dice_research.nbraderutils.javatemplate; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.opentest4j.AssertionFailedError; + +/** + * Feel free to change the parameters of the method test(...). + * + * Overview of Assertions: + * https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/Assertions.html + */ +class Exercise1Test { + + void test(String inputString, int[] expectedResult, String testDescription) { + try { + long time = System.currentTimeMillis(); + + Assertions.assertArrayEquals(expectedResult, new Exercise1().toNumericAscii(inputString), testDescription); + + time = System.currentTimeMillis() - time; + System.out.println("Test(s) successfully completed. Calculation took " + time + " ms."); + } catch (AssertionFailedError e) { + System.err.println("Your solution returned an unexpected result. "); + throw e; + } catch (Throwable e) { + System.err.println("Your solution caused an unexpected error. "); + throw e; + } + } + + @Test + void testVisible() { + + test("Hi", new int[] { 72, 105 }, "Testing 'Hi'"); + + } + + @Test + void testHidden1() { + // Ignore this cell + // BEGIN HIDDEN TESTS + + // The first hidden test should be similar to the visible test. + test("Ho", new int[] { 72, 111 }, "Testing 'Ho'"); + + // END HIDDEN TESTS + + // Set the points for this test. + OverallPointsTest.addPoints(14, this.getClass()); + + } + + @Test + void testHidden2() { + // Ignore this cell + // BEGIN HIDDEN TESTS + + // An additional test. + test("HiHo", new int[] { 72, 105, 72, 111 }, "Testing 'HiHo'"); + + // END HIDDEN TESTS + + // Set the points for this test. + OverallPointsTest.addPoints(10, this.getClass()); + + } +} \ No newline at end of file diff --git a/src/test/java/org/dice_research/nbraderutils/javatemplate/OverallPointsTest.java b/src/test/java/org/dice_research/nbraderutils/javatemplate/OverallPointsTest.java new file mode 100644 index 0000000..f5510ef --- /dev/null +++ b/src/test/java/org/dice_research/nbraderutils/javatemplate/OverallPointsTest.java @@ -0,0 +1,62 @@ +package org.dice_research.nbraderutils.javatemplate; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class OverallPointsTest { + + private static Map> pointsMap = new TreeMap<>(); + + public static void addPoints(int points, Class exerciseTestClass) { + if (!pointsMap.containsKey(exerciseTestClass.getSimpleName())) { + pointsMap.put(exerciseTestClass.getSimpleName(), new LinkedList<>()); + } + pointsMap.get(exerciseTestClass.getSimpleName()).add(points); + } + + @Test + void test() { + + // Print point overview + + int pointsAssignment = 0; + int pointsExercise; + StringBuilder exerciseBuilder = new StringBuilder(); + StringBuilder testBuilder; + for (Entry> exercise : pointsMap.entrySet()) { + pointsExercise = 0; + testBuilder = new StringBuilder(); + for (int i = 0; i < exercise.getValue().size(); i++) { + if (i != 0) { + testBuilder.append(" + "); + } + testBuilder.append(exercise.getValue().get(i)); + pointsExercise += exercise.getValue().get(i); + } + exerciseBuilder.append("Points for "); + exerciseBuilder.append(exercise.getKey()); + exerciseBuilder.append(": "); + exerciseBuilder.append(pointsExercise); + exerciseBuilder.append(" = "); + exerciseBuilder.append(testBuilder); + exerciseBuilder.append(System.lineSeparator()); + pointsAssignment += pointsExercise; + } + System.out.println(exerciseBuilder.toString()); + System.out.println("Overall points for assignment: " + pointsAssignment); + + // Check final points + + if (Configuration.EQUAL_POINTS_FOR_ASSIGNMENTS) { + Assertions.assertEquals(Configuration.POINTS_PER_ASSIGNMENT, pointsAssignment, + "Please check your point configuration."); + } + } + +} \ No newline at end of file