diff --git a/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java b/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java index 798030b97d1bbbc43034593d6ea5b3ac199873d0..4a2fb2b6a24c0c93c7c4360e67f016057911dba3 100644 --- a/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java +++ b/src/main/java/de/thm/arsnova/domain/QuestionBasedLearningProgress.java @@ -41,32 +41,29 @@ public class QuestionBasedLearningProgress implements LearningProgress { } private int calculateCourseProgress(CourseScore courseScore) { - int numQuestionsCorrect = numQuestionsCorrectForCourse(courseScore); - final double correctQuestionsOnAverage = (double)numQuestionsCorrect / (double)(courseScore.getQuestionCount()); // calculate percent, cap results to 100 - return (int) Math.min(100, Math.round(correctQuestionsOnAverage*100)); + return (int) Math.min(100, Math.round(correctAnswerRatio(courseScore)*100)); } - private int numQuestionsCorrectForCourse(CourseScore courseScore) { - // a question is seen as "correct" if and only if all participants have answered it correctly - int numQuestionsCorrect = 0; + private double correctAnswerRatio(CourseScore courseScore) { + double ratio = 0; for (QuestionScore questionScore : courseScore) { + int numAnswers = questionScore.getUserCount(); + int numAnswersCorrect = 0; int requiredScore = questionScore.getMaximum(); if (!questionScore.hasScores()) { continue; } - boolean allCorrect = true; for (UserScore userScore : questionScore) { - if (!userScore.hasScore(requiredScore)) { - allCorrect = false; - break; + if (userScore.hasScore(requiredScore)) { + numAnswersCorrect++; } } - if (allCorrect) { - numQuestionsCorrect++; + if (numAnswers != 0) { + ratio += (double)numAnswersCorrect / (numAnswers * courseScore.getQuestionCount()); } } - return numQuestionsCorrect; + return ratio; } @Override diff --git a/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java b/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java index 01148489ad4030f58cab6124a29e48b59c1d9bca..a3389f25009bbb2a8282ca876b55e86767f89099 100644 --- a/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java +++ b/src/test/java/de/thm/arsnova/domain/QuestionBasedLearningProgressTest.java @@ -76,4 +76,79 @@ public class QuestionBasedLearningProgressTest { assertEquals(expected, actual); } + /** + * If 99 users answer a question correctly, and 1 user does not, percentage should be 99%. + */ + @Test + public void shouldCalculatePercentageOfOneQuestionWithSomeWrongAnswers() { + CourseScore courseScore = new CourseScore(); + courseScore.add("question", 10); + for (int i = 0; i < 99; i++) { + courseScore.add("question", new TestUser("user"+i).getUsername(), 10); + } + courseScore.add("question", new TestUser("user-with-a-wrong-answer").getUsername(), 0); + + IDatabaseDao db = mock(IDatabaseDao.class); + when(db.getLearningProgress(null)).thenReturn(courseScore); + LearningProgress lp = new QuestionBasedLearningProgress(db); + + int expected = 99; + int actual = lp.getCourseProgress(null).getCourseProgress(); + + assertEquals(expected, actual); + } + + /** + * Given two users and two questions: the first question is answered correctly by both users, while the second + * is only answered correctly by one user. The first question should receive 100%, the second 50%. This should + * result in an overall score of 75%. + */ + @Test + public void shouldCalculatePercentageOfMultipleQuestionsAndAnswers() { + CourseScore courseScore = new CourseScore(); + // two questions + courseScore.add("question1", 10); + courseScore.add("question2", 10); + // two users + User u1 = new TestUser("user1"); + User u2 = new TestUser("user2"); + // four answers, last one is wrong + courseScore.add("question1", u1.getUsername(), 10); + courseScore.add("question1", u2.getUsername(), 10); + courseScore.add("question2", u1.getUsername(), 10); + courseScore.add("question2", u2.getUsername(), 0); + + IDatabaseDao db = mock(IDatabaseDao.class); + when(db.getLearningProgress(null)).thenReturn(courseScore); + LearningProgress lp = new QuestionBasedLearningProgress(db); + + int expected = 75; + int actual = lp.getCourseProgress(null).getCourseProgress(); + + assertEquals(expected, actual); + } + + @Test + public void shouldNotBeBiasedByPointsOrAnswerCount() { + CourseScore courseScore = new CourseScore(); + // two questions + courseScore.add("question1", 1000); + courseScore.add("question2", 1); + // first question has many answers, all of them correct + for (int i = 0; i < 100; i++) { + courseScore.add("question1", new TestUser("user"+i).getUsername(), 1000); + } + // second question has one wrong answer + courseScore.add("question2", new TestUser("another-user").getUsername(), 0); + + IDatabaseDao db = mock(IDatabaseDao.class); + when(db.getLearningProgress(null)).thenReturn(courseScore); + LearningProgress lp = new QuestionBasedLearningProgress(db); + + int expected = 50; + int actual = lp.getCourseProgress(null).getCourseProgress(); + + assertEquals(expected, actual); + } + }