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 JavaScript programming language template #8859

Merged
merged 49 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
7aaa340
Development: Include git resources in jar
magaupp May 27, 2024
49ada25
Development: Filter directories from ResourceLoaderService
magaupp May 27, 2024
301d1e1
Development: Rename ResourceLoaderService methods to clarify behavior
magaupp May 27, 2024
7678a1f
Development: Add ResourceLoaderService tests
magaupp May 27, 2024
89930f5
Development: Apply filename replacements of resource files
magaupp May 28, 2024
262baf6
Development: Remove filename replacement test
magaupp May 28, 2024
65e7f18
Development: Remove local exception handling
magaupp May 29, 2024
c76621c
Merge branch 'develop' into chore/programming-exercises/allow-all-tem…
magaupp Jun 1, 2024
59759b4
Fix filtering for other resource types
magaupp Jun 3, 2024
dd44e62
Merge branch 'refs/heads/develop' into chore/programming-exercises/al…
magaupp Jun 3, 2024
895be28
Add Javadoc for getFileResources
magaupp Jun 3, 2024
e323780
Merge branch 'develop' into chore/programming-exercises/allow-all-tem…
magaupp Jun 5, 2024
c17aad9
Merge branch 'develop' into chore/programming-exercises/allow-all-tem…
magaupp Jun 7, 2024
5019c2e
Merge branch 'develop' into chore/programming-exercises/allow-all-tem…
magaupp Jun 9, 2024
82c1894
Merge branch 'refs/heads/develop' into chore/programming-exercises/al…
magaupp Jun 16, 2024
81cd641
Merge branch 'develop' into chore/programming-exercises/allow-all-tem…
magaupp Jun 21, 2024
167901e
Merge branch 'develop' into chore/programming-exercises/allow-all-tem…
magaupp Jun 22, 2024
ce78de3
Add JavaScript programming language template
magaupp Jun 23, 2024
c2aca71
Add Jenkins support
magaupp Jun 26, 2024
7ad2d8a
Add GitlabCI support
magaupp Jun 26, 2024
35d9017
Add npm options for speedup
magaupp Jun 26, 2024
ffab1fa
Rename package names
magaupp Jun 26, 2024
752e407
Use docker image with cached dependencies
magaupp Jun 26, 2024
884220b
Fix import name in test
magaupp Jun 26, 2024
25d8a33
Merge branch 'refs/heads/develop' into feature/programming-exercises/…
magaupp Jun 28, 2024
3dfebd6
Be more descriptive with non-implemented functions in the examples
magaupp Jun 29, 2024
8e41ea8
Trigger rebuild
magaupp Jun 29, 2024
31d03a8
Merge branch 'develop' into feature/programming-exercises/javascript-…
magaupp Jul 1, 2024
0167676
Clarify test descriptions
magaupp Jul 1, 2024
6205b70
Fix GitLab CI build
magaupp Jul 5, 2024
1f78059
Remove <testsuites> tag for Jenkins
magaupp Jul 5, 2024
f50dfe8
Remove <testsuites> tag for GitLab CI
magaupp Jul 5, 2024
9c30af5
Hardcode results directory
magaupp Jul 5, 2024
1fac431
Fix <testsuits> removal
magaupp Jul 5, 2024
8a80448
Merge branch 'develop' into feature/programming-exercises/javascript-…
magaupp Jul 14, 2024
2302ab8
Create result directory in GitLab CI
magaupp Jul 16, 2024
ab2cb1a
Merge branch 'refs/heads/develop' into feature/programming-exercises/…
magaupp Jul 20, 2024
62913fe
Merge branch 'develop' into feature/programming-exercises/javascript-…
magaupp Jul 28, 2024
1681a99
Add strategy pattern example
magaupp Aug 17, 2024
d0ba069
Merge branch 'develop' into feature/programming-exercises/javascript-…
magaupp Aug 17, 2024
4089bf4
Fix bubble sort
magaupp Aug 17, 2024
0bc7b32
Use constants in client
magaupp Aug 17, 2024
2e6e5f2
Reset dates array before each test
magaupp Aug 17, 2024
c36a649
Join `<testsuite>`s where required
magaupp Aug 17, 2024
9a1e53e
Update documentation
magaupp Aug 17, 2024
9eb42c2
Simplify `<testsuites>`-workaround
magaupp Aug 22, 2024
f920a9e
Merge branch 'develop' into feature/programming-exercises/javascript-…
magaupp Aug 28, 2024
bc6923d
Merge branch 'develop' into feature/programming-exercises/javascript-…
magaupp Sep 12, 2024
277532b
Merge branch 'develop' into feature/programming-exercises/javascript-…
magaupp Sep 19, 2024
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
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 @@ -35,6 +35,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------+---------+
| Rust | yes | yes |
+----------------------+----------+---------+
| JavaScript | 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 @@ -67,6 +69,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
| Rust | no | no | no | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
| JavaScript | no | no | no | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+

