diff --git a/src/main/java/de/hftstuttgart/dtabackend/models/Result.java b/src/main/java/de/hftstuttgart/dtabackend/models/Result.java index 8d0fefc6be22fba9419c40a49d5960de77f6cd50..4af7920b465b6be06222e2b1cea0fc48f1a2a7bd 100644 --- a/src/main/java/de/hftstuttgart/dtabackend/models/Result.java +++ b/src/main/java/de/hftstuttgart/dtabackend/models/Result.java @@ -2,7 +2,9 @@ package de.hftstuttgart.dtabackend.models; public class Result { - public String name; + public String packageName; + public String className; + public String name; public int state; public String failureType; diff --git a/src/main/java/de/hftstuttgart/dtabackend/models/ResultSummary.java b/src/main/java/de/hftstuttgart/dtabackend/models/ResultSummary.java index 97b61bb0605a14de7349c8d4749f154ce2c28556..b9a11ef87bfb3ddc55cff095ade84f9a278dbca0 100644 --- a/src/main/java/de/hftstuttgart/dtabackend/models/ResultSummary.java +++ b/src/main/java/de/hftstuttgart/dtabackend/models/ResultSummary.java @@ -7,5 +7,7 @@ public class ResultSummary { public long timestamp = System.currentTimeMillis() / 1000; public String globalStacktrace = null; + public String successfulTestCompetencyProfile; + public String overallTestCompetencyProfile; public Set<Result> results = new HashSet<>(); } diff --git a/src/main/java/de/hftstuttgart/dtabackend/models/TestCompetencyProfile.java b/src/main/java/de/hftstuttgart/dtabackend/models/TestCompetencyProfile.java new file mode 100644 index 0000000000000000000000000000000000000000..a6a5e3ab506b7328d140597c46da2dd8d490ceaa --- /dev/null +++ b/src/main/java/de/hftstuttgart/dtabackend/models/TestCompetencyProfile.java @@ -0,0 +1,49 @@ +package de.hftstuttgart.dtabackend.models; + +public class TestCompetencyProfile { + public static final int MAX_COMPETENCY_DIMENSIONS = 16; + + public static final String COMPETENCY_SEPARATOR=";"; + + public String testPackageName; + public String testClassName; + public String testName; + + public float[] competencyAssessments=new float[MAX_COMPETENCY_DIMENSIONS]; + + public static float[] competencyProjection(float[] cp, float[] cp2) { + float z[] = new float[MAX_COMPETENCY_DIMENSIONS]; + + for (int i = 0; i < MAX_COMPETENCY_DIMENSIONS; i++) { + z[i] = cp[i] * cp2[i]; + } + return z; + } + + public static float[] competencyShare(float[] cp, float[] cpTotal) { + float z[] = new float[MAX_COMPETENCY_DIMENSIONS]; + + for (int i = 0; i < MAX_COMPETENCY_DIMENSIONS; i++) { + z[i] = cp[i] / cpTotal[i]; + } + return z; + } + + public static float[] competencySum(float[] cp, float[] cp2) { + float z[] = new float[MAX_COMPETENCY_DIMENSIONS]; + + for (int i = 0; i < MAX_COMPETENCY_DIMENSIONS; i++) { + z[i] = cp[i] + cp2[i]; + } + return z; + } + + @Override + public boolean equals(Object other) { + return other instanceof TestCompetencyProfile && + testPackageName.equals(((TestCompetencyProfile)other).testPackageName) && + testClassName.equals(((TestCompetencyProfile)other).testClassName) && + testName.equals(((TestCompetencyProfile)other).testName); + } + +} diff --git a/src/main/java/de/hftstuttgart/dtabackend/rest/v1/task/TaskUpload.java b/src/main/java/de/hftstuttgart/dtabackend/rest/v1/task/TaskUpload.java index 9f06d329f32421ec8756af2f8968b3faf9e01d61..4c4e520d8241e0082b272c0dc8e377da81be4d25 100644 --- a/src/main/java/de/hftstuttgart/dtabackend/rest/v1/task/TaskUpload.java +++ b/src/main/java/de/hftstuttgart/dtabackend/rest/v1/task/TaskUpload.java @@ -88,6 +88,8 @@ public class TaskUpload { LOG.info("check for provided Ticketsystem information"); UnifiedTicketingUtil.reportResults(taskFileRef.getInputStream(), resultSummary); } + + taskFileRef.getInputStream().close(); LOG.info("submission tested successfully"); return resultSummary; diff --git a/src/main/java/de/hftstuttgart/dtabackend/rest/v1/unittest/UnitTestUpload.java b/src/main/java/de/hftstuttgart/dtabackend/rest/v1/unittest/UnitTestUpload.java index 3621b151d7491dd2f3c9c8764333d58011a3633a..310b8b4c7becba60156339eab5690137d6fcda03 100644 --- a/src/main/java/de/hftstuttgart/dtabackend/rest/v1/unittest/UnitTestUpload.java +++ b/src/main/java/de/hftstuttgart/dtabackend/rest/v1/unittest/UnitTestUpload.java @@ -65,7 +65,7 @@ public class UnitTestUpload { unitTestFileRef.transferTo(file); LOG.debug(String.format("saved config file to: %s", file.getAbsolutePath())); - Pattern pattern = Pattern.compile(this.TESTCONFIGREGEX); + Pattern pattern = Pattern.compile(TESTCONFIGREGEX); Matcher config = null; LOG.debug("reading test configuration file"); diff --git a/src/main/java/de/hftstuttgart/dtabackend/utils/CompetencyAssessmentUtil.java b/src/main/java/de/hftstuttgart/dtabackend/utils/CompetencyAssessmentUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..4df652152d3d6a4776bcfdf8abe1095d0207e4c0 --- /dev/null +++ b/src/main/java/de/hftstuttgart/dtabackend/utils/CompetencyAssessmentUtil.java @@ -0,0 +1,88 @@ +package de.hftstuttgart.dtabackend.utils; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.hftstuttgart.dtabackend.models.Result; +import de.hftstuttgart.dtabackend.models.ResultSummary; +import de.hftstuttgart.dtabackend.models.TestCompetencyProfile; + +import java.io.FileNotFoundException; + +public class CompetencyAssessmentUtil { + private static final Logger LOG = LogManager.getLogger(CompetencyAssessmentUtil.class); + + public static String TEST_COMPETENCY_MANIFEST_FILE_NAME="competency-tests.mft"; + +/* public static void main(String[] args) throws StreamReadException, DatabindException, MalformedURLException, IOException { + List<TestCompetencyProfile> testCompetencyProfiles=readTestCompetencyProfiles(Path.of(args[0]), args[1]); + sumTestCompetencyProfiles(testCompetencyProfiles); + ObjectMapper objectMapper = new ObjectMapper(); + ResultSummary resultSummary = objectMapper.readValue( + new File(Path.of(args[0]).toFile(), args[2]).toURI().toURL(), + ResultSummary.class); + sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary); + } +*/ + public static float[] sumTestCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles) { + float[] tcpTotalProfile=new float[TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS]; + for(TestCompetencyProfile currentProfile: testCompetencyProfiles) { + tcpTotalProfile=TestCompetencyProfile.competencySum(tcpTotalProfile, currentProfile.competencyAssessments); + } + return tcpTotalProfile; + } + + public static float[] sumSuccessfulCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles, ResultSummary resultSummary) { + float[] sumSuccessful=new float[TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS]; + for(Result currentResult: resultSummary.results) { + if(currentResult.state==Result.State.SUCCESS.ordinal()) { + TestCompetencyProfile currentProfile=new TestCompetencyProfile(); + currentProfile.testPackageName=currentResult.packageName; + currentProfile.testClassName=currentResult.className; + currentProfile.testName=currentResult.name; + int testIndex=testCompetencyProfiles.indexOf(currentProfile); + sumSuccessful=TestCompetencyProfile.competencySum(sumSuccessful, testCompetencyProfiles.get(testIndex).competencyAssessments); + } + } + return sumSuccessful; + } + + public static List<TestCompetencyProfile> readTestCompetencyProfiles(Path testPath, String fileName) { + List<TestCompetencyProfile> testCompetencyProfiles=new ArrayList<TestCompetencyProfile>(); + try { + BufferedReader testCompetencyManifest=new BufferedReader(new FileReader(new File(testPath.toFile(), fileName))); + String testEntry=testCompetencyManifest.readLine(); + while(testEntry!=null) + { + String[] testEntyComponents=testEntry.split(TestCompetencyProfile.COMPETENCY_SEPARATOR); + TestCompetencyProfile currentProfile=new TestCompetencyProfile(); + currentProfile.testPackageName=testEntyComponents[0]; + currentProfile.testClassName=testEntyComponents[1]; + currentProfile.testName=testEntyComponents[2]; + for(int competencyIndex=0; competencyIndex<TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS; competencyIndex++) { + currentProfile.competencyAssessments[competencyIndex]=Float.valueOf(testEntyComponents[competencyIndex+3]); + } + testCompetencyProfiles.add(currentProfile); + testEntry=testCompetencyManifest.readLine(); + } + testCompetencyManifest.close(); + LOG.info("Added "+testCompetencyProfiles.size()+" test competency profiles from test competency manifest. Optional agent functionality enabled."); + } catch (FileNotFoundException e) { + LOG.info("Test competency manifest file for agent feedback not found. Skipping optional functionality."); + testCompetencyProfiles=null; + } catch (IOException e) { + LOG.info("Test competency manifest file for agent feedback unreadable. Skipping optional functionality."); + testCompetencyProfiles=null; + } + return testCompetencyProfiles; + } + +} diff --git a/src/main/java/de/hftstuttgart/dtabackend/utils/DockerUtil.java b/src/main/java/de/hftstuttgart/dtabackend/utils/DockerUtil.java index 68f4e941a54c96a7055b48996ee913c1b72cd91d..bf2d5982dbe26ee7dc2dba92ca5b9765c139cf8a 100644 --- a/src/main/java/de/hftstuttgart/dtabackend/utils/DockerUtil.java +++ b/src/main/java/de/hftstuttgart/dtabackend/utils/DockerUtil.java @@ -8,7 +8,6 @@ import com.github.dockerjava.api.model.HostConfig; import com.github.dockerjava.core.DefaultDockerClientConfig; import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.core.DockerClientImpl; -import com.github.dockerjava.transport.DockerHttpClient; import com.github.dockerjava.zerodep.ZerodepDockerHttpClient; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/de/hftstuttgart/dtabackend/utils/ExecuteTestUtil.java b/src/main/java/de/hftstuttgart/dtabackend/utils/ExecuteTestUtil.java index 83dd92436818586170b204eba5864aa3dee971f9..1e496cfac644dff14df71865f3d04dbb86841442 100644 --- a/src/main/java/de/hftstuttgart/dtabackend/utils/ExecuteTestUtil.java +++ b/src/main/java/de/hftstuttgart/dtabackend/utils/ExecuteTestUtil.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dockerjava.api.model.Bind; import com.github.dockerjava.api.model.Volume; import de.hftstuttgart.dtabackend.models.ResultSummary; +import de.hftstuttgart.dtabackend.models.TestCompetencyProfile; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.core.env.Environment; @@ -13,7 +15,10 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import java.util.regex.Matcher; +import java.util.stream.Collectors; +import java.util.stream.IntStream; @Component public class ExecuteTestUtil { @@ -109,7 +114,7 @@ public class ExecuteTestUtil { // check if result file is there if (!resultFile.exists() || !resultFile.isFile()) { - LOG.error(String.format("couln't find result file in %s", resultFile.getAbsolutePath())); + LOG.error(String.format("Could not find result file in %s", resultFile.getAbsolutePath())); throw new RuntimeException("no resultfile found"); } @@ -118,7 +123,21 @@ public class ExecuteTestUtil { ResultSummary resultSummary = objectMapper.readValue( resultFile.toURI().toURL(), ResultSummary.class); - + + LOG.info("Checking for optional test competency profile information for paedagogical agent functionality..."); + List<TestCompetencyProfile> testCompetencyProfiles=CompetencyAssessmentUtil.readTestCompetencyProfiles(testPathHost, CompetencyAssessmentUtil.TEST_COMPETENCY_MANIFEST_FILE_NAME); + if(testCompetencyProfiles!=null) { + LOG.info("Found optional test competency profiles, generating agent profile data..."); + resultSummary.overallTestCompetencyProfile=packFloats(CompetencyAssessmentUtil.sumTestCompetencyProfiles(testCompetencyProfiles)); + resultSummary.successfulTestCompetencyProfile=packFloats(CompetencyAssessmentUtil.sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary)); + } + return resultSummary; } + + private static String packFloats(float[] array) { + return IntStream.range(0, array.length) + .mapToObj(i -> String.valueOf(array[i])) + .collect(Collectors.joining(";")); + } } diff --git a/src/main/java/de/hftstuttgart/dtabackend/utils/RegexUtil.java b/src/main/java/de/hftstuttgart/dtabackend/utils/RegexUtil.java index c0692d715d9da189f1bc976a20d4fd91f0c3e723..64227dd6124510a98b8e2df56dec666ce1060f5f 100644 --- a/src/main/java/de/hftstuttgart/dtabackend/utils/RegexUtil.java +++ b/src/main/java/de/hftstuttgart/dtabackend/utils/RegexUtil.java @@ -15,7 +15,7 @@ import java.util.regex.Pattern; public class RegexUtil { public enum ConfigType { - PROFESSOR, + TEACHER, STUDENT, } @@ -26,13 +26,13 @@ public class RegexUtil { } public static Matcher findProfessorConfig(InputStream is) { - return findConfig(is, ConfigType.PROFESSOR); + return findConfig(is, ConfigType.TEACHER); } public static Matcher findConfig(InputStream is, ConfigType configType) { Pattern pattern; switch (configType) { - case PROFESSOR: + case TEACHER: pattern = Pattern.compile(UnitTestUpload.TESTCONFIGREGEX); break;