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