- *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 @@ -48,7 +48,8 @@ public enum ProgrammingLanguage {
ASSEMBLER,
SWIFT,
OCAML,
RUST
RUST,
JAVASCRIPT
);
// @formatter:on

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 -> "assignment";
case JAVASCRIPT, 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 -> "assignment";
case C_SHARP, C_PLUS_PLUS, SQL, R, 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 -> "";
case JAVA, PYTHON, HASKELL, KOTLIN, SWIFT, EMPTY, RUST, JAVASCRIPT -> "";
case C, VHDL, ASSEMBLER, OCAML -> "tests";
case JAVASCRIPT, C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
case C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException("Unsupported programming language: " + language);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.EMPTY;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.JAVA;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.JAVASCRIPT;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.RUST;
import static de.tum.in.www1.artemis.domain.enumeration.ProjectType.MAVEN_MAVEN;
import static de.tum.in.www1.artemis.domain.enumeration.ProjectType.PLAIN_MAVEN;
Expand All @@ -22,5 +23,6 @@ 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, false, false, false, List.of(), false, false));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, false, false, false, List.of(), false, false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.EMPTY;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.HASKELL;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.JAVA;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.JAVASCRIPT;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.KOTLIN;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.PYTHON;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.RUST;
Expand Down Expand Up @@ -41,5 +42,6 @@ public JenkinsProgrammingLanguageFeatureService() {
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, false, false, false, List.of(), false, false));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, false, 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 -> jenkinsBuildPlanCreator;
case VHDL, ASSEMBLER, OCAML, JAVASCRIPT, 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 -> jenkinsBuildPlanCreator;
case VHDL, ASSEMBLER, OCAML, C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException(programmingLanguage + " templates are not available for Jenkins.");
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.C;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.HASKELL;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.JAVA;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.JAVASCRIPT;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.KOTLIN;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.OCAML;
import static de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage.PYTHON;
Expand Down Expand Up @@ -48,5 +49,6 @@ public LocalCIProgrammingLanguageFeatureService() {
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(RUST, new ProgrammingLanguageFeature(RUST, false, false, false, false, false, List.of(), false, true));
programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, false, false, false, List.of(), false, true));
}
}
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 -> defaultRepositoryUpgradeService;
case JAVASCRIPT, 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 -> defaultRepositoryUpgradeService;
case C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, RUBY, POWERSHELL, ADA, DART, PHP ->
throw new UnsupportedOperationException("Unsupported programming language: " + programmingLanguage);
};
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/config/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ artemis:
default: "ls1tum/artemis-ocaml-docker:v1"
rust:
default: "ghcr.io/ls1intum/artemis-rust-docker:v0.9.70"
javascript:
default: "ghcr.io/ls1intum/artemis-javascript-docker:v1.0.0"

management:
endpoints:
Expand Down
26 changes: 26 additions & 0 deletions src/main/resources/templates/aeolus/javascript/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_dependencies () {
echo '⚙️ executing install_dependencies'
npm ci --prefer-offline --no-audit
}

test () {
echo '⚙️ executing test'
npm run test:ci
}

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_dependencies"
cd "${AEOLUS_INITIAL_DIRECTORY}"
bash -c "source ${_script_name} aeolus_sourcing; test"
}

main "${@}"
14 changes: 14 additions & 0 deletions src/main/resources/templates/aeolus/javascript/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
api: v0.0.1
metadata:
name: JavaScript
description: Run tests using Jest
actions:
- name: install_dependencies
script: 'npm ci --prefer-offline --no-audit'
- name: test
script: 'npm run test:ci'
runAlways: false
results:
- name: junit
path: 'junit.xml'
type: junit
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
stages:
- test
- upload
magaupp marked this conversation as resolved.
Show resolved Hide resolved


