|
1 | 1 | import {readFile} from 'node:fs/promises'; |
| 2 | +import type {EventDirectory, EventDirectoryEvent} from './types.ts'; |
2 | 3 |
|
3 | | -async function getAll(): Promise<string[]> { |
4 | | - const data = await readFile('eventfiles/all.txt', 'utf8'); |
5 | | - const list = data.split('\n').filter(element => element !== ''); |
6 | | - return list; |
| 4 | +async function getAll(): Promise<EventDirectory[]> { |
| 5 | + const data = await readFile('eventfiles/directory.json', 'utf8'); |
| 6 | + return JSON.parse(data) as EventDirectory[]; |
7 | 7 | } |
8 | 8 |
|
9 | 9 | export async function count(): Promise<number> { |
10 | | - const allEvents = await getAll(); |
| 10 | + const allEvents = (await find('', [], [])); |
11 | 11 | return allEvents.length; |
12 | 12 | } |
13 | 13 |
|
14 | | -export async function exists(name: string): Promise<boolean> { |
15 | | - const allEvents = await getAll(); |
16 | | - return allEvents.includes(name); |
| 14 | +export async function exists(id: string): Promise<EventDirectoryEvent | undefined> { |
| 15 | + const allDirectories = await getAll(); |
| 16 | + |
| 17 | + function traverse(directory: EventDirectory): EventDirectoryEvent | undefined { |
| 18 | + const event = directory.Events?.find(event => event.Id === id); |
| 19 | + if (event !== undefined) { |
| 20 | + return event; |
| 21 | + } |
| 22 | + |
| 23 | + for (const subDirectory of directory.SubDirectories ?? []) { |
| 24 | + const eventInSubdirectory = traverse(subDirectory); |
| 25 | + if (eventInSubdirectory !== undefined) { |
| 26 | + return eventInSubdirectory; |
| 27 | + } |
| 28 | + } |
| 29 | + |
| 30 | + return undefined; |
| 31 | + } |
| 32 | + |
| 33 | + for (const subDirectory of allDirectories) { |
| 34 | + const event = traverse(subDirectory); |
| 35 | + if (event !== undefined) { |
| 36 | + return event; |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + return undefined; |
17 | 41 | } |
18 | 42 |
|
19 | | -export async function nonExisting(names: readonly string[]): Promise<string[]> { |
20 | | - const allEvents = new Set(await getAll()); |
21 | | - const result: string[] = []; |
22 | | - for (const event of names) { |
23 | | - if (!allEvents.has(event)) { |
24 | | - result.push(event); |
| 43 | +export async function nonExisting(ids: readonly string[]): Promise<string[]> { |
| 44 | + const allEvents = await getAll(); |
| 45 | + const result = [...ids]; |
| 46 | + |
| 47 | + function traverse(directory: EventDirectory) { |
| 48 | + for (const event of directory.Events ?? []) { |
| 49 | + const eventId = event.Id; |
| 50 | + if (result.includes(eventId)) { |
| 51 | + result.splice(result.indexOf(eventId), 1); |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + for (const subDirectory of directory.SubDirectories ?? []) { |
| 56 | + traverse(subDirectory); |
25 | 57 | } |
26 | 58 | } |
27 | 59 |
|
| 60 | + for (const directory of allEvents) { |
| 61 | + traverse(directory); |
| 62 | + } |
| 63 | + |
28 | 64 | return result; |
29 | 65 | } |
30 | 66 |
|
31 | 67 | export async function find( |
| 68 | + pattern: string | RegExp | undefined, |
| 69 | + ignoreIds: readonly string[] = [], |
| 70 | + startAt: number[] = [], |
| 71 | +): Promise<ReadonlyArray<EventDirectoryEvent | [EventDirectory, number[]]>> { |
| 72 | + if (pattern !== undefined) { |
| 73 | + const accumulator: EventDirectoryEvent[] = []; |
| 74 | + await _find(pattern, ignoreIds, await resolvePath(startAt), accumulator); |
| 75 | + return [...new Set(accumulator)].sort((a, b) => |
| 76 | + a.Name.localeCompare(b.Name)); |
| 77 | + } |
| 78 | + |
| 79 | + const dir = await resolvePath(startAt); |
| 80 | + |
| 81 | + return [ |
| 82 | + ...(dir.SubDirectories ?? []).map((dir, i) => [dir, [...startAt, i]] as [EventDirectory, number[]]), |
| 83 | + ...(dir.Events ?? []).filter(event => !ignoreIds.includes(event.Id)), |
| 84 | + ]; |
| 85 | +} |
| 86 | + |
| 87 | +async function _find( |
32 | 88 | pattern: string | RegExp, |
33 | | - ignore: readonly string[] = [], |
34 | | -): Promise<readonly string[]> { |
35 | | - const allEvents = await getAll(); |
36 | | - const regex = new RegExp(pattern, 'i'); |
37 | | - const filtered = allEvents.filter(event => |
38 | | - regex.test(event) && !ignore.includes(event)); |
39 | | - return filtered; |
| 89 | + ignoreIds: readonly string[], |
| 90 | + startAt: EventDirectory, |
| 91 | + accumulator: EventDirectoryEvent[], |
| 92 | +) { |
| 93 | + if (startAt?.Events !== undefined) { |
| 94 | + const regex = new RegExp(pattern, 'i'); |
| 95 | + accumulator.push(...startAt?.Events |
| 96 | + .filter(event => regex.test(event.Name) && !ignoreIds.includes(event.Id)) ?? []); |
| 97 | + } |
| 98 | + |
| 99 | + await Promise.all(startAt.SubDirectories |
| 100 | + ?.map(async subDirectory => _find(pattern, ignoreIds, subDirectory, accumulator)) |
| 101 | + ?? []); |
| 102 | +} |
| 103 | + |
| 104 | +export async function resolvePath(path: number[]): Promise<EventDirectory> { |
| 105 | + let Name = 'HAW Hamburg'; |
| 106 | + let Events: EventDirectoryEvent[] | undefined; |
| 107 | + let SubDirectories: EventDirectory[] | undefined = await getAll(); |
| 108 | + |
| 109 | + for (const part of path) { |
| 110 | + if (SubDirectories === undefined || SubDirectories.length <= part) { |
| 111 | + throw new Error('Ungültiger Pfad'); |
| 112 | + } |
| 113 | + |
| 114 | + Name = SubDirectories[part]!.Name; |
| 115 | + Events = SubDirectories[part]!.Events; |
| 116 | + SubDirectories = SubDirectories[part]!.SubDirectories; |
| 117 | + } |
| 118 | + |
| 119 | + return {Name, SubDirectories, Events}; |
40 | 120 | } |
0 commit comments