/**
* File ./src/main/java/de/lemo/dms/processing/questions/QCumulativeUserAccess.java
* Lemo-Data-Management-Server for learning analytics.
* Copyright (C) 2013
* Leonard Kappe, Andreas Pursian, Sebastian Schwarzrock, Boris Wenzlaff
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
/**
* File ./main/java/de/lemo/dms/processing/questions/QCumulativeUserAccess.java
* Date 2013-01-24
* Project Lemo Learning Analytics
*/
package de.lemo.dms.processing.questions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import de.lemo.dms.core.config.ServerConfiguration;
import de.lemo.dms.db.mapping.abstractions.ILogMining;
import de.lemo.dms.processing.BoxPlotGeneratorForDates;
import de.lemo.dms.processing.ELearningObjectType;
import de.lemo.dms.processing.MetaParam;
import de.lemo.dms.processing.Question;
import de.lemo.dms.processing.resulttype.BoxPlot;
import de.lemo.dms.processing.resulttype.ResultListBoxPlot;
/**
* Accumulates the requests of the users to the objects over a period
*
* @author Boris Wenzlaff
* @author Sebastian Schwarzrock
*/
@Path("cumulative")
public class QCumulativeUserAccess extends Question {
/**
* @param startTime
* min time for the data
* @param endTime
* max time for the data
* @param types
* list with learning objects to compute
* @param course
* courses for the request
* @return a list with the cumulative user access to the learning objects
* @throws SQLException
* @throws JSONException
*/
@SuppressWarnings("unchecked")
@POST
public ResultListBoxPlot compute(
@FormParam(MetaParam.COURSE_IDS) final List<Long> course,
@FormParam(MetaParam.TYPES) List<String> types,
@FormParam(MetaParam.START_TIME) final Long startTime,
@FormParam(MetaParam.END_TIME) final Long endTime) {
validateTimestamps(startTime, endTime);
final Set<ELearningObjectType> learnObjectTypes = ELearningObjectType.fromNames(types);
if(types != null )
{
List<String> tmp = new ArrayList<String>();
for(String s : types)
{
tmp.add(s.toUpperCase());
}
types = tmp;
}
// generiere querys
final Map<ELearningObjectType, String> querys = this.generateQuerys(startTime,
endTime, learnObjectTypes, course);
super.logger.debug("Query result: " + querys.toString());
final Session session = ServerConfiguration.getInstance().getMiningDbHandler().getMiningSession();
// SQL querys
super.logger.debug("Starting processing ....");
final BoxPlotGeneratorForDates bpg = new BoxPlotGeneratorForDates();
try {
Criteria criteria = session.createCriteria(ILogMining.class, "log");
criteria.add(Restrictions.between("log.timestamp", startTime, endTime));
criteria.add(Restrictions.in("log.course.id", course));
List<ILogMining> logs = criteria.list();
for(ILogMining log : logs)
{
String type = log.getClass().getSimpleName().toUpperCase();
if(type.indexOf("LOG") > -1)
{
type = type.substring(0, type.indexOf("LOG"));
if(types.isEmpty() || types.contains(type))
bpg.addAccess(log.getTimestamp());
}
}
logs.clear();
/*
for (final ELearningObjectType lo : querys.keySet()) {
super.logger.debug("Starting processing -- Entering try catch");
@SuppressWarnings("deprecation")
final Statement statement = session.connection().createStatement();
final ResultSet set = statement.executeQuery(querys.get(lo));
// durchlaufen des result sets
while (set.next()) {
bpg.addAccess(set.getLong("timestamp"));
}
}
*/
final BoxPlot[] bp = bpg.calculateResult();
final List<BoxPlot> l = new ArrayList<BoxPlot>();
for (int i = 0; i < bp.length; i++) {
l.add(bp[i]);
}
final ResultListBoxPlot rlbp = new ResultListBoxPlot(l);
super.logger.debug("Resultlist created ...." + rlbp.toString()
+ " Number of entries: " + rlbp.getElements().size());
session.close();
return rlbp;
} catch (final Exception e) {
this.logger.error(e);
session.close();
return new ResultListBoxPlot();
}
}
/**
* Generiert die Querys für die Zusammenfassung der LearningObjects
* Insbesondere der WHERE Klausel
*
* @param timestampMin
* Untergrenze für den Zeitraum
* @param timestampMax
* Obergrenze für den Zeitraum
* @param types
* Learning Objects die erfasst werden sollen
* @return Liste mit Querys zu den LearningObjects
*/
private Map<ELearningObjectType, String> generateQuerys(
final long timestampMin, final long timestampMax,
final Set<ELearningObjectType> types,
final List<Long> course) {
final Map<ELearningObjectType, String> result = new HashMap<ELearningObjectType, String>();
boolean timeframe = false;
final List<String> qa = new ArrayList<String>();
// prüfen des zeitraums
if ((timestampMax != 0) && (timestampMin != 0)
&& (timestampMax >= timestampMin)) {
timeframe = true;
}
for (final ELearningObjectType loType : types) {
String query = this.generateBaseQuery(loType.name().toLowerCase());
if (timeframe || (course != null)) {
query += " WHERE";
}
// zeitraum
if (timeframe) {
qa.add(" timestamp >= " + timestampMin + " AND timestamp<= "
+ timestampMax);
}
// filter course
if ((course != null) && !course.isEmpty()) {
final StringBuilder sb = new StringBuilder();
sb.append("(");
int i = 0;
for (final Long co : course) {
sb.append(" course.id = " + co.toString());
if (i < (course.size() - 1)) {
sb.append(" OR");
}
i++;
}
sb.append(")");
qa.add(sb.toString());
}
// klauseln für filter hinzufügen
for (int i = 0; i < qa.size(); i++) {
query += qa.get(i);
if (i < (qa.size() - 1)) {
query += " AND";
}
}
result.put(loType, query);
}
return result;
}
// generiert ein einfaches query mit einem inner join für die abfrage
private String generateBaseQuery(final String table) {
final StringBuilder sb = new StringBuilder();
sb.append("SELECT timestamp, user_id, course.title as course, course.id as courseId");
sb.append(" FROM " + table + "_log AS log");
sb.append(" LEFT JOIN course");
sb.append(" ON course.id = log.course_id");
return sb.toString();
}
}