From e4bde20397ebf957809dfe9a48678232b3d68818 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Wed, 24 Jul 2024 11:25:59 +0200 Subject: [PATCH] fix:#3 refactored functions --- frontend/src/api/fetchRoomOccupancy.ts | 35 ++------ .../src/components/RoomOccupationOffline.vue | 38 ++++----- frontend/src/model/roomOccupancyList.ts | 84 ++++++++++--------- 3 files changed, 69 insertions(+), 88 deletions(-) diff --git a/frontend/src/api/fetchRoomOccupancy.ts b/frontend/src/api/fetchRoomOccupancy.ts index 46361d7..59b787b 100644 --- a/frontend/src/api/fetchRoomOccupancy.ts +++ b/frontend/src/api/fetchRoomOccupancy.ts @@ -16,26 +16,7 @@ import { BSON } from "bson"; import { RoomOccupancyList } from "@/model/roomOccupancyList.ts"; -import { - Duration, - NormalizedInterval, - add, - addDays, - addMinutes, - addMonths, - clamp, - differenceInMinutes, - eachDayOfInterval, - endOfDay, - interval, - isAfter, - isBefore, - isEqual, - max, - min, - startOfDay, - subDays, -} from "date-fns"; +import { addMonths } from "date-fns"; import { formatYearMonthDay } from "@/helpers/dates"; const END_OF_SUMMER_SEMESTER = "0930"; @@ -88,19 +69,19 @@ export async function fetchRoomOccupancy( to_date?: string, ): Promise { if (from_date == undefined) { - let new_from_date = getSemesterStart(new Date()); + const new_from_date = getSemesterStart(new Date()); from_date = new_from_date.toISOString(); } if (to_date == undefined) { - let new_to_date = getSemesterStart(addMonths(new Date(), 6)); + const new_to_date = getSemesterStart(addMonths(new Date(), 6)); to_date = new_to_date.toISOString(); } - var roomOccupancyList: RoomOccupancyList = new RoomOccupancyList( - new Date(), - 0, - 0, - [], + let roomOccupancyList: RoomOccupancyList = new RoomOccupancyList( + new Date(), + 0, + 0, + [], ); await fetch("/api/schedule/rooms?from=" + from_date + "&to=" + to_date) diff --git a/frontend/src/components/RoomOccupationOffline.vue b/frontend/src/components/RoomOccupationOffline.vue index fbe69a9..a9ba72f 100644 --- a/frontend/src/components/RoomOccupationOffline.vue +++ b/frontend/src/components/RoomOccupationOffline.vue @@ -21,17 +21,16 @@ import FullCalendar from "@fullcalendar/vue3"; import dayGridPlugin from "@fullcalendar/daygrid"; import interactionPlugin from "@fullcalendar/interaction"; import timeGridPlugin from "@fullcalendar/timegrid"; -import { computed, ComputedRef, inject, ref, Ref } from "vue"; -import { CalendarOptions, DatesSetArg, EventInput } from "@fullcalendar/core"; -import { useI18n } from "vue-i18n"; +import {computed, ComputedRef, inject, ref, Ref, watch} from "vue"; +import {CalendarOptions, DatesSetArg, EventInput} from "@fullcalendar/core"; +import {useI18n} from "vue-i18n"; import allLocales from "@fullcalendar/core/locales-all"; import router from "@/router"; -import { formatYearMonthDay } from "@/helpers/dates"; -import { useQuery } from "@tanstack/vue-query"; -import { watch } from "vue"; -import { fetchRoomOccupancy } from "@/api/fetchRoomOccupancy"; -import { isValid } from "date-fns"; -import { RoomOccupancyList } from "@/model/roomOccupancyList"; +import {formatYearMonthDay} from "@/helpers/dates"; +import {useQuery} from "@tanstack/vue-query"; +import {fetchRoomOccupancy} from "@/api/fetchRoomOccupancy"; +import {isValid} from "date-fns"; +import {RoomOccupancyList} from "@/model/roomOccupancyList"; const { t } = useI18n({ useScope: "global" }); @@ -78,17 +77,16 @@ const selectedRoom = computed(() => props.room); * @returns Anonymized occupancy events */ function transformData(data: RoomOccupancyList) { - const events = data - .decodeOccupancy( - selectedRoom.value, - new Date(currentDateFrom.value), - new Date(currentDateTo.value), - ) - .map((event, index) => ({ - id: index, - event: event, - })); - return events; + return data + .decodeOccupancy( + selectedRoom.value, + new Date(currentDateFrom.value), + new Date(currentDateTo.value), + ) + .map((event, index) => ({ + id: index, + event: event, + })); } const { data: occupancy } = useQuery({ diff --git a/frontend/src/model/roomOccupancyList.ts b/frontend/src/model/roomOccupancyList.ts index 0066e28..c58fc90 100644 --- a/frontend/src/model/roomOccupancyList.ts +++ b/frontend/src/model/roomOccupancyList.ts @@ -14,7 +14,7 @@ //You should have received a copy of the GNU Affero General Public License //along with this program. If not, see . -import { Binary } from "bson"; +import {Binary, Document} from "bson"; import { AnonymizedOccupancy } from "./event"; import { Duration, @@ -93,7 +93,7 @@ export class RoomOccupancyList { const roomOccupancy = this.rooms.find((r) => r.name === room); // Get start and end of decoded time range (within encoded list and requested range) - let decodeInterval = interval( + const decodeInterval = interval( clamp(from, this.getOccupancyInterval()), clamp(to, this.getOccupancyInterval()), ); @@ -108,7 +108,7 @@ export class RoomOccupancyList { const occupancyList = []; - let { decodeSliceStart, decodeSlice } = this.sliceOccupancy( + const { decodeSliceStart, decodeSlice } = this.sliceOccupancy( decodeInterval, roomOccupancy.occupancy.buffer, ); @@ -145,10 +145,10 @@ export class RoomOccupancyList { /** * Slice the important parts of the occupancy list for a given time range. - * @param from the start of the time range. - * @param to the end of the time range. * @returns a new occupancy byte array with the starting time of the first byte * @throws an error, if the selected time range is outside of the occupancy list. + * @param decodeInterval + * @param occupancy */ private sliceOccupancy( decodeInterval: NormalizedInterval, @@ -156,14 +156,14 @@ export class RoomOccupancyList { ): { decodeSliceStart: Date; decodeSlice: Uint8Array } { // Calculate the slice of bytes, that are needed to decode the requested time range // Note: differenceInMinutes calculates (left - right) - let minutesFromStart = differenceInMinutes( + const minutesFromStart = differenceInMinutes( decodeInterval.start, this.start, ); - let minutesToEnd = differenceInMinutes(decodeInterval.end, this.start); + const minutesToEnd = differenceInMinutes(decodeInterval.end, this.start); - let firstByte = Math.floor(minutesFromStart / this.granularity / 8); - let lastByte = Math.ceil(minutesToEnd / this.granularity / 8); + const firstByte = Math.floor(minutesFromStart / this.granularity / 8); + const lastByte = Math.ceil(minutesToEnd / this.granularity / 8); // check if firstByte and lastByte are within the bounds of the occupancy array and throw an error if not if ( @@ -175,11 +175,11 @@ export class RoomOccupancyList { throw new Error("Requested time range is outside of the occupancy list."); } - let decodeSliceStart = addMinutes( + const decodeSliceStart = addMinutes( this.start, firstByte * 8 * this.granularity, ); - let decodeSlice = occupancy.buffer.slice(firstByte, lastByte); + const decodeSlice = occupancy.buffer.slice(firstByte, lastByte); return { decodeSliceStart, decodeSlice: new Uint8Array(decodeSlice) }; } @@ -209,43 +209,44 @@ export class RoomOccupancyList { granularity: number, room: string, ): AnonymizedOccupancy[] { - let occupancyList = []; + const occupancyList = []; let firstOccupancyBit: number | null = null; // Iterate over all bytes that are in the array for (let byte_i = 0; byte_i < occupancy.length; byte_i++) { - let byte = occupancy[byte_i]; - + const byte = occupancy[byte_i]; // Iterate over all bits in the current byte for (let bit_i = 0; bit_i < 8; bit_i++) { - let isOccupied = (byte & (1 << (7 - bit_i))) !== 0; + const isOccupied = (byte & (1 << (7 - bit_i))) !== 0; + const calculateOccupancyBitIndex = (byte_i: number, bit_i: number) => byte_i * 8 + bit_i; - if (firstOccupancyBit === null && isOccupied) { - firstOccupancyBit = byte_i * 8 + bit_i; - } else if (firstOccupancyBit !== null && !isOccupied) { - let startTime = addMinutes(start, firstOccupancyBit * granularity); - let endTime = addMinutes(start, (byte_i * 8 + bit_i) * granularity); - - // add event between start and end of a block of boolean true values - occupancyList.push( - new AnonymizedOccupancy( - startTime.toISOString(), - endTime.toISOString(), - room, - false, - false, - ), - ); - - firstOccupancyBit = null; + if(firstOccupancyBit === null){ + if (isOccupied) { + firstOccupancyBit = calculateOccupancyBitIndex(byte_i, bit_i); + } + } else { + if (!isOccupied) { + const startTime = addMinutes(start, firstOccupancyBit * granularity); + const endTime = addMinutes(start, calculateOccupancyBitIndex(byte_i, bit_i) * granularity); + // add event between start and end of a block of boolean true values + occupancyList.push( + new AnonymizedOccupancy( + startTime.toISOString(), + endTime.toISOString(), + room, + false, + false, + ), + ); + firstOccupancyBit = null; + } + } } } - } - // add last event if it is still ongoing if (firstOccupancyBit !== null) { - let startTime = addMinutes(start, firstOccupancyBit * granularity); - let endTime = addMinutes(start, occupancy.length * 8 * granularity); + const startTime = addMinutes(start, firstOccupancyBit * granularity); + const endTime = addMinutes(start, occupancy.length * 8 * granularity); occupancyList.push( new AnonymizedOccupancy( @@ -265,6 +266,7 @@ export class RoomOccupancyList { * Generate a list of AnonymizedOccupancy objects for a given time range. * The generated events are always lying within the time range [START_OF_DAY, END_OF_DAY]. * + * @param rooms * @param from The start time within the specified start day. * @param to The end time within the specified end day. * @returns a list of AnonymizedEventDTO objects, from start to end. @@ -282,11 +284,11 @@ export class RoomOccupancyList { } return eachDayOfInterval({ start: from, end: to }).map((day) => { - let startTime = max([ + const startTime = max([ from, RoomOccupancyList.setTimeOfDay(day, START_OF_WORKDAY), ]); - let endTime = min([ + const endTime = min([ to, RoomOccupancyList.setTimeOfDay(day, END_OF_WORKDAY), ]); @@ -307,13 +309,13 @@ export class RoomOccupancyList { * @param json the JS object to read from. * @returns a RoomOccupancyList object. */ - public static fromJSON(json: any): RoomOccupancyList { + public static fromJSON(json: Document): RoomOccupancyList { return new RoomOccupancyList( json.start, json.granularity, json.blocks, json.rooms.map( - (room: any) => new RoomOccupancy(room.name, room.occupancy), + (room: { name: string, occupancy: Binary }) => new RoomOccupancy(room.name, room.occupancy), ), ); }