diff --git a/optaplanner-examples/data/conferencescheduling/unsolved/108talks-18timeslots-10rooms.xlsx b/optaplanner-examples/data/conferencescheduling/unsolved/108talks-18timeslots-10rooms.xlsx index 6d99c7a404..7f6a04dd84 100644 Binary files a/optaplanner-examples/data/conferencescheduling/unsolved/108talks-18timeslots-10rooms.xlsx and b/optaplanner-examples/data/conferencescheduling/unsolved/108talks-18timeslots-10rooms.xlsx differ diff --git a/optaplanner-examples/data/conferencescheduling/unsolved/18talks-6timeslots-5rooms.xlsx b/optaplanner-examples/data/conferencescheduling/unsolved/18talks-6timeslots-5rooms.xlsx index 444b885047..987c16a472 100644 Binary files a/optaplanner-examples/data/conferencescheduling/unsolved/18talks-6timeslots-5rooms.xlsx and b/optaplanner-examples/data/conferencescheduling/unsolved/18talks-6timeslots-5rooms.xlsx differ diff --git a/optaplanner-examples/data/conferencescheduling/unsolved/216talks-18timeslots-20rooms.xlsx b/optaplanner-examples/data/conferencescheduling/unsolved/216talks-18timeslots-20rooms.xlsx index bac36814cf..fcab2ed440 100644 Binary files a/optaplanner-examples/data/conferencescheduling/unsolved/216talks-18timeslots-20rooms.xlsx and b/optaplanner-examples/data/conferencescheduling/unsolved/216talks-18timeslots-20rooms.xlsx differ diff --git a/optaplanner-examples/data/conferencescheduling/unsolved/36talks-12timeslots-5rooms.xlsx b/optaplanner-examples/data/conferencescheduling/unsolved/36talks-12timeslots-5rooms.xlsx index f60c9c716f..6441d0eb10 100644 Binary files a/optaplanner-examples/data/conferencescheduling/unsolved/36talks-12timeslots-5rooms.xlsx and b/optaplanner-examples/data/conferencescheduling/unsolved/36talks-12timeslots-5rooms.xlsx differ diff --git a/optaplanner-examples/data/conferencescheduling/unsolved/72talks-12timeslots-10rooms.xlsx b/optaplanner-examples/data/conferencescheduling/unsolved/72talks-12timeslots-10rooms.xlsx index 14d51f579f..ea7910a09a 100644 Binary files a/optaplanner-examples/data/conferencescheduling/unsolved/72talks-12timeslots-10rooms.xlsx and b/optaplanner-examples/data/conferencescheduling/unsolved/72talks-12timeslots-10rooms.xlsx differ diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporter.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporter.java index 4bc80bc5bc..e0fe4527a1 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporter.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporter.java @@ -19,13 +19,10 @@ import java.io.File; import java.math.BigInteger; import java.math.RoundingMode; -import java.util.Arrays; import com.google.common.math.BigIntegerMath; import org.optaplanner.core.api.domain.solution.PlanningSolution; import org.optaplanner.examples.common.app.LoggingMain; -import org.optaplanner.examples.common.business.ProblemFileComparator; -import org.optaplanner.persistence.common.api.domain.solution.SolutionFileIO; /** * @param the solution type, the class with the {@link PlanningSolution} annotation @@ -49,18 +46,18 @@ public boolean isInputFileDirectory() { public static abstract class InputBuilder extends LoggingMain { - public static BigInteger factorial(int base) { - if (base > 100000) { - // Calculation takes too long - return null; - } - BigInteger value = BigInteger.ONE; - for (int i = 1; i <= base; i++) { - value = value.multiply(BigInteger.valueOf(i)); - } - return value; - } + } + public static BigInteger factorial(int base) { + if (base > 100000) { + // Calculation takes too long + return null; + } + BigInteger value = BigInteger.ONE; + for (int i = 1; i <= base; i++) { + value = value.multiply(BigInteger.valueOf(i)); + } + return value; } public static String getFlooredPossibleSolutionSize(BigInteger possibleSolutionSize) { diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/AbstractXslxSolutionFileIO.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/AbstractXslxSolutionFileIO.java new file mode 100644 index 0000000000..012ad96489 --- /dev/null +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/AbstractXslxSolutionFileIO.java @@ -0,0 +1,382 @@ +/* + * Copyright 2018 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.optaplanner.examples.common.persistence; + +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.regex.Pattern; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.optaplanner.core.api.score.constraint.ConstraintMatchTotal; +import org.optaplanner.core.api.score.constraint.Indictment; +import org.optaplanner.core.api.solver.SolverFactory; +import org.optaplanner.core.impl.score.director.ScoreDirector; +import org.optaplanner.core.impl.score.director.ScoreDirectorFactory; +import org.optaplanner.persistence.common.api.domain.solution.SolutionFileIO; +import org.optaplanner.swing.impl.TangoColorFactory; + +public abstract class AbstractXslxSolutionFileIO implements SolutionFileIO { + + protected static final Pattern VALID_TAG_PATTERN = Pattern.compile("(?U)^[\\w&\\-\\.\\/\\(\\)\\'][\\w&\\-\\.\\/\\(\\)\\' ]*[\\w&\\-\\.\\/\\(\\)\\']?$"); + protected static final Pattern VALID_NAME_PATTERN = AbstractXslxSolutionFileIO.VALID_TAG_PATTERN; + protected static final Pattern VALID_CODE_PATTERN = Pattern.compile("(?U)^[\\w\\-\\.\\/\\(\\)]+$"); + + protected static final DateTimeFormatter DAY_FORMATTER + = DateTimeFormatter.ofPattern("E yyyy-MM-dd", Locale.ENGLISH); + protected static final DateTimeFormatter TIME_FORMATTER + = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH); + + protected static final XSSFColor VIEW_TAB_COLOR = new XSSFColor(TangoColorFactory.BUTTER_1); + protected static final XSSFColor UNAVAILABLE_COLOR = new XSSFColor(TangoColorFactory.ALUMINIUM_5); + protected static final XSSFColor PINNED_COLOR = new XSSFColor(TangoColorFactory.PLUM_1); + protected static final XSSFColor HARD_PENALTY_COLOR = new XSSFColor(TangoColorFactory.SCARLET_1); + protected static final XSSFColor SOFT_PENALTY_COLOR = new XSSFColor(TangoColorFactory.ORANGE_1); + + @Override + public String getInputFileExtension() { + return "xlsx"; + } + + public static abstract class AbstractXslxReader { + + protected final XSSFWorkbook workbook; + + protected Solution_ solution; + + protected XSSFSheet currentSheet; + protected Iterator currentRowIterator; + protected XSSFRow currentRow; + protected int currentRowNumber; + protected int currentColumnNumber; + + public AbstractXslxReader(XSSFWorkbook workbook) { + this.workbook = workbook; + } + + public abstract Solution_ read(); + + protected void readConstraintLine(String name, Consumer consumer, String constraintdescription) { + nextRow(); + readHeaderCell(name); + XSSFCell weightCell = nextCell(); + if (consumer != null) { + if (weightCell.getCellTypeEnum() != CellType.NUMERIC) { + throw new IllegalArgumentException(currentPosition() + ": The value (" + + weightCell.getStringCellValue() + + ") for constraint (" + name + ") must be a number and the cell type must be numeric."); + } + double value = weightCell.getNumericCellValue(); + if (((double) ((int) value)) != value) { + throw new IllegalArgumentException(currentPosition() + ": The value (" + value + + ") for constraint (" + name + ") must be an integer."); + } + consumer.accept((int) value); + } else { + if (weightCell.getCellTypeEnum() == CellType.NUMERIC + || !weightCell.getStringCellValue().equals("n/a")) { + throw new IllegalArgumentException(currentPosition() + ": The value (" + + weightCell.getStringCellValue() + + ") for constraint (" + name + ") must be an n/a."); + } + } + readHeaderCell(constraintdescription); + } + + protected String currentPosition() { + return "Sheet (" + currentSheet.getSheetName() + ") cell (" + + (currentRowNumber + 1) + CellReference.convertNumToColString(currentColumnNumber) + ")"; + } + + protected void nextSheet(String sheetName) { + currentSheet = workbook.getSheet(sheetName); + if (currentSheet == null) { + throw new IllegalStateException("The workbook does not contain a sheet with name (" + + sheetName + ")."); + } + currentRowIterator = currentSheet.rowIterator(); + if (currentRowIterator == null) { + throw new IllegalStateException(currentPosition() + ": The sheet has no rows."); + } + currentRowNumber = -1; + } + + protected boolean nextRow() { + return nextRow(true); + } + + protected boolean nextRow(boolean skipEmptyRows) { + currentRowNumber++; + currentColumnNumber = -1; + if (!currentRowIterator.hasNext()) { + currentRow = null; + return false; + } + currentRow = (XSSFRow) currentRowIterator.next(); + while (skipEmptyRows && currentRowIsEmpty()) { + if (!currentRowIterator.hasNext()) { + currentRow = null; + return false; + } + currentRow = (XSSFRow) currentRowIterator.next(); + } + if (currentRow.getRowNum() != currentRowNumber) { + if (currentRow.getRowNum() == currentRowNumber + 1) { + currentRowNumber++; + } else { + throw new IllegalStateException(currentPosition() + ": The next row (" + currentRow.getRowNum() + + ") has a gap of more than 1 empty line with the previous."); + } + } + return true; + } + + protected boolean currentRowIsEmpty() { + if (currentRow.getPhysicalNumberOfCells() == 0) { + return true; + } + for (Cell cell : currentRow) { + if (cell.getCellTypeEnum() == CellType.STRING) { + if (!cell.getStringCellValue().isEmpty()) { + return false; + } + } else if (cell.getCellTypeEnum() != CellType.BLANK) { + return false; + } + } + return true; + } + + protected void readHeaderCell(String value) { + XSSFCell cell = currentRow == null ? null : nextStringCell(); + if (cell == null || !cell.getStringCellValue().equals(value)) { + throw new IllegalStateException(currentPosition() + ": The cell does not contain the expected value (" + + value + ")."); + } + } + + protected XSSFCell nextStringCell() { + XSSFCell cell = nextCell(); + if (cell.getCellTypeEnum() == CellType.NUMERIC) { + throw new IllegalStateException(currentPosition() + ": The cell with value (" + + cell.getNumericCellValue() + ") has a numeric type but should be a string."); + } + return cell; + } + + protected XSSFCell nextNumericCell() { + XSSFCell cell = nextCell(); + if (cell.getCellTypeEnum() == CellType.STRING) { + throw new IllegalStateException(currentPosition() + ": The cell with value (" + + cell.getStringCellValue() + ") has a string type but should be numeric."); + } + return cell; + } + + protected XSSFCell nextBooleanCell() { + XSSFCell cell = nextCell(); + if (cell.getCellTypeEnum() == CellType.STRING) { + throw new IllegalStateException(currentPosition() + ": The cell with value (" + + cell.getStringCellValue() + ") has a string type but should be boolean."); + } + if (cell.getCellTypeEnum() == CellType.NUMERIC) { + throw new IllegalStateException(currentPosition() + ": The cell with value (" + + cell.getNumericCellValue() + ") has a numeric type but should be a boolean."); + } + return cell; + } + + protected XSSFCell nextCell() { + currentColumnNumber++; + XSSFCell cell = currentRow.getCell(currentColumnNumber); + // TODO HACK to workaround the fact that LibreOffice and Excel automatically remove empty trailing cells + if (cell == null) { + // Return dummy cell + return currentRow.createCell(currentColumnNumber); + } + return cell; + } + + protected XSSFColor extractColor(XSSFCell cell, XSSFColor... acceptableColors) { + XSSFCellStyle cellStyle = cell.getCellStyle(); + FillPatternType fillPattern = cellStyle.getFillPatternEnum(); + if (fillPattern == null || fillPattern == FillPatternType.NO_FILL) { + return null; + } + if (fillPattern != FillPatternType.SOLID_FOREGROUND) { + throw new IllegalStateException(currentPosition() + ": The fill pattern (" + fillPattern + + ") should be either " + FillPatternType.NO_FILL + + " or " + FillPatternType.SOLID_FOREGROUND + "."); + } + XSSFColor color = cellStyle.getFillForegroundColorColor(); + for (XSSFColor acceptableColor : acceptableColors) { + if (acceptableColor.equals(color)) { + return acceptableColor; + } + } + throw new IllegalStateException(currentPosition() + ": The fill color (" + color + + ") is not one of the acceptableColors (" + Arrays.toString(acceptableColors) + ")."); + } + + } + + public static abstract class AbstractXlsxWriter { + + protected final Solution_ solution; + protected final List constraintMatchTotalList; + protected final Map indictmentMap; + + protected XSSFWorkbook workbook; + protected CreationHelper creationHelper; + + protected XSSFCellStyle headerStyle; + protected XSSFCellStyle defaultStyle; + protected XSSFCellStyle unavailableStyle; + protected XSSFCellStyle pinnedStyle; + protected XSSFCellStyle hardPenaltyStyle; + protected XSSFCellStyle softPenaltyStyle; + protected XSSFCellStyle wrappedStyle; + + protected XSSFSheet currentSheet; + protected Drawing currentDrawing; + protected XSSFRow currentRow; + protected int currentRowNumber; + protected int currentColumnNumber; + protected int headerCellCount; + + public AbstractXlsxWriter(Solution_ solution, String solverConfigResource) { + this.solution = solution; + ScoreDirectorFactory scoreDirectorFactory + = SolverFactory.createFromXmlResource(solverConfigResource) + .buildSolver().getScoreDirectorFactory(); + try (ScoreDirector scoreDirector = scoreDirectorFactory.buildScoreDirector()) { + scoreDirector.setWorkingSolution(solution); + scoreDirector.calculateScore(); + constraintMatchTotalList = new ArrayList<>(scoreDirector.getConstraintMatchTotals()); + constraintMatchTotalList.sort(Comparator.comparing(ConstraintMatchTotal::getScore)); + indictmentMap = scoreDirector.getIndictmentMap(); + } + } + + public abstract Workbook write(); + + public void writeSetup() { + workbook = new XSSFWorkbook(); + creationHelper = workbook.getCreationHelper(); + createStyles(); + } + + protected void createStyles() { + headerStyle = createStyle(null); + Font font = workbook.createFont(); + font.setBold(true); + headerStyle.setFont(font); + defaultStyle = createStyle(null); + unavailableStyle = createStyle(UNAVAILABLE_COLOR); + pinnedStyle = createStyle(PINNED_COLOR); + hardPenaltyStyle = createStyle(HARD_PENALTY_COLOR); + softPenaltyStyle = createStyle(SOFT_PENALTY_COLOR); + wrappedStyle = createStyle(null); + } + + protected XSSFCellStyle createStyle(XSSFColor color) { + XSSFCellStyle style = workbook.createCellStyle(); + if (color != null) { + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setFillForegroundColor(color); + } + style.setWrapText(true); + style.setVerticalAlignment(VerticalAlignment.CENTER); + return style; + } + + protected void writeConstraintLine(String name, Supplier supplier, String constraintdescription) { + nextRow(); + nextHeaderCell(name); + XSSFCell weightCell = nextCell(); + if (supplier != null) { + weightCell.setCellValue(supplier.get()); + } else { + weightCell.setCellValue("n/a"); + } + nextHeaderCell(constraintdescription); + } + + protected void nextSheet(String sheetName, int colSplit, int rowSplit, boolean view) { + currentSheet = workbook.createSheet(sheetName); + currentDrawing = currentSheet.createDrawingPatriarch(); + currentSheet.createFreezePane(colSplit, rowSplit); + currentRowNumber = -1; + headerCellCount = 0; + if (view) { + currentSheet.setTabColor(VIEW_TAB_COLOR); + } + } + + protected void nextRow() { + currentRowNumber++; + currentRow = currentSheet.createRow(currentRowNumber); + currentColumnNumber = -1; + } + + protected void nextHeaderCell(String value) { + nextCell(headerStyle).setCellValue(value); + headerCellCount++; + } + + protected XSSFCell nextCell() { + return nextCell(defaultStyle); + } + + protected XSSFCell nextCell(XSSFCellStyle cellStyle) { + currentColumnNumber++; + XSSFCell cell = currentRow.createCell(currentColumnNumber); + cell.setCellStyle(cellStyle); + return cell; + } + + protected void autoSizeColumnsWithHeader() { + for (int i = 0; i < headerCellCount; i++) { + currentSheet.autoSizeColumn(i); + } + } + + } + +} diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/generator/LocationDataGenerator.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/generator/LocationDataGenerator.java new file mode 100644 index 0000000000..e78f295af4 --- /dev/null +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/generator/LocationDataGenerator.java @@ -0,0 +1,98 @@ +/* + * Copyright 2018 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.optaplanner.examples.common.persistence.generator; + +public class LocationDataGenerator { + + public static final LocationData[] US_MAINLAND_STATE_CAPITALS = { + new LocationData("Montgomery, Alabama", 32.377716, -86.300568), + // new LocationData("Juneau, Alaska", 58.301598, -134.420212), + new LocationData("Phoenix, Arizona", 33.448143, -112.096962), + new LocationData("Little Rock, Arkansas", 34.746613, -92.288986), + new LocationData("Sacramento, California", 38.576668, -121.493629), + new LocationData("Denver, Colorado", 39.739227, -104.984856), + new LocationData("Hartford, Connecticut", 41.764046, -72.682198), + new LocationData("Dover, Delaware", 39.157307, -75.519722), + new LocationData("Tallahassee, Florida", 30.438118, -84.281296), + new LocationData("Atlanta, Georgia", 33.749027, -84.388229), + // new LocationData("Honolulu, Hawaii", 21.307442, -157.857376), + new LocationData("Boise, Idaho", 43.617775, -116.199722), + new LocationData("Springfield, Illinois", 39.798363, -89.654961), + new LocationData("Indianapolis, Indiana", 39.768623, -86.162643), + new LocationData("Des Moines, Iowa", 41.591087, -93.603729), + new LocationData("Topeka, Kansas", 39.048191, -95.677956), + new LocationData("Frankfort, Kentucky", 38.186722, -84.875374), + new LocationData("Baton Rouge, Louisiana", 30.457069, -91.187393), + new LocationData("Augusta, Maine", 44.307167, -69.781693), + new LocationData("Annapolis, Maryland", 38.978764, -76.490936), + new LocationData("Boston, Massachusetts", 42.358162, -71.063698), + new LocationData("Lansing, Michigan", 42.733635, -84.555328), + new LocationData("St. Paul, Minnesota", 44.955097, -93.102211), + new LocationData("Jackson, Mississippi", 32.303848, -90.182106), + new LocationData("Jefferson City, Missouri", 38.579201, -92.172935), + new LocationData("Helena, Montana", 46.585709, -112.018417), + new LocationData("Lincoln, Nebraska", 40.808075, -96.699654), + new LocationData("Carson City, Nevada", 39.163914, -119.766121), + new LocationData("Concord, New Hampshire", 43.206898, -71.537994), + new LocationData("Trenton, New Jersey", 40.220596, -74.769913), + new LocationData("Santa Fe, New Mexico", 35.68224, -105.939728), + new LocationData("Raleigh, North Carolina", 35.78043, -78.639099), + new LocationData("Bismarck, North Dakota", 46.82085, -100.783318), + new LocationData("Albany, New York", 42.652843, -73.757874), + new LocationData("Columbus, Ohio", 39.961346, -82.999069), + new LocationData("Oklahoma City, Oklahoma", 35.492207, -97.503342), + new LocationData("Salem, Oregon", 44.938461, -123.030403), + new LocationData("Harrisburg, Pennsylvania", 40.264378, -76.883598), + new LocationData("Providence, Rhode Island", 41.830914, -71.414963), + new LocationData("Columbia, South Carolina", 34.000343, -81.033211), + new LocationData("Pierre, South Dakota", 44.367031, -100.346405), + new LocationData("Nashville, Tennessee", 36.16581, -86.784241), + new LocationData("Austin, Texas", 30.27467, -97.740349), + new LocationData("Salt Lake City, Utah", 40.777477, -111.888237), + new LocationData("Montpelier, Vermont", 44.262436, -72.580536), + new LocationData("Richmond, Virginia", 37.538857, -77.43364), + new LocationData("Olympia, Washington", 47.035805, -122.905014), + new LocationData("Charleston, West Virginia", 38.336246, -81.612328), + new LocationData("Madison, Wisconsin", 43.074684, -89.384445), + new LocationData("Cheyenne, Wyoming", 41.140259, -104.820236) + }; + + public static class LocationData { + private String name; + protected double latitude; + protected double longitude; + + public LocationData(String name, double latitude, double longitude) { + this.name = name; + this.latitude = latitude; + this.longitude = longitude; + } + + public String getName() { + return name; + } + + public double getLatitude() { + return latitude; + } + + public double getLongitude() { + return longitude; + } + } + +} diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/StringDataGenerator.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/generator/StringDataGenerator.java similarity index 99% rename from optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/StringDataGenerator.java rename to optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/generator/StringDataGenerator.java index 67fecbcc2e..586076bbff 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/StringDataGenerator.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/common/persistence/generator/StringDataGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Red Hat, Inc. and/or its affiliates. + * Copyright 2018 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.optaplanner.examples.common.persistence; +package org.optaplanner.examples.common.persistence.generator; import java.util.ArrayList; import java.util.List; diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java index a44d9350a5..7c68f79f88 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingGenerator.java @@ -35,7 +35,7 @@ import org.optaplanner.examples.common.app.CommonApp; import org.optaplanner.examples.common.app.LoggingMain; import org.optaplanner.examples.common.persistence.AbstractSolutionImporter; -import org.optaplanner.examples.common.persistence.StringDataGenerator; +import org.optaplanner.examples.common.persistence.generator.StringDataGenerator; import org.optaplanner.examples.conferencescheduling.app.ConferenceSchedulingApp; import org.optaplanner.examples.conferencescheduling.domain.ConferenceParametrization; import org.optaplanner.examples.conferencescheduling.domain.ConferenceSolution; @@ -241,7 +241,7 @@ private void writeConferenceSolution(int dayListSize, int roomListSize) { } public ConferenceSolution createConferenceSolution(String fileName, int timeslotListSize, int roomListSize, - int speakerListSize, int talkListSize) { + int speakerListSize, int talkListSize) { random = new Random(37); ConferenceSolution solution = new ConferenceSolution(); solution.setId(0L); diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingXslxFileIO.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingXslxFileIO.java index 44bcd3cabf..72b6f11de5 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingXslxFileIO.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/persistence/ConferenceSchedulingXslxFileIO.java @@ -25,7 +25,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Arrays; @@ -33,48 +32,28 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Supplier; -import java.util.regex.Pattern; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Comment; -import org.apache.poi.ss.usermodel.CreationHelper; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.usermodel.XSSFCell; -import org.apache.poi.xssf.usermodel.XSSFCellStyle; -import org.apache.poi.xssf.usermodel.XSSFColor; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.optaplanner.core.api.score.Score; import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; import org.optaplanner.core.api.score.constraint.ConstraintMatch; import org.optaplanner.core.api.score.constraint.ConstraintMatchTotal; import org.optaplanner.core.api.score.constraint.Indictment; -import org.optaplanner.core.api.solver.SolverFactory; -import org.optaplanner.core.impl.score.director.ScoreDirector; -import org.optaplanner.core.impl.score.director.ScoreDirectorFactory; +import org.optaplanner.examples.common.persistence.AbstractXslxSolutionFileIO; import org.optaplanner.examples.conferencescheduling.app.ConferenceSchedulingApp; import org.optaplanner.examples.conferencescheduling.domain.ConferenceParametrization; import org.optaplanner.examples.conferencescheduling.domain.ConferenceSolution; @@ -83,34 +62,11 @@ import org.optaplanner.examples.conferencescheduling.domain.Talk; import org.optaplanner.examples.conferencescheduling.domain.TalkType; import org.optaplanner.examples.conferencescheduling.domain.Timeslot; -import org.optaplanner.persistence.common.api.domain.solution.SolutionFileIO; -import org.optaplanner.swing.impl.TangoColorFactory; import static java.util.stream.Collectors.*; import static org.optaplanner.examples.conferencescheduling.domain.ConferenceParametrization.*; -public class ConferenceSchedulingXslxFileIO implements SolutionFileIO { - - protected static final Pattern VALID_TAG_PATTERN = Pattern.compile("(?U)^[\\w&\\-\\.\\/\\(\\)\\'][\\w&\\-\\.\\/\\(\\)\\' ]*[\\w&\\-\\.\\/\\(\\)\\']?$"); - protected static final Pattern VALID_NAME_PATTERN = VALID_TAG_PATTERN; - protected static final Pattern VALID_CODE_PATTERN = Pattern.compile("(?U)^[\\w\\-\\.\\/\\(\\)]+$"); - - protected static final DateTimeFormatter DAY_FORMATTER - = DateTimeFormatter.ofPattern("E yyyy-MM-dd", Locale.ENGLISH); - protected static final DateTimeFormatter TIME_FORMATTER - = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH); - - protected static final XSSFColor VIEW_TAB_COLOR = new XSSFColor(TangoColorFactory.BUTTER_1); - - protected static final XSSFColor UNAVAILABLE_COLOR = new XSSFColor(TangoColorFactory.ALUMINIUM_5); - protected static final XSSFColor PINNED_COLOR = new XSSFColor(TangoColorFactory.PLUM_1); - protected static final XSSFColor HARD_PENALTY_COLOR = new XSSFColor(TangoColorFactory.SCARLET_1); - protected static final XSSFColor SOFT_PENALTY_COLOR = new XSSFColor(TangoColorFactory.ORANGE_1); - - @Override - public String getInputFileExtension() { - return "xlsx"; - } +public class ConferenceSchedulingXslxFileIO extends AbstractXslxSolutionFileIO { @Override public ConferenceSolution read(File inputSolutionFile) { @@ -123,25 +79,17 @@ public ConferenceSolution read(File inputSolutionFile) { } } - private static class ConferenceSchedulingXslxReader { - - protected final XSSFWorkbook workbook; + private static class ConferenceSchedulingXslxReader extends AbstractXslxReader { - protected ConferenceSolution solution; private Map totalTalkTypeMap; private Set totalTimeslotTagSet; private Set totalRoomTagSet; - protected XSSFSheet currentSheet; - protected Iterator currentRowIterator; - protected XSSFRow currentRow; - protected int currentRowNumber; - protected int currentColumnNumber; - public ConferenceSchedulingXslxReader(XSSFWorkbook workbook) { - this.workbook = workbook; + super(workbook); } + @Override public ConferenceSolution read() { solution = new ConferenceSolution(); totalTalkTypeMap = new HashMap<>(); @@ -234,33 +182,6 @@ private void readConfiguration() { solution.setParametrization(parametrization); } - private void readConstraintLine(String name, Consumer consumer, String constraintdescription) { - nextRow(); - readHeaderCell(name); - XSSFCell weightCell = nextCell(); - if (consumer != null) { - if (weightCell.getCellTypeEnum() != CellType.NUMERIC) { - throw new IllegalArgumentException(currentPosition() + ": The value (" - + weightCell.getStringCellValue() - + ") for constraint (" + name + ") must be a number and the cell type must be numeric."); - } - double value = weightCell.getNumericCellValue(); - if (((double) ((int) value)) != value) { - throw new IllegalArgumentException(currentPosition() + ": The value (" + value - + ") for constraint (" + name + ") must be an integer."); - } - consumer.accept((int) value); - } else { - if (weightCell.getCellTypeEnum() == CellType.NUMERIC - || !weightCell.getStringCellValue().equals("n/a")) { - throw new IllegalArgumentException(currentPosition() + ": The value (" - + weightCell.getStringCellValue() - + ") for constraint (" + name + ") must be an n/a."); - } - } - readHeaderCell(constraintdescription); - } - private void readTimeslotList() { nextSheet("Timeslots"); nextRow(false); @@ -680,141 +601,6 @@ private void readTimeslotHoursHeaders() { } } - protected String currentPosition() { - return "Sheet (" + currentSheet.getSheetName() + ") cell (" - + (currentRowNumber + 1) + CellReference.convertNumToColString(currentColumnNumber) + ")"; - } - - protected void nextSheet(String sheetName) { - currentSheet = workbook.getSheet(sheetName); - if (currentSheet == null) { - throw new IllegalStateException("The workbook does not contain a sheet with name (" - + sheetName + ")."); - } - currentRowIterator = currentSheet.rowIterator(); - if (currentRowIterator == null) { - throw new IllegalStateException(currentPosition() + ": The sheet has no rows."); - } - currentRowNumber = -1; - } - - protected boolean nextRow() { - return nextRow(true); - } - - protected boolean nextRow(boolean skipEmptyRows) { - currentRowNumber++; - currentColumnNumber = -1; - if (!currentRowIterator.hasNext()) { - currentRow = null; - return false; - } - currentRow = (XSSFRow) currentRowIterator.next(); - while (skipEmptyRows && currentRowIsEmpty()) { - if (!currentRowIterator.hasNext()) { - currentRow = null; - return false; - } - currentRow = (XSSFRow) currentRowIterator.next(); - } - if (currentRow.getRowNum() != currentRowNumber) { - if (currentRow.getRowNum() == currentRowNumber + 1) { - currentRowNumber++; - } else { - throw new IllegalStateException(currentPosition() + ": The next row (" + currentRow.getRowNum() - + ") has a gap of more than 1 empty line with the previous."); - } - } - return true; - } - - protected boolean currentRowIsEmpty() { - if (currentRow.getPhysicalNumberOfCells() == 0) { - return true; - } - for (Cell cell : currentRow) { - if (cell.getCellTypeEnum() == CellType.STRING) { - if (!cell.getStringCellValue().isEmpty()) { - return false; - } - } else if (cell.getCellTypeEnum() != CellType.BLANK) { - return false; - } - } - return true; - } - - protected void readHeaderCell(String value) { - XSSFCell cell = currentRow == null ? null : nextStringCell(); - if (cell == null || !cell.getStringCellValue().equals(value)) { - throw new IllegalStateException(currentPosition() + ": The cell does not contain the expected value (" - + value + ")."); - } - } - - protected XSSFCell nextStringCell() { - XSSFCell cell = nextCell(); - if (cell.getCellTypeEnum() == CellType.NUMERIC) { - throw new IllegalStateException(currentPosition() + ": The cell with value (" - + cell.getNumericCellValue() + ") has a numeric type but should be a string."); - } - return cell; - } - - protected XSSFCell nextNumericCell() { - XSSFCell cell = nextCell(); - if (cell.getCellTypeEnum() == CellType.STRING) { - throw new IllegalStateException(currentPosition() + ": The cell with value (" - + cell.getStringCellValue() + ") has a string type but should be numeric."); - } - return cell; - } - - protected XSSFCell nextBooleanCell() { - XSSFCell cell = nextCell(); - if (cell.getCellTypeEnum() == CellType.STRING) { - throw new IllegalStateException(currentPosition() + ": The cell with value (" - + cell.getStringCellValue() + ") has a string type but should be boolean."); - } - if (cell.getCellTypeEnum() == CellType.NUMERIC) { - throw new IllegalStateException(currentPosition() + ": The cell with value (" - + cell.getNumericCellValue() + ") has a numeric type but should be a boolean."); - } - return cell; - } - - protected XSSFCell nextCell() { - currentColumnNumber++; - XSSFCell cell = currentRow.getCell(currentColumnNumber); - // TODO HACK to workaround the fact that LibreOffice and Excel automatically remove empty trailing cells - if (cell == null) { - // Return dummy cell - return currentRow.createCell(currentColumnNumber); - } - return cell; - } - - protected XSSFColor extractColor(XSSFCell cell, XSSFColor... acceptableColors) { - XSSFCellStyle cellStyle = cell.getCellStyle(); - FillPatternType fillPattern = cellStyle.getFillPatternEnum(); - if (fillPattern == null || fillPattern == FillPatternType.NO_FILL) { - return null; - } - if (fillPattern != FillPatternType.SOLID_FOREGROUND) { - throw new IllegalStateException(currentPosition() + ": The fill pattern (" + fillPattern - + ") should be either " + FillPatternType.NO_FILL - + " or " + FillPatternType.SOLID_FOREGROUND + "."); - } - XSSFColor color = cellStyle.getFillForegroundColorColor(); - for (XSSFColor acceptableColor : acceptableColors) { - if (acceptableColor.equals(color)) { - return acceptableColor; - } - } - throw new IllegalStateException(currentPosition() + ": The fill color (" + color - + ") is not one of the acceptableColors (" + Arrays.toString(acceptableColors) + ")."); - } - } @@ -829,48 +615,15 @@ public void write(ConferenceSolution solution, File outputSolutionFile) { } } - private static class ConferenceSchedulingXlsxWriter { - - protected final ConferenceSolution solution; - protected final List constraintMatchTotalList; - protected final Map indictmentMap; - - protected XSSFWorkbook workbook; - protected CreationHelper creationHelper; - - protected XSSFCellStyle headerStyle; - protected XSSFCellStyle defaultStyle; - protected XSSFCellStyle unavailableStyle; - protected XSSFCellStyle pinnedStyle; - protected XSSFCellStyle hardPenaltyStyle; - protected XSSFCellStyle softPenaltyStyle; - protected XSSFCellStyle wrappedStyle; - - protected XSSFSheet currentSheet; - protected Drawing currentDrawing; - protected XSSFRow currentRow; - protected int currentRowNumber; - protected int currentColumnNumber; - protected int headerCellCount; + private static class ConferenceSchedulingXlsxWriter extends AbstractXlsxWriter { public ConferenceSchedulingXlsxWriter(ConferenceSolution solution) { - this.solution = solution; - ScoreDirectorFactory scoreDirectorFactory - = SolverFactory.createFromXmlResource(ConferenceSchedulingApp.SOLVER_CONFIG) - .buildSolver().getScoreDirectorFactory(); - try (ScoreDirector scoreDirector = scoreDirectorFactory.buildScoreDirector()) { - scoreDirector.setWorkingSolution(solution); - scoreDirector.calculateScore(); - constraintMatchTotalList = new ArrayList<>(scoreDirector.getConstraintMatchTotals()); - constraintMatchTotalList.sort(Comparator.comparing(ConstraintMatchTotal::getScore)); - indictmentMap = scoreDirector.getIndictmentMap(); - } + super(solution, ConferenceSchedulingApp.SOLVER_CONFIG); } + @Override public Workbook write() { - workbook = new XSSFWorkbook(); - creationHelper = workbook.getCreationHelper(); - createStyles(); + writeSetup(); writeConfiguration(); writeTimeslotList(); writeRoomList(); @@ -889,30 +642,6 @@ public Workbook write() { return workbook; } - public void createStyles() { - headerStyle = createStyle(null); - Font font = workbook.createFont(); - font.setBold(true); - headerStyle.setFont(font); - defaultStyle = createStyle(null); - unavailableStyle = createStyle(UNAVAILABLE_COLOR); - pinnedStyle = createStyle(PINNED_COLOR); - hardPenaltyStyle = createStyle(HARD_PENALTY_COLOR); - softPenaltyStyle = createStyle(SOFT_PENALTY_COLOR); - wrappedStyle = createStyle(null); - } - - private XSSFCellStyle createStyle(XSSFColor color) { - XSSFCellStyle style = workbook.createCellStyle(); - if (color != null) { - style.setFillPattern(FillPatternType.SOLID_FOREGROUND); - style.setFillForegroundColor(color); - } - style.setWrapText(true); - style.setVerticalAlignment(VerticalAlignment.CENTER); - return style; - } - private void writeConfiguration() { nextSheet("Configuration", 1, 3, false); nextRow(); @@ -987,18 +716,6 @@ private void writeConfiguration() { autoSizeColumnsWithHeader(); } - private void writeConstraintLine(String name, Supplier supplier, String constraintdescription) { - nextRow(); - nextHeaderCell(name); - XSSFCell weightCell = nextCell(); - if (supplier != null) { - weightCell.setCellValue(supplier.get()); - } else { - weightCell.setCellValue("n/a"); - } - nextHeaderCell(constraintdescription); - } - private void writeTimeslotList() { nextSheet("Timeslots", 3, 1, false); nextRow(); @@ -1455,8 +1172,6 @@ private void writeLanguagesView() { private void writeScoreView() { nextSheet("Score view", 1, 1, true); - nextRow(); - nextCell(); nextHeaderCell("Score"); nextCell().setCellValue(solution.getScore() == null ? "Not yet solved" : solution.getScore().toShortString()); nextRow(); @@ -1512,28 +1227,6 @@ private void writeTimeslotHoursHeaders() { } } - protected void nextSheet(String sheetName, int colSplit, int rowSplit, boolean view) { - currentSheet = workbook.createSheet(sheetName); - currentDrawing = currentSheet.createDrawingPatriarch(); - currentSheet.createFreezePane(colSplit, rowSplit); - currentRowNumber = -1; - headerCellCount = 0; - if (view) { - currentSheet.setTabColor(VIEW_TAB_COLOR); - } - } - - protected void nextRow() { - currentRowNumber++; - currentRow = currentSheet.createRow(currentRowNumber); - currentColumnNumber = -1; - } - - protected void nextHeaderCell(String value) { - nextCell(headerStyle).setCellValue(value); - headerCellCount++; - } - protected void nextTalkListCell(List talkList, String[] filteredConstraintNames) { nextTalkListCell(false, talkList, filteredConstraintNames); } @@ -1626,23 +1319,6 @@ protected void nextTalkListCell(boolean unavailable, List talkList, Functi currentRow.setHeightInPoints(Math.max(currentRow.getHeightInPoints(), talkList.size() * currentSheet.getDefaultRowHeightInPoints())); } - protected XSSFCell nextCell() { - return nextCell(defaultStyle); - } - - protected XSSFCell nextCell(XSSFCellStyle cellStyle) { - currentColumnNumber++; - XSSFCell cell = currentRow.createCell(currentColumnNumber); - cell.setCellStyle(cellStyle); - return cell; - } - - protected void autoSizeColumnsWithHeader() { - for (int i = 0; i < headerCellCount; i++) { - currentSheet.autoSizeColumn(i); - } - } - } } diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/swingui/ConferenceSchedulingPanel.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/swingui/ConferenceSchedulingPanel.java index ca8728e935..9cdeb02387 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/swingui/ConferenceSchedulingPanel.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/conferencescheduling/swingui/ConferenceSchedulingPanel.java @@ -53,7 +53,7 @@ public ConferenceSchedulingPanel() { } @Override - public void resetPanel(ConferenceSolution meetingSchedule) { + public void resetPanel(ConferenceSolution solution) { } } diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/curriculumcourse/persistence/CurriculumCourseGenerator.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/curriculumcourse/persistence/CurriculumCourseGenerator.java index d51f842574..c4eb8bf841 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/curriculumcourse/persistence/CurriculumCourseGenerator.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/curriculumcourse/persistence/CurriculumCourseGenerator.java @@ -28,7 +28,7 @@ import org.optaplanner.examples.common.app.CommonApp; import org.optaplanner.examples.common.app.LoggingMain; -import org.optaplanner.examples.common.persistence.StringDataGenerator; +import org.optaplanner.examples.common.persistence.generator.StringDataGenerator; import org.optaplanner.examples.curriculumcourse.app.CurriculumCourseApp; import org.optaplanner.examples.curriculumcourse.domain.Course; import org.optaplanner.examples.curriculumcourse.domain.CourseSchedule; diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/meetingscheduling/persistence/MeetingSchedulingGenerator.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/meetingscheduling/persistence/MeetingSchedulingGenerator.java index 3ff11d95a9..85cafa2d9c 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/meetingscheduling/persistence/MeetingSchedulingGenerator.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/meetingscheduling/persistence/MeetingSchedulingGenerator.java @@ -25,7 +25,7 @@ import org.optaplanner.examples.common.app.CommonApp; import org.optaplanner.examples.common.app.LoggingMain; import org.optaplanner.examples.common.persistence.AbstractSolutionImporter; -import org.optaplanner.examples.common.persistence.StringDataGenerator; +import org.optaplanner.examples.common.persistence.generator.StringDataGenerator; import org.optaplanner.examples.meetingscheduling.app.MeetingSchedulingApp; import org.optaplanner.examples.meetingscheduling.domain.Attendance; import org.optaplanner.examples.meetingscheduling.domain.Day; diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/taskassigning/persistence/TaskAssigningGenerator.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/taskassigning/persistence/TaskAssigningGenerator.java index 27f30af28c..137f02cd35 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/taskassigning/persistence/TaskAssigningGenerator.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/taskassigning/persistence/TaskAssigningGenerator.java @@ -30,7 +30,7 @@ import org.optaplanner.examples.common.app.CommonApp; import org.optaplanner.examples.common.app.LoggingMain; import org.optaplanner.examples.common.persistence.AbstractSolutionImporter; -import org.optaplanner.examples.common.persistence.StringDataGenerator; +import org.optaplanner.examples.common.persistence.generator.StringDataGenerator; import org.optaplanner.examples.taskassigning.app.TaskAssigningApp; import org.optaplanner.examples.taskassigning.domain.Affinity; import org.optaplanner.examples.taskassigning.domain.Customer; @@ -159,8 +159,8 @@ public TaskAssigningSolution createTaskAssigningSolution(String fileName, int ta createTaskList(solution, taskListSize); solution.setFrozenCutoff(0); - BigInteger a = AbstractSolutionImporter.InputBuilder.factorial(taskListSize + employeeListSize - 1); - BigInteger b = AbstractSolutionImporter.InputBuilder.factorial(employeeListSize - 1); + BigInteger a = AbstractSolutionImporter.factorial(taskListSize + employeeListSize - 1); + BigInteger b = AbstractSolutionImporter.factorial(employeeListSize - 1); BigInteger possibleSolutionSize = (a == null || b == null) ? null : a.divide(b); logger.info("TaskAssigningSolution {} has {} tasks, {} skills, {} employees, {} task types and {} customers with a search space of {}.", fileName, diff --git a/optaplanner-examples/src/main/java/org/optaplanner/examples/tsp/domain/location/Location.java b/optaplanner-examples/src/main/java/org/optaplanner/examples/tsp/domain/location/Location.java index db0962ef8d..6321e9ba1f 100644 --- a/optaplanner-examples/src/main/java/org/optaplanner/examples/tsp/domain/location/Location.java +++ b/optaplanner-examples/src/main/java/org/optaplanner/examples/tsp/domain/location/Location.java @@ -19,7 +19,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamInclude; import org.optaplanner.examples.common.domain.AbstractPersistable; -import org.optaplanner.examples.vehiclerouting.domain.VehicleRoutingSolution; +import org.optaplanner.examples.tsp.domain.TspSolution; @XStreamAlias("TspLocation") @XStreamInclude({ @@ -70,7 +70,7 @@ public void setLongitude(double longitude) { // ************************************************************************ /** - * The distance's unit of measurement depends on the {@link VehicleRoutingSolution}'s {@link DistanceType}. + * The distance's unit of measurement depends on the {@link TspSolution}'s {@link DistanceType}. * It can be in miles or km, but for most cases it's in the TSPLIB's unit of measurement. * @param location never null * @return a positive number, the distance multiplied by 1000 to avoid floating point arithmetic rounding errors diff --git a/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporterTest.java b/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporterTest.java index 09203e905b..a17985147b 100644 --- a/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporterTest.java +++ b/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/AbstractSolutionImporterTest.java @@ -26,10 +26,10 @@ public class AbstractSolutionImporterTest { @Test public void factorial() { - assertEquals(BigInteger.valueOf(1), AbstractSolutionImporter.InputBuilder.factorial(1)); - assertEquals(BigInteger.valueOf(2), AbstractSolutionImporter.InputBuilder.factorial(2)); - assertEquals(BigInteger.valueOf(6), AbstractSolutionImporter.InputBuilder.factorial(3)); - assertEquals(BigInteger.valueOf(24), AbstractSolutionImporter.InputBuilder.factorial(4)); + assertEquals(BigInteger.valueOf(1), AbstractSolutionImporter.factorial(1)); + assertEquals(BigInteger.valueOf(2), AbstractSolutionImporter.factorial(2)); + assertEquals(BigInteger.valueOf(6), AbstractSolutionImporter.factorial(3)); + assertEquals(BigInteger.valueOf(24), AbstractSolutionImporter.factorial(4)); } } diff --git a/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/StringDataGeneratorTest.java b/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/StringDataGeneratorTest.java index c9b7f0449b..8cce55312f 100644 --- a/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/StringDataGeneratorTest.java +++ b/optaplanner-examples/src/test/java/org/optaplanner/examples/common/persistence/StringDataGeneratorTest.java @@ -17,6 +17,7 @@ package org.optaplanner.examples.common.persistence; import org.junit.Test; +import org.optaplanner.examples.common.persistence.generator.StringDataGenerator; import static org.junit.Assert.*;