/* * File : Report.java * Created : 25-jan-2003 18:52 * 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.rp; import edu.xtec.jclic.report.ActivityData; import edu.xtec.jclic.report.GroupData; import edu.xtec.jclic.report.ReportUtils; import edu.xtec.jclic.report.SessionData; import edu.xtec.jclic.report.UserData; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.09.17 */ public abstract class Report extends BasicReport { public static final int DEFAULT_SELECT_WIDTH=180; public static final String SESSION="session"; protected boolean isEditable=true; protected boolean userTables=true; protected String change; protected String opcioDefecte; protected Object[] session; protected List<GroupData> groups; protected List<UserData> users; protected List projects; @Override public boolean init() throws Exception{ if(!super.init()) return false; isEditable=!(FALSE.equalsIgnoreCase(getParamNotNull(EDIT))); userTables=bridge.hasUserTables(); if(userTables){ groups=bridge.getGroups(); if(groupId.length()>0) users=bridge.getUsers(groupId); } session=getParams(SESSION); change=getParam(CHANGE); switch( GROUP.equals(change) ? 0 : USER.equals(change) ? 1 : DATE.equals(change) ? 2 : PROJECT.equals(change) ? 3 : ACTIVITY.equals(change) ? 4 : 5){ case 0: if(users!=null && users.size()>0) userId=((UserData)users.get(0)).getId(); else userId=""; case 1: projectName=WILDCARD; case 2: case 3: session=null; activityName=WILDCARD; case 4: default: break; } return true; } @Override public void head(java.io.PrintWriter out) throws Exception{ super.head(out); StringBuilder sb=new StringBuilder(300); writeGoScript(sb); dm.writeDateScript(sb); out.println(sb.substring(0)); } @Override public void body(java.io.PrintWriter out) throws Exception{ super.body(out); StringBuilder sb=new StringBuilder(2000); if(isEditable) sb.append(linkTo(urlParam(Main.URL, LANG, lang), bundle.getString(Main.TITLE), null)); standardHeader(out, filter(getTitle(bundle)), sb.substring(0)); sb.setLength(0); sb.append("<form action=\"").append(getUrl()).append("\" method=\"post\" name=\"").append(MAIN_FORM).append("\">\n"); sb.append("<input type=\"hidden\" name=\"").append(CHANGE).append("\" value=\"").append(NEW).append("\">\n"); sb.append("<input type=\"hidden\" name=\"").append(LANG).append("\" value=\"").append(lang).append("\">\n"); dm.writeHiddenFields(sb); if(session!=null){ for(int i=0; i<=session.length; i++){ sb.append("<input type=\"hidden\" name=\"").append(SESSION).append("\" value=\""); sb.append(i<session.length && session[i]!=null ? (String)session[i] : FALSE).append("\">\n"); } } if(!isEditable) sb.append("<input type=\"hidden\" name=\"").append(EDIT).append("\" value=\"").append(FALSE).append("\">\n"); out.println(sb.substring(0)); } protected void writeGoScript(StringBuilder sb){ sb.append("<script language=\"JavaScript\" type=\"text/javascript\">\n"); sb.append("<!--\n"); sb.append(" function go(canvi){\n"); sb.append(" document.").append(MAIN_FORM).append(".").append(CHANGE).append(".value=canvi;\n"); sb.append(" document.").append(MAIN_FORM).append(".submit();\n"); sb.append(" };\n"); sb.append("//-->\n"); sb.append("</script>\n"); } protected void writeSessionScript(StringBuilder sb){ sb.append("<script language=\"JavaScript\" type=\"text/javascript\">\n"); sb.append("<!--\n"); sb.append(" function session(id,v){\n"); sb.append(" document.").append(MAIN_FORM).append(".").append(SESSION).append("[id].value=v\n"); sb.append(" go('").append(SESSION).append("');\n"); sb.append(" };\n"); sb.append("//-->\n"); sb.append("</script>\n"); } protected void llista(StringBuilder sb, String selectName, boolean submitOnChange, String defaultOption, String[][] values, String selectedValue, int width){ /* Mostra una llista desplegable (objecte SELECT) amb opcions */ sb.append("<select name=\"").append(selectName); if(width>0) sb.append("\" style=\"width:").append(width).append("px\""); sb.append(" size=\"1\""); if(submitOnChange){ sb.append(" onChange=\"go('").append(selectName).append("')\""); } sb.append(">\n"); if(defaultOption!=null) sb.append("<option>").append(filter(defaultOption)).append("</option>\n"); if(values!=null && values.length>0){ for(int i=0; i<values.length; i++){ sb.append("<option value=\"").append(filter(values[i][0])).append("\""); if(selectedValue!=null && selectedValue.equals(values[i][0])) sb.append(" selected"); sb.append(">").append(filter(values[i][1])).append("</option>\n"); } } else{ sb.append("<option>"); for(int i=0; i<27; i++) sb.append(" "); sb.append("</option>\n"); } sb.append("</select>\n"); } protected void zona(StringBuilder sb, String descKey, String selectName, boolean submitOnChange, String defaultOption, String[][] values, String selectedValue, boolean showList, int width){ sb.append("<p>").append(filter(getMsg(descKey))).append(" "); if(showList && values!=null) llista(sb, selectName, submitOnChange, defaultOption, values, selectedValue, width); else{ sb.append("<input type=\"hidden\" name=\"").append(selectName).append("\""); if(selectedValue!=null) sb.append(" value=\"").append(filter(selectedValue)).append("\""); sb.append("/>\n"); if(selectedValue!=null && values!=null){ for(int i=0; i<values.length; i++){ if(selectedValue.equals(values[i][0])){ sb.append(filter(values[i][1])).append("\n"); break; } } } } sb.append("</p>\n"); } protected void zonaData(StringBuilder sb){ StringBuilder sb2=new StringBuilder(100); sb2.append("go('").append(DATE).append("')"); dm.zonaData(sb, buttonAction(sb2.substring(0), getMsg("submit"), null)); } public static final String[] KCC_LABELS={"report_key", "report_code", "report_context"}; protected void zonaParams(StringBuilder sb){ sb.append("<div class=\"inputForm\" id=\"compact\">\n"); for(int i=0; i<KCC.length; i++){ sb.append("<p>"); //zonaParam(sb, KCC[i], kcc[i], KCC_LABELS[i], !isEditable); if(isEditable) sb.append(filter(getMsg(KCC_LABELS[i]))).append(" "); sb.append("<input name=\"").append(KCC[i]).append("\" size=\"8\""); if(kcc[i]!=null) sb.append(" value=\"").append(filter(kcc[i])).append("\""); if(!isEditable) sb.append(" type=\"hidden\""); sb.append("></p>\n"); } sb.append("</div>\n"); } protected void grafic(StringBuilder sb, String type, boolean dist, boolean withHeader) throws Exception{ int w=dist ? Img.DIST_WIDTH : Img.DEFAULT_WIDTH; int h=Img.DEFAULT_HEIGHT+Img.DEFAULT_HEADER_HEIGHT; StringBuilder urlG=new StringBuilder(300); urlG.append(Img.URL); urlParamSb(urlG, Img.TYPE, type, true); if(dist) urlParamSb(urlG, Img.DIST, TRUE, false); if(withHeader) urlParamSb(urlG, Img.HEADER, TRUE, false); urlParamSb(urlG, Img.WIDTH, Integer.toString(w), false); urlParamSb(urlG, Img.HEIGHT, Integer.toString(h), false); urlParamSb(urlG, PID, pageId, false); urlParamSb(urlG, USER, userId, false); urlParamSb(urlG, GROUP, groupId, false); if(projectName.length()>0 && !projectName.equals(WILDCARD)) urlParamSb(urlG, PROJECT, projectName, false); if(activityName.length()>0 && !activityName.equals(WILDCARD)) urlParamSb(urlG, ACTIVITY, activityName, false); for(int i=0; i<KCC.length; i++) urlParamSb(urlG, KCC[i], kcc[i], false); urlParamSb(urlG, DateManager.FROM, ReportUtils.dateToStr(dm.dFrom), false); urlParamSb(urlG, DateManager.TO, ReportUtils.dateToStr(dm.dTo), false); sb.append("<img src=\"").append(urlG).append("\" width=\"").append(w).append("\" height=\"").append(h).append("\">"); } protected void llistaSessions(StringBuilder sb, List<SessionData> v, boolean expandable, String className, String style) throws Exception{ //String cl=" CLASS=\"T1\""; //String clh=" CLASS=\"T1header\""; //Html html=new Html(sb); int n=0; sb.append("<table class=\"").append(className).append("\""); if(style!=null) sb.append(" style=\"").append(style).append(""); sb.append(">\n"); sb.append("<tr>"); sb.append("<th>").append(toNbsp(getMsg("report_header_date"))).append("</th>\n"); n++; if(type==PRJ || type==GRP){ sb.append("<th>").append(toNbsp(getMsg("report_header_user"))).append("</th>\n"); sb.append("<th>").append(toNbsp(getMsg("report_header_sessions"))).append("</th>\n"); n+=2; } if(type==USR){ sb.append("<th colspan=2>").append(toNbsp(getMsg("report_header_project"))).append("</th>\n"); n+=2; } sb.append("<th>").append(toNbsp(getMsg("report_header_numActs"))).append("</th>\n"); sb.append("<th>").append(toNbsp(getMsg("report_header_actsSolved"))).append("</th>\n"); sb.append("<th>").append(toNbsp(getMsg("report_header_time"))).append("</th>\n"); sb.append("<th>").append(toNbsp(getMsg("report_header_prec"))).append("</th>\n"); n+=4; sb.append("</tr>\n"); //html.tr(false); StringBuilder sb2=new StringBuilder(500); StringBuilder sb3=new StringBuilder(100); int numSess=0; Iterator<SessionData> it=v.iterator(); while(it.hasNext()){ SessionData sd=it.next(); sb.append("<tr>\n"); sb2.setLength(0); boolean link = expandable && sd.id!=null && sd.id.length()>0; boolean status = link && sd.actData!=null; if(expandable){ if(link){ sb2.append("<a href=\"javascript:session(").append(numSess).append(",'").append(status ? FALSE : TRUE).append("')\">"); sb2.append("<img src=\"").append(resourceUrl(status ? "menys.gif" : "mes.gif")); sb2.append("\" width=\"9\" height=\"9\" border=\"0\" alt=\""); sb2.append(getMsg("report_session_detail_" + (status ? "hide" : "show"))).append("\" id=\"noPrint\">"); sb2.append("</a> "); } else sb2.append("  "); } sb2.append(shortDateFormat.format(sd.date)); sb3.setLength(0); //sb3.append(cl); if(status) sb3.append(" valign=\"top\" rowspan=\"").append(sd.actData.size()+2).append("\""); sb.append("<td align=\"right\"").append(sb3.substring(0)).append(">").append(sb2.substring(0)).append("</td>\n"); //html.td(sb2.substring(0), Html.LEFT, false, sb3.substring(0)); if(type==GRP || type==PRJ){ String s=sd.getUsr(); if("*".equals(s)){ sb2.setLength(0); sb2.append("(").append(numberFormat.format(sd.users.size())).append(" ").append(bundle.getString("report_n_users")).append(")"); s=sb2.substring(0); } sb.append("<td align=\"right\">").append(filter(s)).append("</td>\n"); //html.td(filter(s), Html.RIGHT, false, cl); sb.append("<td align=\"right\">").append(numberFormat.format(sd.sessionCount)).append("</td>\n"); //html.td(Integer.toString(sd.sessionCount), Html.RIGHT, false, cl); } if(type==USR){ sb.append("<td align=\"left\" colspan=2>").append(filter(sd.project)).append("</td>\n"); //html.td(filter(sd.project), Html.LEFT, false, "COLSPAN=\"2\" "+cl); } sb.append("<td align=\"right\">").append(numberFormat.format(sd.numActs)).append("</td>\n"); //html.td(Integer.toString(sd.numActs), Html.RIGHT, false, cl); sb.append("<td align=\"right\">").append(numberFormat.format(sd.actsSolved)).append(" (").append(numberFormat.format(sd.percentSolved())).append("%)</td>\n"); //html.td(Integer.toString(sd.actsSolved)+" ("+sd.percentSolved()+"%)", Html.RIGHT, false, cl); sb.append("<td align=\"right\">").append(formatTime(sd.totalTime)).append("</td>\n"); //html.td(formatTime(sd.totalTime), Html.RIGHT, false, cl); sb.append("<td align=\"right\">").append(numberFormat.format(sd.percentPrec())).append("%</td>\n"); //html.td(Integer.toString(sd.percentPrec())+"%", Html.RIGHT, false, cl); sb.append("</tr>\n"); //html.tr(false); if(status){ llistaActivitats(sb, sd.actData); } numSess++; } sb.append("</table>"); } protected void llistaActivitats(StringBuilder sb, List<ActivityData> v) throws Exception{ //String cl=" CLASS=\"T2\""; //String clh=" CLASS=\"T2header\""; //String clGreen=" CLASS=\"Tgreen\""; //String clRed=" CLASS=\"Tred\""; //Html html=new Html(sb); sb.append("<tr id=\"t2x\">\n"); //html.tr(true); sb.append("<th>").append(toNbsp(getMsg("report_header_activity"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_activity")), Html.LEFT, true, clh); if(type==PRJ || type==GRP){ sb.append("<th>").append(toNbsp(getMsg("report_header_user"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_user")), Html.LEFT, true, clh); } if(type==GRP){ sb.append("<th>").append(toNbsp(getMsg("report_header_project"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_project")), Html.LEFT, true, clh); } sb.append("<th>").append(toNbsp(getMsg("report_header_solved"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_solved")), Html.RIGHT, true, clh); sb.append("<th>").append(toNbsp(getMsg("report_header_actions"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_actions")), Html.RIGHT, true, clh); sb.append("<th>").append(toNbsp(getMsg("report_header_score"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_score")), Html.RIGHT, true, clh); sb.append("<th>").append(toNbsp(getMsg("report_header_time"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_time")), Html.RIGHT, true, clh); sb.append("<th>").append(toNbsp(getMsg("report_header_prec"))).append("</th>\n"); //html.td(toNbsp(getMsg("report_header_prec")), Html.RIGHT, true, clh); sb.append("</tr>\n"); //html.tr(false); Iterator<ActivityData> it=v.iterator(); while(it.hasNext()){ ActivityData ad=it.next(); sb.append("<tr id=\"t2x\">\n"); //html.tr(true); sb.append("<td>").append(filter(ad.activityName)).append("</td>\n"); //html.td(filter(ad.activityName), Html.LEFT, false, cl); if(type==PRJ || type==GRP){ sb.append("<td></td>\n"); //html.td("", Html.LEFT, false, cl); } if(type==GRP){ sb.append("<td>").append(filter(ad.project)).append("</td>\n"); //html.td(filter(ad.project), Html.LEFT, false, cl); } sb.append("<td id=\"").append(ad.solved ? "green" : "red").append("\">"); sb.append(getMsg(ad.solved ? "YES_SHORT" : "NOT_SHORT")).append("</td>\n"); //html.td(getMsg(ad.solved ? "Y" : "N"), Html.CENTER, false, ad.solved ? clGreen : clRed); sb.append("<td align=\"right\">").append(numberFormat.format(ad.actions)).append("</td>\n"); //html.td(Integer.toString(ad.actions), Html.RIGHT, false, cl); sb.append("<td align=\"right\">").append(numberFormat.format(ad.score)).append(" (").append(numberFormat.format(ad.percentSolved())).append("%)</td>\n"); //html.td(Integer.toString(ad.score)+" ("+ad.percentSolved()+"%)", Html.RIGHT, false, cl); sb.append("<td align=\"right\">").append(formatTime(ad.time)).append("</td>\n"); //html.td(formatTime(ad.time), Html.RIGHT, false, cl); sb.append("<td align=\"right\">").append(numberFormat.format(ad.qualification)).append("%</td>\n"); //html.td(Integer.toString(ad.qualification)+"%", Html.RIGHT, false, cl); sb.append("</tr>\n"); //html.tr(false); } } protected void resumGlobal(StringBuilder sb, List<SessionData> v, String className, String style) throws Exception{ int sess=0, usrs, numProjects=0, act_fetes=0, act_res=0, temps=0, precisio=0; if(!projectName.equals(WILDCARD)) numProjects=1; else if(projects!=null){ numProjects=projects.size(); if(projects.size()>0 && WILDCARD.equals(projects.get(0))) numProjects--; } Set<String> hs=new HashSet<String>(); Iterator<SessionData> it=v.iterator(); while(it.hasNext()){ SessionData sd=it.next(); act_fetes+=sd.numActs; act_res+=sd.actsSolved; temps+=sd.totalTime; precisio+=sd.totalPrec; sess+=sd.sessionCount; hs.addAll(sd.users); } usrs=hs.size(); sb.append("<table class=\"").append(className).append("\""); if(style!=null) sb.append(" style=\"").append(style).append("\""); sb.append(">\n"); sb.append("<tr><th colspan=2>").append(filter(getMsg("report_globalSummary"))).append("</th></tr>\n"); if(usrs>1) resumTD(sb, getMsg("report_users"), numberFormat.format(usrs)); resumTD(sb, getMsg("report_sessions"), numberFormat.format(sess)); if(type!=PRJ) resumTD(sb, getMsg("report_projects"), numberFormat.format(numProjects)); resumTD(sb, getMsg("report_actDone"), numberFormat.format(act_fetes)); StringBuilder sb2=new StringBuilder(200); sb2.append(numberFormat.format(act_res)).append(" (").append(numberFormat.format(act_fetes==0 ? 0 : 100*act_res/act_fetes)).append("%)"); resumTD(sb, getMsg("report_actSolved"), sb2.substring(0)); resumTD(sb, getMsg("report_totalTime"), formatTime(temps)); sb2.setLength(0); sb2.append(numberFormat.format(act_fetes==0 ? 0 : precisio/act_fetes)).append("%"); resumTD(sb, getMsg("report_globalPrec"), sb2.substring(0)); sb.append("</table>\n"); } protected void resumTD(StringBuilder sb, String td1, String td2){ sb.append("<tr><td>").append(toNbsp(td1)); sb.append("</td><td align=\"right\">").append(toNbsp(td2)).append("</td></tr>\n"); } public String formatTime(int secs){ secs=Math.max(0, secs); String[] n=getFormattedNumbers(); int h=secs/(60*60); int m=(secs-(h*60*60))/60; int s=secs%60; StringBuilder sb=new StringBuilder(8); if(h>0) sb.append(h).append(":"); sb.append(n[m]).append(":").append(n[s]); return sb.substring(0); } }