001package org.cpsolver.instructor.test; 002 003import java.io.BufferedReader; 004import java.io.File; 005import java.io.FileReader; 006import java.io.IOException; 007import java.io.PrintWriter; 008import java.text.DecimalFormat; 009import java.util.ArrayList; 010import java.util.Collections; 011import java.util.Comparator; 012import java.util.HashMap; 013import java.util.HashSet; 014import java.util.List; 015import java.util.Map; 016import java.util.Set; 017import java.util.TreeSet; 018 019import org.apache.logging.log4j.Logger; 020import org.cpsolver.coursett.Constants; 021import org.cpsolver.coursett.model.TimeLocation; 022import org.cpsolver.ifs.assignment.Assignment; 023import org.cpsolver.ifs.model.Constraint; 024import org.cpsolver.ifs.util.DataProperties; 025import org.cpsolver.ifs.util.ToolBox; 026import org.cpsolver.instructor.Test; 027import org.cpsolver.instructor.constraints.SameInstructorConstraint; 028import org.cpsolver.instructor.constraints.SameLinkConstraint; 029import org.cpsolver.instructor.criteria.DifferentLecture; 030import org.cpsolver.instructor.model.Course; 031import org.cpsolver.instructor.model.Instructor; 032import org.cpsolver.instructor.model.Attribute; 033import org.cpsolver.instructor.model.Preference; 034import org.cpsolver.instructor.model.Section; 035import org.cpsolver.instructor.model.TeachingAssignment; 036import org.cpsolver.instructor.model.TeachingRequest; 037 038/** 039 * Math teaching assistant assignment problem. Different file format for the input data. 040 * 041 * @author Tomáš Müller 042 * @version IFS 1.3 (Instructor Sectioning)<br> 043 * Copyright (C) 2016 Tomáš Müller<br> 044 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 045 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 046 * <br> 047 * This library is free software; you can redistribute it and/or modify 048 * it under the terms of the GNU Lesser General Public License as 049 * published by the Free Software Foundation; either version 3 of the 050 * License, or (at your option) any later version. <br> 051 * <br> 052 * This library is distributed in the hope that it will be useful, but 053 * WITHOUT ANY WARRANTY; without even the implied warranty of 054 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 055 * Lesser General Public License for more details. <br> 056 * <br> 057 * You should have received a copy of the GNU Lesser General Public 058 * License along with this library; if not see 059 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 060 */ 061public class MathTest extends Test { 062 private static Logger sLog = org.apache.logging.log4j.LogManager.getLogger(MathTest.class); 063 064 public MathTest(DataProperties properties) { 065 super(properties); 066 removeCriterion(DifferentLecture.class); 067 } 068 069 public String getLevel(Instructor instructor) { 070 for (Attribute attribute: instructor.getAttributes()) 071 if (attribute.getType().getTypeName().equals("Level")) return attribute.getAttributeName(); 072 return null; 073 } 074 075 public String toString(Instructor instructor) { 076 StringBuffer sb = new StringBuffer(); 077 sb.append(instructor.getExternalId()); 078 sb.append(",\"" + instructor.getAvailable() + "\""); 079 Collections.sort(instructor.getCoursePreferences(), new Comparator<Preference<Course>>() { 080 @Override 081 public int compare(Preference<Course> p1, Preference<Course> p2) { 082 if (p1.getPreference() == p2.getPreference()) 083 return p1.getTarget().getCourseName().compareTo(p2.getTarget().getCourseName()); 084 return p1.getPreference() < p2.getPreference() ? -1 : 1; 085 } 086 }); 087 for (int i = 0; i < 3; i++) { 088 Preference<Course> p = (i < instructor.getCoursePreferences().size() ? instructor.getCoursePreferences().get(i) : null); 089 sb.append("," + (p == null ? "" : p.getTarget().getCourseName())); 090 } 091 sb.append("," + (instructor.getPreference() == 0 ? "Yes" : "No")); 092 sb.append("," + (instructor.isBackToBackPreferred() ? "1" : instructor.isBackToBackDiscouraged() ? "-1" : "0")); 093 sb.append("," + new DecimalFormat("0.0").format(instructor.getMaxLoad())); 094 String level = getLevel(instructor); 095 sb.append("," + (level == null ? "" : level)); 096 return sb.toString(); 097 } 098 099 public String getLink(TeachingRequest.Variable request) { 100 for (Constraint<TeachingRequest.Variable, TeachingAssignment> c: request.constraints()) { 101 if (c instanceof SameLinkConstraint) 102 return c.getName().substring(c.getName().indexOf('-') + 1); 103 } 104 return null; 105 } 106 107 public Long getAssignmentId(TeachingRequest.Variable request) { 108 for (Constraint<TeachingRequest.Variable, TeachingAssignment> c: request.constraints()) { 109 if (c instanceof SameInstructorConstraint && ((SameInstructorConstraint) c).getConstraintId() != null) 110 return ((SameInstructorConstraint) c).getConstraintId(); 111 } 112 return null; 113 } 114 115 public int countDiffLinks(Set<TeachingAssignment> assignments) { 116 Set<String> links = new HashSet<String>(); 117 for (TeachingAssignment assignment : assignments) { 118 String link = getLink(assignment.variable()); 119 if (link != null) 120 links.add(link); 121 } 122 return Math.max(0, links.size() - 1); 123 } 124 125 public String toString(TeachingRequest.Variable request) { 126 StringBuffer sb = new StringBuffer(); 127 Long assId = getAssignmentId(request); 128 sb.append(assId == null ? "" : assId); 129 sb.append("," + request.getCourse().getCourseName()); 130 Section section = request.getSections().get(0); 131 sb.append("," + section.getSectionName()); 132 sb.append("," + section.getTimeName(true)); 133 sb.append(",\"" + (section.hasRoom() ? section.getRoom() : "") + "\""); 134 String link = getLink(request); 135 sb.append("," + (link == null ? "" : link)); 136 Map<String, Integer> levels = new HashMap<String, Integer>(); 137 for (Preference<Attribute> p: request.getRequest().getAttributePreferences()) 138 levels.put(p.getTarget().getAttributeName(), - p.getPreference()); 139 sb.append(",\"" + levels + "\""); 140 sb.append("," + new DecimalFormat("0.0").format(request.getRequest().getLoad())); 141 return sb.toString(); 142 } 143 144 @Override 145 protected boolean load(File dir, Assignment<TeachingRequest.Variable, TeachingAssignment> assignment) { 146 if (!dir.isDirectory()) 147 return super.load(dir, assignment); 148 try { 149 String line = null; 150 BufferedReader r = new BufferedReader(new FileReader(new File(dir, "courses.csv"))); 151 Map<String, Course> courses = new HashMap<String, Course>(); 152 Map<Long, List<TeachingRequest>> id2classes = new HashMap<Long, List<TeachingRequest>>(); 153 Map<String, List<TeachingRequest>> link2classes = new HashMap<String, List<TeachingRequest>>(); 154 long assId = 0, reqId = 0; 155 while ((line = r.readLine()) != null) { 156 if (line.trim().isEmpty()) 157 continue; 158 String[] fields = line.split(","); 159 Long id = Long.valueOf(fields[0]); 160 String course = fields[1]; 161 String section = fields[2]; 162 int idx = 3; 163 int dayCode = 0; 164 idx: while (idx < fields.length && (idx == 3 || fields[idx].length() == 1)) { 165 for (int i = 0; i < fields[idx].length(); i++) { 166 switch (fields[idx].charAt(i)) { 167 case 'M': 168 dayCode += Constants.DAY_CODES[0]; 169 break; 170 case 'T': 171 dayCode += Constants.DAY_CODES[1]; 172 break; 173 case 'W': 174 dayCode += Constants.DAY_CODES[2]; 175 break; 176 case 'R': 177 dayCode += Constants.DAY_CODES[3]; 178 break; 179 case 'F': 180 dayCode += Constants.DAY_CODES[4]; 181 break; 182 default: 183 break idx; 184 } 185 } 186 idx++; 187 } 188 int startSlot = 0; 189 if (dayCode > 0) { 190 int time = Integer.parseInt(fields[idx++]); 191 startSlot = 12 * (time / 100) + (time % 100) / 5; 192 } 193 String room = null; 194 if (idx < fields.length) 195 room = fields[idx++]; 196 String link = null; 197 if (idx < fields.length) 198 link = fields[idx++]; 199 int length = 12; 200 if (idx < fields.length) { 201 int time = Integer.parseInt(fields[idx++]); 202 int endSlot = 12 * (time / 100) + (time % 100) / 5; 203 length = endSlot - startSlot; 204 if (length == 10) 205 length = 12; 206 else if (length == 15) 207 length = 18; 208 } 209 List<Section> sections = new ArrayList<Section>(); 210 TimeLocation time = new TimeLocation(dayCode, startSlot, length, 0, 0.0, 0, null, "", null, (length == 18 ? 15 : 10)); 211 sections.add(new Section(assId++, id.toString(), section, course + " " + section + " " + time.getName(true) + (room == null ? "" : " " + room), time, room, false, false)); 212 Course c = courses.get(course); 213 if (c == null) { 214 c = new Course(courses.size(), course); 215 courses.put(course, c); 216 } 217 TeachingRequest clazz = new TeachingRequest(reqId++, 1, c, 0f, sections, Constants.sPreferenceLevelRequired, Constants.sPreferenceLevelNeutral); 218 addRequest(clazz); 219 List<TeachingRequest> classes = id2classes.get(id); 220 if (classes == null) { 221 classes = new ArrayList<TeachingRequest>(); 222 id2classes.put(id, classes); 223 } 224 classes.add(clazz); 225 if (link != null && !link.isEmpty()) { 226 List<TeachingRequest> linked = link2classes.get(course + "-" + link); 227 if (linked == null) { 228 linked = new ArrayList<TeachingRequest>(); 229 link2classes.put(course + "-" + link, linked); 230 } 231 linked.add(clazz); 232 } 233 } 234 235 for (Map.Entry<Long, List<TeachingRequest>> e : id2classes.entrySet()) { 236 Long id = e.getKey(); 237 List<TeachingRequest> classes = e.getValue(); 238 if (classes.size() > 1) { 239 SameInstructorConstraint sa = new SameInstructorConstraint(id, "A" + id.toString(), Constants.sPreferenceRequired); 240 for (TeachingRequest c : classes) 241 sa.addVariable(c.getVariables()[0]); 242 addConstraint(sa); 243 } 244 } 245 for (Map.Entry<String, List<TeachingRequest>> e : link2classes.entrySet()) { 246 String link = e.getKey(); 247 List<TeachingRequest> classes = e.getValue(); 248 if (classes.size() > 1) { 249 SameLinkConstraint sa = new SameLinkConstraint(null, link, Constants.sPreferencePreferred); 250 for (TeachingRequest c : classes) 251 sa.addVariable(c.getVariables()[0]); 252 addConstraint(sa); 253 } 254 } 255 256 Attribute.Type level = new Attribute.Type(0l, "Level", false, true); 257 addAttributeType(level); 258 Map<String, Attribute> code2attribute = new HashMap<String, Attribute>(); 259 r.close(); 260 261 r = new BufferedReader(new FileReader(new File(dir, "level_codes.csv"))); 262 String[] codes = r.readLine().split(","); 263 while ((line = r.readLine()) != null) { 264 if (line.trim().isEmpty()) 265 continue; 266 String[] fields = line.split(","); 267 String code = fields[0]; 268 if (code.startsWith("\"") && code.endsWith("\"")) 269 code = code.substring(1, code.length() - 1); 270 Attribute attribute = code2attribute.get(code); 271 if (attribute == null) { 272 attribute = new Attribute(code2attribute.size(), code, level); 273 code2attribute.put(code, attribute); 274 } 275 for (int i = 1; i < codes.length; i++) { 276 int pref = Integer.parseInt(fields[i]); 277 if (pref > 0) 278 for (TeachingRequest clazz : getRequests()) { 279 if (clazz.getCourse().getCourseName().contains(codes[i])) 280 clazz.addAttributePreference(new Preference<Attribute>(attribute, -pref)); 281 } 282 } 283 } 284 r.close(); 285 286 r = new BufferedReader(new FileReader(new File(dir, "hours_per_course.csv"))); 287 while ((line = r.readLine()) != null) { 288 if (line.trim().isEmpty()) 289 continue; 290 String[] fields = line.split(","); 291 for (TeachingRequest clazz : getRequests()) { 292 if (clazz.getCourse().getCourseName().contains(fields[0])) 293 clazz.setLoad(Float.parseFloat(fields[1])); 294 } 295 } 296 297 String defaultCode = getProperties().getProperty("TA.DefaultLevelCode", "XXX"); 298 Attribute defaultAttribute = code2attribute.get(defaultCode); 299 if (defaultAttribute == null) { 300 defaultAttribute = new Attribute(code2attribute.size(), defaultCode, level); 301 code2attribute.put(defaultCode, defaultAttribute); 302 } 303 for (TeachingRequest.Variable clazz : variables()) { 304 sLog.info("Added class " + toString(clazz)); 305 if (clazz.getRequest().getAttributePreferences().isEmpty()) { 306 sLog.error("No level: " + toString(clazz)); 307 clazz.getRequest().addAttributePreference(new Preference<Attribute>(defaultAttribute, -1)); 308 } 309 if (clazz.getRequest().getLoad() == 0.0) { 310 sLog.error("No load: " + toString(clazz)); 311 clazz.getRequest().setLoad(getProperties().getPropertyFloat("TA.DefaultLoad", 10f)); 312 } 313 } 314 r.close(); 315 316 r = new BufferedReader(new FileReader(new File(dir, "students.csv"))); 317 Set<String> studentIds = new HashSet<String>(); 318 double studentMaxLoad = 0.0; 319 while ((line = r.readLine()) != null) { 320 if (line.trim().isEmpty()) 321 continue; 322 String[] fields = line.split(","); 323 if ("puid".equals(fields[0])) 324 continue; 325 int idx = 0; 326 String id = fields[idx++]; 327 if (!studentIds.add(id)) { 328 sLog.error("Student " + id + " is two or more times in the file."); 329 } 330 boolean[] av = new boolean[50]; 331 for (int i = 0; i < 50; i++) 332 av[i] = "1".equals(fields[idx++]); 333 List<String> prefs = new ArrayList<String>(); 334 for (int i = 0; i < 3; i++) { 335 String p = fields[idx++].replace("Large lecture", "LEC").replace("Lecture", "LEC").replace("Recitation", "REC"); 336 if (p.startsWith("MA ")) 337 p = p.substring(3); 338 if ("I have no preference".equals(p)) 339 continue; 340 prefs.add(p); 341 } 342 boolean grad = "Yes".equals(fields[idx++]); 343 int b2b = Integer.parseInt(fields[idx++]); 344 float maxLoad = Float.parseFloat(fields[idx++]); 345 if (maxLoad == 0) 346 maxLoad = getProperties().getPropertyFloat("TA.DefaultMaxLoad", 20f); 347 String code = (idx < fields.length ? fields[idx++] : null); 348 Instructor instructor = new Instructor(Long.valueOf(id.replace("-","")), id, null, grad ? Constants.sPreferenceLevelNeutral : Constants.sPreferenceLevelDiscouraged, maxLoad); 349 for (int i = 0; i < prefs.size(); i++) { 350 String pref = prefs.get(i); 351 if (pref.indexOf(' ') > 0) pref = pref.substring(0, pref.indexOf(' ')); 352 Course c = courses.get(pref); 353 if (c == null) { 354 c = new Course(courses.size(), pref); 355 courses.put(pref, c); 356 } 357 instructor.addCoursePreference(new Preference<Course>(c, i == 0 ? -10 : i == 1 ? -8 : -5)); 358 } 359 if (code != null) { 360 Attribute attribute = code2attribute.get(code); 361 if (attribute == null) { 362 attribute = new Attribute(code2attribute.size(), code, level); 363 code2attribute.put(code, attribute); 364 } 365 instructor.addAttribute(attribute); 366 } 367 if (b2b == 1) 368 instructor.setBackToBackPreference(Constants.sPreferenceLevelPreferred); 369 else if (b2b == -1) 370 instructor.setBackToBackPreference(Constants.sPreferenceLevelDiscouraged); 371 for (int d = 0; d < 5; d++) { 372 int f = -1; 373 for (int t = 0; t < 10; t++) { 374 if (!av[10 * d + t]) { 375 if (f < 0) f = t; 376 } else { 377 if (f >= 0) { 378 instructor.addTimePreference(new Preference<TimeLocation>(new TimeLocation(Constants.DAY_CODES[d], 90 + 12 * f, (t - f) * 12, 0, 0.0, null, "", null, 0), Constants.sPreferenceLevelProhibited)); 379 f = -1; 380 } 381 } 382 } 383 if (f >= 0) { 384 instructor.addTimePreference(new Preference<TimeLocation>(new TimeLocation(Constants.DAY_CODES[d], 90 + 12 * f, (10 - f) * 12, 0, 0.0, null, "", null, 0), Constants.sPreferenceLevelProhibited)); 385 f = -1; 386 } 387 } 388 if (instructor.getMaxLoad() > 0) { 389 addInstructor(instructor); 390 sLog.info("Added student " + toString(instructor)); 391 int nrClasses = 0; 392 for (TeachingRequest.Variable req : variables()) { 393 if (instructor.canTeach(req.getRequest()) && !req.getRequest().getAttributePreference(instructor).isProhibited()) { 394 sLog.info(" -- " + toString(req) + "," + (-req.getRequest().getAttributePreference(instructor).getPreferenceInt()) + "," + (-instructor.getCoursePreference(req.getCourse()).getPreference())); 395 nrClasses++; 396 } 397 } 398 if (nrClasses == 0) { 399 sLog.info(" -- no courses available"); 400 } 401 studentMaxLoad += instructor.getMaxLoad(); 402 } else { 403 sLog.info("Ignoring student " + instructor); 404 if (instructor.getMaxLoad() == 0) 405 sLog.info(" -- zero max load"); 406 else 407 sLog.info(" -- no courses available"); 408 } 409 } 410 r.close(); 411 412 double totalLoad = 0.0; 413 for (TeachingRequest.Variable clazz : variables()) { 414 if (clazz.values(getEmptyAssignment()).isEmpty()) 415 sLog.error("No values: " + toString(clazz)); 416 totalLoad += clazz.getRequest().getLoad(); 417 } 418 419 Map<String, Double> studentLevel2load = new HashMap<String, Double>(); 420 for (Instructor instructor: getInstructors()) { 421 Set<Attribute> levels = instructor.getAttributes(level); 422 String studentLevel = (levels.isEmpty() ? "null" : levels.iterator().next().getAttributeName()); 423 Double load = studentLevel2load.get(studentLevel); 424 studentLevel2load.put(studentLevel, instructor.getMaxLoad() + (load == null ? 0.0 : load)); 425 } 426 sLog.info("Student max loads: (total: " + sDoubleFormat.format(studentMaxLoad) + ")"); 427 for (String studentLevel : new TreeSet<String>(studentLevel2load.keySet())) { 428 Double load = studentLevel2load.get(studentLevel); 429 sLog.info(" " + studentLevel + ": " + sDoubleFormat.format(load)); 430 } 431 Map<String, Double> clazzLevel2load = new HashMap<String, Double>(); 432 for (TeachingRequest.Variable clazz : variables()) { 433 String classLevel = null; 434 TreeSet<String> levels = new TreeSet<String>(); 435 for (Preference<Attribute> ap: clazz.getRequest().getAttributePreferences()) 436 levels.add(ap.getTarget().getAttributeName()); 437 for (String l : levels) { 438 classLevel = (classLevel == null ? "" : classLevel + ",") + l; 439 } 440 if (classLevel == null) 441 classLevel = "null"; 442 if (clazz.getId() < 0) 443 classLevel = clazz.getName(); 444 Double load = clazzLevel2load.get(classLevel); 445 clazzLevel2load.put(classLevel, clazz.getRequest().getLoad() + (load == null ? 0.0 : load)); 446 } 447 sLog.info("Class loads: (total: " + sDoubleFormat.format(totalLoad) + ")"); 448 for (String classLevel : new TreeSet<String>(clazzLevel2load.keySet())) { 449 Double load = clazzLevel2load.get(classLevel); 450 sLog.info(" " + level + ": " + sDoubleFormat.format(load)); 451 } 452 return true; 453 } catch (IOException e) { 454 sLog.error("Failed to load the problem: " + e.getMessage(), e); 455 return false; 456 } 457 } 458 459 @Override 460 protected void generateReports(File dir, Assignment<TeachingRequest.Variable, TeachingAssignment> assignment) throws IOException { 461 PrintWriter out = new PrintWriter(new File(dir, "solution-assignments.csv")); 462 out.println("Assignment Id,Course,Section,Time,Room,Link,Level,Load,Student,Availability,1st Preference,2nd Preference,3rd Preference,Graduate,Back-To-Back,Max Load,Level,Level,Preference"); 463 for (TeachingRequest.Variable request : variables()) { 464 Long assId = getAssignmentId(request); 465 out.print(assId == null ? "" : assId); 466 out.print("," + request.getCourse().getCourseName()); 467 Section section = request.getSections().get(0); 468 out.print("," + section.getSectionType()); 469 out.print("," + section.getTimeName(true)); 470 out.print(",\"" + (section.hasRoom() ? section.getRoom() : "") + "\""); 471 String link = getLink(request); 472 out.print("," + (link == null ? "" : link)); 473 Map<String, Integer> levels = new HashMap<String, Integer>(); 474 for (Preference<Attribute> p: request.getRequest().getAttributePreferences()) 475 if (p.getTarget().getType().getTypeName().equals("Level")) 476 levels.put(p.getTarget().getAttributeName(), - p.getPreference()); 477 out.print(",\"" + levels + "\""); 478 out.print("," + new DecimalFormat("0.0").format(request.getRequest().getLoad())); 479 TeachingAssignment value = assignment.getValue(request); 480 if (value != null) { 481 out.print("," + toString(value.getInstructor())); 482 out.print("," + (-value.getAttributePreference())); 483 out.print("," + (value.getCoursePreference() == -10 ? "1" : value.getCoursePreference() == -8 ? "2" : value.getCoursePreference() == -5 ? "3" : value.getCoursePreference())); 484 } 485 out.println(); 486 } 487 out.flush(); 488 out.close(); 489 490 out = new PrintWriter(new File(dir, "solution-students.csv")); 491 out.println("Student,Availability,1st Preference,2nd Preference,3rd Preference,Graduate,Back-To-Back,Max Load,Level,Assigned Load,Avg Level,Avg Preference,Back-To-Back,Diff Links,1st Assignment,2nd Assignment, 3rd Assignment"); 492 for (Instructor instructor: getInstructors()) { 493 out.print(instructor.getExternalId()); 494 out.print(",\"" + instructor.getAvailable() + "\""); 495 for (int i = 0; i < 3; i++) { 496 Preference<Course> p = (i < instructor.getCoursePreferences().size() ? instructor.getCoursePreferences().get(i) : null); 497 out.print("," + (p == null ? "" : p.getTarget().getCourseName())); 498 } 499 out.print("," + (instructor.getPreference() == 0 ? "Yes" : "No")); 500 out.print("," + (instructor.isBackToBackPreferred() ? "1" : instructor.isBackToBackDiscouraged() ? "-1" : "0")); 501 out.print("," + new DecimalFormat("0.0").format(instructor.getMaxLoad())); 502 String level = getLevel(instructor); 503 out.print("," + (level == null ? "" : level)); 504 Instructor.Context context = instructor.getContext(assignment); 505 out.print("," + new DecimalFormat("0.0").format(context.getLoad())); 506 double att = 0.0, pref = 0.0; 507 for (TeachingAssignment ta : context.getAssignments()) { 508 att += Math.abs(ta.getAttributePreference()); 509 pref += (ta.getCoursePreference() == -10 ? 1 : ta.getCoursePreference() == -8 ? 2 : ta.getCoursePreference() == -5 ? 3 : ta.getCoursePreference()); 510 } 511 int diffLinks = countDiffLinks(context.getAssignments()); 512 out.print("," + (context.getAssignments().isEmpty() ? "" : new DecimalFormat("0.0").format(att / context.getAssignments().size()))); 513 out.print("," + (context.getAssignments().isEmpty() || pref == 0.0 ? "" : new DecimalFormat("0.0").format(pref / context.getAssignments().size()))); 514 out.print("," + new DecimalFormat("0.0").format(100.0 * context.countBackToBackPercentage())); 515 out.print("," + (diffLinks <= 0 ? "" : diffLinks)); 516 for (TeachingAssignment ta : context.getAssignments()) { 517 String link = getLink(ta.variable()); 518 out.print("," + ta.variable().getCourse() + " " + ta.variable().getSections().get(0).getSectionType() + " " + ta.variable().getSections().get(0).getTime().getName(true) + (link == null ? "" : " " + link)); 519 } 520 out.println(); 521 } 522 out.flush(); 523 out.close(); 524 525 out = new PrintWriter(new File(dir, "input-courses.csv")); 526 Set<String> levels = new TreeSet<String>(); 527 for (TeachingRequest.Variable request : variables()) { 528 for (Preference<Attribute> p: request.getRequest().getAttributePreferences()) 529 levels.add(p.getTarget().getAttributeName()); 530 } 531 out.print("Course,Type,Load"); 532 for (String level: levels) 533 out.print("," + level); 534 out.println(); 535 Set<String> courses = new HashSet<String>(); 536 for (TeachingRequest.Variable request : variables()) { 537 if (courses.add(request.getCourse() + "," + request.getSections().get(0).getSectionType())) { 538 out.print(request.getCourse().getCourseName() + "," + request.getSections().get(0).getSectionType() + "," + request.getRequest().getLoad()); 539 for (String level: levels) { 540 int pref = 0; 541 for (Preference<Attribute> p: request.getRequest().getAttributePreferences()) 542 if (p.getTarget().getAttributeName().equals(level)) pref = p.getPreference(); 543 out.print("," + (pref == 0 ? "" : -pref)); 544 } 545 out.println(); 546 } 547 } 548 out.flush(); 549 out.close(); 550 } 551 552 public static void main(String[] args) throws Exception { 553 DataProperties config = new DataProperties(); 554 config.load(MathTest.class.getClass().getResourceAsStream("/org/cpsolver/instructor/test/math.properties")); 555 config.putAll(System.getProperties()); 556 ToolBox.configureLogging(); 557 558 new MathTest(config).execute(); 559 } 560}