Carga de horarios

master
Araozu 2022-10-14 12:05:15 -05:00
parent 44d19d97d1
commit 93eb18cd6d
3 changed files with 191 additions and 107 deletions

6
API.md
View File

@ -52,8 +52,8 @@
# Carga de horarios
```ts
// HTTP GET
// Url: /horarios?cursos=...
// HTTP POST
// Url: /horarios
// El frontend envia una lista de cursos, de los cuales recuperar sus datos
{
@ -74,13 +74,13 @@
{
id_laboratorio: number,
id_curso: number,
id_horario: number,
grupo: string,
docente: string,
// Array de objetos de la entidad Horario
horario: [
{
id_horario: number,
id_laboratorio: number,
dia: string,
hora_inicio: string,
hora_fin: string,

View File

@ -1,143 +1,52 @@
// Exclusivo de un unico dia
import { GrupoDia, TableInput } from "../src/Views/SistemasMovil/Table";
import { generarMapaCeldas, MapaCeldas } from "../src/Views/SistemasMovil/mapaCeldas";
type Input = {
horaInicio: number,
offsetVertical: number,
nroHoras: number,
}
type Output = {
horaInicio: number,
nroHoras: number,
offset: number, // 0, 1, 2
fraccion: number, // por cuanto dividir la celda. 1, 2, 3, ...
}
class MapaCeldas {
// Almacena referencias a input
private mapa: Map<number, Map<number, null>> = new Map();
private disponible(nroFila: number, nroColumna: number): boolean {
if (!this.mapa.has(nroFila)) return true;
const fila = this.mapa.get(nroFila)!;
return fila.has(nroColumna) === false;
}
private obtenerFilaOCrear(nro: number): Map<number, null> {
if (!this.mapa.has(nro)) {
const m = new Map<number, null>();
this.mapa.set(nro, m);
return m;
}
return this.mapa.get(nro)!;
}
// Devuelve el offset
public solicitar(inicio: number, cantidad: number): number {
const filas = [];
for (let i = 0; i < cantidad; i += 1) filas.push(inicio + i);
for (let offsetActual = 0; offsetActual < 8; offsetActual += 1) {
let todasCeldasDisponibles = true;
for (const fila of filas) {
if (!this.disponible(fila, offsetActual)) {
todasCeldasDisponibles = false;
break;
}
}
if (todasCeldasDisponibles) {
// Crear estas celdas y almacenar
filas.forEach((nroFila) => {
const fila = this.obtenerFilaOCrear(nroFila);
fila.set(offsetActual, null);
});
// Devolver nro de offset
return offsetActual;
}
}
throw new Error("Limite de celdas alcanzado");
}
public generarFraccion(nroFila: number, nroColumna: number, cantidad: number): number {
let fraccionActual = 1;
for (let i = 0; i < cantidad; i += 1) {
const nroFilaActual = nroFila + i;
const filaActual = this.mapa.get(nroFilaActual)!;
const numeroColumnas = filaActual.size;
if (numeroColumnas > fraccionActual) {
fraccionActual = numeroColumnas;
}
}
return fraccionActual;
}
}
function generarMapaCeldas(entrada: Readonly<Array<Input>>): Array<Output> {
const mapa = new MapaCeldas();
const salida: Array<Output> = [];
// Obtener los offsets de cada curso
for (const input of entrada) {
const offset = mapa.solicitar(input.horaInicio, input.nroHoras);
salida.push({
...input,
offset,
fraccion: -1,
});
}
// Generar las fracciones de cada curso
for (const output of salida) {
output.fraccion = mapa.generarFraccion(output.horaInicio, output.offset, output.nroHoras);
}
return salida;
}
describe("generarMapaCeldas", () => {
it("vacio si input es vacio", () => {
const input: Array<Input> = [];
const input: Array<GrupoDia> = [];
const output = generarMapaCeldas(input);
expect(output.length).toBe(0);
});
it("funciona con 1 curso", () => {
const input: Array<Input> = [
const input: Array<any> = [
{
horaInicio: 0,
offsetVertical: 0,
nroHoras: 2,
},
];
const output = generarMapaCeldas(input)[0];
expect(output).not.toBeUndefined();
expect(output.offset).toBe(0);
expect(output.offsetHorizontal).toBe(0);
expect(output.fraccion).toBe(1);
});
it("funciona con 2 cursos", () => {
const input: Array<Input> = [
const input: Array<any> = [
{
horaInicio: 0,
offsetVertical: 0,
nroHoras: 2,
},
{
horaInicio: 1,
offsetVertical: 1,
nroHoras: 3,
},
];
const output1 = generarMapaCeldas(input)[0];
expect(output1.offset).toBe(0);
expect(output1.offsetHorizontal).toBe(0);
expect(output1.fraccion).toBe(2);
const output2 = generarMapaCeldas(input)[1];
expect(output2.offset).toBe(1);
expect(output2.offsetHorizontal).toBe(1);
expect(output2.fraccion).toBe(2);
});
});

175
src/API/CargaHorarios.ts Normal file
View File

@ -0,0 +1,175 @@
/*
// HTTP POST
// Url: /horarios
// El frontend envia una lista de cursos, de los cuales recuperar sus datos
{
cursos: Array<number> // Un array de id_curso
}
// Backend responde con los cursos especificados y sus horarios
[
// Cada objeto dentro del array sera un Curso
{
id_curso: number,
id_datos_carrera: any, // Opcional
nombre_curso: string,
curso_anio: number | string,
abreviado: string,
// Un array de objetos, estos objetos son de la entidad Laboratorio
laboratorios: [
{
id_laboratorio: number,
id_curso: number,
grupo: string,
docente: string,
// Array de objetos de la entidad Horario
horario: [
{
id_horario: number,
dia: string,
hora_inicio: string,
hora_fin: string,
}
]
}
]
}
]
*/
import { SERVER_PATH } from "../Store";
export type Horario = {
id_horario: number,
id_laboratorio: number,
dia: string,
hora_inicio: string,
hora_fin: string,
}
export type Laboratorio = {
id_laboratorio: number,
id_curso: number,
grupo: string,
docente: string,
// Array de objetos de la entidad Horario
horario: Array<Horario>
}
export type CursoCompleto = {
id_curso: number,
nombre_curso: string,
curso_anio: number | string,
abreviado: string,
// Un array de objetos, estos objetos son de la entidad Laboratorio
laboratorios: Array<Laboratorio>
}
type InputData = {
cursos: Array<number>
}
export type ListaCursosCompleto = Array<CursoCompleto>
type GetHorariosFn = (_: InputData) => Promise<ListaCursosCompleto>
export const getHorarios: GetHorariosFn = async(data) => {
const response = await fetch(`${SERVER_PATH}/horarios`, {
body: JSON.stringify(data),
});
return await response.json();
};
export const getHorariosMock: GetHorariosFn = async(_) => {
const c1: CursoCompleto = {
id_curso: 0,
nombre_curso: "Gestion de Sistemas y Tecnologias de Informacion",
curso_anio: "5to",
abreviado: "GSTI",
laboratorios: [
{
id_laboratorio: 0,
id_curso: 0,
grupo: "A",
docente: "Luis Rocha",
horario: [
{
id_horario: 0,
id_laboratorio: 0,
hora_inicio: "1830",
hora_fin: "1920",
dia: "Jueves",
},
{
id_horario: 1,
id_laboratorio: 0,
hora_inicio: "1550",
hora_fin: "1740",
dia: "Viernes",
},
],
},
{
id_laboratorio: 1,
id_curso: 0,
grupo: "B",
docente: "Luis Rocha",
horario: [
{
id_horario: 2,
id_laboratorio: 1,
hora_inicio: "0700",
hora_fin: "0850",
dia: "Lunes",
},
{
id_horario: 3,
id_laboratorio: 1,
hora_inicio: "1400",
hora_fin: "1640",
dia: "Miercoles",
},
],
},
],
};
const c2: CursoCompleto = {
id_curso: 1,
nombre_curso: "Plataformas Emergentes",
curso_anio: "5to",
abreviado: "PE",
laboratorios: [
{
id_laboratorio: 2,
id_curso: 1,
grupo: "A",
docente: "Diego Iquira",
horario: [
{
id_horario: 4,
id_laboratorio: 2,
hora_inicio: "0850",
hora_fin: "0940",
dia: "Jueves",
},
],
},
{
id_laboratorio: 3,
id_curso: 1,
grupo: "B",
docente: "Diego Iquira",
horario: [
{
id_horario: 5,
id_laboratorio: 3,
hora_inicio: "1740",
hora_fin: "1830",
dia: "Martes",
},
],
},
],
};
return [c1, c2];
};