mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender-pwa.git
synced 2025-07-16 09:38:51 +02:00
fix:#3 refactored functions
This commit is contained in:
@ -16,26 +16,7 @@
|
|||||||
|
|
||||||
import { BSON } from "bson";
|
import { BSON } from "bson";
|
||||||
import { RoomOccupancyList } from "@/model/roomOccupancyList.ts";
|
import { RoomOccupancyList } from "@/model/roomOccupancyList.ts";
|
||||||
import {
|
import { addMonths } from "date-fns";
|
||||||
Duration,
|
|
||||||
NormalizedInterval,
|
|
||||||
add,
|
|
||||||
addDays,
|
|
||||||
addMinutes,
|
|
||||||
addMonths,
|
|
||||||
clamp,
|
|
||||||
differenceInMinutes,
|
|
||||||
eachDayOfInterval,
|
|
||||||
endOfDay,
|
|
||||||
interval,
|
|
||||||
isAfter,
|
|
||||||
isBefore,
|
|
||||||
isEqual,
|
|
||||||
max,
|
|
||||||
min,
|
|
||||||
startOfDay,
|
|
||||||
subDays,
|
|
||||||
} from "date-fns";
|
|
||||||
import { formatYearMonthDay } from "@/helpers/dates";
|
import { formatYearMonthDay } from "@/helpers/dates";
|
||||||
|
|
||||||
const END_OF_SUMMER_SEMESTER = "0930";
|
const END_OF_SUMMER_SEMESTER = "0930";
|
||||||
@ -88,19 +69,19 @@ export async function fetchRoomOccupancy(
|
|||||||
to_date?: string,
|
to_date?: string,
|
||||||
): Promise<RoomOccupancyList> {
|
): Promise<RoomOccupancyList> {
|
||||||
if (from_date == undefined) {
|
if (from_date == undefined) {
|
||||||
let new_from_date = getSemesterStart(new Date());
|
const new_from_date = getSemesterStart(new Date());
|
||||||
from_date = new_from_date.toISOString();
|
from_date = new_from_date.toISOString();
|
||||||
}
|
}
|
||||||
if (to_date == undefined) {
|
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();
|
to_date = new_to_date.toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var roomOccupancyList: RoomOccupancyList = new RoomOccupancyList(
|
let roomOccupancyList: RoomOccupancyList = new RoomOccupancyList(
|
||||||
new Date(),
|
new Date(),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
await fetch("/api/schedule/rooms?from=" + from_date + "&to=" + to_date)
|
await fetch("/api/schedule/rooms?from=" + from_date + "&to=" + to_date)
|
||||||
|
@ -21,17 +21,16 @@ import FullCalendar from "@fullcalendar/vue3";
|
|||||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||||
import interactionPlugin from "@fullcalendar/interaction";
|
import interactionPlugin from "@fullcalendar/interaction";
|
||||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||||
import { computed, ComputedRef, inject, ref, Ref } from "vue";
|
import {computed, ComputedRef, inject, ref, Ref, watch} from "vue";
|
||||||
import { CalendarOptions, DatesSetArg, EventInput } from "@fullcalendar/core";
|
import {CalendarOptions, DatesSetArg, EventInput} from "@fullcalendar/core";
|
||||||
import { useI18n } from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
import allLocales from "@fullcalendar/core/locales-all";
|
import allLocales from "@fullcalendar/core/locales-all";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { formatYearMonthDay } from "@/helpers/dates";
|
import {formatYearMonthDay} from "@/helpers/dates";
|
||||||
import { useQuery } from "@tanstack/vue-query";
|
import {useQuery} from "@tanstack/vue-query";
|
||||||
import { watch } from "vue";
|
import {fetchRoomOccupancy} from "@/api/fetchRoomOccupancy";
|
||||||
import { fetchRoomOccupancy } from "@/api/fetchRoomOccupancy";
|
import {isValid} from "date-fns";
|
||||||
import { isValid } from "date-fns";
|
import {RoomOccupancyList} from "@/model/roomOccupancyList";
|
||||||
import { RoomOccupancyList } from "@/model/roomOccupancyList";
|
|
||||||
|
|
||||||
const { t } = useI18n({ useScope: "global" });
|
const { t } = useI18n({ useScope: "global" });
|
||||||
|
|
||||||
@ -78,17 +77,16 @@ const selectedRoom = computed(() => props.room);
|
|||||||
* @returns Anonymized occupancy events
|
* @returns Anonymized occupancy events
|
||||||
*/
|
*/
|
||||||
function transformData(data: RoomOccupancyList) {
|
function transformData(data: RoomOccupancyList) {
|
||||||
const events = data
|
return data
|
||||||
.decodeOccupancy(
|
.decodeOccupancy(
|
||||||
selectedRoom.value,
|
selectedRoom.value,
|
||||||
new Date(currentDateFrom.value),
|
new Date(currentDateFrom.value),
|
||||||
new Date(currentDateTo.value),
|
new Date(currentDateTo.value),
|
||||||
)
|
)
|
||||||
.map((event, index) => ({
|
.map((event, index) => ({
|
||||||
id: index,
|
id: index,
|
||||||
event: event,
|
event: event,
|
||||||
}));
|
}));
|
||||||
return events;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: occupancy } = useQuery({
|
const { data: occupancy } = useQuery({
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
//You should have received a copy of the GNU Affero General Public License
|
//You should have received a copy of the GNU Affero General Public License
|
||||||
//along with this program. If not, see <https://www.gnu.org/licenses/>.
|
//along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import { Binary } from "bson";
|
import {Binary, Document} from "bson";
|
||||||
import { AnonymizedOccupancy } from "./event";
|
import { AnonymizedOccupancy } from "./event";
|
||||||
import {
|
import {
|
||||||
Duration,
|
Duration,
|
||||||
@ -93,7 +93,7 @@ export class RoomOccupancyList {
|
|||||||
const roomOccupancy = this.rooms.find((r) => r.name === room);
|
const roomOccupancy = this.rooms.find((r) => r.name === room);
|
||||||
|
|
||||||
// Get start and end of decoded time range (within encoded list and requested range)
|
// 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(from, this.getOccupancyInterval()),
|
||||||
clamp(to, this.getOccupancyInterval()),
|
clamp(to, this.getOccupancyInterval()),
|
||||||
);
|
);
|
||||||
@ -108,7 +108,7 @@ export class RoomOccupancyList {
|
|||||||
|
|
||||||
const occupancyList = [];
|
const occupancyList = [];
|
||||||
|
|
||||||
let { decodeSliceStart, decodeSlice } = this.sliceOccupancy(
|
const { decodeSliceStart, decodeSlice } = this.sliceOccupancy(
|
||||||
decodeInterval,
|
decodeInterval,
|
||||||
roomOccupancy.occupancy.buffer,
|
roomOccupancy.occupancy.buffer,
|
||||||
);
|
);
|
||||||
@ -145,10 +145,10 @@ export class RoomOccupancyList {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Slice the important parts of the occupancy list for a given time range.
|
* 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
|
* @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.
|
* @throws an error, if the selected time range is outside of the occupancy list.
|
||||||
|
* @param decodeInterval
|
||||||
|
* @param occupancy
|
||||||
*/
|
*/
|
||||||
private sliceOccupancy(
|
private sliceOccupancy(
|
||||||
decodeInterval: NormalizedInterval,
|
decodeInterval: NormalizedInterval,
|
||||||
@ -156,14 +156,14 @@ export class RoomOccupancyList {
|
|||||||
): { decodeSliceStart: Date; decodeSlice: Uint8Array } {
|
): { decodeSliceStart: Date; decodeSlice: Uint8Array } {
|
||||||
// Calculate the slice of bytes, that are needed to decode the requested time range
|
// Calculate the slice of bytes, that are needed to decode the requested time range
|
||||||
// Note: differenceInMinutes calculates (left - right)
|
// Note: differenceInMinutes calculates (left - right)
|
||||||
let minutesFromStart = differenceInMinutes(
|
const minutesFromStart = differenceInMinutes(
|
||||||
decodeInterval.start,
|
decodeInterval.start,
|
||||||
this.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);
|
const firstByte = Math.floor(minutesFromStart / this.granularity / 8);
|
||||||
let lastByte = Math.ceil(minutesToEnd / 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
|
// check if firstByte and lastByte are within the bounds of the occupancy array and throw an error if not
|
||||||
if (
|
if (
|
||||||
@ -175,11 +175,11 @@ export class RoomOccupancyList {
|
|||||||
throw new Error("Requested time range is outside of the occupancy list.");
|
throw new Error("Requested time range is outside of the occupancy list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let decodeSliceStart = addMinutes(
|
const decodeSliceStart = addMinutes(
|
||||||
this.start,
|
this.start,
|
||||||
firstByte * 8 * this.granularity,
|
firstByte * 8 * this.granularity,
|
||||||
);
|
);
|
||||||
let decodeSlice = occupancy.buffer.slice(firstByte, lastByte);
|
const decodeSlice = occupancy.buffer.slice(firstByte, lastByte);
|
||||||
|
|
||||||
return { decodeSliceStart, decodeSlice: new Uint8Array(decodeSlice) };
|
return { decodeSliceStart, decodeSlice: new Uint8Array(decodeSlice) };
|
||||||
}
|
}
|
||||||
@ -209,43 +209,44 @@ export class RoomOccupancyList {
|
|||||||
granularity: number,
|
granularity: number,
|
||||||
room: string,
|
room: string,
|
||||||
): AnonymizedOccupancy[] {
|
): AnonymizedOccupancy[] {
|
||||||
let occupancyList = [];
|
const occupancyList = [];
|
||||||
let firstOccupancyBit: number | null = null;
|
let firstOccupancyBit: number | null = null;
|
||||||
|
|
||||||
// Iterate over all bytes that are in the array
|
// Iterate over all bytes that are in the array
|
||||||
for (let byte_i = 0; byte_i < occupancy.length; byte_i++) {
|
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
|
// Iterate over all bits in the current byte
|
||||||
for (let bit_i = 0; bit_i < 8; bit_i++) {
|
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) {
|
if(firstOccupancyBit === null){
|
||||||
firstOccupancyBit = byte_i * 8 + bit_i;
|
if (isOccupied) {
|
||||||
} else if (firstOccupancyBit !== null && !isOccupied) {
|
firstOccupancyBit = calculateOccupancyBitIndex(byte_i, bit_i);
|
||||||
let startTime = addMinutes(start, firstOccupancyBit * granularity);
|
}
|
||||||
let endTime = addMinutes(start, (byte_i * 8 + bit_i) * granularity);
|
} else {
|
||||||
|
if (!isOccupied) {
|
||||||
// add event between start and end of a block of boolean true values
|
const startTime = addMinutes(start, firstOccupancyBit * granularity);
|
||||||
occupancyList.push(
|
const endTime = addMinutes(start, calculateOccupancyBitIndex(byte_i, bit_i) * granularity);
|
||||||
new AnonymizedOccupancy(
|
// add event between start and end of a block of boolean true values
|
||||||
startTime.toISOString(),
|
occupancyList.push(
|
||||||
endTime.toISOString(),
|
new AnonymizedOccupancy(
|
||||||
room,
|
startTime.toISOString(),
|
||||||
false,
|
endTime.toISOString(),
|
||||||
false,
|
room,
|
||||||
),
|
false,
|
||||||
);
|
false,
|
||||||
|
),
|
||||||
firstOccupancyBit = null;
|
);
|
||||||
|
firstOccupancyBit = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// add last event if it is still ongoing
|
// add last event if it is still ongoing
|
||||||
if (firstOccupancyBit !== null) {
|
if (firstOccupancyBit !== null) {
|
||||||
let startTime = addMinutes(start, firstOccupancyBit * granularity);
|
const startTime = addMinutes(start, firstOccupancyBit * granularity);
|
||||||
let endTime = addMinutes(start, occupancy.length * 8 * granularity);
|
const endTime = addMinutes(start, occupancy.length * 8 * granularity);
|
||||||
|
|
||||||
occupancyList.push(
|
occupancyList.push(
|
||||||
new AnonymizedOccupancy(
|
new AnonymizedOccupancy(
|
||||||
@ -265,6 +266,7 @@ export class RoomOccupancyList {
|
|||||||
* Generate a list of AnonymizedOccupancy objects for a given time range.
|
* 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].
|
* 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 from The start time within the specified start day.
|
||||||
* @param to The end time within the specified end day.
|
* @param to The end time within the specified end day.
|
||||||
* @returns a list of AnonymizedEventDTO objects, from start to end.
|
* @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) => {
|
return eachDayOfInterval({ start: from, end: to }).map((day) => {
|
||||||
let startTime = max([
|
const startTime = max([
|
||||||
from,
|
from,
|
||||||
RoomOccupancyList.setTimeOfDay(day, START_OF_WORKDAY),
|
RoomOccupancyList.setTimeOfDay(day, START_OF_WORKDAY),
|
||||||
]);
|
]);
|
||||||
let endTime = min([
|
const endTime = min([
|
||||||
to,
|
to,
|
||||||
RoomOccupancyList.setTimeOfDay(day, END_OF_WORKDAY),
|
RoomOccupancyList.setTimeOfDay(day, END_OF_WORKDAY),
|
||||||
]);
|
]);
|
||||||
@ -307,13 +309,13 @@ export class RoomOccupancyList {
|
|||||||
* @param json the JS object to read from.
|
* @param json the JS object to read from.
|
||||||
* @returns a RoomOccupancyList object.
|
* @returns a RoomOccupancyList object.
|
||||||
*/
|
*/
|
||||||
public static fromJSON(json: any): RoomOccupancyList {
|
public static fromJSON(json: Document): RoomOccupancyList {
|
||||||
return new RoomOccupancyList(
|
return new RoomOccupancyList(
|
||||||
json.start,
|
json.start,
|
||||||
json.granularity,
|
json.granularity,
|
||||||
json.blocks,
|
json.blocks,
|
||||||
json.rooms.map(
|
json.rooms.map(
|
||||||
(room: any) => new RoomOccupancy(room.name, room.occupancy),
|
(room: { name: string, occupancy: Binary }) => new RoomOccupancy(room.name, room.occupancy),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user