package es.upm.dit.gsi;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.model.MySQLJDBCIDMigrator;
import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.TanimotoCoefficientSimilarity;
import org.apache.mahout.cf.taste.model.JDBCDataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
import com.google.gson.Gson;
import contentDiscriminator.CDConfiguration;
import contentDiscriminator.Content;
import contentDiscriminator.ContentDiscriminator;
import es.upm.dit.gsi.database.ContentDB;
import es.upm.dit.gsi.database.DatabaseHandler;
import es.upm.dit.gsi.database.PreferenceDB;
import es.upm.dit.gsi.database.UserDB;
import es.upm.dit.gsi.logger.Logger;
import es.upm.dit.gsi.model.Conjunto;
import es.upm.dit.gsi.model.Noticia;
import es.upm.dit.gsi.model.Usuario;
import es.upm.dit.gsi.recommender.MyRecommender;
import es.upm.dit.gsi.util.Constants;
public class NoticiasTVi extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger("servlet.Mahout");
public MyRecommender myRecommender;
public Gson gson;
public Conjunto conjunto;
public List<Noticia> noticiasList = new ArrayList<Noticia>();
public String have = "0";
public void init() throws ServletException {
super.init();
gson = new Gson();
myRecommender = new MyRecommender();
}
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
System.out.println("Esperando respuesta");
res.setCharacterEncoding("UTF-8");
if (req.getParameter("action").equals("getRecommendation")) {
getRecommendation(req, res);
} else if (req.getParameter("action").equals("getPopular")) {
getPopular(req, res);
} else if (req.getParameter("action").equals("getNews")) {
getNews(req, res);
} else if (req.getParameter("action").equals("setPreference")) {
setPreference(req, res);
} else if (req.getParameter("action").equals("removePreference")) {
removePreference(req, res);
} else if (req.getParameter("action").equals("newUser")) {
newUser(req, res);
} else if (req.getParameter("action").equals("removeUser")) {
removeUser(req, res);
} else if (req.getParameter("action").equals("getRatingOfContent")) {
getRatingOfContent(req, res);
} else if (req.getParameter("action").equals("getFavorites")) {
getFavorites(req, res);
} else if (req.getParameter("action").equals("getRandom")) {
getRandom(req, res);
}
res.setStatus(HttpServletResponse.SC_OK);
}
/**
* Genera la recomendación para un determinado usuario del servicio.
*/
private void getRecommendation(HttpServletRequest req, HttpServletResponse res) throws ServletException,
IOException {
try {
PrintWriter out = res.getWriter();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
LOGGER.info("El usuario es: " + UserDB.getnameOfUser(userId));
noticiasList.clear();
if (userId != null) {
List<RecommendedItem> recommendations = myRecommender.getRecommendations(userId);
if (recommendations.size() == 0) {
LOGGER.info("No hay recomendaciones para el usuario, le recomendamos lo más popular");
getPopular(req, res);
} else {
for (int i = 0; i < recommendations.size(); i++) {
RecommendedItem recommendation = recommendations.get(i);
long contentId = recommendation.getItemID();
float estimation = myRecommender.estimatePreference(userId, contentId);
Noticia noticia = new Noticia(Long.toString(contentId), ContentDB.getTitleOfContent(contentId),
ContentDB.getVideoOfContent(contentId), ContentDB.getCaptureOfContent(contentId),
ContentDB.getDateOfContent(contentId), ContentDB.getContent(contentId),
ContentDB.getAuthorOfContent(contentId), have, Float.toString(estimation));
noticiasList.add(noticia);
}
conjunto = new Conjunto(noticiasList);
String ans = (String) gson.toJson(conjunto).subSequence(12, gson.toJson(conjunto).length() - 1);
out.print(ans);
}
} else {
LOGGER.warning("No se puede dar recomendación ya que no existe el usuario");
}
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
}
}
/**
* Devuelve los contenidos más populares (los mejores votados) por los
* clientes del servicio
*
* @param req
* @param res
* @throws ServletException
* si se produce algún error
* @throws IOException
* si se produce algún error
*/
private void getPopular(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
PrintWriter out = res.getWriter();
noticiasList.clear();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
int popular = Constants.NUM_RESULTS;
HashMap<Long, Float> averageRatings = PreferenceDB.averageRatings();
Object[] idsContents = averageRatings.keySet().toArray();
if (averageRatings.size() < popular) {
popular = averageRatings.size();
for (int j = 0; j < averageRatings.size(); j++) {
if (PreferenceDB.numVoteOfContent((Long) idsContents[j]) < Constants.MIN_NUM_VOTE)
popular = popular - 1;
}
}
long[] id = new long[popular];
float[] value = new float[popular];
for (int j = 0; j < popular; j++) {
value[j] = 0;
}
boolean noPopular = true;
for (int i = 0; i < idsContents.length; i++) {
for (int k = 0; k < popular; k++) {
if (PreferenceDB.numVoteOfContent((Long) idsContents[i]) >= Constants.MIN_NUM_VOTE) {
noPopular = false;
if ((averageRatings.get((Long) idsContents[i])) != null) {
if (averageRatings.get((Long) idsContents[i]) > value[k]) {
for (int h = popular - 1; h > k; h--) {
id[h] = id[h - 1];
value[h] = value[h - 1];
}
id[k] = (Long) idsContents[i];
value[k] = averageRatings.get((Long) idsContents[i]);
break;
}
if (averageRatings.get((Long) idsContents[i]) == value[k]
&& PreferenceDB.numVoteOfContent((Long) idsContents[i]) > PreferenceDB
.numVoteOfContent(id[k])) {
for (int h = popular - 1; h > k; h--) {
id[h] = id[h - 1];
value[h] = value[h - 1];
}
id[k] = (Long) idsContents[i];
value[k] = averageRatings.get((Long) idsContents[i]);
break;
}
}
}
}
}
if (noPopular) {
LOGGER.info("No hay nada popular, recomendamos los más reciente");
getNews(req, res);
return;
}
for (int j = 0; j < popular; j++) {
if (myRecommender.getPreferenceValue(userId, id[j]) != null)
have = "1";
Noticia not = new Noticia(Long.toString(id[j]), ContentDB.getTitleOfContent(id[j]),
ContentDB.getVideoOfContent(id[j]), ContentDB.getCaptureOfContent(id[j]),
ContentDB.getDateOfContent(id[j]), ContentDB.getContent(id[j]),
ContentDB.getAuthorOfContent(id[j]), have, "");
noticiasList.add(not);
have = "0";
}
conjunto = new Conjunto(noticiasList);
String ans = (String) gson.toJson(conjunto).subSequence(12, gson.toJson(conjunto).length() - 1);
out.print(ans);
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
}
/**
* Nos devuelve las noticias más recientes en el tiempo.
*
* @param req
* @param res
* @throws ServletException
* si se produce algún error
* @throws IOException
* si se produce algún error
*/
private void getNews(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
PrintWriter out = res.getWriter();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
long[] ids = ContentDB.getMoreRecients(Constants.NUM_RESULTS);
noticiasList.clear();
for (int k = 0; k < ids.length; k++) {
if (myRecommender.getPreferenceValue(userId, ids[k]) != null)
have = "1";
Noticia not = new Noticia(Long.toString(ids[k]), ContentDB.getTitleOfContent(ids[k]),
ContentDB.getVideoOfContent(ids[k]), ContentDB.getCaptureOfContent(ids[k]),
ContentDB.getDateOfContent(ids[k]), ContentDB.getContent(ids[k]),
ContentDB.getAuthorOfContent(ids[k]), have, "");
noticiasList.add(not);
have = "0";
}
conjunto = new Conjunto(noticiasList);
String ans = (String) gson.toJson(conjunto).subSequence(12, gson.toJson(conjunto).length() - 1);
out.print(ans);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Pone en la base de datos la preferencia de un cierto usuario asociada a
* un contenido.
*
* @param req
* ,HttpServletRequest
* @param res
* ,HttpServletResponse
* @throws ServletException
* si se produce alg??n error
* @throws IOException
* si se produce alg??n error
*/
private void setPreference(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
PrintWriter out = res.getWriter();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
Long contentId = Long.parseLong(req.getParameter(Constants.CONTENT));
String nameOfContent = ContentDB.getTitleOfContent(contentId);
float preference = new Float(req.getParameter(Constants.PREFERENCE_PARAM));
if (PreferenceDB.userHaveContent(userId, contentId)) {
myRecommender.removePreference(contentId, userId);
LOGGER.info("El usuario " + UserDB.getnameOfUser(userId)
+ " ha modificado la valoración del contenido " + nameOfContent + " a " + preference);
} else {
LOGGER.info("El usuario " + UserDB.getnameOfUser(userId) + " añade un valoración de " + preference
+ " al contenido " + nameOfContent);
}
myRecommender.setPreference(userId, contentId, preference);
out.print("ok");
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
}
}
/**
* Elimina la valoraci??n a un contenido de la base de datos.
*
* @param req
* ,HttpServletRequest
* @param res
* ,HttpServletResponse
* @throws ServletException
* si se produce alg??n error
* @throws IOException
* si se produce alg??n error
*/
private void removePreference(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
PrintWriter out = res.getWriter();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
Long contentId = Long.parseLong(req.getParameter(Constants.CONTENT));
String nameOfContent = ContentDB.getTitleOfContent(contentId);
if (userId != null && contentId != null) {
if (PreferenceDB.userHaveContent(userId, contentId)) {
myRecommender.removePreference(contentId, userId);
LOGGER.info("Eliminamos la valoración del usuario " + UserDB.getnameOfUser(userId)
+ " para el contenido " + nameOfContent);
}
} else {
LOGGER.warning("Usuario u objeto no encontrado");
}
out.print("ok");
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
}
/**
* Introduce un nuevo usuario en la base de datos
*
* @param req
* ,HttpServletRequest
* @param res
* ,HttpServletResponse
* @throws ServletException
* si se produce alg??n error
* @throws IOException
* si se produce alg??n error
*/
private void newUser(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
PrintWriter out = res.getWriter();
String name = req.getParameter(Constants.NAME_USER);
UserDB.introduceUser(name);
long id = UserDB.getUserId(name);
Usuario u = new Usuario(name, Long.toString(id));
out.print(gson.toJson(u));
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
}
/**
* Borra un usuario ya creado de la base de datos
*
* @param req
* ,HttpServletRequest
* @param res
* ,HttpServletResponse
* @throws ServletException
* si se produce alg??n error
* @throws IOException
* si se produce alg??n error
*/
private void removeUser(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
PrintWriter out = res.getWriter();
PreferenceDB.removePreferencesUser(Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER)));
if (UserDB.getnameOfUser(Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER))) == null)
out.print("ok");
UserDB.removeUser(Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER)));
out.print("ok");
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
}
/**
* Nos devuelve los contenidos que ha valorado un usuario dado y su
* valoraci??n.
*
* @param req
* ,HttpServletRequest
* @param res
* ,HttpServletResponse
* @throws ServletException
* si se produce alg??n error
* @throws IOException
* si se produce alg??n error
*/
private void getFavorites(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
noticiasList.clear();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
PrintWriter out = res.getWriter();
if (userId != null) {
LOGGER.info("Los contenidos valorados por el usuario " + UserDB.getnameOfUser(userId) + " son:");
PreferenceArray preferencesUser = myRecommender.getPreferencesFromUser(userId);
for (int i = 0; i < preferencesUser.length(); i++) {
have = "1";
String content = ContentDB.getTitleOfContent(preferencesUser.getItemID(i));
float value = preferencesUser.getValue(i);
Noticia not = new Noticia(Long.toString(ContentDB.getContentId(content)), content,
ContentDB.getVideoOfContent(preferencesUser.getItemID(i)),
ContentDB.getCaptureOfContent(preferencesUser.getItemID(i)),
ContentDB.getDateOfContent(preferencesUser.getItemID(i)),
ContentDB.getContent(preferencesUser.getItemID(i)),
ContentDB.getAuthorOfContent(preferencesUser.getItemID(i)), have, Float.toString(value));
noticiasList.add(not);
}
conjunto = new Conjunto(noticiasList);
out.print(gson.toJson(conjunto).subSequence(12, gson.toJson(conjunto).length() - 1));
} else {
LOGGER.warning("Usuario no encontrado");
}
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
}
}
/**
* Nos devuelve la valoraci??n que le ha dado el usuario un determinado
* contenido.
*
* @param req
* ,HttpServletRequest
* @param res
* ,HttpServletResponse
* @throws ServletException
* si se produce alg??n error
* @throws IOException
* si se produce alg??n error
*/
private void getRatingOfContent(HttpServletRequest req, HttpServletResponse res) throws ServletException,
IOException {
try {
PrintWriter out = res.getWriter();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
Long contentId = Long.parseLong(req.getParameter(Constants.CONTENT));
if (userId != null) {
if (PreferenceDB.userHaveContent(userId, contentId)) {
out.print("[");
float rating = myRecommender.getPreferenceValue(userId, contentId);
LOGGER.info("La valoraci??n al contenido " + ContentDB.getTitleOfContent(contentId)
+ " por el usuario " + UserDB.getnameOfUser(userId) + " es:" + rating);
out.print(rating);
out.print("]");
} else {
LOGGER.warning("El usuario no ha valorado el contenido");
}
} else {
LOGGER.warning("Usuario no encontrado");
}
} catch (Exception e) {
e.printStackTrace();
res.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
}
}
/**
* Nos devuelve las noticias de la base de datos de forma aleatoria.
*
* @param req
* ,HttpServletRequest
* @param res
* ,HttpServletResponse
* @throws ServletException
* si se produce alg??n error
* @throws IOException
* si se produce alg??n error
*/
private void getRandom(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
String rate = "0";
try {
Random random = new Random();
long contentId;
noticiasList.clear();
int num = ContentDB.getNumContents();
PrintWriter out = res.getWriter();
Long userId = Long.parseLong(req.getParameter(Constants.USER_IDENTIFIER));
for (int k = Constants.NUM_RESULTS - 50; k < Constants.NUM_RESULTS; k++) {
contentId = (long) (random.nextDouble() * num);
while (ContentDB.getTitleOfContent(contentId) == "") {
contentId = (long) (random.nextDouble() * num);
}
if (myRecommender.getPreferenceValue(userId, contentId) != null)
rate = "1";
Noticia not = new Noticia(Long.toString(contentId), ContentDB.getTitleOfContent(contentId),
ContentDB.getVideoOfContent(contentId), ContentDB.getCaptureOfContent(contentId),
ContentDB.getDateOfContent(contentId), ContentDB.getContent(contentId),
ContentDB.getAuthorOfContent(contentId), rate, "");
noticiasList.add(not);
}
conjunto = new Conjunto(noticiasList);
String ans = (String) gson.toJson(conjunto).subSequence(12, gson.toJson(conjunto).length() - 1);
out.print(ans);
} catch (Exception e) {
e.printStackTrace();
}
}
}