/** * File ./src/main/java/de/lemo/dms/processing/questions/QPerformanceUserTest.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/QPerformanceUserTest.java * Date 2013-02-26 * Project Lemo Learning Analytics */ package de.lemo.dms.processing.questions; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import org.apache.log4j.Logger; 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.IDBHandler; import de.lemo.dms.db.mapping.abstractions.ICourseRatedObjectAssociation; import de.lemo.dms.db.mapping.abstractions.IRatedLogObject; import de.lemo.dms.processing.MetaParam; import de.lemo.dms.processing.StudentHelper; import de.lemo.dms.processing.resulttype.ResultListLongObject; import de.lemo.dms.processing.resulttype.ResultListStringObject; import de.lemo.dms.service.ServiceRatedObjects; /** * Gathers and returns all all test results for every student and every test in a course * * @author Sebastian Schwarzrock */ @Path("performanceUserTest") public class QPerformanceUserTest { private Logger logger = Logger.getLogger(this.getClass()); /** * @param courses * (optional) List of course-ids that shall be included * @param users * (optional) List of user-ids * @param quizzes * (mandatory) List of learning object ids (the ids have to start with the type specific prefix (11 for * "assignment", 14 for "quiz", 17 for "scorm")) * @param resolution * (mandatory) Used to scale the results. If set to 0, the method * returns the actual results of the test. Otherwise it returns the * results scaled using the value of resolution. * @param startTime * (mandatory) * @param endTime * (mandatory) * @return */ @SuppressWarnings("unchecked") @POST public ResultListLongObject compute( @FormParam(MetaParam.COURSE_IDS) final List<Long> courses, @FormParam(MetaParam.USER_IDS) List<Long> users, @FormParam(MetaParam.QUIZ_IDS) final List<Long> quizzes, @FormParam(MetaParam.RESOLUTION) final Long resolution, @FormParam(MetaParam.START_TIME) final Long startTime, @FormParam(MetaParam.END_TIME) final Long endTime, @FormParam(MetaParam.GENDER) final List<Long> gender) { if (logger.isDebugEnabled()) { if ((courses != null) && (courses.size() > 0)) { StringBuffer buffer = new StringBuffer(); buffer.append("Parameter list: Courses: " + courses.get(0)); for (int i = 1; i < courses.size(); i++) { buffer.append(", " + courses.get(i)); } logger.debug(buffer.toString()); } if ((users != null) && (users.size() > 0)) { StringBuffer buffer = new StringBuffer(); buffer.append("Parameter list: Users: " + users.get(0)); for (int i = 1; i < users.size(); i++) { buffer.append(", " + users.get(i)); } logger.debug(buffer.toString()); } logger.debug("Parameter list: Resolution: : " + resolution); logger.debug("Parameter list: Start time: : " + startTime); logger.debug("Parameter list: End time: : " + endTime); } final IDBHandler dbHandler = ServerConfiguration.getInstance().getMiningDbHandler(); final Session session = dbHandler.getMiningSession(); Criteria criteria; if(users == null || users.size() == 0) { users = new ArrayList<Long>(StudentHelper.getCourseStudentsAliasKeys(courses, gender).values()); } else { Map<Long, Long> userMap = StudentHelper.getCourseStudentsAliasKeys(courses, gender); List<Long> tmp = new ArrayList<Long>(); for(int i = 0; i < users.size(); i++) { tmp.add(userMap.get(users.get(i))); } users = tmp; } criteria = session.createCriteria(IRatedLogObject.class, "log"); criteria.add(Restrictions.between("log.timestamp", startTime, endTime)); if ((courses != null) && (courses.size() > 0)) { criteria.add(Restrictions.in("log.course.id", courses)); } if(users != null && users.size() > 0) criteria.add(Restrictions.in("log.user.id", users)); final ArrayList<IRatedLogObject> list = (ArrayList<IRatedLogObject>) criteria.list(); final Map<Long, Integer> obj = new HashMap<Long, Integer>(); if(quizzes.size() > 0) { for (int i = 0; i < quizzes.size(); i++) { obj.put(quizzes.get(i), i); } } else { ServiceRatedObjects sro = new ServiceRatedObjects(); ResultListStringObject rso = sro.getRatedObjects(courses); String s = new String(); int count = 0; for(int i = 0; i < rso.getElements().size(); i++) { if((i + 1) % 3 != 0) { s += rso.getElements().get(i); } else { obj.put(Long.valueOf(s), count); quizzes.add(Long.valueOf(s)); s= ""; count++; } } } final Map<String, IRatedLogObject> singleResults = new HashMap<String, IRatedLogObject>(); Collections.sort(list); Set<Long> u = new HashSet<Long>(); // This is for making sure there is just one entry per student and test for (int i = list.size() - 1; i >= 0; i--) { final IRatedLogObject log = list.get(i); final String key = log.getPrefix() + " " + log.getLearnObjId() + " " + log.getUser().getId(); u.add(log.getUser().getId()); if (log.getFinalGrade() != null && (singleResults.get(key) == null || (log.getFinalGrade() > singleResults.get(key).getFinalGrade()))) { singleResults.put(key, log); } } // Determine length of result array final int objects = quizzes.size() + u.size() * quizzes.size() + u.size(); final Long[] results = new Long[objects]; Map<Long, ArrayList<Long>> fin = new HashMap<Long, ArrayList<Long>>(); for (final IRatedLogObject log : singleResults.values()) { if ((obj.get(Long.valueOf(log.getPrefix() + "" + log.getLearnObjId())) != null) && (log.getFinalGrade() != null) && (log.getMaxGrade() != null) && (log.getMaxGrade() > 0)) { Double step = 1d; // Determine size of each interval if(resolution != 0) step = log.getMaxGrade() / resolution; if (step > 0d) { // Determine interval for specific grade Integer pos = (int) (log.getFinalGrade() / step); if (resolution > 0 && pos > (resolution - 1)) { pos = resolution.intValue() - 1; } if(fin.get(log.getUser().getId()) == null) { ArrayList<Long> l = new ArrayList<Long>(); for(int i = 0; i < quizzes.size(); i++) { l.add(-1L); } fin.put(log.getUser().getId(), l); fin.get(log.getUser().getId()).set(quizzes.indexOf(Long.valueOf(log.getPrefix() + "" + log.getLearnObjId())), pos.longValue()); } else { fin.get(log.getUser().getId()).set(quizzes.indexOf(Long.valueOf(log.getPrefix() + "" + log.getLearnObjId())), pos.longValue()); } } } } criteria = session.createCriteria(ICourseRatedObjectAssociation.class, "aso"); criteria.add(Restrictions.in("aso.course.id", courses)); ArrayList<ICourseRatedObjectAssociation> q = (ArrayList<ICourseRatedObjectAssociation>) criteria.list(); HashMap<Long, Double> maxGrades = new HashMap<Long, Double>(); for(ICourseRatedObjectAssociation aso : q) { maxGrades.put(Long.valueOf(aso.getPrefix() + "" + aso.getRatedObject().getId()), aso.getRatedObject().getMaxGrade()); } //Determine maximum number of points for every quiz for(int i = 0; i < quizzes.size(); i++) { if(maxGrades.get(quizzes.get(i)) != null) results[i] = maxGrades.get(quizzes.get(i)).longValue(); else results[i] = -1L; } int i = quizzes.size(); Map<Long, Long> idToAlias = StudentHelper.getCourseStudentsRealKeys(courses, gender); for(Entry<Long, ArrayList<Long>> entry : fin.entrySet()) { //Insert user-id into result list results[i] = idToAlias.get(entry.getKey()); //Insert all test results for user to result list for(Long l : entry.getValue()) { i++; results[i] = l; } i++; } session.close(); return new ResultListLongObject(Arrays.asList(results)); } }