Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Programming exercises: Add R programming language template #9256

Merged
merged 17 commits into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,15 @@ dependencies {
implementation "org.gitlab4j:gitlab4j-api:6.0.0-rc.5"

implementation "de.jplag:jplag:${jplag_version}"
implementation "de.jplag:java:${jplag_version}"
implementation "de.jplag:kotlin:${jplag_version}"

implementation "de.jplag:c:${jplag_version}"
implementation "de.jplag:swift:${jplag_version}"
implementation "de.jplag:java:${jplag_version}"
implementation "de.jplag:javascript:${jplag_version}"
implementation "de.jplag:kotlin:${jplag_version}"
implementation "de.jplag:python-3:${jplag_version}"
implementation "de.jplag:rlang:${jplag_version}"
implementation "de.jplag:rust:${jplag_version}"
implementation "de.jplag:javascript:${jplag_version}"
implementation "de.jplag:swift:${jplag_version}"
magaupp marked this conversation as resolved.
Show resolved Hide resolved
implementation "de.jplag:text:${jplag_version}"

// those are transitive dependencies of JPlag Text --> Stanford NLP
Expand Down
4 changes: 4 additions & 0 deletions docs/user/exercises/programming-exercise-features.inc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------+---------+
| JavaScript | yes | yes |
+----------------------+----------+---------+
| R | yes | yes |
+----------------------+----------+---------+

- Not all ``templates`` support the same feature set and supported features can also change depending on the continuous integration system setup.
Depending on the feature set, some options might not be available during the creation of the programming exercise.
Expand Down Expand Up @@ -71,6 +73,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
| JavaScript | no | no | yes | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
| R | no | no | yes | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
magaupp marked this conversation as resolved.
Show resolved Hide resolved

- *Sequential Test Runs*: ``Artemis`` can generate a build plan which first executes structural and then behavioral tests. This feature can help students to better concentrate on the immediate challenge at hand.
- *Static Code Analysis*: ``Artemis`` can generate a build plan which additionally executes static code analysis tools.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import de.jplag.options.JPlagOptions;
import de.jplag.python3.PythonLanguage;
import de.jplag.reporting.reportobject.ReportObjectFactory;
import de.jplag.rlang.RLanguage;
import de.jplag.rust.RustLanguage;
import de.jplag.swift.SwiftLanguage;
import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
Expand Down Expand Up @@ -310,14 +311,15 @@ public void deleteTempLocalRepository(Repository repository) {

private Language getJPlagProgrammingLanguage(ProgrammingExercise programmingExercise) {
return switch (programmingExercise.getProgrammingLanguage()) {
case JAVA -> new JavaLanguage();
case C -> new CLanguage();
case PYTHON -> new PythonLanguage();
case SWIFT -> new SwiftLanguage();
case JAVA -> new JavaLanguage();
case JAVASCRIPT -> new JavaScriptLanguage();
case KOTLIN -> new KotlinLanguage();
case PYTHON -> new PythonLanguage();
case R -> new RLanguage();
case RUST -> new RustLanguage();
case JAVASCRIPT -> new JavaScriptLanguage();
case EMPTY, PHP, DART, HASKELL, ASSEMBLER, OCAML, C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, VHDL, RUBY, POWERSHELL, ADA ->
case SWIFT -> new SwiftLanguage();
case EMPTY, PHP, DART, HASKELL, ASSEMBLER, OCAML, C_SHARP, C_PLUS_PLUS, SQL, TYPESCRIPT, GO, MATLAB, BASH, VHDL, RUBY, POWERSHELL, ADA ->
magaupp marked this conversation as resolved.
Show resolved Hide resolved
throw new BadRequestAlertException("Programming language " + programmingExercise.getProgrammingLanguage() + " not supported for plagiarism check.",
"ProgrammingExercise", "notSupported");
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,19 @@ public enum ProgrammingLanguage {
PHP("php");

private static final Set<ProgrammingLanguage> ENABLED_LANGUAGES = Set.of(
EMPTY,
JAVA,
PYTHON,
ASSEMBLER,
C,
HASKELL,
JAVA,
JAVASCRIPT,
KOTLIN,
VHDL,
ASSEMBLER,
SWIFT,
OCAML,
PYTHON,
R,
RUST,
JAVASCRIPT
SWIFT,
VHDL,
EMPTY
magaupp marked this conversation as resolved.
Show resolved Hide resolved
);
// @formatter:on

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public TemplateUpgradePolicyService(JavaTemplateUpgradeService javaRepositoryUpg
public TemplateUpgradeService getUpgradeService(ProgrammingLanguage programmingLanguage) {
return switch (programmingLanguage) {
case JAVA -> javaRepositoryUpgradeService;
case KOTLIN, PYTHON, C, HASKELL, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT -> defaultRepositoryUpgradeService;
case C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case KOTLIN, PYTHON, C, HASKELL, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT, R -> defaultRepositoryUpgradeService;
case C_SHARP, C_PLUS_PLUS, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException("Unsupported programming language: " + programmingLanguage);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ enum RepositoryCheckoutPath implements CustomizableCheckoutPath {
@Override
public String forProgrammingLanguage(ProgrammingLanguage language) {
return switch (language) {
case JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT -> "assignment";
case C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case JAVA, PYTHON, C, HASKELL, KOTLIN, VHDL, ASSEMBLER, SWIFT, OCAML, EMPTY, RUST, JAVASCRIPT, R -> "assignment";
case C_SHARP, C_PLUS_PLUS, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException("Unsupported programming language: " + language);
};
}
Expand All @@ -230,9 +230,9 @@ public String forProgrammingLanguage(ProgrammingLanguage language) {
@Override
public String forProgrammingLanguage(ProgrammingLanguage language) {
return switch (language) {
case JAVA, PYTHON, HASKELL, KOTLIN, SWIFT, EMPTY, RUST, JAVASCRIPT -> "";
case JAVA, PYTHON, HASKELL, KOTLIN, SWIFT, EMPTY, RUST, JAVASCRIPT, R -> "";
case C, VHDL, ASSEMBLER, OCAML -> "tests";
case C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case C_SHARP, C_PLUS_PLUS, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
magaupp marked this conversation as resolved.
Show resolved Hide resolved
throw new UnsupportedOperationException("Unsupported programming language: " + language);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class GitLabCIProgrammingLanguageFeatureService extends ProgrammingLangua
public GitLabCIProgrammingLanguageFeatureService() {
programmingLanguageFeatures.put(EMPTY, new ProgrammingLanguageFeature(EMPTY, false, false, false, false, false, List.of(), false, false));
programmingLanguageFeatures.put(JAVA, new ProgrammingLanguageFeature(JAVA, false, false, false, true, false, List.of(PLAIN_MAVEN, MAVEN_MAVEN), false, false));
programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, false));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, false));
programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.JAVASCRIPT;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.KOTLIN;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.PYTHON;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.R;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.RUST;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.SWIFT;
import static de.tum.cit.aet.artemis.programming.domain.ProjectType.FACT;
Expand All @@ -33,15 +34,16 @@ public class JenkinsProgrammingLanguageFeatureService extends ProgrammingLanguag
public JenkinsProgrammingLanguageFeatureService() {
// Must be extended once a new programming language is added
programmingLanguageFeatures.put(EMPTY, new ProgrammingLanguageFeature(EMPTY, false, false, false, false, false, List.of(), false, false));
programmingLanguageFeatures.put(C, new ProgrammingLanguageFeature(C, false, false, true, false, false, List.of(FACT, GCC), false, false));
programmingLanguageFeatures.put(HASKELL, new ProgrammingLanguageFeature(HASKELL, false, false, false, false, true, List.of(), false, false));
programmingLanguageFeatures.put(JAVA,
new ProgrammingLanguageFeature(JAVA, true, true, true, true, false, List.of(PLAIN_GRADLE, GRADLE_GRADLE, PLAIN_MAVEN, MAVEN_MAVEN, MAVEN_BLACKBOX), true, false));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, false));
programmingLanguageFeatures.put(KOTLIN, new ProgrammingLanguageFeature(KOTLIN, true, false, true, true, false, List.of(), true, false));
programmingLanguageFeatures.put(PYTHON, new ProgrammingLanguageFeature(PYTHON, false, false, true, false, false, List.of(), false, false));
programmingLanguageFeatures.put(R, new ProgrammingLanguageFeature(R, false, false, true, false, false, List.of(), false, false));
programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, false));
magaupp marked this conversation as resolved.
Show resolved Hide resolved
// Jenkins is not supporting XCODE at the moment
programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, true, true, true, false, List.of(PLAIN), false, false));
programmingLanguageFeatures.put(C, new ProgrammingLanguageFeature(C, false, false, true, false, false, List.of(FACT, GCC), false, false));
programmingLanguageFeatures.put(HASKELL, new ProgrammingLanguageFeature(HASKELL, false, false, false, false, true, List.of(), false, false));
programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, false));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ private JenkinsXmlConfigBuilder builderFor(ProgrammingLanguage programmingLangua
throw new UnsupportedOperationException("Xcode templates are not available for Jenkins.");
}
return switch (programmingLanguage) {
case JAVA, KOTLIN, PYTHON, C, HASKELL, SWIFT, EMPTY, RUST, JAVASCRIPT -> jenkinsBuildPlanCreator;
case VHDL, ASSEMBLER, OCAML, C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case JAVA, KOTLIN, PYTHON, C, HASKELL, SWIFT, EMPTY, RUST, JAVASCRIPT, R -> jenkinsBuildPlanCreator;
case VHDL, ASSEMBLER, OCAML, C_SHARP, C_PLUS_PLUS, SQL, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
magaupp marked this conversation as resolved.
Show resolved Hide resolved
throw new UnsupportedOperationException(programmingLanguage + " templates are not available for Jenkins.");
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.KOTLIN;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.OCAML;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.PYTHON;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.R;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.RUST;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.SWIFT;
import static de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage.VHDL;
Expand Down Expand Up @@ -39,17 +40,18 @@ public class LocalCIProgrammingLanguageFeatureService extends ProgrammingLanguag
public LocalCIProgrammingLanguageFeatureService() {
// Must be extended once a new programming language is added
programmingLanguageFeatures.put(EMPTY, new ProgrammingLanguageFeature(EMPTY, false, false, false, false, false, List.of(), false, true));
programmingLanguageFeatures.put(ASSEMBLER, new ProgrammingLanguageFeature(ASSEMBLER, false, false, false, false, false, List.of(), false, true));
programmingLanguageFeatures.put(C, new ProgrammingLanguageFeature(C, false, true, true, false, false, List.of(FACT, GCC), false, true));
programmingLanguageFeatures.put(HASKELL, new ProgrammingLanguageFeature(HASKELL, true, false, false, false, true, List.of(), false, true));
programmingLanguageFeatures.put(JAVA,
new ProgrammingLanguageFeature(JAVA, true, true, true, true, false, List.of(PLAIN_GRADLE, GRADLE_GRADLE, PLAIN_MAVEN, MAVEN_MAVEN), false, true));
programmingLanguageFeatures.put(PYTHON, new ProgrammingLanguageFeature(PYTHON, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(C, new ProgrammingLanguageFeature(C, false, true, true, false, false, List.of(FACT, GCC), false, true));
programmingLanguageFeatures.put(ASSEMBLER, new ProgrammingLanguageFeature(ASSEMBLER, false, false, false, false, false, List.of(), false, true));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(KOTLIN, new ProgrammingLanguageFeature(KOTLIN, false, false, true, true, false, List.of(), false, true));
programmingLanguageFeatures.put(VHDL, new ProgrammingLanguageFeature(VHDL, false, false, false, false, false, List.of(), false, true));
programmingLanguageFeatures.put(HASKELL, new ProgrammingLanguageFeature(HASKELL, true, false, false, false, true, List.of(), false, true));
programmingLanguageFeatures.put(OCAML, new ProgrammingLanguageFeature(OCAML, false, false, false, false, true, List.of(), false, true));
programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, false, true, true, false, List.of(PLAIN), false, true));
programmingLanguageFeatures.put(PYTHON, new ProgrammingLanguageFeature(PYTHON, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(R, new ProgrammingLanguageFeature(R, false, false, true, false, false, List.of(), false, true));
magaupp marked this conversation as resolved.
Show resolved Hide resolved
programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, true));
programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, false, true, true, false, List.of(PLAIN), false, true));
programmingLanguageFeatures.put(VHDL, new ProgrammingLanguageFeature(VHDL, false, false, false, false, false, List.of(), false, true));
}
}
2 changes: 2 additions & 0 deletions src/main/resources/config/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ artemis:
default: "ghcr.io/ls1intum/artemis-rust-docker:v0.9.70"
javascript:
default: "ghcr.io/ls1intum/artemis-javascript-docker:v1.0.0"
r:
default: "ghcr.io/ls1intum/artemis-r-docker:v1.0.0"
magaupp marked this conversation as resolved.
Show resolved Hide resolved

