{"action":"created","comment":{"url":"https://api.github.com/repos/kiegroup/optaplanner/pulls/comments/212312207","pull_request_review_id":148914779,"id":212312207,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMjMxMjIwNw==","diff_hunk":"@@ -0,0 +1,298 @@\n+/*\n+ * Copyright 2018 Red Hat, Inc. and/or its affiliates.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *      http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+package org.optaplanner.examples.flightcrewscheduling.persistence;\n+\n+import java.io.File;\n+import java.math.BigInteger;\n+import java.time.LocalDate;\n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.Comparator;\n+import java.util.LinkedHashMap;\n+import java.util.LinkedHashSet;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.Random;\n+import java.util.Set;\n+import java.util.TreeSet;\n+import java.util.stream.Collectors;\n+\n+import org.optaplanner.examples.common.app.CommonApp;\n+import org.optaplanner.examples.common.app.LoggingMain;\n+import org.optaplanner.examples.common.persistence.AbstractSolutionImporter;\n+import org.optaplanner.examples.common.persistence.generator.LocationDataGenerator;\n+import org.optaplanner.examples.common.persistence.generator.StringDataGenerator;\n+import org.optaplanner.examples.flightcrewscheduling.app.FlightCrewSchedulingApp;\n+import org.optaplanner.examples.flightcrewscheduling.domain.Airport;\n+import org.optaplanner.examples.flightcrewscheduling.domain.Employee;\n+import org.optaplanner.examples.flightcrewscheduling.domain.Flight;\n+import org.optaplanner.examples.flightcrewscheduling.domain.FlightAssignment;\n+import org.optaplanner.examples.flightcrewscheduling.domain.FlightCrewParametrization;\n+import org.optaplanner.examples.flightcrewscheduling.domain.FlightCrewSolution;\n+import org.optaplanner.examples.flightcrewscheduling.domain.Skill;\n+import org.optaplanner.persistence.common.api.domain.solution.SolutionFileIO;\n+\n+import static java.time.temporal.ChronoUnit.*;\n+import static org.optaplanner.examples.common.persistence.generator.ProbabilisticDataGenerator.*;\n+\n+public class FlightCrewSchedulingGenerator extends LoggingMain {\n+\n+    private static final double TAXI_KM_THRESHOLD = 500.0;\n+    private static final double TAXI_SPEED_IN_KM_PER_MINUTE = 90.0 / 60.0;\n+    private static final double PLANE_SPEED_IN_KM_PER_MINUTE = 1000.0 / 60.0;\n+    private static final double PLANE_TAKE_OFF_AND_LANDING_MINUTES = 90.0;\n+\n+    private static final int START_MINUTE_OF_DAY = 6 * 60;\n+    private static final int END_MINUTE_OF_DAY = 22 * 60;\n+\n+    private static final int PILOT_COUNT_PER_FLIGHT = 2;\n+    private static final int FLIGHT_ATTENDANT_COUNT_PER_FLIGHT = 3;\n+    private static final int EMPLOYEE_COUNT_PER_FLIGHT = PILOT_COUNT_PER_FLIGHT + FLIGHT_ATTENDANT_COUNT_PER_FLIGHT;\n+\n+    public static void main(String[] args) {\n+        FlightCrewSchedulingGenerator generator = new FlightCrewSchedulingGenerator();\n+        generator.writeFlightCrewSolution(\"Europe\", LocationDataGenerator.EUROPE_BUSIEST_AIRPORTS, 10, 7);\n+        generator.writeFlightCrewSolution(\"Europe\", LocationDataGenerator.EUROPE_BUSIEST_AIRPORTS, 50, 7);\n+        generator.writeFlightCrewSolution(\"Europe\", LocationDataGenerator.EUROPE_BUSIEST_AIRPORTS, 10, 4 * 7);\n+        generator.writeFlightCrewSolution(\"US\", LocationDataGenerator.US_MAINLAND_STATE_CAPITALS, 10, 7);\n+    }\n+\n+    private final StringDataGenerator employeeNameGenerator = StringDataGenerator.buildFullNames();\n+\n+    protected final SolutionFileIO<FlightCrewSolution> solutionFileIO;\n+    protected final File outputDir;\n+\n+    protected Skill pilotSkill;\n+    protected Skill flightAttendantSkill;\n+    protected List<Airport> homeAirportList;\n+\n+    protected Random random;\n+\n+    public FlightCrewSchedulingGenerator() {\n+        solutionFileIO = new FlightCrewSchedulingXlsxFileIO();\n+        outputDir = new File(CommonApp.determineDataDir(FlightCrewSchedulingApp.DATA_DIR_NAME), \"unsolved\");\n+    }\n+\n+    private void writeFlightCrewSolution(String locationDataName,\n+            LocationDataGenerator.LocationData[] locationDataArray, int flightRoundTripsPerDay, int dayCount) {\n+        int flightListSize = (flightRoundTripsPerDay * 5 / 2) * dayCount;\n+        String fileName = flightListSize + \"flights-\" + dayCount + \"days-\" + locationDataName;\n+        File outputFile = new File(outputDir, fileName + \".\" + solutionFileIO.getOutputFileExtension());\n+        FlightCrewSolution solution = createFlightCrewSolution(\n+                fileName, locationDataArray, flightRoundTripsPerDay, dayCount);\n+        solutionFileIO.write(solution, outputFile);\n+    }\n+\n+    public FlightCrewSolution createFlightCrewSolution(String fileName,\n+            LocationDataGenerator.LocationData[] locationDataArray, int flightRoundTripsPerDay, int dayCount) {\n+        random = new Random(37);\n+        FlightCrewSolution solution = new FlightCrewSolution();\n+        solution.setId(0L);\n+        LocalDate firstDate = LocalDate.of(2018, 1, 1);\n+        solution.setScheduleFirstUTCDate(firstDate);\n+        solution.setScheduleLastUTCDate(firstDate.plusDays(dayCount - 1));\n+        FlightCrewParametrization parametrization = new FlightCrewParametrization();\n+        parametrization.setId(0L);\n+        solution.setParametrization(parametrization);\n+\n+        createSkillList(solution);\n+        createAirportList(solution, locationDataArray);\n+        createFlightListAndFlightAssignmentList(solution, flightRoundTripsPerDay, dayCount);\n+        createEmployeeList(solution, flightRoundTripsPerDay, dayCount);\n+\n+        int employeeListSize = solution.getEmployeeList().size();\n+        int flightAssignmentListSize = solution.getFlightAssignmentList().size();\n+        BigInteger possibleSolutionSize = BigInteger.valueOf((long) employeeListSize).pow(flightAssignmentListSize);\n+        logger.info(\"FlightCrew {} has {} skills, {} airports, {} employees, {} flights and {} flight assignments with a search space of {}.\",\n+                fileName,\n+                solution.getSkillList().size(),\n+                solution.getAirportList().size(),\n+                solution.getEmployeeList().size(),\n+                solution.getFlightList().size(),\n+                flightAssignmentListSize,\n+                AbstractSolutionImporter.getFlooredPossibleSolutionSize(possibleSolutionSize));\n+        return solution;\n+    }\n+\n+    private void createSkillList(FlightCrewSolution solution) {\n+        List<Skill> skillList = new ArrayList<>(2);\n+        pilotSkill = new Skill();\n+        pilotSkill.setId(0L);\n+        pilotSkill.setName(\"Pilot\");\n+        skillList.add(pilotSkill);\n+        flightAttendantSkill = new Skill();\n+        flightAttendantSkill.setId(1L);\n+        flightAttendantSkill.setName(\"Flight attendant\");\n+        skillList.add(flightAttendantSkill);\n+        solution.setSkillList(skillList);\n+    }\n+\n+    private void createAirportList(FlightCrewSolution solution, LocationDataGenerator.LocationData[] locationDataArray) {\n+        List<Airport> airportList = new ArrayList<>(locationDataArray.length);\n+        long id = 0L;\n+        for (LocationDataGenerator.LocationData locationData : locationDataArray) {\n+            Airport airport = new Airport();\n+            airport.setId(id);\n+            id++;\n+            airport.setCode(locationData.getName().replaceAll(\"\\\\,.*\", \"\"));\n+            airport.setName(locationData.getName());\n+            airport.setLatitude(locationData.getLatitude());\n+            airport.setLongitude(locationData.getLongitude());\n+            logger.trace(\"Created airport ({}).\", airport);\n+            airportList.add(airport);\n+        }\n+        for (Airport a : airportList) {\n+            Map<Airport, Long> taxiTimeInMinutesMap = new LinkedHashMap<>(airportList.size());\n+            for (Airport b : airportList) {\n+                double distanceInKm = a.getHaversineDistanceInKmTo(b);\n+                if (distanceInKm < TAXI_KM_THRESHOLD) {\n+                    taxiTimeInMinutesMap.put(b, (long) (distanceInKm / TAXI_SPEED_IN_KM_PER_MINUTE));\n+                }\n+            }\n+            a.setTaxiTimeInMinutesMap(taxiTimeInMinutesMap);\n+        }\n+        solution.setAirportList(airportList);\n+    }\n+\n+    private void createFlightListAndFlightAssignmentList(FlightCrewSolution solution, int flightRoundTripsPerDay, int dayCount) {\n+        int flightListSize = flightRoundTripsPerDay * dayCount;\n+        List<Flight> flightList = new ArrayList<>(flightListSize);\n+        List<FlightAssignment> flightAssignmentList = new ArrayList<>(flightListSize * EMPLOYEE_COUNT_PER_FLIGHT);\n+\n+        List<Airport> airportList = solution.getAirportList();\n+        Airport centerAirport = airportList.get(0);\n+        int homeAirportListSize = Math.min(airportList.size() / 10, flightRoundTripsPerDay / 5);\n+        homeAirportList = airportList.stream()\n+                .sorted(Comparator.comparingDouble(centerAirport::getHaversineDistanceInKmTo))\n+                .limit(homeAirportListSize)\n+                .collect(Collectors.toList());\n+        LocalDate firstDate = solution.getScheduleFirstUTCDate();\n+        LocalDate lastDate = solution.getScheduleLastUTCDate();\n+        int flightNumberSuffix = 1;\n+        long flightId = 0L;\n+        long flightAssignmentId = 0L;\n+        for (int i = 0; i < flightRoundTripsPerDay; i++) {\n+            int flightCount = i % 2 == 0 ? 2 : 3;\n+            ArrayList<Airport> selectedAirports = new ArrayList<>(flightCount);\n+            Airport firstAirport = extractRandomElement(random, homeAirportList);\n+            selectedAirports.add(firstAirport);\n+            ArrayList<Airport> nonFirstAirports = new ArrayList<>(airportList);\n+            nonFirstAirports.remove(firstAirport);\n+            Collections.shuffle(nonFirstAirports, random);\n+            selectedAirports.addAll(nonFirstAirports.subList(0, flightCount - 1));\n+            for (int j = 0; j < flightCount; j++) {\n+                String flightNumber = \"AB\" + String.format(\"%03d\", flightNumberSuffix);\n+                flightNumberSuffix++;\n+                Airport departureAirport = selectedAirports.get(j);\n+                Airport arrivalAirport = selectedAirports.get((j + 1) % flightCount);\n+                int flyingTime = (int) ((departureAirport.getHaversineDistanceInKmTo(arrivalAirport)\n+                        / PLANE_SPEED_IN_KM_PER_MINUTE) + PLANE_TAKE_OFF_AND_LANDING_MINUTES);\n+                int departureMinute = START_MINUTE_OF_DAY + random.nextInt(\n+                        END_MINUTE_OF_DAY - flyingTime - START_MINUTE_OF_DAY + 1);\n+                int arrivalMinute = departureMinute + flyingTime;\n+                for (LocalDate date = firstDate; date.compareTo(lastDate) <= 0; date = date.plusDays(1)) {\n+                    Flight flight = new Flight();\n+                    flight.setId((long) flightId);\n+                    flightId++;\n+                    flight.setFlightNumber(flightNumber);\n+                    flight.setDepartureAirport(departureAirport);\n+                    flight.setDepartureUTCDateTime(date.atTime(departureMinute / 60, departureMinute % 60));\n+                    flight.setArrivalAirport(arrivalAirport);\n+                    flight.setArrivalUTCDateTime(date.atTime(arrivalMinute / 60, arrivalMinute % 60));\n+                    for (int indexInFlight = 0; indexInFlight < EMPLOYEE_COUNT_PER_FLIGHT; indexInFlight++) {\n+                        FlightAssignment flightAssignment = new FlightAssignment();\n+                        flightAssignment.setId((long) flightAssignmentId);\n+                        flightAssignmentId++;\n+                        flightAssignment.setFlight(flight);\n+                        flightAssignment.setIndexInFlight(indexInFlight);\n+                        Skill requiredSkill = indexInFlight < PILOT_COUNT_PER_FLIGHT ? pilotSkill : flightAttendantSkill;\n+                        flightAssignment.setRequiredSkill(requiredSkill);\n+                        flightAssignmentList.add(flightAssignment);\n+                    }\n+                    logger.trace(\"Created flight ({}).\", flight);\n+                    flightList.add(flight);\n+                }\n+            }\n+        }\n+        flightList.sort(Comparator.comparing(Flight::getDepartureUTCDate)\n+                .thenComparing(Flight::getDepartureAirport)\n+                .thenComparing(Flight::getDepartureUTCDateTime)\n+                .thenComparing(Flight::getArrivalAirport)\n+                .thenComparing(Flight::getArrivalUTCDateTime));\n+        solution.setFlightList(flightList);\n+        solution.setFlightAssignmentList(flightAssignmentList);\n+    }\n+\n+\n+    private void createEmployeeList(FlightCrewSolution solution, int flightRoundTripsPerDay, int dayCount) {\n+        int employeeListSize = flightRoundTripsPerDay * EMPLOYEE_COUNT_PER_FLIGHT * 3;\n+        List<Employee> employeeList = new ArrayList<>(employeeListSize);\n+        employeeNameGenerator.predictMaximumSizeAndReset(employeeListSize);\n+        LocalDate firstDate = solution.getScheduleFirstUTCDate();\n+        LocalDate lastDate = solution.getScheduleLastUTCDate();\n+        List<LocalDate> allDayList = new ArrayList<>((int) DAYS.between(firstDate, lastDate) + 1);\n+        for (LocalDate date = firstDate; date.compareTo(lastDate) <= 0; date = date.plusDays(1)) {\n+            allDayList.add(date);\n+        }\n+        List<LocalDate> unavailableDayPool = new ArrayList<>(allDayList);\n+        Collections.shuffle(unavailableDayPool, random);\n+        long id = 0L;\n+        for (int i = 0; i < employeeListSize; i++) {\n+            Employee employee = new Employee();\n+            employee.setId(id);\n+            id++;\n+            employee.setName(employeeNameGenerator.generateNextValue());\n+            employee.setHomeAirport(extractRandomElement(random, homeAirportList));\n+            employee.setSkillSet(Collections.singleton((i % 5) < 2 ? pilotSkill : flightAttendantSkill));\n+            int unavailableDayCount = 0;\n+            for (int j = 0; j < dayCount && unavailableDayCount < dayCount; j++) {\n+                if (random.nextDouble() < (20.0 / 365.0)) {\n+                    unavailableDayCount++;\n+                }\n+            }\n+            Set<LocalDate> unavailableDaySet = new LinkedHashSet<>();\n+            if (unavailableDayPool.size() >= unavailableDayCount) {\n+                List<LocalDate> selection = unavailableDayPool.subList(0, unavailableDayCount);\n+                unavailableDaySet.addAll(selection);\n+                selection.clear();\n+            } else {\n+                unavailableDaySet.addAll(unavailableDayPool);\n+                unavailableDayPool.clear();\n+                unavailableDayPool.addAll(allDayList);\n+                Collections.shuffle(unavailableDayPool, random);\n+                for (int j = 0; j < unavailableDayPool.size() && unavailableDaySet.size() < unavailableDayCount; j++) {\n+                    if (unavailableDaySet.add(unavailableDayPool.get(j))) {\n+                        unavailableDayPool.remove(j);","path":"optaplanner-examples/src/main/java/org/optaplanner/examples/flightcrewscheduling/persistence/FlightCrewSchedulingGenerator.java","position":279,"original_position":279,"commit_id":"f57313b47e83d915b181cfa69681e819963a2cb3","original_commit_id":"f57313b47e83d915b181cfa69681e819963a2cb3","user":{"login":"ge0ffrey","id":176880,"node_id":"MDQ6VXNlcjE3Njg4MA==","avatar_url":"https://avatars1.githubusercontent.com/u/176880?v=4","gravatar_id":"","url":"https://api.github.com/users/ge0ffrey","html_url":"https://github.com/ge0ffrey","followers_url":"https://api.github.com/users/ge0ffrey/followers","following_url":"https://api.github.com/users/ge0ffrey/following{/other_user}","gists_url":"https://api.github.com/users/ge0ffrey/gists{/gist_id}","starred_url":"https://api.github.com/users/ge0ffrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ge0ffrey/subscriptions","organizations_url":"https://api.github.com/users/ge0ffrey/orgs","repos_url":"https://api.github.com/users/ge0ffrey/repos","events_url":"https://api.github.com/users/ge0ffrey/events{/privacy}","received_events_url":"https://api.github.com/users/ge0ffrey/received_events","type":"User","site_admin":false},"body":"this is broken because  removing hurts the index...","created_at":"2018-08-23T13:39:26Z","updated_at":"2018-08-23T13:39:26Z","html_url":"https://github.com/kiegroup/optaplanner/pull/412#discussion_r212312207","pull_request_url":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/kiegroup/optaplanner/pulls/comments/212312207"},"html":{"href":"https://github.com/kiegroup/optaplanner/pull/412#discussion_r212312207"},"pull_request":{"href":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412"}}},"pull_request":{"url":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412","id":208232915,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA4MjMyOTE1","html_url":"https://github.com/kiegroup/optaplanner/pull/412","diff_url":"https://github.com/kiegroup/optaplanner/pull/412.diff","patch_url":"https://github.com/kiegroup/optaplanner/pull/412.patch","issue_url":"https://api.github.com/repos/kiegroup/optaplanner/issues/412","number":412,"state":"open","locked":false,"title":"New example: Flight Crew Scheduling","user":{"login":"ge0ffrey","id":176880,"node_id":"MDQ6VXNlcjE3Njg4MA==","avatar_url":"https://avatars1.githubusercontent.com/u/176880?v=4","gravatar_id":"","url":"https://api.github.com/users/ge0ffrey","html_url":"https://github.com/ge0ffrey","followers_url":"https://api.github.com/users/ge0ffrey/followers","following_url":"https://api.github.com/users/ge0ffrey/following{/other_user}","gists_url":"https://api.github.com/users/ge0ffrey/gists{/gist_id}","starred_url":"https://api.github.com/users/ge0ffrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ge0ffrey/subscriptions","organizations_url":"https://api.github.com/users/ge0ffrey/orgs","repos_url":"https://api.github.com/users/ge0ffrey/repos","events_url":"https://api.github.com/users/ge0ffrey/events{/privacy}","received_events_url":"https://api.github.com/users/ge0ffrey/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-08-14T10:15:16Z","updated_at":"2018-08-23T13:39:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9d855c7454290d6da9aaef499f35c68c2b5eda7b","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412/commits","review_comments_url":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412/comments","review_comment_url":"https://api.github.com/repos/kiegroup/optaplanner/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kiegroup/optaplanner/issues/412/comments","statuses_url":"https://api.github.com/repos/kiegroup/optaplanner/statuses/f57313b47e83d915b181cfa69681e819963a2cb3","head":{"label":"ge0ffrey:airlinecrewscheduling","ref":"airlinecrewscheduling","sha":"f57313b47e83d915b181cfa69681e819963a2cb3","user":{"login":"ge0ffrey","id":176880,"node_id":"MDQ6VXNlcjE3Njg4MA==","avatar_url":"https://avatars1.githubusercontent.com/u/176880?v=4","gravatar_id":"","url":"https://api.github.com/users/ge0ffrey","html_url":"https://github.com/ge0ffrey","followers_url":"https://api.github.com/users/ge0ffrey/followers","following_url":"https://api.github.com/users/ge0ffrey/following{/other_user}","gists_url":"https://api.github.com/users/ge0ffrey/gists{/gist_id}","starred_url":"https://api.github.com/users/ge0ffrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ge0ffrey/subscriptions","organizations_url":"https://api.github.com/users/ge0ffrey/orgs","repos_url":"https://api.github.com/users/ge0ffrey/repos","events_url":"https://api.github.com/users/ge0ffrey/events{/privacy}","received_events_url":"https://api.github.com/users/ge0ffrey/received_events","type":"User","site_admin":false},"repo":{"id":1792278,"node_id":"MDEwOlJlcG9zaXRvcnkxNzkyMjc4","name":"optaplanner","full_name":"ge0ffrey/optaplanner","owner":{"login":"ge0ffrey","id":176880,"node_id":"MDQ6VXNlcjE3Njg4MA==","avatar_url":"https://avatars1.githubusercontent.com/u/176880?v=4","gravatar_id":"","url":"https://api.github.com/users/ge0ffrey","html_url":"https://github.com/ge0ffrey","followers_url":"https://api.github.com/users/ge0ffrey/followers","following_url":"https://api.github.com/users/ge0ffrey/following{/other_user}","gists_url":"https://api.github.com/users/ge0ffrey/gists{/gist_id}","starred_url":"https://api.github.com/users/ge0ffrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ge0ffrey/subscriptions","organizations_url":"https://api.github.com/users/ge0ffrey/orgs","repos_url":"https://api.github.com/users/ge0ffrey/repos","events_url":"https://api.github.com/users/ge0ffrey/events{/privacy}","received_events_url":"https://api.github.com/users/ge0ffrey/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ge0ffrey/optaplanner","description":"This is my fork. Go to the blessed repo instead!","fork":true,"url":"https://api.github.com/repos/ge0ffrey/optaplanner","forks_url":"https://api.github.com/repos/ge0ffrey/optaplanner/forks","keys_url":"https://api.github.com/repos/ge0ffrey/optaplanner/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ge0ffrey/optaplanner/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ge0ffrey/optaplanner/teams","hooks_url":"https://api.github.com/repos/ge0ffrey/optaplanner/hooks","issue_events_url":"https://api.github.com/repos/ge0ffrey/optaplanner/issues/events{/number}","events_url":"https://api.github.com/repos/ge0ffrey/optaplanner/events","assignees_url":"https://api.github.com/repos/ge0ffrey/optaplanner/assignees{/user}","branches_url":"https://api.github.com/repos/ge0ffrey/optaplanner/branches{/branch}","tags_url":"https://api.github.com/repos/ge0ffrey/optaplanner/tags","blobs_url":"https://api.github.com/repos/ge0ffrey/optaplanner/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ge0ffrey/optaplanner/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ge0ffrey/optaplanner/git/refs{/sha}","trees_url":"https://api.github.com/repos/ge0ffrey/optaplanner/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ge0ffrey/optaplanner/statuses/{sha}","languages_url":"https://api.github.com/repos/ge0ffrey/optaplanner/languages","stargazers_url":"https://api.github.com/repos/ge0ffrey/optaplanner/stargazers","contributors_url":"https://api.github.com/repos/ge0ffrey/optaplanner/contributors","subscribers_url":"https://api.github.com/repos/ge0ffrey/optaplanner/subscribers","subscription_url":"https://api.github.com/repos/ge0ffrey/optaplanner/subscription","commits_url":"https://api.github.com/repos/ge0ffrey/optaplanner/commits{/sha}","git_commits_url":"https://api.github.com/repos/ge0ffrey/optaplanner/git/commits{/sha}","comments_url":"https://api.github.com/repos/ge0ffrey/optaplanner/comments{/number}","issue_comment_url":"https://api.github.com/repos/ge0ffrey/optaplanner/issues/comments{/number}","contents_url":"https://api.github.com/repos/ge0ffrey/optaplanner/contents/{+path}","compare_url":"https://api.github.com/repos/ge0ffrey/optaplanner/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ge0ffrey/optaplanner/merges","archive_url":"https://api.github.com/repos/ge0ffrey/optaplanner/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ge0ffrey/optaplanner/downloads","issues_url":"https://api.github.com/repos/ge0ffrey/optaplanner/issues{/number}","pulls_url":"https://api.github.com/repos/ge0ffrey/optaplanner/pulls{/number}","milestones_url":"https://api.github.com/repos/ge0ffrey/optaplanner/milestones{/number}","notifications_url":"https://api.github.com/repos/ge0ffrey/optaplanner/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ge0ffrey/optaplanner/labels{/name}","releases_url":"https://api.github.com/repos/ge0ffrey/optaplanner/releases{/id}","deployments_url":"https://api.github.com/repos/ge0ffrey/optaplanner/deployments","created_at":"2011-05-24T07:49:08Z","updated_at":"2018-07-18T18:54:48Z","pushed_at":"2018-08-22T17:25:53Z","git_url":"git://github.com/ge0ffrey/optaplanner.git","ssh_url":"git@github.com:ge0ffrey/optaplanner.git","clone_url":"https://github.com/ge0ffrey/optaplanner.git","svn_url":"https://github.com/ge0ffrey/optaplanner","homepage":"https://www.optaplanner.org/","size":170207,"stargazers_count":9,"watchers_count":9,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":9,"default_branch":"master"}},"base":{"label":"kiegroup:master","ref":"master","sha":"89498c7266aa602f71f4c7a5eaa1b6db3783fcaf","user":{"login":"kiegroup","id":517980,"node_id":"MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==","avatar_url":"https://avatars3.githubusercontent.com/u/517980?v=4","gravatar_id":"","url":"https://api.github.com/users/kiegroup","html_url":"https://github.com/kiegroup","followers_url":"https://api.github.com/users/kiegroup/followers","following_url":"https://api.github.com/users/kiegroup/following{/other_user}","gists_url":"https://api.github.com/users/kiegroup/gists{/gist_id}","starred_url":"https://api.github.com/users/kiegroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kiegroup/subscriptions","organizations_url":"https://api.github.com/users/kiegroup/orgs","repos_url":"https://api.github.com/users/kiegroup/repos","events_url":"https://api.github.com/users/kiegroup/events{/privacy}","received_events_url":"https://api.github.com/users/kiegroup/received_events","type":"Organization","site_admin":false},"repo":{"id":1370858,"node_id":"MDEwOlJlcG9zaXRvcnkxMzcwODU4","name":"optaplanner","full_name":"kiegroup/optaplanner","owner":{"login":"kiegroup","id":517980,"node_id":"MDEyOk9yZ2FuaXphdGlvbjUxNzk4MA==","avatar_url":"https://avatars3.githubusercontent.com/u/517980?v=4","gravatar_id":"","url":"https://api.github.com/users/kiegroup","html_url":"https://github.com/kiegroup","followers_url":"https://api.github.com/users/kiegroup/followers","following_url":"https://api.github.com/users/kiegroup/following{/other_user}","gists_url":"https://api.github.com/users/kiegroup/gists{/gist_id}","starred_url":"https://api.github.com/users/kiegroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kiegroup/subscriptions","organizations_url":"https://api.github.com/users/kiegroup/orgs","repos_url":"https://api.github.com/users/kiegroup/repos","events_url":"https://api.github.com/users/kiegroup/events{/privacy}","received_events_url":"https://api.github.com/users/kiegroup/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kiegroup/optaplanner","description":"Java Constraint Solver to solve vehicle routing, employee rostering and other planning problems.","fork":false,"url":"https://api.github.com/repos/kiegroup/optaplanner","forks_url":"https://api.github.com/repos/kiegroup/optaplanner/forks","keys_url":"https://api.github.com/repos/kiegroup/optaplanner/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kiegroup/optaplanner/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kiegroup/optaplanner/teams","hooks_url":"https://api.github.com/repos/kiegroup/optaplanner/hooks","issue_events_url":"https://api.github.com/repos/kiegroup/optaplanner/issues/events{/number}","events_url":"https://api.github.com/repos/kiegroup/optaplanner/events","assignees_url":"https://api.github.com/repos/kiegroup/optaplanner/assignees{/user}","branches_url":"https://api.github.com/repos/kiegroup/optaplanner/branches{/branch}","tags_url":"https://api.github.com/repos/kiegroup/optaplanner/tags","blobs_url":"https://api.github.com/repos/kiegroup/optaplanner/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kiegroup/optaplanner/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kiegroup/optaplanner/git/refs{/sha}","trees_url":"https://api.github.com/repos/kiegroup/optaplanner/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kiegroup/optaplanner/statuses/{sha}","languages_url":"https://api.github.com/repos/kiegroup/optaplanner/languages","stargazers_url":"https://api.github.com/repos/kiegroup/optaplanner/stargazers","contributors_url":"https://api.github.com/repos/kiegroup/optaplanner/contributors","subscribers_url":"https://api.github.com/repos/kiegroup/optaplanner/subscribers","subscription_url":"https://api.github.com/repos/kiegroup/optaplanner/subscription","commits_url":"https://api.github.com/repos/kiegroup/optaplanner/commits{/sha}","git_commits_url":"https://api.github.com/repos/kiegroup/optaplanner/git/commits{/sha}","comments_url":"https://api.github.com/repos/kiegroup/optaplanner/comments{/number}","issue_comment_url":"https://api.github.com/repos/kiegroup/optaplanner/issues/comments{/number}","contents_url":"https://api.github.com/repos/kiegroup/optaplanner/contents/{+path}","compare_url":"https://api.github.com/repos/kiegroup/optaplanner/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kiegroup/optaplanner/merges","archive_url":"https://api.github.com/repos/kiegroup/optaplanner/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kiegroup/optaplanner/downloads","issues_url":"https://api.github.com/repos/kiegroup/optaplanner/issues{/number}","pulls_url":"https://api.github.com/repos/kiegroup/optaplanner/pulls{/number}","milestones_url":"https://api.github.com/repos/kiegroup/optaplanner/milestones{/number}","notifications_url":"https://api.github.com/repos/kiegroup/optaplanner/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kiegroup/optaplanner/labels{/name}","releases_url":"https://api.github.com/repos/kiegroup/optaplanner/releases{/id}","deployments_url":"https://api.github.com/repos/kiegroup/optaplanner/deployments","created_at":"2011-02-15T19:38:23Z","updated_at":"2018-08-23T09:28:02Z","pushed_at":"2018-08-23T08:32:47Z","git_url":"git://github.com/kiegroup/optaplanner.git","ssh_url":"git@github.com:kiegroup/optaplanner.git","clone_url":"https://github.com/kiegroup/optaplanner.git","svn_url":"https://github.com/kiegroup/optaplanner","homepage":"https://www.optaplanner.org","size":170680,"stargazers_count":886,"watchers_count":886,"language":"Java","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":441,"mirror_url":null,"archived":false,"open_issues_count":6,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":441,"open_issues":6,"watchers":886,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412"},"html":{"href":"https://github.com/kiegroup/optaplanner/pull/412"},"issue":{"href":"https://api.github.com/repos/kiegroup/optaplanner/issues/412"},"comments":{"href":"https://api.github.com/repos/kiegroup/optaplanner/issues/412/comments"},"review_comments":{"href":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412/comments"},"review_comment":{"href":"https://api.github.com/repos/kiegroup/optaplanner/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kiegroup/optaplanner/pulls/412/commits"},"statuses":{"href":"https://api.github.com/repos/kiegroup/optaplanner/statuses/f57313b47e83d915b181cfa69681e819963a2cb3"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"ge0ffrey"}}