add generation logic

This commit is contained in:
ilia 2023-05-23 17:51:01 +03:00
parent 67260adb55
commit 7d8f0578f5
5 changed files with 178 additions and 32 deletions

View File

@ -291,7 +291,7 @@
CELERY_REDIS_DB = env("CELERY_REDIS_DB", default=0)
CELERY_REDIS_SSL = env.bool("CELERY_REDIS_SSL", default=False)
CELERY_BROKER_URL = env("CELERY_BROKER_URL")
CELERY_BROKER_URL = env("CELERY_BROKER_URL", default='')
CELERY_TASK_SERIALIZER = "json"
CELERY_ACCEPT_CONTENT = ["application/json"]
CELERY_ENABLE_UTC = True
@ -346,7 +346,7 @@
# ------------------------------------------------------------------------------
CLICKHOUSE_DATABASES = {
"default": {
"db_url": env("CLICKHOUSE_URL", default="http://localhost:8123"),
"db_url": env("CLICKHOUSE_URL", default="http://akarpov.ru:1337"),
"db_name": env("CLICKHOUSE_DB", default="default"),
"username": env("CLICKHOUSE_USER", default="default"),
"password": env("CLICKHOUSE_PASSWORD", default="default"),

View File

@ -0,0 +1,43 @@
# Generated by Django 4.2.1 on 2023-05-23 09:32
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("events", "0016_remove_basepoint_location_remove_city_location_and_more"),
("recomendations", "0003_nearestevent"),
]
operations = [
migrations.CreateModel(
name="NearestHotel",
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,
related_name="nearest_hotel_rel",
to="events.hotel",
),
),
(
"nearest_events",
models.ManyToManyField(
related_name="nearest_hotel_rev_rel", to="events.event"
),
),
],
),
]

View File

@ -1,6 +1,6 @@
from django.db import models
from passfinder.users.models import User
from passfinder.events.models import Event
from passfinder.events.models import Event, Hotel
class UserPreferences(models.Model):
@ -18,4 +18,9 @@ class UserPreferences(models.Model):
class NearestEvent(models.Model):
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')
class NearestHotel(models.Model):
hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE, related_name='nearest_hotel_rel')
nearest_events = models.ManyToManyField(Event, related_name='nearest_hotel_rev_rel')

View File

@ -6,8 +6,20 @@
excursion_mapping = None
concert_mapping = None
rev_attraction_mapping = None
rev_cinema_mapping = None
rev_plays_mapping = None
rev_excursion_mapping = None
rev_concert_mapping = None
def build_dict(list_mapping):
mapping = {}
for idx, elem in enumerate(list_mapping):
mapping.update({idx: elem})
return mapping
def build_rev_dict(list_mapping):
mapping = {}
for idx, elem in enumerate(list_mapping):
mapping.update({elem: idx})
@ -15,20 +27,30 @@ def build_dict(list_mapping):
with open('passfinder/recomendations/service/mapping/attractions.pickle', 'rb') as file:
attraction_mapping = build_dict(pickle.load(file))
lst = pickle.load(file)
attraction_mapping = build_dict(lst)
rev_attraction_mapping = build_rev_dict(lst)
with open('passfinder/recomendations/service/mapping/kino.pickle', 'rb') as file:
cinema_mapping = build_dict(pickle.load(file))
lst = pickle.load(file)
cinema_mapping = build_dict(lst)
rev_cinema_mapping = build_rev_dict(lst)
with open('passfinder/recomendations/service/mapping/spektakli.pickle', 'rb') as file:
plays_mapping = build_dict(pickle.load(file))
lst = pickle.load(file)
plays_mapping = build_dict(lst)
rev_plays_mapping = build_rev_dict(lst)
with open('passfinder/recomendations/service/mapping/excursii.pickle', 'rb') as file:
excursion_mapping = build_dict(pickle.load(file))
lst = pickle.load(file)
excursion_mapping = build_dict(lst)
rev_excursion_mapping = build_rev_dict(lst)
with open('passfinder/recomendations/service/mapping/concerts.pickle', 'rb') as file:
concert_mapping = build_dict(pickle.load(file))
lst = pickle.load(file)
concert_mapping = build_dict(lst)
rev_concert_mapping = build_rev_dict(lst)

View File