management:
endpoints:
Expand Down
26 changes: 26 additions & 0 deletions src/main/resources/templates/aeolus/r/default.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
export AEOLUS_INITIAL_DIRECTORY=${PWD}
install () {
echo '⚙️ executing install'
R CMD INSTALL assignment
}

run_all_tests () {
echo '⚙️ executing run_all_tests'
Rscript -e 'library("testthat"); options(testthat.output_file = "junit.xml"); test_local(".", reporter = "junit")'
}

main () {
if [[ "${1}" == "aeolus_sourcing" ]]; then
return 0 # just source to use the methods in the subshell, no execution
fi
local _script_name
_script_name=${BASH_SOURCE[0]:-$0}
cd "${AEOLUS_INITIAL_DIRECTORY}"
bash -c "source ${_script_name} aeolus_sourcing; install"
cd "${AEOLUS_INITIAL_DIRECTORY}"
bash -c "source ${_script_name} aeolus_sourcing; run_all_tests"
}

main "${@}"
14 changes: 14 additions & 0 deletions src/main/resources/templates/aeolus/r/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
api: v0.0.1
metadata:
name: R
id: r
description: Test package using testthat
actions:
- name: install
script: R CMD INSTALL assignment
- name: run_all_tests
script: Rscript -e 'library("testthat"); options(testthat.output_file = "junit.xml"); test_local(".", reporter = "junit")'
results:
- name: junit
path: tests/testthat/junit.xml
type: junit
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* This file configures the actual build steps for the automatic grading.
*
* !!!
* For regular exercises, there is no need to make changes to this file.
* Only this base configuration is actively supported by the Artemis maintainers
* and/or your Artemis instance administrators.
* !!!
*/

