/*
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 common;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
// TODO -----------------------------------------------------
// extend with fields and methods for title and description
public class Bookmark implements Comparable<Bookmark> {
private int userID;
private int resID;
private String timestamp;
private List<Integer> tags;
private List<Integer> categories;
private double rating;
private String title;
public Bookmark(int userID, int wikiID, String timestamp) {
this.userID = userID;
this.resID = wikiID;
//if (timestamp.contains(".")) {
// this.timestamp = timestamp.substring(0, timestamp.indexOf("."));
//} else {
this.timestamp = timestamp;
//}
this.categories = new ArrayList<Integer>();
this.tags = new ArrayList<Integer>();
this.rating = -2.0;
this.title = null;
}
@Override
public int compareTo(Bookmark data) {
//return (Long.parseLong(getTimestamp()) <= Long.parseLong(data.getTimestamp()) ? - 1 : 1);
if (this.userID < data.getUserID()) {
return -1;
} else if (this.userID > data.userID) {
return 1;
} else {
if (!this.timestamp.isEmpty() && !data.timestamp.isEmpty()) {
if (Long.parseLong(this.timestamp) < Long.parseLong(data.timestamp)) { // <
return -1;
} else if (Long.parseLong(this.timestamp) > Long.parseLong(data.timestamp)) { // >
return 1;
}
}
}
return 0;
}
// Getter -------------------------------------------------------------------------
public void setUserID(int userID) {
this.userID = userID;
}
public int getUserID() {
return this.userID;
}
public void setWikiID(int wikiID) {
this.resID = wikiID;
}
public int getResourceID() {
return this.resID;
}
public String getTimestamp() {
return this.timestamp;
}
public double getRating() {
return this.rating;
}
public void setRating(double rating) {
this.rating = rating;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public List<Integer> getCategories() {
return this.categories;
}
public void setTags(List<Integer> tags) {
this.tags = tags;
}
public List<Integer> getTags() {
return this.tags;
}
public Long getTimestampAsLong(){
return Long.parseLong(this.timestamp);
}
// Statics ----------------------------------------------------------------------------------
public static double getAvgNumberOfTopics(List<Bookmark> lines) {
double sum = 0.0;
for (Bookmark line : lines) {
sum += line.getCategories().size();
}
return sum / lines.size();
}
public static double getBookmarkDiversity(List<Bookmark> lines) {
if (lines.size() == 0) {
return 0.0;
}
if (lines.size() == 1) {
return 1.0;
}
double diversity = 0.0;
int size = 0;
for (int i = 0; i < lines.size() - 1; i++) {
for (int j = i + 1; j < lines.size(); j++) {
Bookmark srcBookmark = lines.get(i);
Bookmark destBookmark = lines.get(j);
diversity += Utilities.getJaccardSimLists(srcBookmark.getCategories(), destBookmark.getCategories());
size++;
}
}
if (size == 0) {
return 0.0;
}
return diversity / size;
}
public static Bookmark getBookmark(List<Bookmark> lines, int userID, int resID) {
Bookmark returnData = null;
for (Bookmark data : lines) {
if (data.userID == userID) {
returnData = data; // old
if (resID != -1 && data.resID == resID) {
returnData = data;
return returnData;
}
}
}
return returnData;
}
public static List<Integer> getTagsOfBookmark(List<Bookmark> lines, int userID, int resID) {
if (userID != -1 && resID != -1) {
for (Bookmark data : lines) {
if (data.userID == userID && data.resID == resID) {
return data.getTags();
}
}
}
return new ArrayList<Integer>();
}
public static Bookmark getResData(List<Bookmark> lines, int userID, int resID) {
Bookmark returnData = null;
for (Bookmark data : lines) {
if (data.resID == resID) {
returnData = data; // old
if (userID != -1 && data.userID == userID) {
returnData = data;
return returnData;
}
}
}
return returnData;
}
public static Bookmark getLastData(List<Bookmark> lines, Set<Integer> ids) {
long maxTimestamp = Long.MAX_VALUE;
Bookmark returnData = null;
for (Bookmark data : lines) {
if (ids.contains(data.userID)) {
long timestamp = Long.parseLong(data.timestamp);
if (timestamp < maxTimestamp) {
maxTimestamp = timestamp;
returnData = data;
}
}
}
return returnData;
}
public static List<Integer> getResourcesFromUser(List<Bookmark> lines, int userID) {
if (userID == -1) {
return null;
}
Set<Integer> resourceList = new HashSet<Integer>();
for (Bookmark data : lines) {
if (data.userID == userID) {
resourceList.add(data.resID);
}
}
return new ArrayList<Integer>(resourceList);
}
public static List<Integer> getUsersFromResource(List<Bookmark> lines, int resID) {
if (resID == -1) {
return null;
}
Set<Integer> userList = new HashSet<Integer>();
for (Bookmark data : lines) {
if (data.resID == resID) {
userList.add(data.userID);
}
}
return new ArrayList<Integer>(userList);
}
public static List<Integer> getTagsFromResource(List<Bookmark> lines, int resID) {
if (resID == -1) {
return null;
}
Set<Integer> tagList = new HashSet<Integer>();
for (Bookmark data : lines) {
if (data.resID == resID) {
for (int tagID : data.getTags()) {
tagList.add(tagID);
}
}
}
return new ArrayList<Integer>(tagList);
}
public static Map<Integer, Double> getResourcesFromUserWithBLL(List<Bookmark> trainData, List<Bookmark> testData, int userID, List<Map<Integer, Double>> bllValues) {
Map<Integer, Double> resourceMap = new LinkedHashMap<Integer, Double>();
Map<Integer, Double> values = null;
if (bllValues != null && userID < bllValues.size()) {
values = bllValues.get(userID);
}
for (Bookmark data : trainData) {
if (data.userID == userID) {
double val = 1.0;
if (values != null) {
val = 0.0;
for (Integer t : data.getTags()) {
Double v = values.get(t);
if (v != null) {
val += v.doubleValue();
}
}
}
resourceMap.put(data.resID, val);
}
}
return resourceMap;
}
public static Map<Integer, Double> getResourcesFromUserWithRec(List<Bookmark> trainData, List<Bookmark> testData, int userID, Double dValue, boolean sorting) {
Map<Integer, Double> resourceMap = new LinkedHashMap<Integer, Double>();
long refTimestamp = Utilities.getBaselineTimestamp(testData, userID, false);
for (Bookmark data : trainData) {
if (data.userID == userID) {
if (dValue != null) {
long timestamp = 0;
if (!data.getTimestamp().isEmpty()) {
timestamp = Long.parseLong(data.getTimestamp());
}
Double rec = Math.pow(refTimestamp - timestamp + 1.0, dValue.doubleValue() * (-1.0));
if (!rec.isInfinite() && !rec.isNaN()) {
//resourceMap.put(data.resID, Math.log(rec.doubleValue() + 1.0));
resourceMap.put(data.resID, rec.doubleValue());
} else {
//System.out.println("BLL - NAN");
//resourceMap.put(data.resID, Math.log(1.0 + 1.0));
resourceMap.put(data.resID, 1.0);
}
} else {
resourceMap.put(data.resID, 1.0);
}
}
}
if (sorting) {
// return the sorted resources
Map<Integer, Double> sortedRankedResources = new TreeMap<Integer, Double>(new DoubleMapComparator(resourceMap));
sortedRankedResources.putAll(resourceMap);
return sortedRankedResources;
} else {
return resourceMap;
}
}
}