/* * Copyright 2007 Zhang, Zheng <oldbig@gmail.com> * * This file is part of ZOJ. * * ZOJ 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 revision 3 of the License, or (at your option) any later revision. * * ZOJ 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 ZOJ. if not, see * <http://www.gnu.org/licenses/>. */ package cn.edu.zju.acm.onlinejudge.action; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import cn.edu.zju.acm.onlinejudge.bean.AbstractContest; import cn.edu.zju.acm.onlinejudge.bean.Problem; import cn.edu.zju.acm.onlinejudge.util.ProblemsetRankList; import cn.edu.zju.acm.onlinejudge.util.RankList; import cn.edu.zju.acm.onlinejudge.util.RankListEntry; import cn.edu.zju.acm.onlinejudge.util.StatisticsManager; import cn.edu.zju.acm.onlinejudge.util.Utility; /** * <p> * ShowRankListAction * </p> * * * @author Zhang, Zheng * @author Chen, Zhengguang * @version 2.0 */ public class ShowRankListAction extends BaseAction { /** * <p> * Default constructor. * </p> */ public ShowRankListAction() { // empty } /** * ShowRankListAction. * * @param mapping * action mapping * @param form * action form * @param request * http servlet request * @param response * http servlet response * * @return action forward instance * * @throws Exception * any errors happened */ @Override public ActionForward execute(ActionMapping mapping, ActionForm form, ContextAdapter context) throws Exception { // check contest boolean isProblemset = context.getRequest().getRequestURI().endsWith("showRankList.do"); ActionForward forward = this.checkContestViewPermission(mapping, context, isProblemset, true); if (forward != null) { return forward; } AbstractContest contest = context.getContest(); if (!isProblemset) { List<Problem> problems = context.getProblems(); context.setAttribute("problems", problems); long roleId = Utility.parseLong(context.getRequest().getParameter("roleId")); RankList ranklist = StatisticsManager.getInstance().getRankList(contest.getId(), roleId); String export = context.getRequest().getParameter("export"); if ("txt".equalsIgnoreCase(export)) { return this.export(context, contest, problems, ranklist, export); } else if ("xls".equalsIgnoreCase(export)) { return this.export(context, contest, problems, ranklist, export); } context.setAttribute("RankList", ranklist); } else { int from = Utility.parseInt(context.getRequest().getParameter("from")); if (from < 0) { from = 0; } int count = 30; String sort=context.getRequest().getParameter("order"); if(sort == null || !sort.equalsIgnoreCase("submit")) { sort="ac"; } ProblemsetRankList ranklist = StatisticsManager.getInstance().getProblemsetRankList(contest.getId(), from, count, sort); if (from > 0) { context.setAttribute("previousFrom", from - count > 0 ? from - count : 0); } if (ranklist.getSolved().length == count) { context.setAttribute("nextFrom", from + count); } context.setAttribute("RankList", ranklist); } return this.handleSuccess(mapping, context, "success"); } private ActionForward export(ContextAdapter context, AbstractContest contest, List<Problem> problems, RankList ranklist, String export) throws Exception { byte[] out; String fileName = this.getFileName(contest); HttpServletResponse response = context.getResponse(); if ("xls".equalsIgnoreCase(export)) { out = this.exportToExcel(contest, problems, ranklist); response.setContentType("application/doc"); response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls"); } else { boolean windows = true; String userAgentHeader = context.getRequest().getHeader("user-agent"); if (userAgentHeader != null && userAgentHeader.length() > 0) { windows = userAgentHeader.indexOf("Windows") != -1; } out = this.exportToText(contest, problems, ranklist, windows); response.setContentType("text/plain"); response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".txt"); } response.getOutputStream().write(out); response.getOutputStream().close(); return null; } private byte[] exportToExcel(AbstractContest contest, List<Problem> problems, RankList ranklist) throws Exception { List<RankListEntry> entries = ranklist.getEntries(); long time = this.getTimeEscaped(contest); HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(); HSSFRow row = sheet.createRow(0); HSSFCell cell = row.createCell((short) 0); cell.setCellValue(contest.getTitle()); if (ranklist.getRole() != null) { row = sheet.createRow(1); cell = row.createCell((short) 0); cell.setEncoding(HSSFCell.ENCODING_UTF_16); cell.setCellValue(ranklist.getRole().getDescription()); } row = sheet.createRow(2); cell = row.createCell((short) 0); cell.setCellValue("Length"); cell = row.createCell((short) 1); cell.setCellValue(Utility.toTime(contest.getLength() / 1000)); row = sheet.createRow(3); cell = row.createCell((short) 0); cell.setCellValue("Time Escaped"); cell = row.createCell((short) 1); cell.setCellValue(Utility.toTime(time / 1000)); row = sheet.createRow(5); row.createCell((short) 0).setCellValue("Rank"); row.createCell((short) 1).setCellValue("Handle"); row.createCell((short) 2).setCellValue("Nickname"); row.createCell((short) 3).setCellValue("Solved"); short columnIndex = 4; for (Problem problem2 : problems) { Problem problem = problem2; row.createCell(columnIndex).setCellValue(problem.getCode()); columnIndex++; } row.createCell(columnIndex).setCellValue("Penalty"); int rowIndex = 6; for (RankListEntry rankListEntry : entries) { RankListEntry entry = rankListEntry; row = sheet.createRow(rowIndex); row.createCell((short) 0).setCellValue(rowIndex - 5); row.createCell((short) 1).setCellValue(entry.getUserProfile().getHandle()); String nick = entry.getUserProfile().getHandle(); if (entry.getUserProfile().getNickName() != null) { nick = entry.getUserProfile().getNickName(); } cell = row.createCell((short) 2); cell.setEncoding(HSSFCell.ENCODING_UTF_16); cell.setCellValue(nick); row.createCell((short) 3).setCellValue(entry.getSolved()); for (short i = 0; i < problems.size(); ++i) { String score = entry.getAcceptTime(i) > 0 ? entry.getAcceptTime(i) + "(" + entry.getSubmitNumber(i) + ")" : "" + entry.getSubmitNumber(i); row.createCell((short) (4 + i)).setCellValue(score); } row.createCell((short) (4 + problems.size())).setCellValue(entry.getPenalty()); rowIndex++; } // output to stream ByteArrayOutputStream out = new ByteArrayOutputStream(); try { wb.write(out); return out.toByteArray(); } finally { out.close(); } } private byte[] exportToText(AbstractContest contest, List<Problem> problems, RankList ranklist, boolean windows) throws Exception { List<RankListEntry> entries = ranklist.getEntries(); String lineHolder = windows ? "\r\n" : "\n"; long time = this.getTimeEscaped(contest); ByteArrayOutputStream out = new ByteArrayOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out)); writer.write(contest.getTitle()); writer.write(lineHolder); writer.write(ranklist.getRole() == null ? "" : ranklist.getRole().getDescription()); writer.write(lineHolder); writer.write("Length: " + Utility.toTime(contest.getLength() / 1000)); writer.write(lineHolder); writer.write("Time Escaped: " + Utility.toTime(time / 1000)); writer.write(lineHolder); writer.write(lineHolder); writer.write("Rank\tHandle\tNickname\tSolved\t"); for (Problem problem2 : problems) { Problem problem = problem2; writer.write(problem.getCode()); writer.write("\t"); } writer.write("Penalty"); writer.write(lineHolder); int index = 0; for (RankListEntry rankListEntry : entries) { index++; RankListEntry entry = rankListEntry; writer.write(index + "\t"); writer.write(entry.getUserProfile().getHandle() + "\t"); writer.write((entry.getUserProfile().getNickName() == null ? entry.getUserProfile().getHandle() : entry.getUserProfile().getNickName()) + "\t"); writer.write(entry.getSolved() + "\t"); for (int i = 0; i < problems.size(); ++i) { String score = entry.getAcceptTime(i) > 0 ? entry.getAcceptTime(i) + "(" + entry.getSubmitNumber(i) + ")" : "" + entry.getSubmitNumber(i); writer.write(score + "\t"); } writer.write(entry.getPenalty() + lineHolder); } writer.close(); return out.toByteArray(); } private String getFileName(AbstractContest contest) { long time = this.getTimeEscaped(contest); String contestName = contest.getTitle().trim() + "_RankList_" + Utility.toTime(time / 1000); StringBuilder sb = new StringBuilder(); boolean last = false; for (int i = 0; i < contestName.length(); ++i) { char ch = contestName.charAt(i); if (ch <= 'Z' && ch >= 'A' || ch <= 'z' && ch >= 'a' || ch <= '9' && ch >= '0') { if (last) { sb.append('_'); last = false; } sb.append(ch); } else { last = true; } } return sb.toString(); } private long getTimeEscaped(AbstractContest contest) { long time = System.currentTimeMillis() - contest.getStartTime().getTime(); if (time < 0) { time = 0; } if (time > contest.getLength()) { time = contest.getLength(); } return time; } }