Commit 4fdae855 authored by mamunozgil's avatar mamunozgil
Browse files

Added debug logs

1 merge request!3Fix: dev recommendations
Pipeline #10595 passed with stage
in 18 seconds
Showing with 241 additions and 170 deletions
+241 -170
...@@ -27,110 +27,127 @@ import java.io.FileNotFoundException; ...@@ -27,110 +27,127 @@ import java.io.FileNotFoundException;
public class CompetencyAssessmentUtil { public class CompetencyAssessmentUtil {
private static final Logger LOG = LogManager.getLogger(CompetencyAssessmentUtil.class); private static final Logger LOG = LogManager.getLogger(CompetencyAssessmentUtil.class);
public static String TEST_COMPETENCY_MANIFEST_FILE_NAME="competency-tests.mft"; public static String TEST_COMPETENCY_MANIFEST_FILE_NAME = "competency-tests.mft";
public static String EXERCISE_COMPETENCY_MANIFEST_FILE_NAME="exercise-tests.mft"; public static String EXERCISE_COMPETENCY_MANIFEST_FILE_NAME = "exercise-tests.mft";
/*public static void main(String[] args) throws StreamReadException, DatabindException, MalformedURLException, IOException {
ResultSummary summary=ExecuteTestUtil.generateResult("1", Path.of(args[0]), Path.of(args[1]));
System.out.println(summary.successfulTestCompetencyProfile);
}
*/
public static float[] sumTestCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles) { public static float[] sumTestCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles) {
float[] tcpTotalProfile=new float[ICompetencyProfile.MAX_COMPETENCY_DIMENSIONS]; LOG.debug("Starting sumTestCompetencyProfiles with {} test profiles.", testCompetencyProfiles.size());
for(TestCompetencyProfile currentProfile: testCompetencyProfiles) {
tcpTotalProfile=ICompetencyProfile.competencySum(tcpTotalProfile, currentProfile.competencyAssessments); float[] tcpTotalProfile = new float[ICompetencyProfile.MAX_COMPETENCY_DIMENSIONS];
for (TestCompetencyProfile currentProfile : testCompetencyProfiles) {
LOG.debug("Adding competency assessments from profile: {}", currentProfile.testName);
tcpTotalProfile = ICompetencyProfile.competencySum(tcpTotalProfile, currentProfile.competencyAssessments);
} }
LOG.debug("Completed summing test competency profiles. Total profile: {}", packFloats(tcpTotalProfile));
return tcpTotalProfile; return tcpTotalProfile;
} }
public static float[] sumSuccessfulCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles, ResultSummary resultSummary, boolean success) { public static float[] sumSuccessfulCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles, ResultSummary resultSummary, boolean success) {
float[] sumSuccessful=new float[ICompetencyProfile.MAX_COMPETENCY_DIMENSIONS]; LOG.debug("Starting sumSuccessfulCompetencyProfiles. Success flag: {}", success);
for(Result currentResult: resultSummary.results) {
float[] sumSuccessful = new float[ICompetencyProfile.MAX_COMPETENCY_DIMENSIONS];
for (Result currentResult : resultSummary.results) {
boolean isSuccess = Integer.valueOf(currentResult.state).equals(Result.State.SUCCESS.ordinal()); boolean isSuccess = Integer.valueOf(currentResult.state).equals(Result.State.SUCCESS.ordinal());
if (isSuccess == success) { LOG.debug("Processing result: {} with success state: {}", currentResult.name, isSuccess);
TestCompetencyProfile currentProfile=new TestCompetencyProfile();
currentProfile.testPackageName=(currentResult.packageName!=null)?currentResult.packageName:""; if (isSuccess == success) {
currentProfile.testClassName=(currentResult.className!=null)?currentResult.className:""; TestCompetencyProfile currentProfile = new TestCompetencyProfile();
currentProfile.testName=(currentResult.name!=null)?currentResult.name:""; currentProfile.testPackageName = (currentResult.packageName != null) ? currentResult.packageName : "";
int testIndex=testCompetencyProfiles.indexOf(currentProfile); currentProfile.testClassName = (currentResult.className != null) ? currentResult.className : "";
if(testIndex!=-1) { currentProfile.testName = (currentResult.name != null) ? currentResult.name : "";
sumSuccessful=ICompetencyProfile.competencySum(sumSuccessful, testCompetencyProfiles.get(testIndex).competencyAssessments);
int testIndex = testCompetencyProfiles.indexOf(currentProfile);
if (testIndex != -1) {
LOG.debug("Found matching profile for result: {}. Adding competencies.", currentResult.name);
sumSuccessful = ICompetencyProfile.competencySum(sumSuccessful, testCompetencyProfiles.get(testIndex).competencyAssessments);
} else {
LOG.debug("No matching profile found for result: {}", currentResult.name);
} }
} }
} }
LOG.debug("Completed summing successful competency profiles. Sum: {}", packFloats(sumSuccessful));
return sumSuccessful; return sumSuccessful;
} }
public static List<TestCompetencyProfile> readTestCompetencyProfiles(Path testPath, String fileName) { public static List<TestCompetencyProfile> readTestCompetencyProfiles(Path testPath, String fileName) {
List<TestCompetencyProfile> testCompetencyProfiles=new ArrayList<TestCompetencyProfile>(); LOG.debug("Reading test competency profiles from path: {}, file: {}", testPath, fileName);
try {
BufferedReader testCompetencyManifest=new BufferedReader(new FileReader(new File(testPath.toFile(), fileName))); List<TestCompetencyProfile> testCompetencyProfiles = new ArrayList<>();
String testEntry=testCompetencyManifest.readLine(); try (BufferedReader testCompetencyManifest = new BufferedReader(new FileReader(new File(testPath.toFile(), fileName)))) {
while(testEntry!=null) String testEntry = testCompetencyManifest.readLine();
{
String[] testEntyComponents=testEntry.split(ICompetencyProfile.COMPETENCY_SEPARATOR); while (testEntry != null) {
TestCompetencyProfile currentProfile=new TestCompetencyProfile(); String[] testEntyComponents = testEntry.split(ICompetencyProfile.COMPETENCY_SEPARATOR);
currentProfile.testPackageName=testEntyComponents[0]; TestCompetencyProfile currentProfile = new TestCompetencyProfile();
currentProfile.testClassName=testEntyComponents[1];
currentProfile.testName=testEntyComponents[2]; currentProfile.testPackageName = testEntyComponents[0];
for(int competencyIndex=0; competencyIndex<ICompetencyProfile.MAX_COMPETENCY_DIMENSIONS; competencyIndex++) { currentProfile.testClassName = testEntyComponents[1];
currentProfile.competencyAssessments[competencyIndex]=Float.valueOf(testEntyComponents[competencyIndex+3]); currentProfile.testName = testEntyComponents[2];
for (int competencyIndex = 0; competencyIndex < ICompetencyProfile.MAX_COMPETENCY_DIMENSIONS; competencyIndex++) {
currentProfile.competencyAssessments[competencyIndex] = Float.valueOf(testEntyComponents[competencyIndex + 3]);
} }
testCompetencyProfiles.add(currentProfile); testCompetencyProfiles.add(currentProfile);
testEntry=testCompetencyManifest.readLine(); LOG.debug("Added test competency profile: {}", currentProfile.testName);
testEntry = testCompetencyManifest.readLine();
} }
testCompetencyManifest.close();
LOG.info("Added "+testCompetencyProfiles.size()+" test competency profiles from test competency manifest. Optional agent functionality enabled."); LOG.info("Added {} test competency profiles from manifest.", testCompetencyProfiles.size());
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
LOG.info("Test competency manifest file for agent feedback not found. Skipping optional functionality."); LOG.info("Test competency manifest file not found. Skipping functionality.");
testCompetencyProfiles=null;
} catch (IOException e) { } catch (IOException e) {
LOG.info("Test competency manifest file for agent feedback unreadable. Skipping optional functionality."); LOG.info("Test competency manifest file unreadable. Skipping functionality.");
testCompetencyProfiles=null; }
}
return testCompetencyProfiles; return testCompetencyProfiles;
} }
public static List<ExerciseCompetencyProfile> readExerciseCompetencyProfiles(Path exercisePath, String fileName) { public static List<ExerciseCompetencyProfile> readExerciseCompetencyProfiles(Path exercisePath, String fileName) {
List<ExerciseCompetencyProfile> exerciseCompetencyProfiles = new ArrayList<>(); LOG.debug("Reading exercise competency profiles from path: {}, file: {}", exercisePath, fileName);
try (BufferedReader exerciseCompetencyManifest = new BufferedReader(new FileReader(new File(exercisePath.toFile(), fileName)))) { List<ExerciseCompetencyProfile> exerciseCompetencyProfiles = new ArrayList<>();
String exerciseEntry = exerciseCompetencyManifest.readLine();
try (BufferedReader exerciseCompetencyManifest = new BufferedReader(new FileReader(new File(exercisePath.toFile(), fileName)))) {
while (exerciseEntry != null) { String exerciseEntry = exerciseCompetencyManifest.readLine();
String[] exerciseEntyComponents = exerciseEntry.split(ExerciseCompetencyProfile.COMPETENCY_SEPARATOR);
ExerciseCompetencyProfile currentProfile = new ExerciseCompetencyProfile(); while (exerciseEntry != null) {
String[] exerciseEntyComponents = exerciseEntry.split(ExerciseCompetencyProfile.COMPETENCY_SEPARATOR);
currentProfile.exerciseTopicName = exerciseEntyComponents[0]; ExerciseCompetencyProfile currentProfile = new ExerciseCompetencyProfile();
currentProfile.exerciseName = exerciseEntyComponents[1];
currentProfile.exerciseURL = exerciseEntyComponents[2]; currentProfile.exerciseTopicName = exerciseEntyComponents[0];
currentProfile.exerciseName = exerciseEntyComponents[1];
for (int competencyIndex = 0; competencyIndex < ExerciseCompetencyProfile.MAX_COMPETENCY_DIMENSIONS; competencyIndex++) { currentProfile.exerciseURL = exerciseEntyComponents[2];
currentProfile.competencyAssessments[competencyIndex] = Float.valueOf(exerciseEntyComponents[competencyIndex+3]);
} for (int competencyIndex = 0; competencyIndex < ExerciseCompetencyProfile.MAX_COMPETENCY_DIMENSIONS; competencyIndex++) {
currentProfile.competencyAssessments[competencyIndex] = Float.valueOf(exerciseEntyComponents[competencyIndex + 3]);
currentProfile.difficulty = Float.parseFloat(exerciseEntyComponents[19]); }
exerciseCompetencyProfiles.add(currentProfile); currentProfile.difficulty = Float.parseFloat(exerciseEntyComponents[19]);
exerciseEntry = exerciseCompetencyManifest.readLine(); exerciseCompetencyProfiles.add(currentProfile);
} LOG.debug("Added exercise competency profile: {}", currentProfile.exerciseName);
exerciseCompetencyManifest.close();
LOG.info("Added " + exerciseCompetencyProfiles.size() + " test competency profiles from exercise competency manifest."); exerciseEntry = exerciseCompetencyManifest.readLine();
} catch (FileNotFoundException e) { }
LOG.info("Exercise competency manifest file not found.");
} catch (IOException e) { LOG.info("Added {} exercise competency profiles from manifest.", exerciseCompetencyProfiles.size());
LOG.info("Exercise competency manifest file unreadable."); } catch (FileNotFoundException e) {
} LOG.info("Exercise competency manifest file not found.");
} catch (IOException e) {
return exerciseCompetencyProfiles; LOG.info("Exercise competency manifest file unreadable.");
}
return exerciseCompetencyProfiles;
} }
public static String packFloats(float[] array) { public static String packFloats(float[] array) {
LOG.debug("Packing float array into string: {}", array);
return IntStream.range(0, array.length) return IntStream.range(0, array.length)
.mapToObj(i -> String.valueOf(array[i])) .mapToObj(i -> String.valueOf(array[i]))
.collect(Collectors.joining(";")); .collect(Collectors.joining(";"));
} }
} }
...@@ -71,7 +71,7 @@ public class ExecuteTestUtil { ...@@ -71,7 +71,7 @@ public class ExecuteTestUtil {
assignmentBasePath + assignmentId + "_checkout", assignmentBasePath + assignmentId + "_checkout",
testPath.toString() ); testPath.toString() );
Files.copy(Paths.get( Files.copy(Paths.get(
assignmentBasePath, assignmentId + "_checkout", assignmentBasePath, assignmentId + "_checkout",
CompetencyAssessmentUtil.EXERCISE_COMPETENCY_MANIFEST_FILE_NAME), CompetencyAssessmentUtil.EXERCISE_COMPETENCY_MANIFEST_FILE_NAME),
Paths.get( Paths.get(
testPath.toString(), testPath.toString(),
...@@ -177,99 +177,153 @@ public class ExecuteTestUtil { ...@@ -177,99 +177,153 @@ public class ExecuteTestUtil {
return resultSummary; return resultSummary;
} }
/* /*
* exercise recommendation part * exercise recommendation part
*/ */
public List<Recommendation> recommendNextExercises(String assignmentId, Path testPathHost, List<TestCompetencyProfile> testCompetencyProfiles, ResultSummary resultSummary) public List<Recommendation> recommendNextExercises(String assignmentId, Path testPathHost, List<TestCompetencyProfile> testCompetencyProfiles, ResultSummary resultSummary)
throws FileNotFoundException { throws FileNotFoundException {
// fetch repo url from original test upload LOG.debug("Starting recommendNextExercises with assignmentId: {}", assignmentId);
Pattern pattern = Pattern.compile(RegexUtil.DTA_TESTCONFIGREGEX);
File file = Paths.get(assignmentBasePath, assignmentId + ".txt").toFile(); // fetch repo url from original test upload
FileInputStream configFileStream = new FileInputStream(file); Pattern pattern = Pattern.compile(RegexUtil.DTA_TESTCONFIGREGEX);
Matcher config = RegexUtil.extractConfig(configFileStream, pattern); LOG.debug("Compiled regex pattern for DTA_TESTCONFIGREGEX.");
String testRepoURL = config.group(1)+config.group(4);
File file = Paths.get(assignmentBasePath, assignmentId + ".txt").toFile();
List<ExerciseCompetencyProfile> exerciseCompetencyProfiles = CompetencyAssessmentUtil.readExerciseCompetencyProfiles(testPathHost, CompetencyAssessmentUtil.EXERCISE_COMPETENCY_MANIFEST_FILE_NAME); LOG.debug("Resolved file path for assignmentId {}: {}", assignmentId, file.getAbsolutePath());
int currentTopicIndex=0; FileInputStream configFileStream = new FileInputStream(file);
float currentDifficulty=0.0f; LOG.debug("Opened FileInputStream for file: {}", file.getAbsolutePath());
//build course topic order Matcher config = RegexUtil.extractConfig(configFileStream, pattern);
Map<String, Integer> topicOrder = new HashMap<>(); LOG.debug("Extracted configuration using regex pattern.");
int order = 1;
for (ExerciseCompetencyProfile e : exerciseCompetencyProfiles) { String testRepoURL = config.group(1) + config.group(4);
if (!topicOrder.containsKey(e.exerciseTopicName)) { LOG.debug("Constructed testRepoURL: {}", testRepoURL);
topicOrder.put(e.exerciseTopicName, order++);
} List<ExerciseCompetencyProfile> exerciseCompetencyProfiles = CompetencyAssessmentUtil.readExerciseCompetencyProfiles(
if (e.exerciseURL.equals(testRepoURL)) { testPathHost, CompetencyAssessmentUtil.EXERCISE_COMPETENCY_MANIFEST_FILE_NAME);
currentTopicIndex = order; LOG.debug("Read exercise competency profiles from path: {}", testPathHost.resolve(CompetencyAssessmentUtil.EXERCISE_COMPETENCY_MANIFEST_FILE_NAME));
currentDifficulty = e.difficulty;
} int currentTopicIndex = 0;
float currentDifficulty = 0.0f;
// build course topic order
LOG.debug("Building course topic order.");
Map<String, Integer> topicOrder = new HashMap<>();
int order = 1;
for (ExerciseCompetencyProfile e : exerciseCompetencyProfiles) {
if (!topicOrder.containsKey(e.exerciseTopicName)) {
topicOrder.put(e.exerciseTopicName, order++);
LOG.debug("Added topic {} to topicOrder with order {}", e.exerciseTopicName, order - 1);
} }
if (e.exerciseURL.equals(testRepoURL)) {
//filter exercises according to success currentTopicIndex = order;
float[] unsuccessful = CompetencyAssessmentUtil.sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary, false); currentDifficulty = e.difficulty;
List<ExerciseCompetencyProfile> filteredExercises = filterExercisesByTopicsAndDifficulty( LOG.debug("Matched current testRepoURL to topic: {}, index: {}, difficulty: {}", e.exerciseTopicName, currentTopicIndex, currentDifficulty);
exerciseCompetencyProfiles, topicOrder, currentTopicIndex, testRepoURL,
currentDifficulty, unsuccessful, resultSummary);
//compute recommendations
List<Recommendation> recommendedExercises = new ArrayList<>();
for (ExerciseCompetencyProfile exerciseProfile : filteredExercises) {
Recommendation recommendation = new Recommendation(exerciseProfile.exerciseTopicName, exerciseProfile.exerciseURL, exerciseProfile.exerciseName,
exerciseProfile.difficulty, calculateScore(exerciseProfile, unsuccessful, topicOrder, currentDifficulty));
recommendedExercises.add(recommendation);
LOG.info("Recommending exercise "+recommendation.topic+"/"+recommendation.exerciseName+" with score "+recommendation.score);
} }
//sort the recommendations for successful or resilient learners, otherwise reverse in display
recommendedExercises.stream().sorted(Recommendation.COMPARE_BY_SCORE).collect(Collectors.toList());
return recommendedExercises;
} }
public static List<ExerciseCompetencyProfile> filterExercisesByTopicsAndDifficulty(List<ExerciseCompetencyProfile> exerciseCompetencyProfiles, // filter exercises according to success
Map<String, Integer> topicOrder, int currentTopicIndex, String testRepoURL, float currentDifficulty, float[] unsuccessful, LOG.debug("Filtering exercises according to success.");
ResultSummary resultSummary) { float[] unsuccessful = CompetencyAssessmentUtil.sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary, false);
//filter out all advanced topics in any case LOG.debug("Computed unsuccessful competency profile: {}", unsuccessful);
//option for later: include next topic if fullsuccess and current difficulty == max difficulty
List<ExerciseCompetencyProfile> filteredExercises = exerciseCompetencyProfiles.stream()
.filter(testProfile -> topicOrder.get(testProfile.exerciseTopicName) <= currentTopicIndex)
.collect(Collectors.toList());
//filter by difficulty according to success
if (isFullSuccess(unsuccessful)) {
filteredExercises = filteredExercises.stream().filter(profile -> profile.difficulty >= currentDifficulty && !testRepoURL.equals(profile.exerciseURL)).collect(Collectors.toList());
} else {
filteredExercises = filteredExercises.stream().filter(profile -> profile.difficulty <= currentDifficulty).collect(Collectors.toList());
}
return filteredExercises; List<ExerciseCompetencyProfile> filteredExercises = filterExercisesByTopicsAndDifficulty(
} exerciseCompetencyProfiles, topicOrder, currentTopicIndex, testRepoURL,
currentDifficulty, unsuccessful, resultSummary);
public static boolean isFullSuccess(float[] unsuccessful) { LOG.debug("Filtered exercises count: {}", filteredExercises.size());
for (float value : unsuccessful) {
if (value != 0.0f) {
return false;
}
}
return true;
}
public static float calculateScore(ExerciseCompetencyProfile exerciseProfile, float[] unsuccessful, Map<String, Integer> topicOrder, float currentDifficulty) { // compute recommendations
//ensure factor 1 for full success not to blank out score, thus offset the base LOG.debug("Computing recommendations from filtered exercises.");
float score = 1.0f; List<Recommendation> recommendedExercises = new ArrayList<>();
//competency profile difference to not fully achieved competencies component for (ExerciseCompetencyProfile exerciseProfile : filteredExercises) {
for (int i = 0; i < exerciseProfile.competencyAssessments.length-1; i++) { Recommendation recommendation = new Recommendation(
score += exerciseProfile.competencyAssessments[i] * unsuccessful[i]; exerciseProfile.exerciseTopicName, exerciseProfile.exerciseURL, exerciseProfile.exerciseName,
} exerciseProfile.difficulty, calculateScore(exerciseProfile, unsuccessful, topicOrder, currentDifficulty));
recommendedExercises.add(recommendation);
//difficulty component LOG.info("Recommending exercise {}/{} with score {}", recommendation.topic, recommendation.exerciseName, recommendation.score);
score = score * (exerciseProfile.difficulty*(0.5f+Math.abs(currentDifficulty-exerciseProfile.difficulty)));
//topic component
score *= topicOrder.get(exerciseProfile.exerciseTopicName);
score = Math.round(score * 10.0f) / 10.0f;
return score;
} }
// sort the recommendations for successful or resilient learners, otherwise reverse in display
LOG.debug("Sorting recommendations.");
recommendedExercises.stream().sorted(Recommendation.COMPARE_BY_SCORE).collect(Collectors.toList());
LOG.debug("Completed recommendNextExercises with {} recommendations.", recommendedExercises.size());
return recommendedExercises;
}
public static List<ExerciseCompetencyProfile> filterExercisesByTopicsAndDifficulty(
List<ExerciseCompetencyProfile> exerciseCompetencyProfiles,
Map<String, Integer> topicOrder, int currentTopicIndex, String testRepoURL,
float currentDifficulty, float[] unsuccessful, ResultSummary resultSummary) {
LOG.debug("Starting filterExercisesByTopicsAndDifficulty with currentTopicIndex: {}, currentDifficulty: {}, testRepoURL: {}",
currentTopicIndex, currentDifficulty, testRepoURL);
// Filter out all advanced topics in any case
List<ExerciseCompetencyProfile> filteredExercises = exerciseCompetencyProfiles.stream()
.filter(testProfile -> topicOrder.get(testProfile.exerciseTopicName) <= currentTopicIndex)
.collect(Collectors.toList());
LOG.debug("Filtered exercises by topic index. Remaining exercises count: {}", filteredExercises.size());
// Filter by difficulty according to success
if (isFullSuccess(unsuccessful)) {
LOG.debug("Detected full success, filtering exercises with difficulty >= {} and excluding current testRepoURL.", currentDifficulty);
filteredExercises = filteredExercises.stream()
.filter(profile -> profile.difficulty >= currentDifficulty && !testRepoURL.equals(profile.exerciseURL))
.collect(Collectors.toList());
} else {
LOG.debug("Detected partial success, filtering exercises with difficulty <= {}.", currentDifficulty);
filteredExercises = filteredExercises.stream()
.filter(profile -> profile.difficulty <= currentDifficulty)
.collect(Collectors.toList());
}
LOG.debug("Filtered exercises count after difficulty filter: {}", filteredExercises.size());
return filteredExercises;
}
public static boolean isFullSuccess(float[] unsuccessful) {
LOG.debug("Checking for full success. Unsuccessful array: {}", unsuccessful);
for (float value : unsuccessful) {
if (value != 0.0f) {
LOG.debug("Found non-zero value in unsuccessful array: {}. Returning false for full success.", value);
return false;
}
}
LOG.debug("All values in unsuccessful array are zero. Returning true for full success.");
return true;
}
public static float calculateScore(ExerciseCompetencyProfile exerciseProfile, float[] unsuccessful,
Map<String, Integer> topicOrder, float currentDifficulty) {
LOG.debug("Starting calculateScore for exercise: {}, difficulty: {}, currentDifficulty: {}",
exerciseProfile.exerciseName, exerciseProfile.difficulty, currentDifficulty);
float score = 1.0f;
LOG.debug("Initial score set to 1.0");
// Competency profile difference to not fully achieved competencies component
for (int i = 0; i < exerciseProfile.competencyAssessments.length - 1; i++) {
float adjustment = exerciseProfile.competencyAssessments[i] * unsuccessful[i];
score += adjustment;
LOG.debug("Adjusted score by competency index {}: {}, new score: {}", i, adjustment, score);
}
// Difficulty component
float difficultyComponent = exerciseProfile.difficulty * (0.5f + Math.abs(currentDifficulty - exerciseProfile.difficulty));
score = score * difficultyComponent;
LOG.debug("Applied difficulty component: {}, updated score: {}", difficultyComponent, score);
// Topic component
float topicMultiplier = topicOrder.get(exerciseProfile.exerciseTopicName);
score *= topicMultiplier;
LOG.debug("Applied topic multiplier: {}, updated score: {}", topicMultiplier, score);
// Round score
score = Math.round(score * 10.0f) / 10.0f;
LOG.debug("Final rounded score: {}", score);
return score;
}
} }
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment