diff --git a/src/main/java/com/whichclasses/statistics/ConcreteAggregator.java b/src/main/java/com/whichclasses/statistics/ConcreteAggregator.java new file mode 100644 index 0000000..9666ee1 --- /dev/null +++ b/src/main/java/com/whichclasses/statistics/ConcreteAggregator.java @@ -0,0 +1,35 @@ +package com.whichclasses.statistics; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.google.inject.Inject; +import com.whichclasses.model.Course; +import com.whichclasses.model.DataSource; +import com.whichclasses.model.Department; +import com.whichclasses.model.proto.TceRating.Question; + +public class ConcreteAggregator implements DataAggregator { + + DataSource dataSource; + Map> courseScoreDataMap = Maps.newHashMap(); + + @Inject + public ConcreteAggregator(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public List getRankedCourses(String deptId, Question question) { + Department dept = dataSource.getDepartmentList().getChildren().get(deptId); + Collection courses = dept.getChildren().values(); + List courseList = new ArrayList(courses); + Collections.sort(courseList, new SimpleCourseComparator(question)); + return courseList; + } + +} diff --git a/src/main/java/com/whichclasses/statistics/DataAggregator.java b/src/main/java/com/whichclasses/statistics/DataAggregator.java new file mode 100644 index 0000000..c450580 --- /dev/null +++ b/src/main/java/com/whichclasses/statistics/DataAggregator.java @@ -0,0 +1,10 @@ +package com.whichclasses.statistics; + +import java.util.List; + +import com.whichclasses.model.Course; +import com.whichclasses.model.proto.TceRating.Question; + +public interface DataAggregator { + public List getRankedCourses(String deptId, Question question); +} diff --git a/src/main/java/com/whichclasses/statistics/Rateable.java b/src/main/java/com/whichclasses/statistics/Rateable.java new file mode 100644 index 0000000..c74360e --- /dev/null +++ b/src/main/java/com/whichclasses/statistics/Rateable.java @@ -0,0 +1,9 @@ +package com.whichclasses.statistics; + +import com.whichclasses.model.proto.TceRating; + +public interface Rateable { + public int getRatingCount(TceRating.Question question); + public double getAverageScore(TceRating.Question question); + public double getWilsonScore(TceRating.Question question); +} diff --git a/src/main/java/com/whichclasses/statistics/RateableCollection.java b/src/main/java/com/whichclasses/statistics/RateableCollection.java new file mode 100644 index 0000000..2d5e880 --- /dev/null +++ b/src/main/java/com/whichclasses/statistics/RateableCollection.java @@ -0,0 +1,65 @@ +package com.whichclasses.statistics; + +import java.util.Collection; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.whichclasses.model.proto.TceRating; +import com.whichclasses.model.proto.TceRating.Question; + +public class RateableCollection implements Rateable { + + private Collection children; + private Map questionToScore = Maps.newHashMap(); + private Map questionToWilsonScore = Maps.newHashMap(); + private Map questionToNumRatings = Maps.newHashMap(); + + public RateableCollection( Collection children ) { + this.children = children; + calculateStatistics(); + } + + private void calculateStatistics() { + for(Question question : Question.values()) { + double qualityPoints = 0; + int numRatings = 0; + for(Rateable rateable : children) { + qualityPoints += rateable.getAverageScore(question) * rateable.getRatingCount(question); + numRatings += rateable.getRatingCount(question); + } + double averageScore = numRatings != 0 ? qualityPoints / numRatings : 0; + double wilsonScore = calculateWilsonScore((averageScore - 1) / 4, numRatings) * 4 + 1; + questionToScore.put(question, averageScore); + questionToWilsonScore.put(question, wilsonScore); + questionToNumRatings.put(question, numRatings); + } + } + + @Override + public double getAverageScore(TceRating.Question question) { + return questionToScore.get(question); + } + + @Override + public int getRatingCount(TceRating.Question question) { + return questionToNumRatings.get(question); + } + + @Override + public double getWilsonScore(TceRating.Question question) { + return questionToWilsonScore.get(question); + } + + /** + * Calculates the lower bound of the 95% confidence interval of a normalized data set of data + * @param p - Normalized average of sample data set + * @param n - Number of samples + * @return The normalized Wilson score of a normalized data set + */ + private double calculateWilsonScore(double p, int n) { + if(n == 0) return 0; + double z = 1.96; + return (p + z*z/(2*n) - z*Math.sqrt(p*(1-p)/n + z*z/(4*n*n)))/(1 + z*z/n); + } + +} diff --git a/src/main/java/com/whichclasses/statistics/SimpleCourseComparator.java b/src/main/java/com/whichclasses/statistics/SimpleCourseComparator.java new file mode 100644 index 0000000..c5c631e --- /dev/null +++ b/src/main/java/com/whichclasses/statistics/SimpleCourseComparator.java @@ -0,0 +1,23 @@ +package com.whichclasses.statistics; + +import java.util.Comparator; + +import com.whichclasses.model.Course; +import com.whichclasses.model.proto.TceRating.Question; + +public class SimpleCourseComparator implements Comparator { + + private Question question; + + public SimpleCourseComparator(Question question) { + this.question = question; + } + + @Override + public int compare(Course o1, Course o2) { + double diff = o2.getAverageScore(question) - o1.getAverageScore(question); + return (int) (diff < 0 ? Math.floor(diff) : Math.ceil(diff)); + } + + +}