mirror of
https://github.com/task-17-lct/backend.git
synced 2024-11-13 09:26:33 +03:00
add route generation route
This commit is contained in:
parent
5115deef66
commit
b229e017a0
226
passfinder/events/api/consts.py
Normal file
226
passfinder/events/api/consts.py
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
city_in_hotels = ['Абзаково',
|
||||||
|
'Абрамовка',
|
||||||
|
'Абрау-Дюрсо',
|
||||||
|
'Адлер',
|
||||||
|
'Азов',
|
||||||
|
'Аксай',
|
||||||
|
'Альметьевск',
|
||||||
|
'Анапа',
|
||||||
|
'Андрианово',
|
||||||
|
'Арамиль',
|
||||||
|
'Арзамас',
|
||||||
|
'Арнеево',
|
||||||
|
'Архипо-Осиповка',
|
||||||
|
'Бабкино',
|
||||||
|
'Базы отдыха ВТО',
|
||||||
|
'Балашиха',
|
||||||
|
'Батайск',
|
||||||
|
'Беличье',
|
||||||
|
'Белореченск',
|
||||||
|
'Бердск',
|
||||||
|
'Бердяш',
|
||||||
|
'Березовка',
|
||||||
|
'Бжид',
|
||||||
|
'Битца',
|
||||||
|
'Благовещенская',
|
||||||
|
'Болтино',
|
||||||
|
'Большой Сочи',
|
||||||
|
'Бор, Нижегородская область',
|
||||||
|
'Борисово',
|
||||||
|
'Борносово',
|
||||||
|
'Будённовск',
|
||||||
|
'Вардане',
|
||||||
|
'Васильево, Ленинградская область',
|
||||||
|
'Васкелово',
|
||||||
|
'Вербилки',
|
||||||
|
'Веселовка, Краснодарский край',
|
||||||
|
'Видное',
|
||||||
|
'Витязево',
|
||||||
|
'Владимировка',
|
||||||
|
'Внуково',
|
||||||
|
'Воскресенск',
|
||||||
|
'Вотря',
|
||||||
|
'Всеволожск',
|
||||||
|
'Всходы',
|
||||||
|
'Выборг',
|
||||||
|
'Вырубово',
|
||||||
|
'Гатчина',
|
||||||
|
'Гвардейское',
|
||||||
|
'Геленджик',
|
||||||
|
'Голиково',
|
||||||
|
'Головинка Краснодарский край',
|
||||||
|
'Голубицкая',
|
||||||
|
'Горки',
|
||||||
|
'Городец',
|
||||||
|
'Горячий ключ',
|
||||||
|
'Григорчиково',
|
||||||
|
'Гуамка',
|
||||||
|
'Д/О Авангард',
|
||||||
|
'Дагомыс',
|
||||||
|
'Джемете',
|
||||||
|
'Джубга',
|
||||||
|
'Дзержинск',
|
||||||
|
'Дивеево',
|
||||||
|
'Дивногорье, Краснодарский край',
|
||||||
|
'Дивноморское',
|
||||||
|
'Дмитров',
|
||||||
|
'Домодедово',
|
||||||
|
'Дракино',
|
||||||
|
'Дранишники',
|
||||||
|
'Дубечино',
|
||||||
|
'Егорьевск',
|
||||||
|
'Ейск',
|
||||||
|
'Екатеринбург',
|
||||||
|
'Ершово',
|
||||||
|
'Ессентуки',
|
||||||
|
'Железноводск',
|
||||||
|
'Жуковский',
|
||||||
|
'За Родину',
|
||||||
|
'Звенигород',
|
||||||
|
'Зеленая поляна',
|
||||||
|
'Ивантеевка',
|
||||||
|
'Ильичево',
|
||||||
|
'Иннолово ',
|
||||||
|
'Иноземцево',
|
||||||
|
'Исаково',
|
||||||
|
'Истра',
|
||||||
|
'Кабардинка',
|
||||||
|
'Казань',
|
||||||
|
'Каменск-Шахтинский',
|
||||||
|
'Каневская',
|
||||||
|
'Кингисепп',
|
||||||
|
'Кисловодск',
|
||||||
|
'Клин',
|
||||||
|
'Коломна',
|
||||||
|
'Коробицыно',
|
||||||
|
'Королев',
|
||||||
|
'Косулино',
|
||||||
|
'Котельники',
|
||||||
|
'Красная Горка',
|
||||||
|
'Красная Поляна',
|
||||||
|
'Красногорск',
|
||||||
|
'Краснодар',
|
||||||
|
'Красный Колос',
|
||||||
|
'Кудряшовский',
|
||||||
|
'Курово',
|
||||||
|
'Кусимовского Рудника',
|
||||||
|
'Кучугуры',
|
||||||
|
'Лабинск',
|
||||||
|
'Лазаревское',
|
||||||
|
'Лермонтово',
|
||||||
|
'Лесной городок',
|
||||||
|
'Лодейное Поле',
|
||||||
|
'Лоо',
|
||||||
|
'Лосево',
|
||||||
|
'Люберцы',
|
||||||
|
'Магнитогорск',
|
||||||
|
'Малые Решники',
|
||||||
|
'Марьино, Ленинградская область',
|
||||||
|
'Маяковского',
|
||||||
|
'Мезмай',
|
||||||
|
'Мещерино',
|
||||||
|
'Миасс',
|
||||||
|
'Минеральные Воды',
|
||||||
|
'Мистолово',
|
||||||
|
'Мишуткино',
|
||||||
|
'Можайск',
|
||||||
|
'Москва',
|
||||||
|
'Мостовской',
|
||||||
|
'Мытищи',
|
||||||
|
'Набережные Челны',
|
||||||
|
'Наро-Фоминск',
|
||||||
|
'Нарынка',
|
||||||
|
'Небуг',
|
||||||
|
'Нестерово',
|
||||||
|
'Нижний Новгород',
|
||||||
|
'Нижний Тагил',
|
||||||
|
'Новая',
|
||||||
|
'Новоабзаково',
|
||||||
|
'Нововолково',
|
||||||
|
'Новомихайловский',
|
||||||
|
'Новороссийск',
|
||||||
|
'Новосибирск',
|
||||||
|
'Новочеркасск',
|
||||||
|
'Новый путь',
|
||||||
|
'Ногинск',
|
||||||
|
'Нурлат',
|
||||||
|
'Овсяники',
|
||||||
|
'Одинцово',
|
||||||
|
'Озеры',
|
||||||
|
'Оксино',
|
||||||
|
'Октябрьский, Московская область',
|
||||||
|
'Ольгинка',
|
||||||
|
'Остров, Московская область',
|
||||||
|
'Павловск',
|
||||||
|
'Падиково',
|
||||||
|
'Пересвет',
|
||||||
|
'Платформа 69-й километр, Сосновское сельское поселение',
|
||||||
|
'Подольск',
|
||||||
|
'Подпорожье',
|
||||||
|
'Полтавская',
|
||||||
|
'Приморско-Ахтарск',
|
||||||
|
'Приозерск',
|
||||||
|
'Прохорово',
|
||||||
|
'Пушкино',
|
||||||
|
'Пятигорск',
|
||||||
|
'Раменское',
|
||||||
|
'Реутов',
|
||||||
|
'Рождествено',
|
||||||
|
'Роза Хутор',
|
||||||
|
'Ростов-на-Дону',
|
||||||
|
'Рощино',
|
||||||
|
'Руза',
|
||||||
|
'Санкт-Петербург',
|
||||||
|
'Светлое',
|
||||||
|
'Светлый',
|
||||||
|
'Свирица',
|
||||||
|
'Сергиев Посад',
|
||||||
|
'Серпухов',
|
||||||
|
'Симагино',
|
||||||
|
'Сириус',
|
||||||
|
'Скоково',
|
||||||
|
'Снегири',
|
||||||
|
'Солнечногорск',
|
||||||
|
'Солохаул',
|
||||||
|
'Сосново',
|
||||||
|
'Сосновый Бор, Ленинградская область',
|
||||||
|
'Сосновый Бор, Московская область',
|
||||||
|
'Софрино',
|
||||||
|
'Сочи',
|
||||||
|
'Ставрополь',
|
||||||
|
'Станица Динская',
|
||||||
|
'Станица Должанская',
|
||||||
|
'Старая Руза',
|
||||||
|
'Степаньково',
|
||||||
|
'Суйда',
|
||||||
|
'Сукко',
|
||||||
|
'Супсех',
|
||||||
|
'Таганрог',
|
||||||
|
'Тарасово',
|
||||||
|
'Тимашевск',
|
||||||
|
'Тихвин',
|
||||||
|
'Тихорецк',
|
||||||
|
'Тобольск',
|
||||||
|
'Туапсе',
|
||||||
|
'Тучково',
|
||||||
|
'Тюмень',
|
||||||
|
'Увильды ',
|
||||||
|
'Углегорский',
|
||||||
|
'Удельная',
|
||||||
|
'Усть-Койсуг',
|
||||||
|
'Усть-Лабинск',
|
||||||
|
'Уфа',
|
||||||
|
'Ушаки',
|
||||||
|
'Фрязино',
|
||||||
|
'Хадыженск',
|
||||||
|
'Химки',
|
||||||
|
'Хоста',
|
||||||
|
'Чебаркуль',
|
||||||
|
'Челябинск',
|
||||||
|
'Чехов, Сахалинская область',
|
||||||
|
'Чудская',
|
||||||
|
'Шахты',
|
||||||
|
'Широкая балка',
|
||||||
|
'Щёлково',
|
||||||
|
'Эсто-Садок',
|
||||||
|
'Якорная щель']
|
|
@ -1,7 +1,7 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.generics import get_object_or_404
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
from passfinder.events.models import Hotel, HotelPhone, City, Event, BasePoint, Region
|
from passfinder.events.models import Hotel, HotelPhone, City, Event, BasePoint, Region, Restaurant
|
||||||
|
|
||||||
|
|
||||||
class HotelPhoneSerializer(serializers.ModelSerializer):
|
class HotelPhoneSerializer(serializers.ModelSerializer):
|
||||||
|
@ -49,7 +49,7 @@ class RouteSerializer(serializers.Serializer):
|
||||||
class RouteInputSerializer(serializers.Serializer):
|
class RouteInputSerializer(serializers.Serializer):
|
||||||
date_from = serializers.DateField(required=False, allow_null=True)
|
date_from = serializers.DateField(required=False, allow_null=True)
|
||||||
date_to = serializers.DateField(required=False, allow_null=True)
|
date_to = serializers.DateField(required=False, allow_null=True)
|
||||||
region = serializers.CharField(
|
city = serializers.CharField(
|
||||||
min_length=24, max_length=24, required=False, allow_blank=True, allow_null=True
|
min_length=24, max_length=24, required=False, allow_blank=True, allow_null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -106,3 +106,16 @@ def validate(self, data):
|
||||||
|
|
||||||
class InputRouteSerializer(serializers.Serializer):
|
class InputRouteSerializer(serializers.Serializer):
|
||||||
points = serializers.ListSerializer(child=InputRoutePointSerializer())
|
points = serializers.ListSerializer(child=InputRoutePointSerializer())
|
||||||
|
|
||||||
|
|
||||||
|
class ResaurantSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Restaurant
|
||||||
|
exclude = ('phones', )
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectRouteSerializer(serializers.Serializer):
|
||||||
|
lat = serializers.FloatField()
|
||||||
|
lon = serializers.FloatField()
|
||||||
|
title = serializers.CharField()
|
||||||
|
description = serializers.CharField()
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
from rest_framework.generics import GenericAPIView, ListAPIView, get_object_or_404
|
from rest_framework.generics import GenericAPIView, ListAPIView, get_object_or_404
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from drf_spectacular.utils import extend_schema
|
from drf_spectacular.utils import extend_schema
|
||||||
|
from django.db.models import Count
|
||||||
|
from random import choice
|
||||||
|
from passfinder.recomendations.service.service import generate_tour
|
||||||
|
from datetime import timedelta, datetime
|
||||||
|
from .consts import *
|
||||||
|
|
||||||
|
|
||||||
from passfinder.events.api.serializers import (
|
from passfinder.events.api.serializers import (
|
||||||
PointSerializer,
|
PointSerializer,
|
||||||
|
@ -46,34 +52,34 @@ def post(self, request):
|
||||||
serializer = RouteInputSerializer(data=request.data)
|
serializer = RouteInputSerializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
data = serializer.data
|
data = serializer.data
|
||||||
region = data["region"]
|
city_id = data["city"]
|
||||||
routes = []
|
start_date = datetime.strptime(data['date_from'], '%Y-%m-%d')
|
||||||
if region:
|
end_date = datetime.strptime(data['date_to'], '%Y-%m-%d')
|
||||||
region = get_object_or_404(Region, oid=region)
|
region = None
|
||||||
for _ in range(2):
|
|
||||||
routes.append(
|
if city_id:
|
||||||
{
|
region = get_object_or_404(City, oid=city_id)
|
||||||
"name": "bebra",
|
|
||||||
"date": data["date_from"],
|
|
||||||
"description": "bebra bebra bebra",
|
|
||||||
"points": PointSerializer(many=True).to_representation(
|
|
||||||
region.points.all().order_by("?")[:10]
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
for _ in range(10):
|
region = choice(City.objects.annotate(points_count=Count('points')).filter(title__in=city_in_hotels))
|
||||||
routes.append(
|
|
||||||
{
|
if not start_date and end_date:
|
||||||
"name": "bebra",
|
tour_length = choice([timedelta(days=i) for i in range(1, 4)])
|
||||||
"date": data["date_from"],
|
start_date = end_date - tour_length
|
||||||
"description": "bebra bebra bebra",
|
if not end_date and start_date:
|
||||||
"points": PointSerializer(many=True).to_representation(
|
tour_length = choice([timedelta(days=i) for i in range(1, 4)])
|
||||||
BasePoint.objects.order_by("?")[:10]
|
end_date = end_date + tour_length
|
||||||
),
|
if not end_date and not start_date:
|
||||||
}
|
max_date = datetime.now() + timedelta(days=15)
|
||||||
)
|
start_date = choice([max_date - timedelta(days=i) for i in range(1, 5)])
|
||||||
return Response(data=routes)
|
tour_length = choice([timedelta(days=i) for i in range(1, 4)])
|
||||||
|
end_date = start_date + tour_length
|
||||||
|
|
||||||
|
print(request.user, region, start_date, end_date)
|
||||||
|
|
||||||
|
tour = generate_tour(request.user, region, start_date, end_date)
|
||||||
|
print(len(tour[1]))
|
||||||
|
|
||||||
|
return Response(data=tour[0])
|
||||||
|
|
||||||
|
|
||||||
class ListRegionApiView(ListAPIView):
|
class ListRegionApiView(ListAPIView):
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Generated by Django 4.2.1 on 2023-05-24 15:57
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("events", "0019_category_pointcategory_delete_tag"),
|
||||||
|
("recomendations", "0005_userpreferences_prefferred_attractions_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="NearestRestaurantToHotel",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"hotel",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE, to="events.hotel"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("restaurants", models.ManyToManyField(to="events.restaurant")),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="NearestRestaurantToEvent",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"event",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE, to="events.event"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("restaurants", models.ManyToManyField(to="events.restaurant")),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,6 +1,6 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from passfinder.users.models import User
|
from passfinder.users.models import User
|
||||||
from passfinder.events.models import Event, Hotel
|
from passfinder.events.models import Event, Hotel, Restaurant
|
||||||
|
|
||||||
|
|
||||||
class UserPreferences(models.Model):
|
class UserPreferences(models.Model):
|
||||||
|
@ -27,7 +27,36 @@ class NearestEvent(models.Model):
|
||||||
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='nearest_model_rel')
|
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='nearest_model_rel')
|
||||||
nearest = models.ManyToManyField(Event, related_name='nearest_model_rev_rel')
|
nearest = models.ManyToManyField(Event, related_name='nearest_model_rev_rel')
|
||||||
|
|
||||||
|
"""
|
||||||
|
from passfinder.recomendations.service.service import generate_tour
|
||||||
|
|
||||||
|
from passfinder.users.models import User
|
||||||
|
|
||||||
|
from passfinder.events.models import City
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
start_date = datetime(year=2023, month=6, day=10)
|
||||||
|
end_date = datetime(year=2023, month=6, day=13)
|
||||||
|
|
||||||
|
c = City.objects.get(title='Таганрог')
|
||||||
|
|
||||||
|
u = User.objects.all()[0]
|
||||||
|
|
||||||
|
generate_tour(u, c, start_date, end_date)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
class NearestHotel(models.Model):
|
class NearestHotel(models.Model):
|
||||||
hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, related_name='nearest_hotel_rel')
|
hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, related_name='nearest_hotel_rel')
|
||||||
nearest_events = models.ManyToManyField(Event, related_name='nearest_hotel_rev_rel')
|
nearest_events = models.ManyToManyField(Event, related_name='nearest_hotel_rev_rel')
|
||||||
|
|
||||||
|
|
||||||
|
class NearestRestaurantToEvent(models.Model):
|
||||||
|
event = models.ForeignKey(Event, on_delete=models.CASCADE)
|
||||||
|
restaurants = models.ManyToManyField(Restaurant)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class NearestRestaurantToHotel(models.Model):
|
||||||
|
hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE)
|
||||||
|
restaurants = models.ManyToManyField(Restaurant)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from annoy import AnnoyIndex
|
from annoy import AnnoyIndex
|
||||||
from .mapping.mapping import *
|
from .mapping.mapping import *
|
||||||
from .models.models import *
|
from .models.models import *
|
||||||
from passfinder.events.models import Event, Region, Hotel, BasePoint, City
|
from passfinder.events.models import Event, Region, Hotel, BasePoint, City, Restaurant
|
||||||
from passfinder.recomendations.models import UserPreferences, NearestEvent, NearestHotel
|
from passfinder.events.api.serializers import HotelSerializer, EventSerializer, ResaurantSerializer, ObjectRouteSerializer
|
||||||
|
from passfinder.recomendations.models import *
|
||||||
from random import choice, sample
|
from random import choice, sample
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from passfinder.users.models import User
|
from passfinder.users.models import User
|
||||||
|
@ -10,6 +11,7 @@
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from geopy.distance import geodesic as GD
|
from geopy.distance import geodesic as GD
|
||||||
from datetime import timedelta, time, datetime
|
from datetime import timedelta, time, datetime
|
||||||
|
from gevent.pool import Pool
|
||||||
|
|
||||||
|
|
||||||
def get_nearest_(instance_model, model_type, mapping, rev_mapping, nearest_n, ml_model):
|
def get_nearest_(instance_model, model_type, mapping, rev_mapping, nearest_n, ml_model):
|
||||||
|
@ -250,14 +252,14 @@ def get_personal_movies_recommendation(user):
|
||||||
|
|
||||||
|
|
||||||
def dist_func(event1: Event, event2: Event):
|
def dist_func(event1: Event, event2: Event):
|
||||||
# cords1 = [event1.lat, event1.lon]
|
cords1 = [event1.lat, event1.lon]
|
||||||
# cords2 = [event2.lat, event2.lon]
|
cords2 = [event2.lat, event2.lon]
|
||||||
# try:
|
try:
|
||||||
# dist = GD(cords1, cords2).km
|
dist = GD(cords1, cords2).km
|
||||||
# return dist
|
return dist
|
||||||
# except:
|
except:
|
||||||
# return 1000000
|
return 1000000
|
||||||
return (event1.lon - event2.lon) ** 2 + (event1.lat - event2.lat) ** 2
|
#return (event1.lon - event2.lon) ** 2 + (event1.lat - event2.lat) ** 2
|
||||||
|
|
||||||
|
|
||||||
def generate_nearest():
|
def generate_nearest():
|
||||||
|
@ -288,6 +290,26 @@ def generate_hotel_nearest():
|
||||||
print(i)
|
print(i)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_nearest_restaurants():
|
||||||
|
rests = list(Restaurant.objects.all())
|
||||||
|
for i, event in enumerate(Event.objects.all()):
|
||||||
|
sorted_rests = list(sorted(rests.copy(), key=lambda x: dist_func(x, event)))
|
||||||
|
nr = NearestRestaurantToEvent.objects.create(event=event)
|
||||||
|
nr.restaurants.set(sorted_rests[0:20])
|
||||||
|
nr.save()
|
||||||
|
if i % 100 == 0:
|
||||||
|
print(i)
|
||||||
|
|
||||||
|
for i, hotel in enumerate(Hotel.objects.all()):
|
||||||
|
sorted_rests = list(sorted(rests.copy(), key=lambda x: dist_func(x, hotel)))
|
||||||
|
nr = NearestRestaurantToHotel.objects.create(hotel=hotel)
|
||||||
|
nr.restaurants.set(sorted_rests[0:20])
|
||||||
|
nr.save()
|
||||||
|
if i % 100 == 0:
|
||||||
|
print(i)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def match_points():
|
def match_points():
|
||||||
regions = list(City.objects.all())
|
regions = list(City.objects.all())
|
||||||
for i, point in enumerate(Event.objects.all()):
|
for i, point in enumerate(Event.objects.all()):
|
||||||
|
@ -339,14 +361,18 @@ def calculate_favorite_metric(event: Event, user: User):
|
||||||
def get_nearest_favorite(
|
def get_nearest_favorite(
|
||||||
events: Iterable[Event], user: User, exclude_events: Iterable[Event] = []
|
events: Iterable[Event], user: User, exclude_events: Iterable[Event] = []
|
||||||
):
|
):
|
||||||
|
print(events)
|
||||||
first_event = None
|
first_event = None
|
||||||
for candidate in events:
|
for candidate in events:
|
||||||
if candidate not in exclude_events:
|
if candidate not in exclude_events:
|
||||||
first_event = candidate
|
first_event = candidate
|
||||||
break
|
break
|
||||||
|
|
||||||
result = first_event
|
if first_event is None:
|
||||||
result_min = calculate_favorite_metric(result, user)
|
result = events[0]
|
||||||
|
else:
|
||||||
|
result = first_event
|
||||||
|
result_min = 1000000
|
||||||
for event in events:
|
for event in events:
|
||||||
if event in exclude_events:
|
if event in exclude_events:
|
||||||
continue
|
continue
|
||||||
|
@ -372,50 +398,142 @@ def generate_route(point1: BasePoint, point2: BasePoint):
|
||||||
time = time_func(distance)
|
time = time_func(distance)
|
||||||
return {
|
return {
|
||||||
"type": "transition",
|
"type": "transition",
|
||||||
"from": point1,
|
|
||||||
"to": point2,
|
|
||||||
"distance": distance,
|
"distance": distance,
|
||||||
"time": time,
|
"time": time.seconds,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def generate_point(point: BasePoint):
|
def generate_point(point: BasePoint):
|
||||||
|
event_data = ObjectRouteSerializer(point).data
|
||||||
return {
|
return {
|
||||||
"type": "point",
|
"type": "point",
|
||||||
"point": point,
|
"point": event_data,
|
||||||
"point_type": "",
|
"point_type": "point",
|
||||||
"time": timedelta(minutes=90+choice(range(-10, 90, 10)))
|
"time": timedelta(minutes=90+choice(range(-10, 90, 10))).seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
def generate_path(region: Region, user: User):
|
|
||||||
|
def generate_restaurant(point: BasePoint):
|
||||||
|
rest_data = ObjectRouteSerializer(point).data
|
||||||
|
|
||||||
|
return {
|
||||||
|
"type": "point",
|
||||||
|
"point": rest_data,
|
||||||
|
"point_type": "restaurant",
|
||||||
|
"time": timedelta(minutes=90+choice(range(-10, 90, 10))).seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def generate_multiple_tours(user: User, city: City, start_date: datetime.date, end_date: datetime.date):
|
||||||
|
hotels = sample(list(Hotel.objects.filter(city=city)), 5)
|
||||||
|
pool = Pool(5)
|
||||||
|
return pool.map(generate_tour, [(user, start_date, end_date, hotel) for hotel in hotels])
|
||||||
|
|
||||||
|
|
||||||
|
def generate_tour(user: User, city: City, start_date: datetime.date, end_date: datetime.date):
|
||||||
|
print("start hotel")
|
||||||
|
hotel = choice(list(Hotel.objects.filter(city=city)))
|
||||||
|
print("end hotel")
|
||||||
|
current_date = start_date
|
||||||
|
paths, points = [], []
|
||||||
|
|
||||||
|
while current_date < end_date:
|
||||||
|
print("start day gen")
|
||||||
|
local_points, local_paths = generate_path(user, points, hotel)
|
||||||
|
points.extend(local_points)
|
||||||
|
paths.append(
|
||||||
|
{
|
||||||
|
'date': current_date,
|
||||||
|
'paths': local_paths
|
||||||
|
}
|
||||||
|
)
|
||||||
|
print("end day gen")
|
||||||
|
|
||||||
|
current_date += timedelta(days=1)
|
||||||
|
|
||||||
|
return paths, points
|
||||||
|
|
||||||
|
|
||||||
|
def generate_hotel(hotel: Hotel):
|
||||||
|
hotel_data = ObjectRouteSerializer(hotel).data
|
||||||
|
return {
|
||||||
|
"type": "point",
|
||||||
|
"point": hotel_data,
|
||||||
|
"point_type": "hotel",
|
||||||
|
"time": timedelta(minutes=90+choice(range(-10, 90, 10))).seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def generate_path(user: User, disallowed_points: Iterable[BasePoint], hotel: Hotel):
|
||||||
# region_events = Event.objects.filter(region=region)
|
# region_events = Event.objects.filter(region=region)
|
||||||
|
|
||||||
hotel = filter_hotel(region, user, [])
|
#candidates = NearestHotel.objects.get(hotel=hotel).nearest_events.all()
|
||||||
|
allowed_types = ['museum', 'attraction']
|
||||||
|
|
||||||
candidates = NearestHotel.objects.get(hotel=hotel).nearest_events.all()
|
print("start start point gen")
|
||||||
|
start_point = NearestRestaurantToHotel.objects.get(hotel=hotel).restaurants.first()
|
||||||
start_point = get_nearest_favorite(candidates, user, [])
|
print("end start point gen")
|
||||||
|
|
||||||
candidates = NearestEvent.objects.get(event=start_point).nearest.all()
|
|
||||||
|
|
||||||
|
print("start first cand gen")
|
||||||
|
candidates = list(filter(lambda x: x.type in allowed_types, map(lambda x: x.event, start_point.nearestrestauranttoevent_set.all()[0:100])))
|
||||||
|
print("end first cand gen")
|
||||||
points = [start_point]
|
points = [start_point]
|
||||||
|
path = [
|
||||||
path = [generate_point(points[-1])]
|
generate_hotel(hotel),
|
||||||
|
generate_route(start_point, hotel),
|
||||||
|
generate_restaurant(points[-1])
|
||||||
|
]
|
||||||
|
|
||||||
start_time = datetime.combine(datetime.now(), time(hour=10))
|
start_time = datetime.combine(datetime.now(), time(hour=10))
|
||||||
|
|
||||||
while start_time.hour < 22:
|
how_many_eat = 1
|
||||||
candidates = NearestEvent.objects.get(event=points[-1]).nearest.all()
|
|
||||||
points.append(get_nearest_favorite(candidates, user, points))
|
|
||||||
|
|
||||||
|
|
||||||
|
while start_time.hour < 22:
|
||||||
|
print(start_time)
|
||||||
|
if (start_time.hour > 13 and how_many_eat == 1) or (start_time.hour > 20 and how_many_eat == 2):
|
||||||
|
print("start rest event gen")
|
||||||
|
point = NearestRestaurantToEvent.objects.get(event=points[-1]).restaurants.all()[0]
|
||||||
|
points.append(point)
|
||||||
|
candidates = list(filter(lambda x: x.type in allowed_types, map(lambda x: x.event, point.nearestrestauranttoevent_set.all()[0:100])))
|
||||||
|
if not len(candidates):
|
||||||
|
candidates = list(map(lambda x: x.event, point.nearestrestauranttoevent_set.all()[0:100]))
|
||||||
|
|
||||||
|
path.append(generate_restaurant(points[-1]))
|
||||||
|
start_time += timedelta(seconds=path[-1]['time'])
|
||||||
|
how_many_eat += 1
|
||||||
|
print("start rest event gen")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if start_time.hour > 17:
|
||||||
|
allowed_types = ['play', 'concert', 'movie']
|
||||||
|
|
||||||
|
print("start events gen")
|
||||||
|
if candidates is None:
|
||||||
|
candidates = NearestEvent.objects.get(event=points[-1]).nearest.filter(type__in=allowed_types)
|
||||||
|
if not len(candidates):
|
||||||
|
candidates = NearestEvent.objects.get(event=points[-1]).nearest.all()
|
||||||
|
print("end events gen")
|
||||||
|
|
||||||
|
print("start events select")
|
||||||
|
try:
|
||||||
|
print(points)
|
||||||
|
points.append(get_nearest_favorite(candidates, user, points + disallowed_points))
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
points.append(get_nearest_favorite(candidates, user, points))
|
||||||
|
print("end events select")
|
||||||
|
|
||||||
|
print("start route gen")
|
||||||
transition_route = generate_route(points[-1], points[-2])
|
transition_route = generate_route(points[-1], points[-2])
|
||||||
start_time += transition_route["time"]
|
start_time += timedelta(seconds=transition_route["time"])
|
||||||
|
|
||||||
point_route = generate_point(points[-1])
|
point_route = generate_point(points[-1])
|
||||||
start_time += point_route["time"]
|
start_time += timedelta(seconds=point_route["time"])
|
||||||
path.extend([transition_route, point_route])
|
path.extend([transition_route, point_route])
|
||||||
|
candidates = None
|
||||||
return hotel, points, path
|
print("end route gen")
|
||||||
|
return points, path
|
||||||
|
|
||||||
|
|
||||||
def calculate_distance(sample1: Event, samples: Iterable[Event], model: AnnoyIndex, rev_mapping):
|
def calculate_distance(sample1: Event, samples: Iterable[Event], model: AnnoyIndex, rev_mapping):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user