example-in-django-waiting-r.../waiting_room/tasks.py

112 lines
3.8 KiB
Python
Raw Permalink Normal View History

2024-11-07 16:20:51 +01:00
from django.conf import settings
import redis
from huey.contrib.djhuey import task, lock_task
2024-11-05 11:46:00 +01:00
import operator
2024-11-07 08:17:10 +01:00
from django.template.loader import render_to_string
2024-11-05 11:46:00 +01:00
from itertools import permutations
from collections import Counter
from functools import reduce
from math import factorial
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
2024-11-07 16:20:51 +01:00
2024-11-07 08:17:10 +01:00
def render_progress_bar(group_name, progress, result=None):
2024-11-05 11:46:00 +01:00
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
group_name,
{
'type': 'channel_message',
2024-11-07 08:17:10 +01:00
'message': render_to_string('components/tasks/update.html', {
'progress': progress,
'result': result,
}),
2024-11-05 11:46:00 +01:00
}
)
2024-11-07 16:20:51 +01:00
def render_location_in_the_queue(group_name, location):
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
group_name,
{
'type': 'channel_message',
'message': render_to_string('components/tasks/location.html', {
'location': location,
}),
}
)
2024-11-05 11:46:00 +01:00
@task()
def calculate_min_distance(group_name):
# Distance matrix between cities
distances = [
[0, 29, 20, 21, 16, 31, 100, 12, 5, 78],
[29, 0, 15, 29, 28, 40, 72, 21, 29, 41],
[20, 15, 0, 15, 14, 25, 81, 9, 23, 27],
[21, 29, 15, 0, 4, 12, 92, 12, 25, 13],
[16, 28, 14, 4, 0, 16, 94, 9, 20, 16],
[31, 40, 25, 12, 16, 0, 95, 24, 36, 3],
[100, 72, 81, 92, 94, 95, 0, 90, 101, 99],
[12, 21, 9, 12, 9, 24, 90, 0, 15, 25],
[5, 29, 23, 25, 20, 36, 101, 15, 0, 35],
[78, 41, 27, 13, 16, 3, 99, 25, 35, 0],
]
num_cities = len(distances)
cities = list(range(num_cities))
def count_permutations(sequence):
total = factorial(len(sequence))
duplicates = Counter(sequence).values()
divisor = reduce(operator.mul, (factorial(v) for v in duplicates), 1)
return total / divisor
def calculate_shortest_route(distances):
shortest_route = float("inf")
city_count = 0
# Calculate all possible permutations of cities (routes)
total_permutations = count_permutations(cities)
percentaje = 0
for perm in permutations(cities):
# Send progress to the group
temp_percentaje = int(city_count / total_permutations * 100)
if temp_percentaje != percentaje:
percentaje = temp_percentaje
render_progress_bar(group_name, percentaje)
city_count += 1
# Calculate the distance of the route
route_distance = 0
for i in range(num_cities - 1):
route_distance += distances[perm[i]][perm[i + 1]]
route_distance += distances[perm[-1]][perm[0]] # Back to the start city
shortest_route = min(shortest_route, route_distance)
2024-11-07 08:17:10 +01:00
render_progress_bar(group_name, 100, shortest_route)
2024-11-05 11:46:00 +01:00
return shortest_route
return calculate_shortest_route(distances)
2024-11-07 16:20:51 +01:00
@task()
@lock_task('run-queue-lock')
def run_tasks_from_queue():
notify_of_new_position()
# Get the first task from the queue
redis_conn = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0)
task = redis_conn.lindex('enqueue', 0)
if task:
# Run task
r = calculate_min_distance(task.decode('utf-8'))
# Wait for task to finish
r(blocking=True)
# Run the next task
redis_conn.lpop('enqueue')
run_tasks_from_queue()
@task()
def notify_of_new_position():
redis_conn = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0)
for index, group_name in enumerate(redis_conn.lrange('enqueue', 0, -1)):
render_location_in_the_queue(group_name.decode('utf-8'), index )