/* * File : SessionReg.java * Created : 29-jan-2002 11:06 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * 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 2 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 General Public License for more details (see the LICENSE file). */ package edu.xtec.jclic.report; import edu.xtec.jclic.Activity; import edu.xtec.jclic.bags.ActivitySequenceElement; import edu.xtec.jclic.project.JClicProject; import edu.xtec.util.Html; import java.util.Iterator; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 1.0 */ public class SessionReg implements java.io.Serializable{ List<SequenceReg> sequences; SequenceReg currentSequence=null; public java.util.Date started; protected long timeMillis; String projectName; protected transient Info info; String code; /** Creates new SessionReg */ public SessionReg(JClicProject jcp) { this(jcp.getName(), jcp.code); } public SessionReg(String projectName, String code) { sequences=new CopyOnWriteArrayList<SequenceReg>(); currentSequence=null; started=new java.util.Date(); timeMillis=System.currentTimeMillis(); this.projectName=projectName; this.code=code; info=new Info(); } public String toHtmlString(edu.xtec.util.Messages msg, boolean recalcInfo, boolean writeProjectName){ String prefix="report_"; Html html=new Html(3000); if(recalcInfo) info.recalc(); if(info.numSequences>0){ if(writeProjectName){ html.append("<TR STYLE=\"").append(msg.get("about_window_html_style_table_header2")).append("\">"); html.append("<TD COLSPAN=\"6\">"); html.bold(msg.get(prefix+"project")+Html.NBSP+projectName); html.td(false).tr(false); } html.append("<TR STYLE=\"").append(msg.get("about_window_html_style_table_header")).append("\">"); html.td(msg.get(prefix+"lb_sequence"), Html.CENTER, true, null); html.td(msg.get(prefix+"lb_activity"), Html.CENTER, true, null); html.td(msg.get(prefix+"lb_solved"), Html.CENTER, true, null); html.td(msg.get(prefix+"lb_actions"), Html.CENTER, true, null); html.td(msg.get(prefix+"lb_score"), Html.CENTER, true, null); html.td(msg.get(prefix+"lb_time"), Html.CENTER, true, null); html.tr(false); Iterator<SequenceReg> it=sequences.iterator(); while(it.hasNext()) html.append(it.next().toHtmlString(msg)); html.append("<TR STYLE=\"").append(msg.get("about_window_html_style_table_totals")).append("\">"); html.td(msg.get(prefix+"lb_totals"), Html.LEFT, true, null); html.td(msg.getNumber(info.nActivities), Html.RIGHT, true, null); html.td(msg.getNumber(info.nActSolved)+" ("+msg.getPercent(info.percentSolved)+")", Html.RIGHT, true, null); html.td(msg.getNumber(info.nActions), Html.RIGHT, true, null); html.td(msg.getPercent(info.tScore), Html.RIGHT, true, null); html.td(msg.getHmsTime(info.tTime), Html.RIGHT, true, null); html.tr(false); } return html.toString(); } public Info getInfo(boolean recalc){ if(recalc) info.recalc(); return info; } public class Info{ public int numSequences, nActivities, nActSolved, nActScore, percentSolved, nActions; public long tScore, tTime; protected Info(){ clear(); } protected void clear(){ numSequences=nActivities=nActSolved=nActScore=percentSolved=nActions=0; tScore=tTime=0L; } public void recalc(){ clear(); Iterator<SequenceReg> it=sequences.iterator(); while(it.hasNext()){ SequenceReg.Info sri=it.next().getInfo(true); if(sri.nActivities>0){ numSequences++; if(sri.nActClosed>0){ nActivities+=sri.nActClosed; nActions+=sri.nActions; if(sri.nActScore>0){ nActScore+=sri.nActScore; tScore+=(sri.tScore*sri.nActScore); } tTime+=sri.tTime; nActSolved+=sri.nActSolved; } } // // 20-Feb-2006 - Correction of bug #41 // This code must be executed after the "for" iteration: // if(nActScore>0) // tScore/=nActScore; // if(nActivities>0) // percentSolved=(nActSolved*100)/nActivities; } if(nActScore>0) tScore/=nActScore; if(nActivities>0) percentSolved=(nActSolved*100)/nActivities; } } @Override protected void finalize() throws Throwable{ end(); super.finalize(); } public void end(){ endSequence(); } public void endSequence(){ if(currentSequence!=null && currentSequence.totalTime==0) currentSequence.endSequence(); currentSequence=null; } public void newSequence(ActivitySequenceElement ase){ endSequence(); currentSequence=new SequenceReg(ase); sequences.add(currentSequence); } public void newActivity(Activity act){ if(currentSequence!=null) currentSequence.newActivity(act); } public void endActivity(int score, int numActions, boolean solved){ if(currentSequence!=null) currentSequence.endActivity(score, numActions, solved); } public void newAction(String type, String source, String dest, boolean ok){ if(currentSequence!=null) currentSequence.newAction(type, source, dest, ok); } public String getCurrentSequenceTag(){ if(currentSequence==null) return null; return currentSequence.name; } public SequenceReg.Info getCurrentSequenceInfo(){ return currentSequence==null ? null : currentSequence.getInfo(true); } }