diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..d505847
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,26 @@
+# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on:
+ push:
+ branches: [ "master" ]
+ pull_request:
+ branches: [ "master" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up JDK 11
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+ - name: Build with Maven
+ run: mvn -B package --file pom.xml
diff --git a/.woodpecker/maven.yml b/.woodpecker/maven.yml
deleted file mode 100644
index 877f1e3..0000000
--- a/.woodpecker/maven.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-steps:
- - name: test
- image: maven:3.9.6-eclipse-temurin-17-alpine
- commands:
- - mvn -B verify
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 3f1e4dc..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- 4.0.0
-
- eu.ztsh.training
- hackerrank
- 1.0-SNAPSHOT
-
-
- 17
- 17
-
-
-
-
- org.junit.jupiter
- junit-jupiter
- 5.9.0
- test
-
-
- org.assertj
- assertj-core
- 3.23.1
-
-
-
-
\ No newline at end of file
diff --git a/src/test/java/eu/ztsh/training/hackerrank/EnvironmentTest.java b/src/test/java/eu/ztsh/training/hackerrank/EnvironmentTest.java
deleted file mode 100644
index fda2bda..0000000
--- a/src/test/java/eu/ztsh/training/hackerrank/EnvironmentTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package eu.ztsh.training.hackerrank;
-
-import java.util.List;
-import java.util.Scanner;
-
-import eu.ztsh.training.hackerrank.SolutionClassDescription.FieldModifier;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class EnvironmentTest {
-
- abstract static class HackerRankEnvironmentTest extends HackerRankTest {
-
- @Test
- public void passTwoLinesTest() {
- var input = List.of(
- "Line 1",
- "Line 2"
- );
- var result = invoke(input);
- assertThat(result).containsExactlyElementsOf(input);
- }
-
- @Test
- public void multiInvokeTest() {
- var input = List.of(
- "Line 1",
- "Line 2"
- );
- invoke(input);
- invoke(input);
- var result = invoke(input);
- assertThat(result).containsExactlyElementsOf(input);
- }
-
- @Test
- public void passTwoAnotherLinesTest() {
- var input = List.of(
- "Line 3",
- "Line 4"
- );
- var result = invoke(input);
- assertThat(result).containsExactlyElementsOf(input);
- }
-
- }
-
- @Nested
- @DisplayName("Test with Scanner created as private static field")
- class EnvironmentPrivateStaticTest extends HackerRankEnvironmentTest {
-
- @Override
- protected SolutionClassDescription getSolutionClassDescription() {
- return new SolutionClassDescription(SampleSolutionWithPrivateStaticScanner.class,
- "scan",
- new FieldModifier[]{FieldModifier.PRIVATE, FieldModifier.STATIC});
- }
-
- }
-
- @Disabled("Disabled: run with --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED")
- @Nested
- @DisplayName("Test with Scanner created as private static final field")
- class EnvironmentPrivateStaticFinalTest extends HackerRankEnvironmentTest {
-
- @Override
- protected SolutionClassDescription getSolutionClassDescription() {
- return new SolutionClassDescription(SampleSolutionWithPrivateStaticScanner.class,
- "scan",
- FieldModifier.values());
- }
-
- }
-
- @Nested
- @DisplayName("Test with Scanner created in main(String[]) method")
- class EnvironmentInlineTest extends HackerRankEnvironmentTest {
-
- @Override
- protected SolutionClassDescription getSolutionClassDescription() {
- return new SolutionClassDescription(SampleSolutionWithInlineScanner.class);
- }
-
- }
-
-}
-
-class SampleSolutionWithPrivateStaticScanner {
-
- public static void main(String... args) {
- while (scan.hasNext()) {
- System.out.println(scan.nextLine());
- }
- }
-
- @SuppressWarnings("FieldMayBeFinal")
- private static Scanner scan = new Scanner(System.in);
-
-}
-
-class SampleSolutionWithPrivateStaticFinalScanner {
-
- public static void main(String... args) {
- while (scan.hasNext()) {
- System.out.println(scan.nextLine());
- }
- }
-
- private static final Scanner scan = new Scanner(System.in);
-
-}
-
-class SampleSolutionWithInlineScanner {
-
- public static void main(String... args) {
- var scan = new Scanner(System.in);
- while (scan.hasNext()) {
- System.out.println(scan.nextLine());
- }
- }
-
-}
diff --git a/src/test/java/eu/ztsh/training/hackerrank/HackerRankTest.java b/src/test/java/eu/ztsh/training/hackerrank/HackerRankTest.java
deleted file mode 100644
index 106f212..0000000
--- a/src/test/java/eu/ztsh/training/hackerrank/HackerRankTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package eu.ztsh.training.hackerrank;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-
-/**
- * Common class with all the necessary logic
- */
-public abstract class HackerRankTest {
-
- @BeforeAll
- public static void setUpStreams() {
- // Redirect stdout & stderr to own streams
- System.setOut(new PrintStream(outContent));
- System.setErr(new PrintStream(errContent));
- }
-
- @AfterAll
- public static void restoreStreams() {
- System.setOut(originalOut);
- System.setErr(originalErr);
- System.setIn(originalIn);
- }
-
- protected List invoke(List input) {
- try {
- // reset our stdout as check is based on it
- outContent.reset();
- // write content to args of Solution#main
- writeLines(input);
- // check if scanner has other name than "scanner"
- if (getSolutionClassDescription().fieldName() != null) {
- ReflectionHelper.reloadScanner(getSolutionClassDescription());
- }
- // run Solution#main
- getSolutionClassDescription().targetClass()
- .getMethod("main", String[].class)
- .invoke(null, (Object) new String[]{});
- // return intercepted output
- return readLines();
- } catch (final NoSuchMethodException | InvocationTargetException | IllegalAccessException |
- NoSuchFieldException e) {
- throw new IllegalStateException(e);
- }
- }
-
- protected abstract SolutionClassDescription getSolutionClassDescription();
-
- private void writeLines(List lines) {
- // https://stackoverflow.com/a/31635737
- System.setIn(new ByteArrayInputStream((String.join(System.lineSeparator(), lines) + System.lineSeparator()).getBytes()));
- }
-
- private List readLines() {
- // https://stackoverflow.com/a/1119559
- return List.copyOf(Arrays.stream(outContent.toString().split(System.lineSeparator())).toList());
- }
-
- private final static ByteArrayOutputStream outContent = new ByteArrayOutputStream();
- private final static ByteArrayOutputStream errContent = new ByteArrayOutputStream();
- private final static PrintStream originalOut = System.out;
- private final static PrintStream originalErr = System.err;
- private final static InputStream originalIn = System.in;
-
-}
diff --git a/src/test/java/eu/ztsh/training/hackerrank/ReflectionHelper.java b/src/test/java/eu/ztsh/training/hackerrank/ReflectionHelper.java
deleted file mode 100644
index d00b23e..0000000
--- a/src/test/java/eu/ztsh/training/hackerrank/ReflectionHelper.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package eu.ztsh.training.hackerrank;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.Scanner;
-
-import eu.ztsh.training.hackerrank.SolutionClassDescription.FieldModifier;
-
-/**
- * Util that helps with scanner declared outside Solution#main
- */
-public class ReflectionHelper {
-
- // https://stackoverflow.com/a/56043252
- static {
- try {
- var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
- MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
- CAN_MODIFY_FINALS = true;
- } catch (IllegalAccessException | NoSuchFieldException ex) {
- CAN_MODIFY_FINALS = false;
- }
- }
-
- /**
- * Modify scanner field to substitute it with custom readable one
- *
- * @param description Solution class parameters
- * @throws NoSuchFieldException when there description.fieldName points to incorrect name
- * @throws IllegalAccessException on scanner substitution error
- */
- static void reloadScanner(SolutionClassDescription description)
- throws NoSuchFieldException, IllegalAccessException {
- // https://stackoverflow.com/a/3301720
- var scannerField = description.hasModifier(FieldModifier.STATIC)
- ? description.targetClass().getDeclaredField(description.fieldName())
- : description.targetClass().getField(description.fieldName());
- if (description.hasModifier(FieldModifier.PRIVATE)) {
- scannerField.setAccessible(true);
- }
- if (description.hasModifier(FieldModifier.FINAL) && CAN_MODIFY_FINALS) {
- MODIFIERS.set(scannerField, scannerField.getModifiers() & ~Modifier.FINAL);
- }
- scannerField.set(null, new Scanner(System.in));
- }
-
- private static VarHandle MODIFIERS;
- private static boolean CAN_MODIFY_FINALS;
-
-}
diff --git a/src/test/java/eu/ztsh/training/hackerrank/SolutionClassDescription.java b/src/test/java/eu/ztsh/training/hackerrank/SolutionClassDescription.java
deleted file mode 100644
index 2ac51dd..0000000
--- a/src/test/java/eu/ztsh/training/hackerrank/SolutionClassDescription.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package eu.ztsh.training.hackerrank;
-
-import java.util.Arrays;
-
-/**
- * Solution params definition
- *
- * @param targetClass Solution
- * @param fieldName scanner field name
- * @param modifiers scanner field modifiers
- */
-public record SolutionClassDescription(Class> targetClass, String fieldName, FieldModifier[] modifiers) {
-
- SolutionClassDescription(Class> targetClass) {
- this(targetClass, null, null);
- }
-
- public boolean hasModifier(FieldModifier modifier) {
- return Arrays.asList(modifiers).contains(modifier);
- }
-
- public enum FieldModifier {
- PRIVATE, FINAL, STATIC
- }
-
-}