dockerImage = '#dockerImage'
dockerFlags = '#dockerArgs'

/**
* Main function called by Jenkins.
*/
void testRunner() {
docker.image(dockerImage).inside(dockerFlags) { c ->
runTestSteps()
}
}

private void runTestSteps() {
test()
}

/**
* Run unit tests
*/
private void test() {
stage('Test') {
sh '''
R CMD INSTALL assignment
Rscript -e 'library("testthat"); options(testthat.output_file = "junit.xml"); test_local(".", reporter = "junit")'
'''
}
}

/**
* Script of the post build tasks aggregating all JUnit files in $WORKSPACE/results.
*
* Called by Jenkins.
*/
void postBuildTasks() {
sh '''
rm -rf results
mkdir results
if [ -e tests/testthat/junit.xml ]
then
sed -i 's/<testsuites[^>]*>/<testsuite>/g ; s/<\\/testsuites>/<\\/testsuite>/g' tests/testthat/junit.xml
fi
cp tests/testthat/junit.xml $WORKSPACE/results/ || true
sed -i 's/[^[:print:]\t]/�/g' $WORKSPACE/results/*.xml || true
'''
}

// very important, do not remove
// required so that Jenkins finds the methods defined in this script
return this
7 changes: 7 additions & 0 deletions src/main/resources/templates/r/exercise/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Package: assignment
Title: Artemis R Student Assignment
Version: 0.0.0.9000
Author: Artemis
Description: This is an assignment to be solved by students.
License: MIT
Encoding: UTF-8
1 change: 1 addition & 0 deletions src/main/resources/templates/r/exercise/NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exportPattern("^[^\\.]")
3 changes: 3 additions & 0 deletions src/main/resources/templates/r/exercise/R/convert.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
matrix_to_column_list <- function(mat) {
# TODO: implement
}
magaupp marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading