Estoy trabajando en un sistema de colas para una clínica. La persona en la recepción tiene dos opciones para agregar pacientes a la cola.

  1. Pacientes con citas fijas.
  2. Pacientes sin cita

Entonces, por ejemplo, ya hay cuatro pacientes en la cola, mi matriz de citas existente parece

existing_appointments = ["09:30", "10:00", "12:15", "13:45"];

Y el tiempo promedio de revisión para una paciente es de 15 minutos.

avg_wait_per_patient = 15;

Tan pronto como entra un paciente, encuentro el mejor horario disponible para él.

Digamos que la hora en este momento es 09:00

current_time = "09:00";

La siguiente función find_free_slot() no funciona porque devuelve 09:15 en lugar de 09:00 ya que no hay cita en este espacio.

Lo que pretendo lograr es que, si no hay nadie cerca de current_time + avg_wait_per_patient, la persona debería tener un espacio current_time. Si esta ranura no está disponible, debería recorrer la matriz a menos que encuentre una libre. Y si falla, la persona debe agregarse a la hora en last_index_of_array + avg_wait.

function toMinutes(t) {
    return 60 * Number(t.split(":")[0]) + Number(t.split(":")[1]);
}
function reverse_toMinutes(t) {
    return ("0" + Math.floor(t / 60)).slice(-2) + ":" + ("0" + t % 60).slice(-2);
}
function find_free_slot(ct,appointments,avg_wait) {
    ct = toMinutes(ct);
    free_slot = '';
    if(appointments.length==0) {
        free_slot = ct;
    } else {
        for(i=0; i<appointments.length; i++) {
            appointment = toMinutes(appointments[i]);
            if(free_slot <= appointment - avg_wait) {
                i == 0 ?
                    free_slot = ct + avg_wait :
                    free_slot = toMinutes(appointments[i - 1]) + avg_wait;
                break;
            }
        }   
    }
    return reverse_toMinutes(free_slot);
}

jsfiddle

4
AZee 17 feb. 2017 a las 10:39

4 respuestas

La mejor respuesta

El problema está en:

i == 0 ?
    free_slot = ct + avg_wait :
    free_slot = toMinutes(appointments[i - 1]) + avg_wait;

Si está revisando la primera cita (9:30) y el espacio libre <= (9:30 - 15), entonces devuelve ct + avg_wait, que es 9:00 + 15.

He reelaborado un poco la lógica para que funcione:

function toMinutes(t) {
  return 60 * Number(t.split(":")[0]) + Number(t.split(":")[1]);
}

function reverse_toMinutes(t) {
  return ("0" + Math.floor(t / 60)).slice(-2) + ":" + ("0" + t % 60).slice(-2);
}

function find_free_slot(ct, appointments, avg_wait) {
  ct = toMinutes(ct);
  free_slot = ct;   // The first slot you want to check is "right now"

  if (appointments.length == 0)
    return reverse_toMinutes(ct);

  for (i = 0; i < appointments.length; i++) {
    appointment = toMinutes(appointments[i]);
    if (ct <= appointment + avg_wait) {        // The appointment must be later than the current appointment's end time.
      if (free_slot <= appointment - avg_wait) // Free slot is enough time before the current appointment
        return reverse_toMinutes(free_slot);   // Return the free slot

      free_slot = toMinutes(appointments[i]) + avg_wait; // Otherwise, set the free slot to `avg` after the current appointment, to check the next iteration of the loop.
    }
  }
  return reverse_toMinutes(free_slot); // No free slot has been found, `free_slot` is `last appointment + avg`
}

var appointments = ["09:30", "10:00", "12:15", "13:45"];

console.log(" time - appointment");
console.log(" 9:00 -", find_free_slot("9:00", appointments, 15));
console.log(" 9:15 -", find_free_slot("9:15", appointments, 15));
console.log(" 9:16 -", find_free_slot("9:16", appointments, 15));
console.log(" 9:31 -", find_free_slot("9:31", appointments, 15));
console.log("10:09 -", find_free_slot("10:09", appointments, 15));
console.log("11:59 -", find_free_slot("11:59", appointments, 15));
console.log("12:00 -", find_free_slot("12:00", appointments, 15));
console.log("12:01 -", find_free_slot("12:01", appointments, 15));
4
Cerbrus 17 feb. 2017 a las 08:17

Hice alguna edición, ahora está bien, tal vez también necesitará un tiempo de cierre y un tiempo de inicio para verificar.

function toMinutes(t) {
	return 60 * Number(t.split(":")[0]) + Number(t.split(":")[1]);
}
function reverse_toMinutes(t) {
	return ("0" + Math.floor(t / 60)).slice(-2) + ":" + ("0" + t % 60).slice(-2);
}

