001    package net.sf.cpsolver.exam.reports;
002    
003    import java.text.DecimalFormat;
004    import java.util.ArrayList;
005    import java.util.List;
006    
007    import net.sf.cpsolver.exam.model.Exam;
008    import net.sf.cpsolver.exam.model.ExamModel;
009    import net.sf.cpsolver.exam.model.ExamPeriod;
010    import net.sf.cpsolver.exam.model.ExamPlacement;
011    import net.sf.cpsolver.ifs.util.CSVFile;
012    import net.sf.cpsolver.ifs.util.CSVFile.CSVField;
013    
014    /**
015     * Export period usage into CSV file. <br>
016     * <br>
017     * Usage:<br>
018     * <code>
019     * &nbsp;&nbsp;&nbsp;&nbsp;new ExamPeriodUsage(model).report().save(file);
020     * </code> <br>
021     * <br>
022     * 
023     * @version ExamTT 1.2 (Examination Timetabling)<br>
024     *          Copyright (C) 2008 - 2010 Tomas Muller<br>
025     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
026     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
027     * <br>
028     *          This library is free software; you can redistribute it and/or modify
029     *          it under the terms of the GNU Lesser General Public License as
030     *          published by the Free Software Foundation; either version 3 of the
031     *          License, or (at your option) any later version. <br>
032     * <br>
033     *          This library is distributed in the hope that it will be useful, but
034     *          WITHOUT ANY WARRANTY; without even the implied warranty of
035     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
036     *          Lesser General Public License for more details. <br>
037     * <br>
038     *          You should have received a copy of the GNU Lesser General Public
039     *          License along with this library; if not see
040     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
041     */
042    public class ExamPeriodUsage {
043        private ExamModel iModel = null;
044        /** Exam enrollment limits */
045        public static int[] sLimits = new int[] { 10, 50, 100, 200 };
046        private static DecimalFormat sDF = new DecimalFormat("0.00");
047    
048        /**
049         * Constructor
050         * 
051         * @param model
052         *            examination timetabling model
053         */
054        public ExamPeriodUsage(ExamModel model) {
055            iModel = model;
056        }
057    
058        /**
059         * generate report
060         */
061        public CSVFile report() {
062            CSVFile csv = new CSVFile();
063            List<CSVField> header = new ArrayList<CSVField>();
064            header.add(new CSVField("Period"));
065            header.add(new CSVField("Date"));
066            header.add(new CSVField("Time"));
067            header.add(new CSVField("Weight"));
068            header.add(new CSVField("NrExams"));
069            header.add(new CSVField("Students"));
070            for (int i = 0; i < sLimits.length; i++) {
071                header.add(new CSVField("NrExams>=" + sLimits[i]));
072            }
073            header.add(new CSVField("AvgPeriod"));
074            header.add(new CSVField("WgAvgPeriod"));
075            csv.setHeader(header);
076            for (ExamPeriod period : iModel.getPeriods()) {
077                int nrExams = 0;
078                int nrStudents = 0;
079                int[] nrExamsLim = new int[sLimits.length];
080                int totAvgPer = 0, nrAvgPer = 0, totWgAvgPer = 0;
081                for (int i = 0; i < sLimits.length; i++)
082                    nrExamsLim[i] = 0;
083                for (Exam exam : iModel.variables()) {
084                    ExamPlacement placement = exam.getAssignment();
085                    if (placement == null || !(placement.getPeriod().equals(period)))
086                        continue;
087                    nrExams++;
088                    nrStudents += exam.getStudents().size();
089                    if (exam.getAveragePeriod() >= 0) {
090                        totAvgPer += exam.getAveragePeriod();
091                        nrAvgPer++;
092                        totWgAvgPer += exam.getAveragePeriod() * exam.getStudents().size();
093                    }
094                    for (int i = 0; i < sLimits.length; i++)
095                        if (exam.getStudents().size() >= sLimits[i])
096                            nrExamsLim[i]++;
097                }
098                List<CSVField> line = new ArrayList<CSVField>();
099                line.add(new CSVField(period.getIndex() + 1));
100                line.add(new CSVField(period.getDayStr()));
101                line.add(new CSVField(period.getTimeStr()));
102                line.add(new CSVField(period.getPenalty()));
103                line.add(new CSVField(nrExams));
104                line.add(new CSVField(nrStudents));
105                for (int i = 0; i < sLimits.length; i++)
106                    line.add(new CSVField(nrExamsLim[i]));
107                if (nrAvgPer > 0) {
108                    line.add(new CSVField(sDF.format(((double) totAvgPer) / nrAvgPer)));
109                    line.add(new CSVField(sDF.format(((double) totWgAvgPer) / nrAvgPer)));
110                }
111                csv.addLine(line);
112            }
113            return csv;
114        }
115    }