From 9ce03fcaa1acd36922314ce2d7b654842dbef4f9 Mon Sep 17 00:00:00 2001 From: Tom Vahlman <tom@dsv.su.se> Date: Sat, 25 Feb 2012 21:47:03 +0100 Subject: [PATCH] Points, total availability (bachelor + master) and type of project class must be considered when sorting a list of Pair representing matches. --- .../scipro/match/GreedyMatchingAlgorithm.java | 81 +++++++++++++++++-- .../match/TestGreedyMatchingAlgorithm.java | 6 +- 2 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/main/java/se/su/dsv/scipro/match/GreedyMatchingAlgorithm.java b/src/main/java/se/su/dsv/scipro/match/GreedyMatchingAlgorithm.java index fd12006d0a..754c16cef5 100644 --- a/src/main/java/se/su/dsv/scipro/match/GreedyMatchingAlgorithm.java +++ b/src/main/java/se/su/dsv/scipro/match/GreedyMatchingAlgorithm.java @@ -20,7 +20,14 @@ public class GreedyMatchingAlgorithm implements MatchingAlgorithm { private Logger logger = Logger.getLogger(GreedyMatchingAlgorithm.class); private Weights weights; - + + /** + * Match project ideas with supervisors (based on availability) and returns the best match. + * @param supervisorAvailability a list of the Availability instances + * @param unmatchedProjectIdeas a list of unmatched project ideas + * @param weights the weights that is used when counting points + * @return Result + */ @Override public Result match(List<Availability> supervisorAvailability, List<ProjectIdea> unmatchedProjectIdeas, Weights weights) { this.weights = weights; @@ -30,14 +37,17 @@ public class GreedyMatchingAlgorithm implements MatchingAlgorithm { while(!unmatchedProjectIdeas.isEmpty()) { pairList.clear(); matchProjectIdeas(unmatchedProjectIdeas, supervisorAvailability, pairList); - Collections.sort(pairList); + if(!pairList.isEmpty()) { + Collections.sort(pairList); + calculateTotalAvailability(pairList); Pair foundPair = pairList.get(0); for(Availability availability : supervisorAvailability) { - if(availability.getSupervisor().equals(foundPair.getMatch().getSupervisor())) { + if(availability.getSupervisor().equals(foundPair.getMatch().getSupervisor()) && + availability.getProjectClass().equals(foundPair.getAvailability().getProjectClass())) { if(availability.getNumCapable() > availability.getNumMatched()) { availability.setNumMatched(availability.getNumMatched() + 1); - matchList.add(foundPair.getMatch()); + matchList.add(foundPair.getMatch()); } } } @@ -178,7 +188,7 @@ public class GreedyMatchingAlgorithm implements MatchingAlgorithm { && supervisor.equals(projectIdea.getPreferredSupervisor())) { points += weights.getPreferredSupervisorPoints(); } - + for (Keyword projectIdeaKeyword : projectIdea.getKeywords().getAll()) { for (Keyword supervisorKeyword : supervisor.getKeywords().getFiltered(projectIdeaKeyword.getType())) { if (projectIdeaKeyword.equals(supervisorKeyword) && !projectIdeaKeyword.isDeleted() && !supervisorKeyword.isDeleted()) { @@ -190,10 +200,39 @@ public class GreedyMatchingAlgorithm implements MatchingAlgorithm { match.setPoints(points); return match; } + + + /** + * Calculates total availability for each supervisor, i.e. the Availability#getAvailability (int) for master + * is added to Availability#getAvailability (int) for bachelor for each supervisor, this total availability is considered when + * matching project ideas to supervisors + * @param pairList all the matches that is produced, represented as instances of the class Pair + * @return + */ + private void calculateTotalAvailability(List<Pair> pairList) { + for(Pair ourMatch : pairList) { + for(Pair pair : pairList) { + if(ourMatch.getTotalAvailability() == 0 && + ourMatch.getAvailability().getSupervisor().equals(pair.getAvailability().getSupervisor()) && + !ourMatch.getAvailability().getProjectClass().equals(pair.getAvailability().getProjectClass())) { + int totalAvailability = ourMatch.getAvailability().getAvailability() + pair.getAvailability().getAvailability(); + ourMatch.setTotalAvailability(totalAvailability); + pair.setTotalAvailability(totalAvailability); + break; + } + } + } + for(Pair ourMatch : pairList) { // we must set total availability for supervisors that only can handle one type of project class, i.e. master or bachelor + if(ourMatch.getTotalAvailability() == 0) { + ourMatch.setTotalAvailability(ourMatch.getAvailability().getAvailability()); + } + } + } private class Pair implements Comparable<Pair> { private Match match; private Availability availability; + private int totalAvailability; public Pair(Match match, Availability availability ) { @@ -209,14 +248,42 @@ public class GreedyMatchingAlgorithm implements MatchingAlgorithm { return availability; } + public int getTotalAvailability() { + return totalAvailability; + } + + public void setTotalAvailability(int totalAvailability) { + this.totalAvailability = totalAvailability; + } + + /** + * Is used to sort the Pairs in an order where the Pair at the top of the list will be chosen. + * @param otherPair the pair we should compare with + * @return int determines if one Pair is more "important" than another Pair. + */ @Override public int compareTo(Pair otherPair) { if(match.getPoints() > otherPair.getMatch().getPoints()) { return -1; } else if(otherPair.getMatch().getPoints() > match.getPoints()) { return 1; - } else { - return availability.compareTo(otherPair.getAvailability()); + } else { // if the points are the same + if(totalAvailability > otherPair.getTotalAvailability()) { // does we have more "slots" than the other Pair + return -1; + } else if(otherPair.getTotalAvailability() > totalAvailability) { + return 1; + } else { // the points and the slots are equal, we must now sort on Project Class because a master supervisor can supervise + // both a master project idea and a bachelor project idea, the "best" match however is if a master supervisor supervises a master project idea... + if(match.getProjectIdea().getProjectClass().equals(availability.getProjectClass()) && + !otherPair.getMatch().getProjectIdea().getProjectClass().equals(otherPair.getAvailability().getProjectClass())) { + return -1; + } else if(!match.getProjectIdea().getProjectClass().equals(availability.getProjectClass()) && + otherPair.getMatch().getProjectIdea().getProjectClass().equals(otherPair.getAvailability().getProjectClass())) { + return 1; + } else { // the supervisor can only one type of project class + return 0; + } + } } } diff --git a/src/test/java/se/su/dsv/scipro/match/TestGreedyMatchingAlgorithm.java b/src/test/java/se/su/dsv/scipro/match/TestGreedyMatchingAlgorithm.java index 0c177e8875..541f700bc2 100644 --- a/src/test/java/se/su/dsv/scipro/match/TestGreedyMatchingAlgorithm.java +++ b/src/test/java/se/su/dsv/scipro/match/TestGreedyMatchingAlgorithm.java @@ -98,9 +98,9 @@ public class TestGreedyMatchingAlgorithm { private void createWeights() { weights = new Weights(); - weights.setKeywordPoints(3); // "Word" (including "Unit"??) - weights.setResearchAreaPoints(10); // "Area" - weights.setPreferredSupervisorPoints(15); + weights.setKeywordPoints(3); // "Word" + "Unit"?? + weights.setResearchAreaPoints(5); // "Area" + weights.setPreferredSupervisorPoints(10); } private void setUpKeyWordTypes() {