var existing_appointments = ["09:30", "10:00", "12:55", "13:45"];
var avg_wait_per_patient = 15; // in minutes
var current_time = "10:00";

function find_free_slot(ct,appointments,avg_wait) {
	ct = toMinutes(ct);
	var free_slot = '';
   
	if(appointments.length==0) {
		free_slot = ct;
	}
  else if (appointments.length==1) {
  	free_slot = toMinutes(appointments[0])+avg_wait;
	}  
  else {
    var i=0;
  	for (i=1;i<appointments.length;i++){
    	if (toMinutes(appointments[i])-toMinutes(appointments[i-1])>=2*avg_wait){
      	free_slot=toMinutes(appointments[i-1])+avg_wait;
            break;
        }    
      }
	}
  
  if (free_slot=='') free_slot=toMinutes(appointments[appointments.length-1])+avg_wait;

	return reverse_toMinutes(free_slot);
}

document.write( find_free_slot(current_time,existing_appointments,avg_wait_per_patient) );
-1
Alex Banu 17 feb. 2017 a las 08:28

Puede verificar si el siguiente espacio más el tiempo promedio es menor que la cita.

Si true, regresa, de lo contrario verifica si el tiempo más el tiempo promedio es mayor o igual al siguiente espacio abierto, luego toma el espacio más el tiempo promedio.

function getMinutes(t) {
    var p = t.split(':');
    return 60 * p[0] + +p[1];
}

function find_free_slot(current_time) {
    var next_time = getMinutes(current_time);

    existing_appointments.some(function (a) {
        var minutes = getMinutes(a);
        if (next_time + avg_wait_per_patient <= minutes) {
            return true;
        }
        next_time = minutes + avg_wait_per_patient >= next_time  ? minutes + avg_wait_per_patient : next_time;
    });
    return ('0' + Math.floor(next_time / 60)).slice(-2) + ':' + ('0' +  next_time % 60).slice(-2);
}

var existing_appointments = ["09:30", "10:00", "12:15", "13:45"],
    avg_wait_per_patient = 15;

console.log(find_free_slot('09:00')); // 09:00
console.log(find_free_slot('09:15')); // 09:15
console.log(find_free_slot('09:16')); // 09:45
console.log(find_free_slot('09:45')); // 09:45
console.log(find_free_slot('09:46')); // 10:15
console.log(find_free_slot('10:00')); // 10:15
console.log(find_free_slot('10:09')); // 10:15
console.log(find_free_slot('11:59')); // 11:59
console.log(find_free_slot('12:00')); // 12:00
console.log(find_free_slot('12:01')); // 12:30
0
Nina Scholz 17 feb. 2017 a las 08:26

Le sugiero que use la biblioteca momentjs para hacer este tipo de cálculos y formateo. Aquí hay una muestra de cómo lograr lo que desea usando moment.

function find_free_slot(ct,appointments,avg_wait) {
  existing_appointments.sort((a,b) => a-b);
  let possibleSlot = ct;
  for(let i=0; i<appointments.length; i++) {
    const a = appointments[i];
    if(a >= +possibleSlot + (avg_wait * 60000)) {
      appointments.splice(i, 0, possibleSlot);
      return possibleSlot;
    }
    const endOfCurrentSlot = a.clone().add(avg_wait,'minute');
    if(endOfCurrentSlot > possibleSlot) {
      possibleSlot = endOfCurrentSlot;
    }
  }
  appointments.push(possibleSlot);
  return possibleSlot;
  
}

const existing_appointments = [
  moment('09:30','HH:mm'),
  moment('10:00','HH:mm'),
  moment('13:45','HH:mm')
];
const avg_wait_per_patient = 15; // in minutes

function getSlotStr(time) {
  var slot = find_free_slot(time, existing_appointments, avg_wait_per_patient);
  return time.format('HH:mm') + ' --> ' + slot.format('HH:mm');
}

document.write( getSlotStr(moment('09:00','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:10','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:20','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:30','HH:mm')) + '<br />');
document.write( getSlotStr(moment('09:40','HH:mm')) + '<br />');
document.write( getSlotStr(moment('10:10','HH:mm')) + '<br />');
document.write( getSlotStr(moment('13:00','HH:mm')) + '<br />');
document.write( getSlotStr(moment('13:40','HH:mm')) + '<br />');
document.write( getSlotStr(moment('13:50','HH:mm')) + '<br />');
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
-1
Bulent Vural 17 feb. 2017 a las 08:49