in use-cases/vaccination-scheduling/src/main/resources/META-INF/resources/app.js [5:202]
function refreshSolution() {
$.getJSON("/vaccinationSchedule?page=0", function (schedule) {
refreshSolvingButtons(schedule.solverStatus != null && schedule.solverStatus !== "NOT_SOLVING");
$("#score").text("Score: " + (schedule.score == null ? "?" : schedule.score));
const vaccineTypesDiv = $("#vaccineTypes");
vaccineTypesDiv.children().remove();
const vaccineTypeMap = new Map();
schedule.vaccineTypeList.forEach((vaccineType) => {
const color = pickColor(vaccineType.name);
vaccineTypesDiv.append($(`<div class="card" style="background-color: ${color}"/>`)
.append($(`<div class="card-body p-2"/>`)
.append($(`<h5 class="card-title mb-0"/>`).text(vaccineType.name))));
vaccineTypeMap.set(vaccineType.name, vaccineType);
});
const scheduleTable = $("#scheduleTable");
scheduleTable.children().remove();
vaccineCenterLeafletGroup.clearLayers();
const unassignedPeronsDiv = $("#unassignedPersons");
unassignedPeronsDiv.children().remove();
if (schedule.appointmentList.size > 10000) {
scheduleTable.append($(`<p/>`)
.text("There are " + schedule.appointmentList.size + " appointments. Too much data to show a schedule."));
return;
}
const vaccinationCenterMap = new Map(
schedule.vaccinationCenterList.map(vaccinationCenter => [vaccinationCenter.id, vaccinationCenter]));
const dateTimeSet = new Set();
const dateTimeList = [];
const vaccinationCenterIdToBoothIdSetMap = new Map(
schedule.vaccinationCenterList.map(vaccinationCenter => [vaccinationCenter.id, new Set()]));
schedule.appointmentList.forEach((appointment) => {
const dateTime = moment(appointment.dateTime, "YYYY,M,D,H,m");
const dateTimeString = dateTime.format("YYYY MMM D HH:mm")
if (!dateTimeSet.has(dateTimeString)) {
dateTimeSet.add(dateTimeString);
dateTimeList.push(dateTime);
}
vaccinationCenterIdToBoothIdSetMap.get(appointment.vaccinationCenter).add(appointment.boothId);
});
dateTimeList.sort((a, b) => a.unix() - b.unix());
const thead = $("<thead>").appendTo(scheduleTable);
const headerRow = $("<tr>").appendTo(thead);
headerRow.append($("<th>Time</th>"));
schedule.vaccinationCenterList.forEach((vaccinationCenter) => {
const boothIdSet = vaccinationCenterIdToBoothIdSetMap.get(vaccinationCenter.id);
boothIdSet.forEach((boothId) => {
headerRow
.append($("<th/>")
.append($("<span/>").text(vaccinationCenter.name + (boothIdSet.size <= 1 ? "" : " booth " + boothId))));
});
});
const appointmentMap = new Map(schedule.appointmentList
.map(appointment => [moment(appointment.dateTime, "YYYY,M,D,H,m") + "/" + appointment.vaccinationCenter + "/" + appointment.boothId, appointment]));
if (schedule.appointmentList.length !== appointmentMap.size) {
var conflicts = schedule.appointmentList.length - appointmentMap.size;
scheduleTable.append($(`<p class="badge badge-danger">There are ${conflicts} double bookings.</span>`));
}
const appointmentToPersonMap = new Map();
schedule.personList.forEach((person) => {
if (person.appointment != null) {
appointmentToPersonMap.set(moment(person.appointment.dateTime, "YYYY,M,D,H,m") + "/" + person.appointment.vaccinationCenter + "/" + person.appointment.boothId, person);
}
});
const tbody = $(`<tbody>`).appendTo(scheduleTable);
var previousDateTime = null;
dateTimeList.forEach((dateTime) => {
const row = $(`<tr>`).appendTo(tbody);
var showDate = (previousDateTime == null || !dateTime.isSame(previousDateTime, "day"));
row
.append($(`<th class="align-middle"/>`)
.append($(`<span style="float: right"/>`).text(showDate ? dateTime.format("ddd MMM D HH:mm") : dateTime.format("HH:mm"))));
previousDateTime = dateTime;
schedule.vaccinationCenterList.forEach((vaccinationCenter) => {
const boothIdSet = vaccinationCenterIdToBoothIdSetMap.get(vaccinationCenter.id);
boothIdSet.forEach((boothId) => {
var appointment = appointmentMap.get(dateTime + "/" + vaccinationCenter.id + "/" + boothId);
if (appointment == null) {
row.append($(`<td class="p-1"/>`));
} else {
const color = pickColor(appointment.vaccineType);
var cardBody = $(`<div class="card-body pt-1 pb-1 pl-2 pr-2"/>`);
const person = appointmentToPersonMap.get(dateTime + "/" + vaccinationCenter.id + "/" + boothId);
if (person == null) {
cardBody.append($(`<h5 class="card-title mb-0"/>`).text("Unassigned"));
} else {
var appointmentDateTime = moment(appointment.dateTime, "YYYY,M,D,H,m");
var birthdate = moment(person.birthdate, "YYYY,M,D");
var age = appointmentDateTime.diff(birthdate, 'years')
cardBody.append($(`<h5 class="card-title mb-1"/>`)
.text(person.name + " (" + age + ")"));
const vaccineType = vaccineTypeMap.get(appointment.vaccineType);
if (vaccineType.maximumAge != null && age > vaccineType.maximumAge) {
cardBody.append($(`<p class="badge badge-danger mb-0"/>`).text(vaccineType.name + " maximum age is " + vaccineType.maximumAge));
}
if (person.requiredVaccineType != null
&& appointment.vaccineType !== person.requiredVaccineType) {
cardBody.append($(`<p class="badge badge-danger ml-2 mb-0"/>`).text("Required vaccine is " + person.requiredVaccineType));
}
if (person.preferredVaccineType != null
&& appointment.vaccineType !== person.preferredVaccineType) {
cardBody.append($(`<p class="badge badge-warning ml-2 mb-0"/>`).text("Preferred vaccine is " + person.preferredVaccineType));
}
if (person.requiredVaccinationCenter != null
&& appointment.vaccinationCenter !== person.requiredVaccinationCenter) {
const requiredVaccinationCenter = vaccinationCenterMap.get(person.requiredVaccinationCenter);
cardBody.append($(`<p class="badge badge-danger ml-2 mb-0"/>`).text("Required vaccination center is " + requiredVaccinationCenter.name));
}
if (person.preferredVaccinationCenter != null
&& appointment.vaccinationCenter !== person.preferredVaccinationCenter) {
const preferredVaccinationCenter = vaccinationCenterMap.get(person.preferredVaccinationCenter);
cardBody.append($(`<p class="badge badge-warning ml-2 mb-0"/>`).text("Preferred vaccination center is " + preferredVaccinationCenter.name));
}
if (person.readyDate != null) {
var readyDate = moment(person.readyDate, "YYYY,M,D");
var readyDateDiff = appointmentDateTime.diff(readyDate, 'days');
if (readyDateDiff < 0) {
cardBody.append($(`<p class="badge badge-danger ml-2 mb-0"/>`).text("Dose is " + (-readyDateDiff) + " days too early"));
}
}
if (person.dueDate != null) {
var dueDate = moment(person.dueDate, "YYYY,M,D");
var dueDateDiff = appointmentDateTime.diff(dueDate, 'days');
if (dueDateDiff > 0) {
cardBody.append($(`<p class="badge badge-danger ml-2 mb-0"/>`).text("Dose is " + (dueDateDiff) + " days too late"));
}
}
var dosePrefix = person.doseNumber.toString() + ((person.doseNumber === 1) ? "st" : "nd");
var doseSuffix = "";
if (person.idealDate != null) {
var idealDate = moment(person.idealDate, "YYYY,M,D");
var idealDateDiff = appointmentDateTime.diff(idealDate, 'days');
doseSuffix = " (" + (idealDateDiff === 0 ? "ideal day"
: (idealDateDiff < 0 ? (-idealDateDiff) + " days too early"
: idealDateDiff + " days too late")) + ")";
}
cardBody.append($(`<p class="card-text ml-2 mb-0"/>`).text(dosePrefix + " dose" + doseSuffix));
}
row.append($(`<td class="p-1"/>`)
.append($(`<div class="card" style="background-color: ${color}"/>`)
.append(cardBody)));
}
});
});
});
schedule.vaccinationCenterList.forEach((vaccinationCenter) => {
L.marker(vaccinationCenter.location).addTo(vaccineCenterLeafletGroup);
});
var assignedPersonCount = 0;
var unassignedPersonCount = 0;
personLeafletGroup.clearLayers();
schedule.personList.forEach((person) => {
const appointment = person.appointment;
const personColor = (appointment == null ? "gray" : pickColor(appointment.vaccineType));
L.circleMarker(person.homeLocation, {radius: 4, color: personColor, weight: 2}).addTo(personLeafletGroup);
if (person.requiredVaccineType != null) {
const requiredVaccineTypeColor = pickColor(person.requiredVaccineType);
L.circleMarker(person.homeLocation, {radius: 3, color: requiredVaccineTypeColor, weight: 0, fillOpacity: 1.0}).addTo(personLeafletGroup);
}
if (appointment != null) {
assignedPersonCount++;
const vaccinationCenter = vaccinationCenterMap.get(appointment.vaccinationCenter);
L.polyline([person.homeLocation, vaccinationCenter.location], {color: personColor, weight: 1}).addTo(personLeafletGroup);
} else {
unassignedPersonCount++;
var firstDateTime = dateTimeList[0];
var birthdate = moment(person.birthdate, "YYYY,M,D");
var age = firstDateTime.diff(birthdate, 'years');
var dosePrefix = person.doseNumber.toString() + ((person.doseNumber === 1) ? "st" : "nd");
var doseSuffix = "";
if (person.requiredVaccineType != null) {
const vaccineType = vaccineTypeMap.get(person.requiredVaccineType);
doseSuffix += " " + vaccineType.name;
}
if (person.idealDate != null) {
doseSuffix += " (ideally " + moment(person.idealDate, "YYYY,M,D").format("ddd MMM D") + ")";
}
unassignedPeronsDiv.append($(`<div class="card"/>`)
.append($(`<div class="card-body pt-1 pb-1 pl-2 pr-2"/>`)
.append($(`<h5 class="card-title mb-1"/>`).text(person.name + " (" + age + ")"))
.append($(`<p class="card-text ml-2"/>`).text(dosePrefix + " dose" + doseSuffix))));
}
});
$("#assignedPersonCount").text(assignedPersonCount);
$("#unassignedPersonCount").text(unassignedPersonCount);
});
}