001package org.cpsolver.coursett; 002 003import java.io.BufferedReader; 004import java.io.File; 005import java.io.FileReader; 006import java.io.StringReader; 007import java.util.ArrayList; 008import java.util.HashMap; 009import java.util.Iterator; 010import java.util.List; 011import java.util.Map; 012import java.util.TreeSet; 013 014 015import org.cpsolver.coursett.model.Lecture; 016import org.cpsolver.coursett.model.Placement; 017import org.cpsolver.coursett.model.TimetableModel; 018import org.cpsolver.ifs.assignment.DefaultSingleAssignment; 019import org.cpsolver.ifs.solution.Solution; 020import org.cpsolver.ifs.util.CSVFile; 021import org.cpsolver.ifs.util.DataProperties; 022import org.cpsolver.ifs.util.Progress; 023import org.cpsolver.ifs.util.ToolBox; 024import org.dom4j.Document; 025import org.dom4j.Element; 026import org.dom4j.io.SAXReader; 027 028/** 029 * Process all solutions (files solution.xml or output.csv) in all subfolders of 030 * the given folder and create a CSV (comma separated values text file) with 031 * solution infos of the found solutions. 032 * 033 * @author Tomáš Müller 034 * @version CourseTT 1.3 (University Course Timetabling)<br> 035 * Copyright (C) 2007 - 2014 Tomáš Müller<br> 036 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 037 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 038 * <br> 039 * This library is free software; you can redistribute it and/or modify 040 * it under the terms of the GNU Lesser General Public License as 041 * published by the Free Software Foundation; either version 3 of the 042 * License, or (at your option) any later version. <br> 043 * <br> 044 * This library is distributed in the hope that it will be useful, but 045 * WITHOUT ANY WARRANTY; without even the implied warranty of 046 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 047 * Lesser General Public License for more details. <br> 048 * <br> 049 * You should have received a copy of the GNU Lesser General Public 050 * License along with this library; if not see 051 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 052 */ 053public class GetInfo { 054 055 public static HashMap<String, String> getInfoOfASolution(File file) { 056 try { 057 DataProperties properties = new DataProperties(); 058 properties.setProperty("General.Input", file.getPath()); 059 TimetableXMLLoader loader = new TimetableXMLLoader(new TimetableModel(properties), new DefaultSingleAssignment<Lecture, Placement>()); 060 loader.load(); 061 File newOutputFile = new File(file.getParentFile(), "new-output.csv"); 062 Test.saveOutputCSV(new Solution<Lecture, Placement>(loader.getModel(), loader.getAssignment()), newOutputFile); 063 Progress.removeInstance(loader.getModel()); 064 System.out.println(" Reading " + newOutputFile + " ..."); 065 HashMap<String, String> info = getInfo(newOutputFile); 066 File outputFile = new File(file.getParentFile(), "output.csv"); 067 if (outputFile.exists()) { 068 System.out.println(" Reading " + outputFile + " ..."); 069 HashMap<String, String> info2 = getInfo(outputFile); 070 if (info2.containsKey("000.002 Time [sec]")) 071 info.put("000.002 Time [sec]", info2.get("000.002 Time [sec]")); 072 } 073 return info; 074 } catch (Exception e) { 075 System.err.println("Error reading info, message: " + e.getMessage()); 076 e.printStackTrace(); 077 return null; 078 } 079 } 080 081 public static HashMap<String, String> getInfo(String comment) { 082 try { 083 BufferedReader reader = new BufferedReader(new StringReader(comment)); 084 String line = null; 085 HashMap<String, String> info = new HashMap<String, String>(); 086 while ((line = reader.readLine()) != null) { 087 int idx = line.indexOf(':'); 088 if (idx >= 0) { 089 String key = line.substring(0, idx).trim(); 090 String value = line.substring(idx + 1).trim(); 091 if (value.indexOf('(') >= 0 && value.indexOf(')') >= 0) { 092 value = value.substring(value.indexOf('(') + 1, value.indexOf(')')); 093 if (value.indexOf('/') >= 0) { 094 String bound = value.substring(value.indexOf('/') + 1); 095 if (bound.indexOf("..") >= 0) { 096 String min = bound.substring(0, bound.indexOf("..")); 097 String max = bound.substring(bound.indexOf("..") + 2); 098 info.put(key + " Min", min); 099 info.put(key + " Max", max); 100 } else { 101 info.put(key + " Bound", bound); 102 } 103 value = value.substring(0, value.indexOf('/')); 104 } 105 } 106 if (value.length() > 0) 107 info.put(key, value); 108 } 109 } 110 reader.close(); 111 return info; 112 } catch (Exception e) { 113 System.err.println("Error reading info, message: " + e.getMessage()); 114 e.printStackTrace(); 115 return null; 116 } 117 } 118 119 public static HashMap<String, String> getInfo(File outputFile) { 120 try { 121 BufferedReader reader = new BufferedReader(new FileReader(outputFile)); 122 String line = null; 123 HashMap<String, String> info = new HashMap<String, String>(); 124 while ((line = reader.readLine()) != null) { 125 int idx = line.indexOf(','); 126 if (idx >= 0) { 127 String key = line.substring(0, idx).trim(); 128 String value = line.substring(idx + 1).trim(); 129 if (value.indexOf('(') >= 0 && value.indexOf(')') >= 0) { 130 value = value.substring(value.indexOf('(') + 1, value.indexOf(')')); 131 if (value.indexOf('/') >= 0) { 132 String bound = value.substring(value.indexOf('/') + 1); 133 if (bound.indexOf("..") >= 0) { 134 String min = bound.substring(0, bound.indexOf("..")); 135 String max = bound.substring(bound.indexOf("..") + 2); 136 info.put(key + " Min", min); 137 info.put(key + " Max", max); 138 } else { 139 info.put(key + " Bound", bound); 140 } 141 value = value.substring(0, value.indexOf('/')); 142 } 143 } 144 if (value.length() > 0) 145 info.put(key, value); 146 } 147 } 148 reader.close(); 149 return info; 150 } catch (Exception e) { 151 System.err.println("Error reading info, message: " + e.getMessage()); 152 e.printStackTrace(); 153 return null; 154 } 155 } 156 157 public static HashMap<String, String> getInfo(Element root) { 158 try { 159 HashMap<String, String> info = new HashMap<String, String>(); 160 for (Iterator<?> i = root.elementIterator("property"); i.hasNext();) { 161 Element property = (Element) i.next(); 162 String key = property.attributeValue("name"); 163 String value = property.getText(); 164 if (key == null || value == null) 165 continue; 166 if (value.indexOf('(') >= 0 && value.indexOf(')') >= 0) { 167 value = value.substring(value.indexOf('(') + 1, value.indexOf(')')); 168 if (value.indexOf('/') >= 0) { 169 String bound = value.substring(value.indexOf('/') + 1); 170 if (bound.indexOf("..") >= 0) { 171 String min = bound.substring(0, bound.indexOf("..")); 172 String max = bound.substring(bound.indexOf("..") + 2); 173 info.put(key + " Min", min); 174 info.put(key + " Max", max); 175 } else { 176 info.put(key + " Bound", bound); 177 } 178 value = value.substring(0, value.indexOf('/')); 179 } 180 } 181 if (value.length() > 0) 182 info.put(key, value); 183 184 } 185 return info; 186 } catch (Exception e) { 187 System.err.println("Error reading info, message: " + e.getMessage()); 188 return null; 189 } 190 } 191 192 public static void getInfo(File folder, List<Info> infos, String prefix) { 193 File infoFile = new File(folder, "info.xml"); 194 if (infoFile.exists()) { 195 System.out.println("Reading " + infoFile + " ..."); 196 try { 197 Document document = (new SAXReader()).read(infoFile); 198 HashMap<String, String> info = getInfo(document.getRootElement()); 199 if (info != null && !info.isEmpty()) { 200 infos.add(new Info(prefix, info)); 201 return; 202 } 203 } catch (Exception e) { 204 System.err.println("Error reading file " + infoFile + ", message: " + e.getMessage()); 205 } 206 } 207 File solutionFile = new File(folder, "solution.xml"); 208 if (solutionFile.exists()) { 209 /* 210 * File newOutputFile = new File(folder, "new-output.csv"); if 211 * (newOutputFile.exists()) { 212 * System.out.println("Reading "+newOutputFile+" ..."); try { 213 * HashMap info = getInfo(newOutputFile); if (info!=null && 214 * !info.isEmpty()) { infos.addElement(new Object[]{prefix,info}); 215 * return; } } catch (Exception e) { 216 * System.err.println("Error reading file " 217 * +infoFile+", message: "+e.getMessage()); } } 218 */ 219 System.out.println("Reading " + solutionFile + " ..."); 220 try { 221 HashMap<String, String> info = getInfoOfASolution(solutionFile); 222 if (info != null && !info.isEmpty()) { 223 infos.add(new Info(prefix, info)); 224 return; 225 } 226 } catch (Exception e) { 227 System.err.println("Error reading file " + infoFile + ", message: " + e.getMessage()); 228 } 229 } 230 File outputFile = new File(folder, "output.csv"); 231 if (outputFile.exists()) { 232 System.out.println("Reading " + outputFile + " ..."); 233 try { 234 HashMap<String, String> info = getInfo(outputFile); 235 if (info != null && !info.isEmpty()) { 236 infos.add(new Info(prefix, info)); 237 return; 238 } 239 } catch (Exception e) { 240 System.err.println("Error reading file " + infoFile + ", message: " + e.getMessage()); 241 } 242 } 243 } 244 245 public static void getInfos(File folder, List<Info> infos, String prefix) { 246 System.out.println("Checking " + folder + " ..."); 247 File[] files = folder.listFiles(); 248 getInfo(folder, infos, (prefix == null ? "" : prefix)); 249 for (int i = 0; i < files.length; i++) 250 if (files[i].isDirectory()) 251 getInfos(files[i], infos, (prefix == null ? "" : prefix + "/") + files[i].getName()); 252 } 253 254 public static void writeInfos(List<Info> infos, File file) { 255 try { 256 System.out.println("Writing " + file + " ..."); 257 TreeSet<String> keys = new TreeSet<String>(); 258 ArrayList<CSVFile.CSVField> headers = new ArrayList<CSVFile.CSVField>(); 259 headers.add(new CSVFile.CSVField("")); 260 for (Info o : infos) { 261 keys.addAll(o.getInfo().keySet()); 262 headers.add(new CSVFile.CSVField(o.getPrefix())); 263 } 264 CSVFile csvFile = new CSVFile(); 265 csvFile.setHeader(headers); 266 for (String key : keys) { 267 ArrayList<CSVFile.CSVField> line = new ArrayList<CSVFile.CSVField>(); 268 line.add(new CSVFile.CSVField(key)); 269 for (Info o : infos) { 270 Map<String, String> info = o.getInfo(); 271 String value = info.get(key); 272 line.add(new CSVFile.CSVField(value == null ? "" : value)); 273 } 274 csvFile.addLine(line); 275 } 276 csvFile.save(file); 277 } catch (Exception e) { 278 System.err.println("Error writing file " + file + ", message: " + e.getMessage()); 279 } 280 } 281 282 public static void main(String[] args) { 283 try { 284 ToolBox.configureLogging(); 285 File folder = new File(args[0]); 286 List<Info> infos = new ArrayList<Info>(); 287 getInfos(folder, infos, null); 288 if (!infos.isEmpty()) 289 writeInfos(infos, new File(folder, "info.csv")); 290 } catch (Exception e) { 291 e.printStackTrace(); 292 } 293 } 294 295 public static class Info { 296 private String iPrefix; 297 private HashMap<String, String> iInfo; 298 299 public Info(String prefix, HashMap<String, String> info) { 300 iPrefix = prefix; 301 iInfo = info; 302 } 303 304 public String getPrefix() { 305 return iPrefix; 306 } 307 308 public Map<String, String> getInfo() { 309 return iInfo; 310 } 311 } 312}