/* TagRecommender: A framework to implement and evaluate algorithms for the recommendation of tags. Copyright (C) 2013 Dominik Kowald This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package engine; import file.BookmarkReader; import itemrecommendations.CFResourceCalculator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import common.Bookmark; import common.DoubleMapComparator; import common.Features; import common.Similarity; // TODO: cache values public class ResourceRecommenderEngine implements EngineInterface { private BookmarkReader reader = null; private CFResourceCalculator calculator = null; private CFResourceCalculator tagCalculator = null; private CFResourceCalculator cbCalculator = null; private CFResourceCalculator resCFCalculator = null; private final Map<Integer, Double> topResources; public ResourceRecommenderEngine() { this.topResources = new LinkedHashMap<Integer, Double>(); this.reader = new BookmarkReader(0, false); } public void loadFile(String path, String filename) throws Exception { BookmarkReader reader = EngineUtils.getSortedBookmarkReader(path, filename); CFResourceCalculator calculator = new CFResourceCalculator(reader, reader.getBookmarks().size(), false, true, false, 5, Similarity.COSINE, Features.ENTITIES); CFResourceCalculator tagCalculator = new CFResourceCalculator(reader, reader.getBookmarks().size(), false, true, false, 5, Similarity.COSINE, Features.TAGS); CFResourceCalculator cbCalculator = new CFResourceCalculator(reader, reader.getBookmarks().size(), false, false, true, 5, Similarity.COSINE, Features.TAGS); CFResourceCalculator resCFCalculator = new CFResourceCalculator(reader, reader.getBookmarks().size(), false, false, true, 5, Similarity.COSINE, Features.ENTITIES); Map<Integer, Double> topResources = EngineUtils.calcTopEntities(reader, EntityType.RESOURCE); resetStructure(reader, calculator, tagCalculator, cbCalculator, resCFCalculator, topResources); } public synchronized Map<String, Double> getEntitiesWithLikelihood(String user, String resource, List<String> topics, Integer count, Boolean filterOwnEntities, Algorithm algorithm, EntityType type) { if (count == null || count.doubleValue() < 1) { count = 10; } if (filterOwnEntities == null) { filterOwnEntities = true; } Map<Integer, Double> resourceIDs = new LinkedHashMap<>(); Map<String, Double> resourceMap = new LinkedHashMap<>(); if (this.reader == null || this.calculator == null) { System.out.println("No data has been loaded"); return resourceMap; } int userID = -1; if (user != null) { userID = this.reader.getUsers().indexOf(user); } int resID = -1; if (resource != null) { resID = this.reader.getResources().indexOf(resource); } // used to filter own resources if necessary List<Integer> userResources = null; if (userID != -1 && filterOwnEntities.booleanValue()) { userResources = Bookmark.getResourcesFromUser(this.reader.getBookmarks(), userID); } if (algorithm == null || algorithm != Algorithm.RESOURCEMP) { if (userID != -1) { if (algorithm == Algorithm.RESOURCETAGCF) { resourceIDs = this.tagCalculator.getRankedResourcesList(userID, -1, false, false, false, filterOwnEntities.booleanValue(), false); // not sorted! } else if (algorithm == Algorithm.RESOURCETAGCB) { resourceIDs = this.cbCalculator.getRankedResourcesList(userID, -1, false, false, false, filterOwnEntities.booleanValue(), false); // not sorted! } else { resourceIDs = this.calculator.getRankedResourcesList(userID, -1, false, false, false, filterOwnEntities.booleanValue(), false); // not sorted! } } else if (resID != -1) { if (algorithm == Algorithm.RESOURCETAGCF) { resourceIDs = this.cbCalculator.getRankedResourcesList(-1, resID, false, false, false, filterOwnEntities.booleanValue(), false); // not sorted! } else { resourceIDs = this.resCFCalculator.getRankedResourcesList(-1, resID, false, false, false, filterOwnEntities.booleanValue(), false); // not sorted! } } } // then call MP if necessary if (resourceIDs.size() < count) { for (Map.Entry<Integer, Double> t : this.topResources.entrySet()) { if (resourceIDs.size() < count) { // add MP resources if they are not already in the recommeded list or already known by this user if (!resourceIDs.containsKey(t.getKey()) && (userResources == null || !userResources.contains(t.getKey()))) { resourceIDs.put(t.getKey(), t.getValue()); } } else { break; } } } // sort Map<Integer, Double> sortedResultMap = new TreeMap<Integer, Double>(new DoubleMapComparator(resourceIDs)); sortedResultMap.putAll(resourceIDs); // last map IDs back to strings for (Map.Entry<Integer, Double> tEntry : sortedResultMap.entrySet()) { if (resourceMap.size() < count) { resourceMap.put(this.reader.getResources().get(tEntry.getKey()), tEntry.getValue()); } else { break; } } return resourceMap; } public synchronized void resetStructure(BookmarkReader reader, CFResourceCalculator calculator, CFResourceCalculator tagCalculator, CFResourceCalculator cbCalculator, CFResourceCalculator resCFCalculator, Map<Integer, Double> topResources) { this.reader = reader; this.calculator = calculator; this.tagCalculator = tagCalculator; this.cbCalculator = cbCalculator; this.resCFCalculator = resCFCalculator; this.topResources.clear(); this.topResources.putAll(topResources); } }