test-job:
image: ${ARTEMIS_BUILD_DOCKER_IMAGE}
stage: test
only:
variables:
- $CI_COMMIT_BRANCH == $ARTEMIS_SUBMISSION_GIT_BRANCH
allow_failure: true
magaupp marked this conversation as resolved.
Show resolved Hide resolved
variables:
GIT_STRATEGY: none
script:
- git clone --branch ${ARTEMIS_TEST_GIT_BRANCH} ${CI_SERVER_PROTOCOL}://${ARTEMIS_TEST_GIT_USER}:${ARTEMIS_TEST_GIT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/${CI_PROJECT_NAMESPACE}/${ARTEMIS_TEST_GIT_REPOSITORY_SLUG} .
- git clone --branch ${ARTEMIS_SUBMISSION_GIT_BRANCH} ${CI_SERVER_PROTOCOL}://${ARTEMIS_TEST_GIT_USER}:${ARTEMIS_TEST_GIT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME} assignment
magaupp marked this conversation as resolved.
Show resolved Hide resolved
- export ARTEMIS_NOTIFICATION_SECRET=[hidden] # Workaround for overwriting the secret
- export ARTEMIS_TEST_GIT_TOKEN=[hidden]
magaupp marked this conversation as resolved.
Show resolved Hide resolved
magaupp marked this conversation as resolved.
Show resolved Hide resolved
- npm ci --prefer-offline --no-audit | tee -a "${ARTEMIS_BUILD_LOGS_FILE}"
- npm run test:ci | tee -a "${ARTEMIS_BUILD_LOGS_FILE}" && echo "ARTEMIS_BUILD_STATUS=success" > .env || echo "ARTEMIS_BUILD_STATUS=failed" > .env
magaupp marked this conversation as resolved.
Show resolved Hide resolved
- test -e junit.xml && sed -i 's/<testsuites[^>]*>/<testsuite>/g ; s/<\/testsuites>/<\/testsuite>/g' junit.xml # <testsuites> not supported by notification plugin
- test -e junit.xml && mkdir test-reports && cp junit.xml test-reports/junit.xml
after_script:
- echo "ARTEMIS_TEST_GIT_HASH=$(git rev-parse HEAD)" >> .env
- echo "ARTEMIS_SUBMISSION_GIT_HASH=${CI_COMMIT_SHA}" >> .env
- echo "ARTEMIS_SUBMISSION_GIT_REPOSITORY_SLUG=${CI_PROJECT_NAME}" >> .env
magaupp marked this conversation as resolved.
Show resolved Hide resolved
artifacts:
paths:
- ${ARTEMIS_BUILD_LOGS_FILE}
- test-reports/junit.xml
reports:
dotenv: .env