@ -1,18 +1,21 @@
from annoy import AnnoyIndex
from .mapping.mapping import *
from .models.models import *
from passfinder.events.models import Event, Region
from passfinder.recomendations.models import UserPreferences, NearestEvent
from passfinder.events.models import Event, Region, Hotel, BasePoint, City
from passfinder.recomendations.models import UserPreferences, NearestEvent, NearestHotel
from random import choice
from collections import Counter
from passfinder.users.models import User
from collections.abc import Iterable
from django.db.models import Q
from geopy.distance import geodesic as GD
from datetime import timedelta, time, datetime
def get_nearest_(instance_model, model_type, mapping, nearest_n, ml_model):
def get_nearest_(instance_model, model_type, mapping, rev_mapping, nearest_n, ml_model):
how_many = len(Event.objects.filter(type=model_type))
index = mapping[instance_model.oid]
index = rev_mapping[instance_model.oid]
nearest = ml_model.get_nns_by_item(index, len(mapping))
res = []
@ -25,23 +28,23 @@ def get_nearest_(instance_model, model_type, mapping, nearest_n, ml_model):
def nearest_attraction(attraction, nearest_n):
return get_nearest_(attraction, 'attraction', attraction_mapping, nearest_n, attracion_model)
return get_nearest_(attraction, 'attraction', attraction_mapping, rev_attraction_mapping, nearest_n, attracion_model)
def nearest_movie(movie, nearest_n):
return get_nearest_(movie, 'movie', cinema_mapping, nearest_n, cinema_model)
return get_nearest_(movie, 'movie', cinema_mapping, rev_cinema_mapping, nearest_n, cinema_model)
def nearest_plays(play, nearest_n):
return get_nearest_(play, 'plays', plays_mapping, nearest_n, plays_model)
return get_nearest_(play, 'plays', plays_mapping, rev_plays_mapping, nearest_n, plays_model)
def nearest_excursion(excursion, nearest_n):
return get_nearest_(excursion, 'excursion', excursion_mapping, nearest_n, excursion_model)
return get_nearest_(excursion, 'excursion', excursion_mapping, rev_excursion_mapping, nearest_n, excursion_model)
def nearest_concert(concert, nearest_n):
return get_nearest_(concert, 'concert', concert_mapping, nearest_n, concert_model)
return get_nearest_(concert, 'concert', concert_mapping, rev_concert_mapping, nearest_n, concert_model)
def get_nearest_event(event, nearest_n):
@ -188,7 +191,9 @@ def get_personal_movies_recommendation(user):
def dist_func(event1: Event, event2: Event):
return (event1.lat - event2.lat) ** 2 + (event2.lon - event2.lon) ** 2
cords1 = [event1.lat, event1.lon]
cords2 = [event2.lat, event2.lon]
return GD(cords1, cords2).km
def generate_nearest():
@ -203,14 +208,33 @@ def generate_nearest():
print(i)
def calculate_mean_metric(favorite_events: Iterable[Event], target_event: Event, model: AnnoyIndex, rev_list: Iterable[str]):
def generate_hotel_nearest():
NearestHotel.objects.all().delete()
all_events = list(Event.objects.all())
hotels = list(Hotel.objects.all())
for i, hotel in enumerate(hotels):
event_all_events = list(sorted(all_events.copy(), key=lambda x: dist_func(hotel, x)))
nearest = NearestHotel.objects.create(hotel=hotel)
nearest.nearest_events.set(event_all_events[0:100])
if i % 100 == 0:
print(i)
def match_museums():
regions = list(Region.objects.all())
for museum in Event.objects.filter(type='museum'):
s_regions = list(sorted(regions.copy(), key=lambda x: dist_func(museum, x)))
museum.region = s_regions[0]
museum.save()
def calculate_mean_metric(favorite_events: Iterable[Event], target_event: Event, model: AnnoyIndex, rev_mapping):
if not len(favorite_events):
return 100000
dists = []
target_event_idx = rev_list[target_event.oid]
target_event_idx = rev_mapping[target_event.oid]
for fav in favorite_events:
dists.append(model.get_distance(rev_list[fav.oid], target_event_idx))
dists.append(model.get_distance(rev_mapping[fav.oid], target_event_idx))
return sum(dists) / len(dists)
@ -222,7 +246,7 @@ def calculate_favorite_metric(event: Event, user: User):
preferred,
event,
plays_model,
plays_mapping
rev_plays_mapping
)
if event.type == 'concert':
preferred = pref.preferred_concerts.all()
@ -230,7 +254,7 @@ def calculate_favorite_metric(event: Event, user: User):
preferred,
event,
concert_model,
concert_mapping
rev_concert_mapping
)
if event.type == 'movie':
preferred = pref.preffered_movies.all()
@ -238,14 +262,21 @@ def calculate_favorite_metric(event: Event, user: User):
preferred,
event,
cinema_model,
cinema_mapping
rev_cinema_mapping
)
return 1000000
def get_nearest_favorite(events: Iterable[Event], user: User, exclude_events: Iterable[Event]=[]):
result = events[0]
result_min = calculate_favorite_metric(events[0], user)
first_event = None
for candidate in events:
if candidate not in exclude_events:
first_event = candidate
break
result = first_event
result_min = calculate_favorite_metric(result, user)
for event in events:
if event in exclude_events: continue
local_min_metric = calculate_favorite_metric(event, user)
@ -256,17 +287,62 @@ def get_nearest_favorite(events: Iterable[Event], user: User, exclude_events: It
return result
def generate_path(region: Region, user: User):
region_events = Event.objects.filter(region=region)
def filter_hotel(region: Region, user: User, stars: Iterable[int]):
hotels = Hotel.objects.filter(region=region)
return choice(hotels)
start_point = get_nearest_favorite(region_events, user, [])
def time_func(km_distance: float):
return timedelta(minutes=(km_distance) / (4.0 / 60))
def generate_route(point1: BasePoint, point2: BasePoint):
distance = dist_func(point1, point2)
time = time_func(distance)
return {
"type": "transition",
"from": point1,
"to": point2,
"distance": distance,
"time": time
}
def generate_point(point: BasePoint):
return {
"type": "point",
"point": point,
"point_type": "",
"time": timedelta(minutes=90+choice(range(-80, 90, 10)))
}
def generate_path(region: Region, user: User):
#region_events = Event.objects.filter(region=region)
hotel = filter_hotel(region, user, [])
candidates = NearestHotel.objects.get(hotel=hotel).nearest_events.all()
start_point = get_nearest_favorite(candidates, user, [])
candidates = NearestEvent.objects.get(event=start_point).nearest.all()
points = [start_point]
while len(points) < 5:
path = [generate_point(points[-1])]
start_time = datetime.combine(datetime.now(), time(hour=10))
while start_time.hour < 22:
candidates = NearestEvent.objects.get(event=points[-1]).nearest.all()
points.append(get_nearest_favorite(candidates, user, points))
transition_route = generate_route(points[-1], points[-2])
start_time += transition_route['time']
point_route = generate_point(points[-1])
start_time += point_route['time']
path.extend([transition_route, point_route])
return points
return hotel, points, path