Commit 81225ae2 authored by Diego Iván's avatar Diego Iván
Browse files

agregando metodo para tomar los lugares validados en una ruta

parent 45e2e7e9
Loading
Loading
Loading
Loading
+64 −9
Original line number Diff line number Diff line
import { RecommendPlace } from '../dto/recommend-route.dto';
import { DataFrame, Series } from './math';
import { customSort } from './sort';
import { customSort, sortByClose } from './sort';

export class RecommendationsSystem {
  getCategories(places: RecommendPlace[]): number[] {
  private visited: RecommendPlace[] = [];
  private candidates: RecommendPlace[] = [];
  private start: number = 0;
  private end: number = 0;

  constructor(visited: RecommendPlace[], candidates: RecommendPlace[], start: number, end: number) {
    this.visited = visited;
    this.candidates = candidates;
    this.start = start;
    this.end = end;
  }

  private getCategories(places: RecommendPlace[]): number[] {
    const categories = new Set<number>();
    for (const place of places) {
      for (const category of place.categories) {
@@ -13,7 +25,7 @@ export class RecommendationsSystem {
    return Array.from(categories);
  }

  oneHotEncode(categories: number[], placesToEncode: RecommendPlace[]): DataFrame {
  private oneHotEncode(categories: number[], placesToEncode: RecommendPlace[]): DataFrame {
    const data: DataFrame = {};
    for (const category of categories) {
      data[category] = [];
@@ -24,7 +36,7 @@ export class RecommendationsSystem {
    return data;
  }

  rankVisited(visited: RecommendPlace[]): Series {
  private rankVisited(visited: RecommendPlace[]): Series {
    const visitedCategories = this.getCategories(visited);
    const visitedEncoded = this.oneHotEncode(visitedCategories, visited);
    const grades = visited.map((place) => place.rating);
@@ -44,7 +56,7 @@ export class RecommendationsSystem {
    return result;
  }

  rankCandidates(candidates: RecommendPlace[], visited: Series): [number, number][] {
  private rankCandidates(candidates: RecommendPlace[], visited: Series): [number, number][] {
    const visitedCategories = Object.keys(visited).map(Number);
    const candidatesEncoded = this.oneHotEncode(visitedCategories, candidates);

@@ -62,9 +74,52 @@ export class RecommendationsSystem {
    return ranked;
  }

  recommend(visited: RecommendPlace[], candidates: RecommendPlace[]) {
    const visitedRanking = this.rankVisited(visited);
    const candidatesRanked = this.rankCandidates(candidates, visitedRanking);
    return candidatesRanked;
  takeTopNValid(recommendations: [number, number][]): RecommendPlace[] {
    const validRecommendations: RecommendPlace[] = [];

    // Filtrar los lugares que existen en candidates
    for (const [id] of recommendations) {
      const place = this.candidates.find((candidate) => candidate.idPlace === id);
      if (place) {
        validRecommendations.push(place);
      }
    }

    validRecommendations.sort(sortByClose);

    const chosen: RecommendPlace[] = [];
    let currentTime = this.start; // Tiempo inicial de la ruta

    for (const place of validRecommendations) {
      // Verificar si el lugar está abierto y si se puede acomodar dentro del horario
      const maxStart = Math.max(currentTime, place.openAt);
      const minEnd = Math.min((currentTime + 2) % 24, place.closeAt);

      if (minEnd - 2 >= maxStart) {
        // Verificar si aún hay tiempo suficiente en el rango total de la ruta
        if ((currentTime + 2) % 24 <= this.end) {
          // Actualizar el lugar con el nuevo horario dentro de la ruta
          place.openAt = Math.max(currentTime, place.openAt);
          place.closeAt = (place.openAt + 2) % 24;

          chosen.push(place);

          // Actualizar la hora actual para el siguiente lugar
          currentTime = (currentTime + 2) % 24;
        } else {
          // Si ya no hay tiempo suficiente para otro lugar, terminamos el bucle
          break;
        }
      }
    }

    return chosen;
  }

  recommend(): RecommendPlace[] {
    const visitedRanking = this.rankVisited(this.visited);
    const candidatesRanked = this.rankCandidates(this.candidates, visitedRanking);
    const chosen = this.takeTopNValid(candidatesRanked);
    return chosen;
  }
}