upload-job:
image: ${ARTEMIS_NOTIFICATION_PLUGIN_DOCKER_IMAGE}
stage: upload
dependencies:
- test-job
only:
variables:
- $CI_COMMIT_BRANCH == $ARTEMIS_SUBMISSION_GIT_BRANCH
variables:
GIT_STRATEGY: none
script:
- cp -r /notification-plugin/* .
- export ARTEMIS_TEST_RESULTS_DIR="test-reports" # override project variable
- gradle run
magaupp marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
11 changes: 11 additions & 0 deletions src/main/resources/templates/javascript/exercise/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "artemis-exercise",
"private": true,
"scripts": {
"start": "node ./src/client.js"
},
magaupp marked this conversation as resolved.
Show resolved Hide resolved
"exports": {
"./*.js": "./src/*.js"
},
magaupp marked this conversation as resolved.
Show resolved Hide resolved
"type": "module"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default class BubbleSort {
// TODO: implement in performSort(Date[])
pzdr7 marked this conversation as resolved.
Show resolved Hide resolved
}
magaupp marked this conversation as resolved.
Show resolved Hide resolved
66 changes: 66 additions & 0 deletions src/main/resources/templates/javascript/exercise/src/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const ITERATIONS = 10;
const DATES_LENGTH_MIN = 5;
const DATES_LENGTH_MAX = 15;

/**
* Main function.
* Add code to demonstrate your implementation here.
*/
function main() {
// TODO: Init Context and Policy

// Run multiple times to simulate different sorting strategies
for (let i = 0; i < ITERATIONS; i++) {
const dates = createRandomDates();

// TODO: Configure context

console.log('Unsorted Array of dates:');
console.log(dates);

// TODO: Sort dates

console.log('Sorted Array of dates:');
console.log(dates);
}
magaupp marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Generates an Array of random Date objects with random Array length between
* {@link DATES_LENGTH_MIN} and {@link DATES_LENGTH_MAX}.
*
* @return an Array of random Date objects
*/
function createRandomDates() {
const length = randomIntegerWithin(DATES_LENGTH_MIN, DATES_LENGTH_MAX);

const lowestDate = new Date('2024-09-15');
const highestDate = new Date('2025-01-15');

return Array.from(Array(length), () => randomDateWithin(lowestDate, highestDate));
}

/**
* Creates a random Date within the given range.
*
* @param low {Date} the lower bound
* @param high {Date} the upper bound
* @return {Date} random Date within the given range
*/
function randomDateWithin(low, high) {
const randomTimestamp = randomIntegerWithin(low.valueOf(), high.valueOf());
return new Date(randomTimestamp);
}

/**
* Creates a random int within the given range.
*
* @param low {number} the lower bound
* @param high {number} the upper bound
* @returns {number} random int within the given range
*/
function randomIntegerWithin(low, high) {
return Math.floor(Math.random() * (high - low + 1)) + low;
}

main();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default class Context {
// TODO: Create and implement a Context class according to the UML class diagram
}
magaupp marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default class MergeSort {
// TODO: implement in performSort(Date[])
pzdr7 marked this conversation as resolved.
Show resolved Hide resolved
}
magaupp marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default class Policy {
// TODO: Create and implement a Policy class as described in the problem statement
}
magaupp marked this conversation as resolved.
Show resolved Hide resolved
82 changes: 82 additions & 0 deletions src/main/resources/templates/javascript/readme
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Sorting with the Strategy Pattern

In this exercise, we want to implement sorting algorithms and choose them based on runtime specific variables.

### Part 1: Sorting

First, we need to implement two sorting algorithms, in this case `MergeSort` and `BubbleSort`.

**You have the following tasks:**

1. [task][Implement Bubble Sort](structural_BubbleSort_has_method,behavior_BubbleSort_should_sort_correctly)
Implement the method `performSort(Date[])` in the class `BubbleSort`. Make sure to follow the Bubble Sort algorithm exactly.
magaupp marked this conversation as resolved.
Show resolved Hide resolved

2. [task][Implement Merge Sort](structural_MergeSort_has_method,behavior_MergeSort_should_sort_correctly)
Implement the method `performSort(Date[])` in the class `MergeSort`. Make sure to follow the Merge Sort algorithm exactly.
magaupp marked this conversation as resolved.
Show resolved Hide resolved

### Part 2: Strategy Pattern

We want the application to apply different algorithms for sorting an Array of `Date` objects.
Use the strategy pattern to select the right sorting algorithm at runtime.

**You have the following tasks:**

1. [task][Context Class](structural_Context_has_properties,structural_Context_has_methods)
Create and implement a `Context` class following the below class diagram.
Add `get` and `set` accessors for the attribute.
magaupp marked this conversation as resolved.
Show resolved Hide resolved

2. [task][Context Policy](structural_Policy_has_properties,structural_Policy_has_methods)
Create and implement a `Policy` class following the below class diagram.
Add `get` and `set` accessors for the attribute.
`Policy` should implement a simple configuration mechanism:
magaupp marked this conversation as resolved.
Show resolved Hide resolved

1. [task][Select MergeSort](behavior_Policy_uses_MergeSort_for_big_list)
Select `MergeSort` when the List has more than 10 dates.

2. [task][Select BubbleSort](behavior_Policy_uses_BubbleSort_for_small_list)
Select `BubbleSort` when the List has less or equal 10 dates.

3. Complete the `main()` function which demonstrates switching between two strategies at runtime.
magaupp marked this conversation as resolved.
Show resolved Hide resolved

@startuml

class Policy {
+Policy(Context) <<constructor>>
<color:testsColor(structural_Policy_has_methods)>+configure()</color>
}

class Context {
<color:testsColor(structural_Context_has_properties)>-dates: Date[]</color>
<color:testsColor(structural_Context_has_methods)>+sort()</color>
}

interface SortStrategy {
+performSort(Date[])
}

class BubbleSort {
<color:testsColor(behavior_BubbleSort_should_sort_correctly)>+performSort(Date[])</color>
}

class MergeSort {
<color:testsColor(behavior_MergeSort_should_sort_correctly)>+performSort(Date[])</color>
}

MergeSort -up-|> SortStrategy #testsColor(structural_MergeSort_has_method)
BubbleSort -up-|> SortStrategy #testsColor(structural_BubbleSort_has_method)
Policy -right-> Context #testsColor(structural_Policy_has_properties): context
Context -right-> SortStrategy #testsColor(structural_Context_has_properties): sortAlgorithm

hide empty fields
hide empty methods

@enduml


### Part 3: Optional Challenges

(These are not tested)

1. Create a new class `QuickSort` that implements `SortStrategy` and implement the Quick Sort algorithm.

2. Think about a useful decision in `Policy` when to use the new `QuickSort` algorithm.
Loading
Loading