/* * ELW : e-learning workspace * Copyright (C) 2010 Anton Kraievoy * * 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 * (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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package elw.web; import elw.dao.Ctx; import elw.vo.*; import elw.vo.Class; import elw.web.core.Summary; import org.joda.time.DateTime; import java.util.List; import java.util.SortedMap; public class VelocityTemplates { public static final VelocityTemplates INSTANCE = new VelocityTemplates(); public static final String MODEL_KEY = "elw_vt"; public <E> Ref<E> ref(E e) { return new Ref<E>(e); } public Solution bestOrLastOrNull(List<Solution> entries) { if (entries == null || entries.isEmpty()) { return null; } for (Solution entry : entries) { if (entry.getScore() != null && entry.getScore().isBest()) { return entry; } } return entries.get(entries.size() - 1); } public VtTuple status( Format f, String mode, String scope, Ctx ctx, FileSlot slot, FileBase file ) { return status(f, mode, scope, ctx, slot, file, file instanceof Solution ? ((Solution) file).getScore() : null); } public VtTuple status( Format f, String mode, String scope, Ctx ctx, FileSlot slot, FileBase file, Score score ) { final StringBuilder text = new StringBuilder(); final StringBuilder cls = new StringBuilder(); final StringBuilder sort = new StringBuilder(); final elw.vo.Class classFrom = ctx.cFrom(); final elw.vo.Class classDue = ctx.cDue(slot.getId()); if (Solution.SCOPE.equalsIgnoreCase(scope)) { if ("a".equalsIgnoreCase(mode)) { if (!classFrom.isStarted()) { text.append("Closed"); // text.append("; Opens ").append(f.format(classFrom.getFromDateTime().getMillis())); cls.append("elw_closed"); sort.append(-1); } else if (file == null) { text.append("Open"); cls.append("elw_open"); sort.append(1); } else if (score == null || score.getApproved() == null) { text.append("Pending"); cls.append("elw_pending"); sort.append(0); } else if (score.getApproved()) { text.append("Approved"); cls.append("elw_approved"); sort.append(-2); } else { text.append("Declined"); cls.append("elw_declined"); sort.append(2); } } else if ("d".equalsIgnoreCase(mode)) { if (classDue == null) { text.append("No Due Date"); sort.append(0); } else { text.append("Due ").append(f.format(classDue.getToDateTime().getMillis())); sort.append(classDue.getToDateTime().getMillis()); } } else if ("dd".equalsIgnoreCase(mode)) { if (classDue == null) { text.append("No Due Date"); sort.append(0); } else { int dueDiff = classDue.computeToDiffStamp(file); if (dueDiff > 0) { text.append(dueDiff).append("d overdue"); } else if (dueDiff == 0) { text.append("Same day"); } else { text.append(-dueDiff).append("d ahead"); } sort.append(dueDiff); } } else if ("p".equalsIgnoreCase(mode)) { if (!classFrom.isStarted()) { text.append("Closed"); cls.append("elw_closed"); sort.append(0); } else { if (ctx.getIndexEntry().getScoreBudget() > 0) { final double scoreStud; if (file != null && score != null) { scoreStud = ctx.getIndexEntry().computePoints(score, slot); } else { scoreStud = 0; } final double scoreSlot = ctx.getIndexEntry().computePoints(slot); text.append(f.format2(scoreStud)).append(" of ").append(f.format2(scoreSlot)); sort.append(scoreStud); } else { sort.append(0); } if (file == null) { text.insert(0, "<span class=\"elw_open\">O</span> "); cls.append("elw_open"); } else if (score == null || score.getApproved() == null) { final String commentSafe = score == null ? "Preliminary" : score.getComment(); text.insert(0, "<span class=\"elw_pending\" title=\"" + f.esc(commentSafe) + "\">P</span> "); cls.append("elw_pending"); } else if (score.getApproved()) { text.insert(0, "<span class=\"elw_approved\" title=\"" + f.esc(score.getComment()) + "\">A</span> "); cls.append("elw_approved"); } else { text.insert(0, "<span class=\"elw_declined\" title=\"" + f.esc(score.getComment()) + "\">D</span> "); cls.append("elw_declined"); } } } else if ("s".equalsIgnoreCase(mode)) { if (!classFrom.isStarted()) { text.append("Closed"); cls.append("elw_closed"); sort.append(0); } else { if (ctx.getIndexEntry().getScoreBudget() > 0) { final double scoreStud; final ScoreTerm[] terms; if (file != null && score != null) { scoreStud = ctx.getIndexEntry().computePoints(score, slot); terms = score.getTerms(ctx.getAssType(), false); } else { scoreStud = 0; terms = new ScoreTerm[0]; } sort.append(scoreStud); text.append(f.format2(scoreStud)); if (terms.length > 0) { text.append(":"); for (ScoreTerm term : terms) { if (term.getPow() > 1) { niceRatio(f, term.getRatio(), term.getCriteria().getName() + " x " + term.getPow(), text); } else { niceRatio(f, term.getRatio(), term.getCriteria().getName(), text); } } } } else { sort.append(0); } if (file == null) { text.insert(0, "<span class=\"elw_open\">O</span> "); cls.append("elw_open"); } else if (score == null || score.getApproved() == null) { final String commentSafe = score == null ? "Preliminary" : score.getComment(); text.insert(0, "<span class=\"elw_pending\" title=\"" + f.esc(commentSafe) + "\">P</span> "); cls.append("elw_pending"); } else if (score.getApproved()) { text.insert(0, "<span class=\"elw_approved\" title=\"" + f.esc(score.getComment()) + "\">A</span> "); cls.append("elw_approved"); } else { text.insert(0, "<span class=\"elw_declined\" title=\"" + f.esc(score.getComment()) + "\">D</span> "); cls.append("elw_declined"); } } } else if ("dta".equalsIgnoreCase(mode)) { if (!classFrom.isStarted()) { text.append("Closed"); cls.append("elw_closed"); sort.append(0); } else if (file == null) { text.append("Open"); cls.append("elw_open"); sort.append(0); } else { final DateTime scoreStamp; if (score == null || score.getStamp() == null) { scoreStamp = new DateTime(); } else { scoreStamp = new DateTime(score.getStamp()); } final int dta = classFrom.computeToDiff(scoreStamp) - classFrom.computeToDiffStamp(file); text.append(dta).append(" days"); sort.append(dta); } } else if ("dtu".equalsIgnoreCase(mode)) { if (!classFrom.isStarted()) { text.append("Closed"); cls.append("elw_closed"); sort.append(0); } else if (file == null) { text.append("Open"); cls.append("elw_open"); sort.append(0); } else { final int dtu = classFrom.computeToDiffStamp(file); text.append(dtu).append(" days"); sort.append(dtu); } } else if ("v".equalsIgnoreCase(mode)) { if (!classFrom.isStarted()) { text.append("Closed"); cls.append("elw_closed"); sort.append(-1); } else { text.append("<span title=\"").append(ctx.getVer().getName()).append("\">").append(ctx.getVer().getId()).append("</span>"); sort.append(ctx.getVer().getId()); } } else if ("ip".equalsIgnoreCase(mode)) { int sortVal = -1; if (file != null) { sortVal++; text.append(file.getSourceAddress()); if (!classFrom.checkOnSite(file.getSourceAddress())) { sortVal += 4; cls.append(" elw_offsite"); } if (!ctx.getEnr().checkOnTime(file)) { sortVal += 2; cls.append(" elw_offtime"); } if (!classFrom.checkOnTime(file)) { sortVal++; cls.append(" elw_rapid"); } } sort.append(sortVal); } overdueClasses(file, classDue, cls); } else { if (file == null) { text.append("Solution"); sort.append(-2); } else if (Attachment.SCOPE.equalsIgnoreCase(scope)) { text.append("Attachment"); sort.append(1); } } return new VtTuple(text.toString(), cls.toString(), sort.toString()); } private static void overdueClasses(FileBase file, Class classDue, StringBuilder cls) { if (classDue != null) { if (classDue.isPassed()) { cls.append(" elw_due_passed"); if (file == null || classDue.computeDaysOverdue(file) > 0) { cls.append(" elw_overdue"); } } } else { cls.append(" elw_nodue"); } } private void niceRatio(Format f, final double ratio, final String title, final StringBuilder sb) { if (Math.abs(ratio - 1) < 1e-2) { return; } final double percentage = Math.round(ratio * 1000) / 10.0; final String niceRatio; if (percentage < 100) { niceRatio = f.format2(100 - percentage) + "%"; } else { niceRatio = f.format2(percentage - 100) + "%"; } sb.append(" <span class=\"elw_").append(ratio < 1 ? "neg" : "pos").append("Term\""); if (title != null && title.trim().length() >= 0) { sb.append(" title=\"").append(f.esc(title)).append("\""); } sb.append(">").append(niceRatio).append("</span>"); } public String niceRatio(Format f, double ratio, String title) { final StringBuilder builder = new StringBuilder(); niceRatio(f, ratio, title, builder); return builder.toString(); } public VtTuple summary(Ctx ctxAss, SortedMap<String, Summary> ctxEsToSummary, int studNum) { final Summary s = ctxEsToSummary.get(ctxAss.ei()); final StringBuffer text = new StringBuffer(); if (ctxAss.cFrom().isStarted()) { if (s.getDeclinedNum() > 0) { text.append("<span class=\"elw_declined\" title=\"Declined\">").append(s.getDeclinedNum()).append(" D;</span>"); } if (s.getOpenNum() > 0) { text.append("<span class=\"elw_open\" title=\"Open\">").append(s.getOpenNum()).append(" O;</span>"); } if (s.getPendingNum() > 0) { text.append("<span class=\"elw_pending\" title=\"Pending\">").append(s.getPendingNum()).append(" P;</span>"); } if (s.getApprovedNum() > 0) { text.append("<span class=\"elw_approved\" title=\"Approved\">").append(s.getApprovedNum()).append(" A;</span>"); } } else { text.append("<span class=\"elw_closed\" title=\"Closed\">").append(s.getDeclinedNum()).append("Closed;</span>"); } final long sort = 5 * s.getOpenNum() + 25 * s.getDeclinedNum() - s.getApprovedNum(); return new VtTuple(text.toString(), "", String.valueOf(sort)); } }