001 package net.sf.cpsolver.coursett.constraint; 002 003 import java.util.ArrayList; 004 import java.util.BitSet; 005 import java.util.Enumeration; 006 import java.util.HashSet; 007 import java.util.List; 008 import java.util.Set; 009 010 import net.sf.cpsolver.coursett.Constants; 011 import net.sf.cpsolver.coursett.model.Lecture; 012 import net.sf.cpsolver.coursett.model.Placement; 013 import net.sf.cpsolver.coursett.model.TimeLocation; 014 import net.sf.cpsolver.coursett.model.TimetableModel; 015 import net.sf.cpsolver.ifs.model.Constraint; 016 import net.sf.cpsolver.ifs.util.DistanceMetric; 017 018 /** 019 * Instructor constraint. <br> 020 * Classes with this instructor can not overlap in time. Also, for back-to-back 021 * classes, there is the following reasoning: 022 * <ul> 023 * <li>if the distance is equal or below 024 * {@link DistanceMetric#getInstructorNoPreferenceLimit()} .. no preference 025 * <li>if the distance is above 026 * {@link DistanceMetric#getInstructorNoPreferenceLimit()} and below 027 * {@link DistanceMetric#getInstructorDiscouragedLimit()} .. constraint is 028 * discouraged (soft, preference = 1) 029 * <li>if the distance is above 030 * {@link DistanceMetric#getInstructorDiscouragedLimit()} and below 031 * {@link DistanceMetric#getInstructorProhibitedLimit()} .. constraint is 032 * strongly discouraged (soft, preference = 2) 033 * <li>if the distance is above 034 * {@link DistanceMetric#getInstructorProhibitedLimit()} .. constraint is 035 * prohibited (hard) 036 * </ul> 037 * <br> 038 * When {@link InstructorConstraint#isIgnoreDistances()} is set to true, the 039 * constraint never prohibits two back-to-back classes (but it still tries to 040 * minimize the above back-to-back preferences). 041 * 042 * @version CourseTT 1.2 (University Course Timetabling)<br> 043 * Copyright (C) 2006 - 2010 Tomas Muller<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 */ 061 062 public class InstructorConstraint extends Constraint<Lecture, Placement> { 063 064 public int iPreference = 0; 065 066 /** 067 * table iResource[slot] = lecture using this resource placed in the given 068 * time slot (null if empty) 069 */ 070 protected List<Placement>[] iResource; 071 private Long iResourceId; 072 private String iName; 073 private String iPuid; 074 private List<Placement>[] iAvailable = null; 075 private boolean iIgnoreDistances = false; 076 private Long iType = null; 077 078 /** 079 * Constructor 080 * 081 * @param id 082 * instructor id 083 * @param name 084 * instructor name 085 */ 086 @SuppressWarnings("unchecked") 087 public InstructorConstraint(Long id, String puid, String name, boolean ignDist) { 088 iResourceId = id; 089 iName = name; 090 iPuid = puid; 091 iIgnoreDistances = ignDist; 092 iResource = new List[Constants.SLOTS_PER_DAY * Constants.DAY_CODES.length]; 093 for (int i = 0; i < iResource.length; i++) 094 iResource[i] = new ArrayList<Placement>(3); 095 } 096 097 public List<Placement> getPlacements(int slot, Placement placement) { 098 return getPlacements(slot, placement.getTimeLocation().getWeekCode()); 099 } 100 101 public List<Placement> getPlacements(int slot, BitSet weekCode) { 102 List<Placement> placements = new ArrayList<Placement>(iResource[slot].size()); 103 for (Placement p : iResource[slot]) { 104 if (p.getTimeLocation().shareWeeks(weekCode)) 105 placements.add(p); 106 } 107 return placements; 108 } 109 110 public Placement getPlacement(int slot, int day) { 111 for (Placement p : iResource[slot]) { 112 if (p.getTimeLocation().hasDay(day)) 113 return p; 114 } 115 return null; 116 } 117 118 @SuppressWarnings("unchecked") 119 public void setNotAvailable(Placement placement) { 120 if (iAvailable == null) { 121 iAvailable = new List[Constants.SLOTS_PER_DAY * Constants.DAY_CODES.length]; 122 for (int i = 0; i < iResource.length; i++) 123 iAvailable[i] = null; 124 } 125 for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) { 126 int slot = e.nextElement(); 127 if (iAvailable[slot] == null) 128 iAvailable[slot] = new ArrayList<Placement>(1); 129 iAvailable[slot].add(placement); 130 } 131 } 132 133 public boolean isAvailable(int slot) { 134 if (iAvailable == null) 135 return true; 136 return (iAvailable[slot] == null || iAvailable[slot].isEmpty()); 137 } 138 139 public boolean isAvailable(Lecture lecture, TimeLocation time) { 140 if (iAvailable == null) 141 return true; 142 for (Enumeration<Integer> e = time.getSlots(); e.hasMoreElements();) { 143 int slot = e.nextElement().intValue(); 144 if (iAvailable[slot] != null) { 145 for (Placement p : iAvailable[slot]) { 146 if (lecture.canShareRoom(p.variable())) 147 continue; 148 if (time.shareWeeks(p.getTimeLocation())) 149 return false; 150 } 151 } 152 } 153 return true; 154 } 155 156 private DistanceMetric getDistanceMetric() { 157 return ((TimetableModel)getModel()).getDistanceMetric(); 158 } 159 160 public boolean isAvailable(Lecture lecture, Placement placement) { 161 if (iAvailable == null) 162 return true; 163 for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) { 164 int slot = e.nextElement(); 165 if (iAvailable[slot] != null) { 166 for (Placement p : iAvailable[slot]) { 167 if (lecture.canShareRoom(p.variable()) && placement.sameRooms(p)) 168 continue; 169 if (placement.getTimeLocation().shareWeeks(p.getTimeLocation())) 170 return false; 171 } 172 } 173 } 174 if (!iIgnoreDistances) { 175 for (Enumeration<Integer> e = placement.getTimeLocation().getStartSlots(); e.hasMoreElements();) { 176 int startSlot = e.nextElement(); 177 int prevSlot = startSlot - 1; 178 if (prevSlot >= 0 && (prevSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 179 if (iAvailable[prevSlot] != null) { 180 for (Placement p : iAvailable[prevSlot]) { 181 if (lecture.canShareRoom(p.variable()) && placement.sameRooms(p)) 182 continue; 183 if (placement.getTimeLocation().shareWeeks(p.getTimeLocation()) 184 && Placement.getDistanceInMeters(getDistanceMetric(), p, placement) > getDistanceMetric().getInstructorProhibitedLimit()) 185 return false; 186 } 187 } 188 } 189 int nextSlot = startSlot + placement.getTimeLocation().getLength(); 190 if ((nextSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 191 if (iAvailable[nextSlot] != null) { 192 for (Placement p : iAvailable[nextSlot]) { 193 if (lecture.canShareRoom(p.variable()) && placement.sameRooms(p)) 194 continue; 195 if (placement.getTimeLocation().shareWeeks(p.getTimeLocation()) 196 && Placement.getDistanceInMeters(getDistanceMetric(), p, placement) > getDistanceMetric().getInstructorProhibitedLimit()) 197 return false; 198 } 199 } 200 } 201 } 202 } 203 return true; 204 } 205 206 public List<Placement>[] getAvailableArray() { 207 return iAvailable; 208 } 209 210 /** Back-to-back preference of two placements (3 means prohibited) */ 211 public int getDistancePreference(Placement p1, Placement p2) { 212 if (!p1.getTimeLocation().shareDays(p2.getTimeLocation())) 213 return 0; 214 if (!p1.getTimeLocation().shareWeeks(p2.getTimeLocation())) 215 return 0; 216 int s1 = p1.getTimeLocation().getStartSlot() % Constants.SLOTS_PER_DAY; 217 int s2 = p2.getTimeLocation().getStartSlot() % Constants.SLOTS_PER_DAY; 218 if (s1 + p1.getTimeLocation().getLength() != s2 && s2 + p2.getTimeLocation().getLength() != s1) 219 return 0; 220 double distance = Placement.getDistanceInMeters(getDistanceMetric(), p1, p2); 221 if (distance <= getDistanceMetric().getInstructorNoPreferenceLimit()) 222 return Constants.sPreferenceLevelNeutral; 223 if (distance <= getDistanceMetric().getInstructorDiscouragedLimit()) 224 return Constants.sPreferenceLevelDiscouraged; 225 if (iIgnoreDistances || distance <= getDistanceMetric().getInstructorProhibitedLimit()) 226 return Constants.sPreferenceLevelStronglyDiscouraged; 227 return Constants.sPreferenceLevelProhibited; 228 } 229 230 /** Resource id */ 231 public Long getResourceId() { 232 return iResourceId; 233 } 234 235 /** Resource name */ 236 @Override 237 public String getName() { 238 return iName; 239 } 240 241 @Override 242 public void computeConflicts(Placement placement, Set<Placement> conflicts) { 243 Lecture lecture = placement.variable(); 244 BitSet weekCode = placement.getTimeLocation().getWeekCode(); 245 246 for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) { 247 int slot = e.nextElement(); 248 for (Placement p : iResource[slot]) { 249 if (!p.equals(lecture.getAssignment()) && p.getTimeLocation().shareWeeks(weekCode)) { 250 if (p.canShareRooms(placement) && p.sameRooms(placement)) 251 continue; 252 conflicts.add(p); 253 } 254 } 255 } 256 if (!iIgnoreDistances) { 257 for (Enumeration<Integer> e = placement.getTimeLocation().getStartSlots(); e.hasMoreElements();) { 258 int startSlot = e.nextElement(); 259 int prevSlot = startSlot - 1; 260 if (prevSlot >= 0 && (prevSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 261 List<Placement> conf = getPlacements(prevSlot, placement); 262 for (Placement c : conf) { 263 if (lecture.equals(c.variable())) 264 continue; 265 if (Placement.getDistanceInMeters(getDistanceMetric(), placement, c) > getDistanceMetric().getInstructorProhibitedLimit()) { 266 if (c.canShareRooms(placement) && c.sameRooms(placement)) 267 continue; 268 conflicts.add(c); 269 } 270 } 271 } 272 int nextSlot = startSlot + placement.getTimeLocation().getLength(); 273 if ((nextSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 274 List<Placement> conf = getPlacements(nextSlot, placement); 275 for (Placement c : conf) { 276 if (lecture.equals(c.variable())) 277 continue; 278 if (Placement.getDistanceInMeters(getDistanceMetric(), placement, c) > getDistanceMetric().getInstructorProhibitedLimit()) { 279 if (c.canShareRooms(placement) && c.sameRooms(placement)) 280 continue; 281 conflicts.add(c); 282 } 283 } 284 } 285 } 286 } 287 } 288 289 @Override 290 public boolean inConflict(Placement placement) { 291 Lecture lecture = placement.variable(); 292 BitSet weekCode = placement.getTimeLocation().getWeekCode(); 293 for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) { 294 int slot = e.nextElement(); 295 for (Placement p : iResource[slot]) { 296 if (!p.equals(lecture.getAssignment()) && p.getTimeLocation().shareWeeks(weekCode)) { 297 if (p.canShareRooms(placement) && p.sameRooms(placement)) 298 continue; 299 return true; 300 } 301 } 302 } 303 if (!iIgnoreDistances) { 304 for (Enumeration<Integer> e = placement.getTimeLocation().getStartSlots(); e.hasMoreElements();) { 305 int startSlot = e.nextElement(); 306 int prevSlot = startSlot - 1; 307 if (prevSlot >= 0 && (prevSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 308 List<Placement> conf = getPlacements(prevSlot, placement); 309 for (Placement c : conf) { 310 if (lecture.equals(c.variable())) 311 continue; 312 if (Placement.getDistanceInMeters(getDistanceMetric(), placement, c) > getDistanceMetric().getInstructorProhibitedLimit()) { 313 if (c.canShareRooms(placement) && c.sameRooms(placement)) 314 continue; 315 return true; 316 } 317 } 318 } 319 int nextSlot = startSlot + placement.getTimeLocation().getLength(); 320 if ((nextSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 321 List<Placement> conf = getPlacements(nextSlot, placement); 322 for (Placement c : conf) { 323 if (lecture.equals(c.variable())) 324 continue; 325 if (Placement.getDistanceInMeters(getDistanceMetric(), placement, c) > getDistanceMetric().getInstructorProhibitedLimit()) { 326 if (c.canShareRooms(placement) && c.sameRooms(placement)) 327 continue; 328 return true; 329 } 330 } 331 } 332 } 333 } 334 return false; 335 } 336 337 @Override 338 public boolean isConsistent(Placement p1, Placement p2) { 339 if (p1.canShareRooms(p2) && p1.sameRooms(p2)) 340 return true; 341 if (p1.getTimeLocation().hasIntersection(p2.getTimeLocation())) 342 return false; 343 return getDistancePreference(p1, p2) != Constants.sPreferenceLevelProhibited; 344 } 345 346 @Override 347 public void assigned(long iteration, Placement placement) { 348 super.assigned(iteration, placement); 349 iPreference += getPreference(placement); 350 for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) { 351 int slot = e.nextElement(); 352 iResource[slot].add(placement); 353 } 354 } 355 356 @Override 357 public void unassigned(long iteration, Placement placement) { 358 super.unassigned(iteration, placement); 359 iPreference -= getPreference(placement); 360 for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) { 361 int slot = e.nextElement(); 362 iResource[slot].remove(placement); 363 } 364 } 365 366 /** 367 * Lookup table getResource()[slot] -> lecture using this resource placed in 368 * the given time slot (null if empty) 369 */ 370 public List<Placement> getResource(int slot) { 371 return iResource[slot]; 372 } 373 374 public Placement[] getResourceOfWeek(int startDay) { 375 Placement[] ret = new Placement[iResource.length]; 376 for (int i = 0; i < iResource.length; i++) { 377 ret[i] = getPlacement(i, startDay + (i / Constants.SLOTS_PER_DAY)); 378 } 379 return ret; 380 } 381 382 /** Number of useless slots for this resource */ 383 public int countUselessSlots() { 384 int ret = 0; 385 for (int d = 0; d < Constants.DAY_CODES.length; d++) { 386 for (int s = 1; s < Constants.SLOTS_PER_DAY - 1; s++) { 387 int slot = d * Constants.SLOTS_PER_DAY + s; 388 if (iResource[slot - 1] != null && iResource[slot] == null && iResource[slot + 1] != null) 389 ret++; 390 } 391 } 392 return ret; 393 } 394 395 /** Resource usage usage */ 396 protected void printUsage(StringBuffer sb) { 397 for (int slot = 0; slot < iResource.length; slot++) { 398 for (Placement p : iResource[slot]) { 399 int day = slot / Constants.SLOTS_PER_DAY; 400 int time = slot * Constants.SLOT_LENGTH_MIN + Constants.FIRST_SLOT_TIME_MIN; 401 int h = time / 60; 402 int m = time % 60; 403 String d = Constants.DAY_NAMES_SHORT[day]; 404 int slots = p.getTimeLocation().getLength(); 405 time += (30 * slots); 406 int h2 = time / 60; 407 int m2 = time % 60; 408 sb.append(sb.length() == 0 ? "" : ",\n ").append( 409 "[" + d + (h > 12 ? h - 12 : h) + ":" + (m < 10 ? "0" : "") + m + (h >= 12 ? "p" : "a") + "-" 410 + (h2 > 12 ? h2 - 12 : h2) + ":" + (m2 < 10 ? "0" : "") + m2 + (h2 >= 12 ? "p" : "a") 411 + "]=").append(p.variable().getName()); 412 slot += slots - 1; 413 // sb.append(sb.length()==0?"":", ").append("s"+(slot+1)+"=").append(((Lecture)getResource()[slot]).getName()); 414 } 415 } 416 } 417 418 @Override 419 public String toString() { 420 return "Instructor " + getName(); 421 } 422 423 /** Back-to-back preference of the given placement */ 424 public int getPreference(Placement value) { 425 Lecture lecture = value.variable(); 426 Placement placement = value; 427 int pref = 0; 428 HashSet<Placement> used = new HashSet<Placement>(); 429 for (Enumeration<Integer> e = placement.getTimeLocation().getStartSlots(); e.hasMoreElements();) { 430 int startSlot = e.nextElement(); 431 int prevSlot = startSlot - 1; 432 if (prevSlot >= 0 && (prevSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 433 List<Placement> conf = getPlacements(prevSlot, placement); 434 for (Placement c : conf) { 435 if (lecture.equals(c.variable())) 436 continue; 437 if (!used.add(c)) 438 continue; 439 double dist = Placement.getDistanceInMeters(getDistanceMetric(), placement, c); 440 if (dist > getDistanceMetric().getInstructorNoPreferenceLimit() && dist <= getDistanceMetric().getInstructorDiscouragedLimit()) 441 pref += Constants.sPreferenceLevelDiscouraged; 442 if (dist > getDistanceMetric().getInstructorDiscouragedLimit() 443 && (dist <= getDistanceMetric().getInstructorProhibitedLimit() || iIgnoreDistances)) 444 pref += Constants.sPreferenceLevelStronglyDiscouraged; 445 if (!iIgnoreDistances && dist > getDistanceMetric().getInstructorProhibitedLimit()) 446 pref += Constants.sPreferenceLevelProhibited; 447 } 448 } 449 int nextSlot = startSlot + placement.getTimeLocation().getLength(); 450 if ((nextSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 451 List<Placement> conf = getPlacements(nextSlot, placement); 452 for (Placement c : conf) { 453 if (lecture.equals(c.variable())) 454 continue; 455 if (!used.add(c)) 456 continue; 457 double dist = Placement.getDistanceInMeters(getDistanceMetric(), placement, c); 458 if (dist > getDistanceMetric().getInstructorNoPreferenceLimit() && dist <= getDistanceMetric().getInstructorDiscouragedLimit()) 459 pref += Constants.sPreferenceLevelDiscouraged; 460 if (dist > getDistanceMetric().getInstructorDiscouragedLimit() 461 && (dist <= getDistanceMetric().getInstructorProhibitedLimit() || iIgnoreDistances)) 462 pref += Constants.sPreferenceLevelStronglyDiscouraged; 463 if (!iIgnoreDistances && dist > getDistanceMetric().getInstructorProhibitedLimit()) 464 pref = Constants.sPreferenceLevelProhibited; 465 } 466 } 467 } 468 return pref; 469 } 470 471 public int getPreferenceCombination(Placement value) { 472 Lecture lecture = value.variable(); 473 Placement placement = value; 474 int pref = 0; 475 HashSet<Placement> used = new HashSet<Placement>(); 476 for (Enumeration<Integer> e = placement.getTimeLocation().getStartSlots(); e.hasMoreElements();) { 477 int startSlot = e.nextElement(); 478 int prevSlot = startSlot - 1; 479 if (prevSlot >= 0 && (prevSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 480 List<Placement> conf = getPlacements(prevSlot, placement); 481 for (Placement c : conf) { 482 if (lecture.equals(c.variable())) 483 continue; 484 if (!used.add(c)) 485 continue; 486 double dist = Placement.getDistanceInMeters(getDistanceMetric(), placement, c); 487 if (dist > getDistanceMetric().getInstructorNoPreferenceLimit() && dist <= getDistanceMetric().getInstructorDiscouragedLimit()) 488 pref = Math.max(pref, Constants.sPreferenceLevelDiscouraged); 489 if (dist > getDistanceMetric().getInstructorDiscouragedLimit() 490 && (dist <= getDistanceMetric().getInstructorProhibitedLimit() || iIgnoreDistances)) 491 pref = Math.max(pref, Constants.sPreferenceLevelStronglyDiscouraged); 492 if (!iIgnoreDistances && dist > getDistanceMetric().getInstructorProhibitedLimit()) 493 pref = Math.max(pref, Constants.sPreferenceLevelProhibited); 494 } 495 } 496 int nextSlot = startSlot + placement.getTimeLocation().getLength(); 497 if ((nextSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) { 498 List<Placement> conf = getPlacements(nextSlot, placement); 499 for (Placement c : conf) { 500 if (lecture.equals(c.variable())) 501 continue; 502 if (!used.add(c)) 503 continue; 504 double dist = Placement.getDistanceInMeters(getDistanceMetric(), placement, c); 505 if (dist > getDistanceMetric().getInstructorNoPreferenceLimit() && dist <= getDistanceMetric().getInstructorDiscouragedLimit()) 506 pref = Math.max(pref, Constants.sPreferenceLevelDiscouraged); 507 if (dist > getDistanceMetric().getInstructorDiscouragedLimit() 508 && (dist <= getDistanceMetric().getInstructorProhibitedLimit() || iIgnoreDistances)) 509 pref = Math.max(pref, Constants.sPreferenceLevelStronglyDiscouraged); 510 if (!iIgnoreDistances && dist > getDistanceMetric().getInstructorProhibitedLimit()) 511 pref = Math.max(pref, Constants.sPreferenceLevelProhibited); 512 } 513 } 514 } 515 return pref; 516 } 517 518 /** Overall back-to-back preference of this instructor */ 519 public int getPreference() { 520 /* 521 * if (iPreference!=countPreference()) {System.err.println( 522 * "InstructorConstraint.getPreference() is not working properly"); } 523 */ 524 return iPreference; 525 } 526 527 public int countPreference() { 528 int pref = 0; 529 HashSet<Placement> used = new HashSet<Placement>(); 530 for (int slot = 1; slot < iResource.length; slot++) { 531 if ((slot % Constants.SLOTS_PER_DAY) == 0) 532 continue; 533 for (Placement placement : iResource[slot]) { 534 List<Placement> prevPlacements = getPlacements(slot - 1, placement); 535 for (Placement prevPlacement : prevPlacements) { 536 if (!used.add(prevPlacement)) 537 continue; 538 double dist = Placement.getDistanceInMeters(getDistanceMetric(), prevPlacement, placement); 539 if (dist > getDistanceMetric().getInstructorNoPreferenceLimit() && dist <= getDistanceMetric().getInstructorDiscouragedLimit()) 540 pref += Constants.sPreferenceLevelDiscouraged; 541 if (dist > getDistanceMetric().getInstructorDiscouragedLimit()) 542 pref += Constants.sPreferenceLevelStronglyDiscouraged; 543 } 544 } 545 } 546 return pref; 547 } 548 549 /** Worst back-to-back preference of this instructor */ 550 public int getWorstPreference() { 551 return Constants.sPreferenceLevelStronglyDiscouraged * (variables().size() - 1); 552 } 553 554 public String getPuid() { 555 return iPuid; 556 } 557 558 public boolean isIgnoreDistances() { 559 return iIgnoreDistances; 560 } 561 562 public void setIgnoreDistances(boolean ignDist) { 563 iIgnoreDistances = ignDist; 564 } 565 566 public Long getType() { 567 return iType; 568 } 569 570 public void setType(Long type) { 571 iType = type; 572 } 573 }