package de.ugoe.cs.swe.memos; import java.util.Vector; import de.ugoe.cs.swe.memos.database.DBSearcher; import de.ugoe.cs.swe.memos.datamodel.IntegerMap; import de.ugoe.cs.swe.memos.datamodel.Memo; public class RelevanceRanker { public static Vector rankMemos(Vector toBeRanked, Vector rankBy) { if (toBeRanked == null || toBeRanked.size() == 0 || rankBy == null || rankBy.size() == 0) return toBeRanked; final int size = toBeRanked.size(); int[] memoAge = new int[size]; int[] overallCounter = new int[size]; int[] overallFreeCounter = new int[size]; boolean[] isFromMe = new boolean[size]; boolean[] isDraft = new boolean[size]; boolean[] inTitle = new boolean[size]; boolean[] inContent = new boolean[size]; boolean[] inAuthor = new boolean[size]; for (int i = 0; i < size; i++) { Memo curMemo = toBeRanked.get(i); isDraft[i] = curMemo.isDraft(); isFromMe[i] = (SettingsManager.getInstance().getUsername() == curMemo .getAuthor()); memoAge[i] = (int) ((new java.util.Date()).getTime() - curMemo .getTimestamp().getTime()) / (1000 * 60 * 60); for (int j = 0; j < rankBy.size(); j++) { int counter = 0, counter2 = 0; String curTag = rankBy.get(j); counter = countAppearances(curMemo.getAuthor(), curTag, false); counter2 = countAppearances(curMemo.getAuthor(), curTag, true); if (counter > 0) inAuthor[i] = true; overallCounter[i] += counter; overallFreeCounter[i] += counter2; counter = countAppearances(curMemo.getTitle(), curTag, false); counter2 = countAppearances(curMemo.getTitle(), curTag, true); if (counter > 0) inTitle[i] = true; overallCounter[i] += counter; overallFreeCounter[i] += counter2; counter = countAppearances(curMemo.getContent(), curTag, false); counter2 = countAppearances(curMemo.getContent(), curTag, true); if (counter > 0) inContent[i] = true; overallCounter[i] += counter; overallFreeCounter[i] += counter2; overallCounter[i] += countAppearances( curMemo.getTagsAsString(), curTag, false); overallFreeCounter[i] += countAppearances(curMemo .getTagsAsString(), curTag, true); overallCounter[i] += countAppearances(curMemo.getTimestamp() .toString(), curTag, false); overallFreeCounter[i] += countAppearances(curMemo .getTimestamp().toString(), curTag, true); } } IntegerMap[] points = new IntegerMap[size]; IntegerMap[] compare = new IntegerMap[size]; // calculate points for each memo for (int i = 0; i < size; i++) points[i] = new IntegerMap(i, 0); // rank memos by total occurances of tags for (int i = 0; i < size; i++) compare[i] = new IntegerMap(i, overallCounter[i]); java.util.Arrays.sort(compare); // add points to memo account according to place in ranking // balance: one point per rank for (int i = 0; i < size; i++) points[compare[i].index].value += i + 1; // rank memos by occurances of tags as single word for (int i = 0; i < size; i++) compare[i] = new IntegerMap(i, overallFreeCounter[i]); java.util.Arrays.sort(compare); // add points to memo account according to place in ranking // balance: three points per rank for (int i = 0; i < size; i++) points[(Integer) compare[i].index].value += (i + 1) * 3; // rank memos by age. older memos rank worse than younger ones. for (int i = 0; i < size; i++) compare[i] = new IntegerMap(i, memoAge[i]); java.util.Arrays.sort(compare); // add points to memo account according to place in ranking // balance: two points per rank for (int i = 0; i < size; i++) points[(Integer) compare[i].index].value += (size - i) * 2; // value or devalue according to different factors as accurances in // title, author, content and wether memo is from searcher or a draft for (int i = 0; i < size; i++) { // devalue if memo is a draft if (toBeRanked.get(i).isDraft()) points[i].value *= 0.4; // value if memo is from searcher itself if (toBeRanked.get(i).getAuthor() == SettingsManager.getInstance() .getUsername()) points[i].value *= 1.8; // value if keyword accures in title, author oder content if (inTitle[i] || inAuthor[i] || inContent[i]) points[i].value *= 1.4; // value if file has attachements if (toBeRanked.get(i).getFiles().size() > 0) points[i].value *= 1.6; } Vector returnVector = new Vector(size); // generate return vector and fetch memos ordered by final balance java.util.Arrays.sort(points); for (int i = size - 1; i >= 0; i--) returnVector.add(toBeRanked.get(points[i].index)); return returnVector; } public static int countAppearances(String source, String search, boolean onlyFreeAppearances) { if (source == null || search == null) return 0; int current = 0, counter = 0; boolean isFree; // walk source string for positive matches with search string for (current = 0; current <= source.length() - search.length(); current++) { String substring; // test for equality; ignore different cases substring = source.substring(current, current + search.length()); if (substring.toLowerCase().equals(search.toLowerCase())) { isFree = true; // if match should be freestanding, test here if (onlyFreeAppearances) { // TEST LEFT SIDE // but only if there is at least one more character leftside if (current != 0 && Character.isLetterOrDigit(source.substring( current - 1, current).toCharArray()[0])) // if left neighbour is alphanumeric it is no match isFree = false; // TEST RIGHT SIDE // but only if there's at least one more character rightside if (current + search.length() < source.length() && Character.isLetterOrDigit(source.substring( current + search.length(), current + search.length() + 1) .toCharArray()[0])) // if right neighbour is alphanumeric it is no match isFree = false; } // if its still a match till here, increment counter if (isFree) { counter++; current = current + search.length() - 1; } } } return counter; } public static void main(String[] args) { Vector fetch = (new DBSearcher("xprakt2/nominiert/organe/der")) .execute(); Vector tags = new Vector(); tags.add("xprakt2"); tags.add("nominiert"); tags.add("organe"); tags.add("der"); rankMemos(fetch, tags); return; } }