/* 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 processing.ThreeLTCalculator; import file.BookmarkReader; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import common.CalculationType; import common.DoubleMapComparator; // TODO: make it work in online setting! (caching + LDA topic calculation) public class ThreeLayersEngine implements EngineInterface { private BookmarkReader reader = null; private ThreeLTCalculator calculator = null; private final Map<Integer, Double> topTags; public ThreeLayersEngine() { this.topTags = new LinkedHashMap<>(); this.reader = null; } public void loadFile(String path, String filename) throws Exception { BookmarkReader reader = EngineUtils.getSortedBookmarkReader(path, filename); ThreeLTCalculator calculator = new ThreeLTCalculator(reader, reader.getBookmarks().size(), 5, 5, true, true, false, CalculationType.NONE); Map<Integer, Double> topTags = EngineUtils.calcTopEntities(reader, EntityType.TAG); resetStructure(reader, calculator, topTags); } 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; } List<Integer> filterTags = new ArrayList<Integer>(); Map<Integer, Double> tagIDs = new LinkedHashMap<>(); Map<String, Double> tagMap = new LinkedHashMap<>(); if (this.reader == null || this.calculator == null) { return tagMap; } if (algorithm == null || algorithm != Algorithm.MP) { int userID = -1; if (user != null) { userID = this.reader.getUsers().indexOf(user); } filterTags = EngineUtils.getFilterTags(filterOwnEntities, this.reader, user, resource/*, this.calculator.getUserMaps().get(userID)*/); int resID = -1; if (resource != null) { resID = this.reader.getResources().indexOf(resource); } List<Integer> topicIDs = new ArrayList<>(); if (topics != null) { for (String t : topics) { int tID = this.reader.getCategories().indexOf(t); if (tID != -1) { topicIDs.add(tID); } } } if (algorithm == null || algorithm == Algorithm.THREELTMPr) { tagIDs = this.calculator.getRankedTagList(userID, resID, topicIDs, System.currentTimeMillis() / 1000.0, count, this.reader.hasTimestamp(), false, false); // not sorted } else if (algorithm == Algorithm.THREELT) { tagIDs = this.calculator.getRankedTagList(userID, -1, topicIDs, System.currentTimeMillis() / 1000.0, count, this.reader.hasTimestamp(), false, false); // not sorted } else if (algorithm == Algorithm.THREEL) { tagIDs = this.calculator.getRankedTagList(userID, -1, topicIDs, System.currentTimeMillis() / 1000.0, count, false, false, false); // not sorted } } // TODO: finish filtering // fill up with MP tags if (tagIDs.size() < count) { for (Map.Entry<Integer, Double> t : this.topTags.entrySet()) { if (tagIDs.size() < count) { if (!tagIDs.containsKey(t.getKey())) { tagIDs.put(t.getKey(), t.getValue()); } } else { break; } } } // sort Map<Integer, Double> sortedResultMap = new TreeMap<Integer, Double>(new DoubleMapComparator(tagIDs)); sortedResultMap.putAll(tagIDs); // map tag-IDs back to strings for (Map.Entry<Integer, Double> tEntry : sortedResultMap.entrySet()) { if (tagMap.size() < count) { tagMap.put(this.reader.getTags().get(tEntry.getKey()), tEntry.getValue()); } } return tagMap; } public synchronized void resetStructure(BookmarkReader reader, ThreeLTCalculator calculator, Map<Integer, Double> topTags) { this.reader = reader; this.calculator = calculator; this.topTags.clear(); this.topTags.putAll(topTags); } }