Skip to content
Snippets Groups Projects
Commit daee57b8 authored by Christoph Thelen's avatar Christoph Thelen
Browse files

Fix for #14841: Properly weight wrong answers

Previously, a single wrong answer was sufficient for a
question to get a 0% score. With this change, they
are counted as much as a correct answer. The only
difference now is that they reduce the overall
score of a question. See test cases for a
few examples.
parent 8dbd71f0
Branches
Tags
No related merge requests found
......@@ -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
......
......@@ -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);
}
}
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