import datetime from django.utils.translation import gettext as _ from django.utils.html import escape from .models import Participant, Date, Event def slots2string( participant : Participant | None, n_slots : int ) -> str : """ Convert the slots of a participant to a string. """ if not participant: return '0' * n_slots # Get the slots of the participant byte_array = participant.slots # Convert the slots to a string string_value = bin(int.from_bytes(byte_array, byteorder='big'))[2:] # Pad the string with 0s if necessary return '0' * (n_slots - len(string_value)) + string_value def string2slots( string : str, n_slots : int ) -> bytes : """ Convert a string to a byte array. """ if len(string) != n_slots: raise ValueError(_("Invalid string length: {0} (expected: {1})").format(len(string), n_slots)) # Convert the string to a byte array return int(string, 2).to_bytes((n_slots + 7) // 8, byteorder='big') def get_slot_count( event ) -> int : """ Get the number of slots in an event. """ # Get the timespan of the event start_time = datetime.datetime.combine(datetime.date.today(), event.start_time) end_time = datetime.datetime.combine(datetime.date.today(), event.end_time) if(start_time>end_time): end_time += datetime.timedelta(days=1) timespan = end_time - start_time # Get the number of slots in the event days = event.date_set.count() slots_per_day = int(timespan.total_seconds() // event.slot_interval.total_seconds()) return days * slots_per_day def slots2grid( event : Event, participants : list[Participant], is_input : bool) -> dict : """ Convert the slots of an event to data for the grid. """ # Get the number of slots in the event n_slots = get_slot_count(event) # Get the timespan of the event start_time = datetime.datetime.combine(datetime.date.today(), event.start_time) end_time = datetime.datetime.combine(datetime.date.today(), event.end_time) if(start_time>end_time): end_time += datetime.timedelta(days=1) timespan = end_time - start_time # Get the slots in a day slots_per_day = int(timespan.total_seconds() // event.slot_interval.total_seconds()) # Get the slots of each day participant_slot_strings = [slots2string(participant, n_slots) for participant in participants] if is_input: html = [] for n, date in reversed(list(enumerate(event.date_set.all()))): day_offset = n * slots_per_day dt = datetime.datetime.combine(date.date, datetime.time()) html += f'
{ dt.strftime("%b %d") }
' slots = [] # Fill the slots of the day for j in range(slots_per_day): slot_begin = (start_time + j * event.slot_interval).strftime('%H:%M') slot_end = (start_time + (j+1) * event.slot_interval).strftime('%H:%M') current_time = start_time + j * event.slot_interval if current_time.minute == 0: time_label = f'
{current_time.strftime("%H:%M")}
' classes = " full-hour" elif current_time.minute == 30: time_label = "" classes = " half-hour" else: time_label = "" classes = "" checked = "" for i in range(len(participant_slot_strings)): if participant_slot_strings[i][day_offset + j] == '1': checked = 'checked' break slots.append( f'
{ time_label }
') html.append(''.join(slots)) html.append('
') return "".join(html) else: max_occupancy = 1 html = [] for n, date in reversed(list(enumerate(event.date_set.all()))): day_offset = n * slots_per_day dt = datetime.datetime.combine(date.date, datetime.time()) html.append(f'
{ dt.strftime("%b %d") }
') slots = [] # Get participants for each slot slot_participants = [[] for i in range(slots_per_day)] for j in range(slots_per_day): for i in range(len(participant_slot_strings)): if participant_slot_strings[i][day_offset + j] == '1': slot_participants[j].append(i) # Fill the slots of the day for j, ps in enumerate(slot_participants): slot_begin = (start_time + j * event.slot_interval).strftime('%H:%M') slot_end = (start_time + (j+1) * event.slot_interval).strftime('%H:%M') current_time = start_time + j * event.slot_interval if current_time.minute == 0: time_label = f'
{current_time.strftime("%H:%M")}
' classes = " full-hour" elif current_time.minute == 30: time_label = "" classes = " half-hour" else: time_label = "" classes = "" slots.append( f'
{ time_label }
') max_occupancy = max(max_occupancy, len(ps)) html.append(''.join(slots)) html.append('
') return f'
{"".join(html)}
'