html5-infobeamer-dhcp/assets/js/solight/sol.js

1090 lines
34 KiB
JavaScript
Raw Permalink Normal View History

2024-10-30 22:30:09 +01:00
'use strict';
// Use luxon for date and time handling
import * as luxon from "../luxon/luxon.es6.js";
// ---------------------------------------------------------
// Helpers
// :: A -> Option[A]
let optional = (x) => x === null ? undefined : x;
// :: A -> Bool
let defined = (x) => x !== undefined;
// :: Option[A] -> (()->B) -> Option[B]
let withDefined = (x, f) => defined(x) ? f() : undefined;
//-:: Option[A] -> (A->B) -> Option[B]
let ifDefined = (x, f) => defined(x) ? f(x) : undefined;
// Note: use only for primitive values ("primary keys")
// :: List[A] -> List[A]
let distinct = (xs) => Array.from(new Set(xs));
// :: List[A] -> List[A] -> List[A]
let intersection = (xs, ys) => xs.filter(v => ys.includes(v));
//-:: String -> String -> Int
let stringCompare = (s1, s2) => {
if (s1 < s2) { return -1; };
if (s1 > s2) { return 1; };
return 0;
};
// ---------------------------------------------------------
// Transform Json into proper Arrays and Maps
//-:: EventAnswerJson -> EventAnswer
let processEventAnswer = (answerJ) => {
let m = new Map();
m.set('question', answerJ.question);
m.set('answer', answerJ.answer);
return m;
};
//-:: AttachmentJson -> Attachment
let processAttachment = (attachmentJ) => undefined;
//-:: LinkJson -> Link
let processLink = (linkJ) => undefined;
//-:: PersonAnswerJson -> PersonAnswer
let processPersonAnswer = (answerJ) => undefined;
//-:: PersonJson -> Person
let processPerson = (personJ) => {
let m = new Map();
m.set('id', personJ.id);
m.set('code', personJ.code);
// Renamed field:
m.set('name', personJ.public_name);
m.set('biography', optional(personJ.biography));
m.set('answers', personJ.answers.map(aj => processPersonAnswer(aj)));
return m;
};
//-:: EventJson -> DayIndex -> Event
let processEvent = (eventJ, dayIndex) => {
let start_date = luxon.DateTime.fromISO(eventJ.date);
let duration = luxon.Duration.fromISOTime(eventJ.duration);
let end_date = start_date.plus(duration);
let m = new Map();
m.set('id', eventJ.id);
m.set('guid', eventJ.guid);
m.set('logo', eventJ.logo);
// Same as processed start date
//m.set('date',
// luxon.DateTime.fromISO(eventJ.date));
m.set('start_date', start_date);
// Synthetic field:
m.set('end_date', end_date);
m.set('duration', duration);
// Synthetic field:
m.set('day_index', dayIndex);
m.set('room', eventJ.room);
m.set('slug', eventJ.slug);
m.set('url', eventJ.url);
// m.set('title', eventJ.title || "");
m.set('title', withDefined(eventJ.title, () => eventJ.title));
m.set('subtitle', withDefined(eventJ.subtitle, () => eventJ.subtitle));
m.set('track', eventJ.track);
m.set('type', eventJ.type);
m.set('language', eventJ.language);
// TODO: Rethink empty strings
m.set('abstract', eventJ.abstract || "");
m.set('description', eventJ.description || "");
m.set('recording_license', eventJ.recording_license);
m.set('do_not_record', eventJ.do_not_record);
m.set('persons', eventJ.persons.map(pj => processPerson(pj)));
m.set('links', eventJ.links.map(lj => processLink(lj)));
m.set('attachments', eventJ.attachments.map(aj => processAttachment(aj)));
m.set('answers', withDefined(eventJ.answers,
() => eventJ.answers.map(aj => processEventAnswer(aj))));
return m;
};
//-:: RoomJson -> DayIndex -> Map[RoomName, List[Event]]
let processRooms = (roomJ, dayIndex) => {
let m = new Map(
Object.entries(roomJ).map(
item => [item[0], item[1].map(e => processEvent(e, dayIndex))]
)
);
return m;
};
//-:: DayJson -> Day
let processDay = (dayJ) => {
let main_date = luxon.DateTime.fromISO(dayJ.date);
let start_date = luxon.DateTime.fromISO(dayJ.day_start);
let end_date = luxon.DateTime.fromISO(dayJ.day_end);
let duration = end_date.diff(start_date);
let m = new Map();
m.set('index', dayJ.index);
m.set('date', main_date);
m.set('start_date', start_date);
m.set('end_date', end_date);
// Synthetic field:
m.set('duration', duration);
// Note: Pass day index down to rooms and finally events
m.set('rooms', processRooms(dayJ.rooms, dayJ.index));
return m;
};
//-:: RoomDefinitionJson -> Room
let processRoomDefinition = (roomJ) => {
let m = new Map();
m.set('name', roomJ.name);
m.set('guid', optional(roomJ.guid));
m.set('description', optional(roomJ.description));
m.set('capacity', optional(roomJ.capacity));
return m;
};
//-:: ConferenceJson -> Conference
let processConference = (conferenceJ) => {
let start_date = luxon.DateTime.fromISO(conferenceJ.start);
let end_date = luxon.DateTime.fromISO(conferenceJ.end);
let duration = end_date.diff(start_date);
let m = new Map();
m.set('acronym', conferenceJ.acronym);
m.set('title', conferenceJ.title);
m.set('start_date', start_date);
m.set('end_date', end_date);
// Synthetic field:
m.set('duration', duration);
m.set('days_count', conferenceJ.daysCount);
m.set('timeslot_duration',
luxon.Duration.fromISOTime(conferenceJ.timeslot_duration));
// TODO:
//m.set('time_zone_name',
// luxon.IANAZone.create(conferenceJ.time_zone_name));
m.set('rooms', conferenceJ.rooms.map(rj => processRoomDefinition(rj)));
m.set('days', conferenceJ.days.map(dj => processDay(dj)));
return m;
};
//-:: ScheduleJson -> Schedule
let processSchedule = (scheduleJ) => {
let m = new Map();
m.set('version', scheduleJ.version);
m.set('base_url', scheduleJ.base_url);
m.set('conference', processConference(scheduleJ.conference));
return m;
};
// :: ScheduleFile -> ScheduleJson
let processScheduleFile = (scheduleFile) =>
processSchedule(scheduleFile.schedule);
//processSchedule(JSON.parse(scheduleFile).schedule);
// ---------------------------------------------------------
// Properties and Accessors ('Data Types')
// :: Schedule -> String
let scheduleVersion = (schedule) => schedule.get('version');
// :: Schedule -> String
let scheduleBaseUrl = (schedule) => schedule.get('base_url');
// :: Conference -> String
let conferenceAcronym = (conference) => conference.get('acronym');
// :: Conference -> String
let conferenceTitle = (conference) => conference.get('title');
// :: Conference -> luxon.DateTime
let conferenceStartDate = (conference) => conference.get('start_date');
// :: Conference -> luxon.DateTime
let conferenceEndDate = (conference) => conference.get('end_date');
// :: Conference -> luxon.Duration
let conferenceDuration = (conference) => conference.get('duration');
// :: Conference -> Int
let conferenceDaysCount = (conference) => conference.get('days_count');
// :: Conference -> luxon.Duration
let conferenceTimeslotDuration = (conference) => conference.get('timeslot_duration');
// :: Conference -> luxon.IANATimeZone
let conferenceTimezoneName = (conference) => conference.get('time_zone_name');
// :: Day -> DayIndex
let dayIndex = (day) => day.get('index');
// :: Day -> luxon.DateTime
let dayDate = (day) => day.get('date');
// :: Day -> luxon.DateTime
let dayStartDate = (day) => day.get('start_date');
// :: Day -> luxon.DateTime
let dayEndDate = (day) => day.get('end_date');
// :: Day -> luxon.Duration
let dayDuration = (day) => day.get('duration');
// :: Room -> String
let roomName = (room) => room.get('name');
// :: Room -> String
let roomGuid = (room) => room.get('guid');
let roomId = (room) => room.get('guid');
// :: Room -> String
let roomDescription = (room) => room.get('description');
// :: Room -> Int
let roomCapacity = (room) => room.get('capacity');
// :: Event -> Int
let eventId = (event) => event.get('id');
// :: Event -> String
let eventGuid = (event) => event.get('guid');
// :: Event -> String
let eventLogo = (event) => event.get('logo');
// :: Event -> luxon.DateTime
let eventStartDate = (event) => event.get('start_date');
// :: Event -> luxon.DateTime
let eventEndDate = (event) => event.get('end_date');
// :: Event -> luxon.Duration
let eventDuration = (event) => event.get('duration');
// :: Event -> Int
let eventDayIndex = (event) => event.get('day_index');
// :: Event -> RoomName
let eventRoomName = (event) => event.get('room');
// :: Event -> String
let eventSlug = (event) => event.get('slug');
// :: Event -> String
let eventUrl = (event) => event.get('url');
// :: Event -> String
let eventTitle = (event) => event.get('title');
// :: Event -> String
let eventSubtitle = (event) => event.get('subtitle');
// :: Event -> TrackName
let eventTrack = (event) => event.get('track');
// :: Event -> EventType
let eventType = (event) => event.get('type');
// :: Event -> Language
let eventLanguage = (event) => event.get('language');
// :: Event -> String
let eventAbstract = (event) => event.get('abstract');
// :: Event -> String
let eventDescription = (event) => event.get('description');
// :: Event -> String
let eventRecordingLicense = (event) => event.get('recording_license');
// :: Event -> Bool
let eventDoNotRecord = (event) => event.get('do_not_record');
// :: Event -> List[Person]
let eventPersons = (event) => event.get('persons');
// :: Event -> Int
let eventPersonCount = (event) => eventPersons(event).length;
// :: Event -> List[AnswerMap]
let eventAnswers = (event) => event.get('answers');
// :: Person -> Int
let personId = (person) => person.get('id');
// :: Person -> String
let personCode = (person) => person.get('code');
// :: Person -> String
let personName = (person) => person.get('name');
// :: Person -> String
let personBiography = (person) => person.get('biography');
// ---------------------------------------------------------
// Filters, Maps and other Pieces of Lisp
// TODO: Use own stable IDs
// :: List[Event] -> DayIndex -> List[Event]
let eventsByDayIndex = (events, dIndex) =>
events.filter(e => eventDayIndex(e) === dIndex);
// :: List[Event] -> Day -> List[Event]
let eventsByDay = (events, day) =>
events.filter(e => eventDayIndex(e) === dayIndex(day));
// :: List[Event] -> RoomName -> List[Event]
let eventsByRoomName = (events, rName) =>
events.filter(e => eventRoomName(e) === rName);
// :: List[Event] -> Room -> List[Event]
let eventsByRoom = (events, room) =>
eventsByRoomName(events, roomName(room));
// :: List[Event] -> PersonId -> List[Event]
let eventsByPersonId = (events, pId) =>
events.filter(e => eventPersons(e).some(p => personId(p) === pId));
// :: List[Event] -> PersonName -> List[Event]
let eventsByPersonName = (events, pName) =>
events.filter(e => eventPersons(e).some(p => personName(p) === pName));
// :: List[Event] -> Person -> List[Event]
let eventsByPerson = (events, person) =>
eventsByPersonName(events, personName(person));
// :: List[Event] -> TrackName -> List[Event]
let eventsByTrack = (events, eventTrackName) =>
events.filter(e => eventTrack(e) === eventTrackName);
// :: List[Event] -> EventType -> List[Event]
let eventsByType = (events, eventTypeName) =>
events.filter(e => eventType(e) === eventTypeName);
// :: List[Event] -> Language -> List[Event]
let eventsByLanguage = (events, language) =>
events.filter(e => eventLanguage(e) === language);
// :: List[Room] -> GUID -> Option[Room]
let roomById = (rooms, id) => rooms.find(r => roomId(r) === id);
// :: List[Room] -> RoomName -> List[Room]
let roomsByName = (rooms, name) => rooms.filter(r => roomName(r) === name);
// :: List[Day] -> Int -> Option[Day]
let dayByIndex = (days, index) => days.find(d => dayIndex(d) === index);
// :: List[Person] -> Int -> Option[Person]
let personById = (persons, id) => persons.find(p => personId(p) === id);
// :: List[Person] -> PersonName -> List[Person]
let personsByName = (persons, name) => persons.filter(p => personName(p) === name);
// :: List[Event] -> Int -> Option[Event]
let eventById = (events, id) => events.find(e => eventId === id);
// :: List[Room] -> List[Room]
let distinctRooms = (rooms) => {
//let ids = distinct(rooms.map(roomId));
//return ids.map(i => rooms.find(r => roomId(r) === i));
// TODO: Room Id might be optional?
let rns = distinct(rooms.map(roomName));
return rns.map(i => rooms.find(r => roomName(r) === i));
};
// :: List[Day] -> List[Day]
let distinctDays = (days) => {
let ids = distinct(days.map(dayIndex));
return ids.map(i => days.find(d => dayIndex(d) === i));
};
// :: List[Event] -> List[Event]
let distinctEvents = (events) => {
let ids = distinct(events.map(eventId));
return ids.map(i => events.find(e => eventId(e) === i));
};
// :: List[Person] -> List[Person]
let distinctPersons = (persons) => {
let ids = distinct(persons.map(personId));
return ids.map(i => persons.find(p => personId(p) === i));
};
// :: List[Person] -> List[Person]
let sortPersonsByName = (persons) =>
persons.sort((p1, p2) => stringCompare(personName(p1), personName(p2)));
// :: List[Room] -> List[Room]
let sortRoomsByName = (rooms) =>
rooms.sort((r1, r2) => stringCompare(roomName(r1), roomName(r2)));
// :: List[Event] -> List[Event]
let sortEventsByTitle = (events) =>
events.sort((e1, e2) => stringCompare(eventTitle(e1), eventTitle(e2)));
// ---------------------------------------------------------
// Advanced Accessors
// Note: Maybe deprecate and replace with 'eventsByDay'?
// :: Day -> List[Event]
let eventsOfDay = (day) =>
Array.from(day.get('rooms').values()).flat();
// :: List[Day] -> List[Event]
let eventsOfDays = (days) => days.flatMap(eventsOfDay);
// Note: Can not implement this, needs more information.
// Use 'eventsByRoom' and 'eventsByRooms' instead.
//-:: Room -> List[Event]
//let eventsOfRoom = (room) =>
// Array.from(room.values());
//-:: List[Room] -> List[Event]
//let eventsOfRooms = (rooms) => rooms.flatMap(eventsOfRoom);
// :: List[Event] -> List[TrackName]
let tracksOfEvents = (events) =>
distinct(events.flatMap(eventLanguage));
// :: List[Event] -> List[EventType]
let typesOfEvents = (events) =>
distinct(events.flatMap(eventType));
// :: List[Event] -> List[Language]
let languagesOfEvents = (events) =>
distinct(events.flatMap(eventLanguage));
// :: Conference -> List[Day]
let conferenceDays = (conference) =>
distinctDays(conference.get('days'));
// :: Conference -> List[Room]
let conferenceRooms = (conference) =>
distinctRooms(Array.from(conference.get('rooms').values()));
// :: Conference -> List[Event]
let conferenceEvents = (conference) =>
distinctEvents(conferenceDays(conference).flatMap(d => eventsOfDay(d)));
// :: Conference -> List[Person]
let conferencePersons = (conference) =>
distinctPersons(conferenceEvents(conference).flatMap(eventPersons));
// :: Conference -> List[TrackName]
let conferenceTracks = (conference) =>
distinct(conferenceEvents(conference).flatMap(eventTrack));
// :: Conference -> List[EventType]
let conferenceTypes = (conference) =>
distinct(conferenceEvents(conference).flatMap(eventType));
// :: Conference -> List[Language]
let conferenceLanguages = (conference) =>
distinct(conferenceEvents(conference).flatMap(eventLanguage));
// :: Schedule -> Conference
let conference = (schedule) => schedule.get('conference');
// ---------------------------------------------------------
// Advanced Filters, Maps and Traces of SQL
// TODO: Use own stable IDs
// :: Conference -> List[RoomName] -> DayIndex -> List[RoomName]
let roomNamesByDayIndex = (conference, roomNames, dayIndex) => {
let evs = eventsByDayIndex(conferenceEvents(conference), dayIndex);
let rns = distinct(evs.map(eventRoomName));
return distinct(roomNames.filter(rn => rns.includes(rn)));
};
// :: Conference -> List[RoomName] -> Day -> List[RoomName]
let roomNamesByDay = (conference, roomNames, day) =>
roomNamesByDayIndex(conference, roomNames, dayIndex(day));
// :: Conference -> List[Room] -> DayIndex -> List[Room]
let roomsByDayIndex = (conference, rooms, dayIndex) => {
let rns = roomNamesByDayIndex(conference, rooms.map(roomName), dayIndex);
return rooms.filter(r => rns.includes(roomName(r)));
};
// :: Conference -> List[Room] -> Day => List[Room]
let roomsByDay = (conference, rooms, day) =>
roomsByDayIndex(conference, rooms, dayIndex(day));
// :: Conference -> List[RoomName] -> PersonId -> List[RoomName]
let roomNamesByPersonId = (conference, roomNames, id) => {
let evs = eventsByPersonId(conferenceEvents(conference), id);
let rns = distinct(evs.map(eventRoomName));
return distinct(roomNames.filter(rn => rns.includes(rn)));
};
// :: Conference -> List[RoomName] -> Person -> List[RoomName]
let roomNamesByPerson = (conference, roomNames, person) =>
roomNamesByPersonId(conference, roomNames, personId(person));
// :: Conference -> List[Room] -> PersonId -> List[Room]
let roomsByPersonId = (conference, rooms, id) => {
let rns = roomNamesByPersonId(conference, rooms.map(roomName), id);
return rooms.filter(r => rns.includes(roomName(r)));
};
// :: Conference -> List[Room] -> Person -> List[Room]
let roomsByPerson = (conference, rooms, person) =>
roomsByPersonId(conference, rooms, personId(person));
// :: Conference -> List[RoomName] -> Track -> List[RoomName]
let roomNamesByTrack = (conference, roomNames, track) => {
let evs = eventsByTrack(conferenceEvents(conference), track);
let rns = evs.map(eventRoomName);
return distinct(roomNames.filter(rn => rns.includes(rn)));
};
// :: Conference -> List[Room] -> Track -> List[Room]
let roomsByTrack = (conference, rooms, track) =>
roomNamesByTrack(conference, rooms.map(roomName), track).flatMap(rn =>
roomsByName(rooms, rn));
// :: Conference -> List[RoomName] -> Type -> List[RoomName]
let roomNamesByType = (conference, roomNames, type) => {
let evs = eventsByType(conferenceEvents(conference), type);
let rns = evs.map(eventRoomName);
return distinct(roomNames.filter(rn => rns.includes(rn)));
};
// :: Conference -> List[Room] -> Type -> List[Room]
let roomsByType = (conference, rooms, type) =>
roomNamesByType(conference, rooms.map(roomName), type).flatMap(rn =>
roomsByName(rooms, rn));
// :: Conference -> List[RoomName] -> Language -> List[RoomName]
let roomNamesByLanguage = (conference, roomNames, language) => {
let evs = eventsByLanguage(conferenceEvents(conference), language);
let rns = evs.map(eventRoomName);
return distinct(roomNames.filter(rn => rns.includes(rn)));
};
// :: Conference -> List[Room] -> Language -> List[Room]
let roomsByLanguage = (conference, rooms, language) =>
roomNamesByLanguage(conference, rooms.map(roomName), language).flatMap(rn =>
roomsByName(rooms, rn));
// :: Conference -> List[PersonId] -> DayIndex -> List[PersonId]
let personIdsByDayIndex = (conference, personIds, dayIndex) => {
let evs = eventsByDayIndex(conferenceEvents(conference), dayIndex);
let pids = distinct(evs.flatMap(eventPersons).map(personId));
return distinct(personIds.filter(pi => pids.includes(pi)));
};
// :: Conference -> List[PersonId] -> Day -> List[PersonId]
let personIdsByDay = (conference, personIds, day) =>
personIdsByDayIndex(conference, personIds, dayIndex(day));
// :: Conference -> List[Person] -> DayIndex -> List[Person]
let personsByDayIndex = (conference, persons, dayIndex) =>
personIdsByDayIndex(conference, persons.map(personId), dayIndex).map(pi =>
personById(persons, pi));
// :: Conference -> List[Person] -> Day -> List[Person]
let personsByDay = (conference, persons, day) =>
personsByDayIndex(conference, persons, dayIndex(day));
// :: Conference -> List[PersonId] -> RoomName -> List[PersonId]
let personIdsByRoomName = (conference, personIds, roomName) => {
let evs = eventsByRoomName(conferenceEvents(conference), roomName);
let pids = distinct(evs.flatMap(eventPersons).map(personId));
return distinct(personIds.filter(pi => pids.includes(pi)));
};
// :: Conference -> List[PersonId] -> Room -> List[PersonId]
let personIdsByRoom = (conference, personIds, room) =>
personIdsByRoomName(conference, personIds, roomName(room));
// :: Conference -> List[Person] -> RoomName -> List[Person]
let personsByRoomName = (conference, persons, roomName) =>
personIdsByRoomName(conference, persons.map(personId), roomName).map(pi =>
personById(persons, pi));
// :: Conference -> List[Person] -> Room -> List[Person]
let personsByRoom = (conference, persons, room) =>
personsByRoomName(conference, persons, roomName(room));
// :: Conference -> List[PersonId] -> Track -> List[PersonId]
let personIdsByTrack = (conference, personIds, track) => {
let evs = eventsByTrack(conferenceEvents(conference), track);
let pids = evs.flatMap(eventPersons).map(personId);
return distinct(personIds.filter(pi => pids.includes(pi)));
};
// :: Conference -> List[PersonId] -> Track -> List[PersonId]
let personsByTrack = (conference, persons, track) =>
personIdsByTrack(conference, persons.map(personId), track).map(pi =>
personById(persons, pi));
// :: Conference -> List[PersonId] -> Type -> List[PersonId]
let personIdsByType = (conference, personIds, type) => {
let evs = eventsByType(conferenceEvents(conference), type);
let pids = evs.flatMap(eventPersons).map(personId);
return distinct(personIds.filter(pi => pids.includes(pi)));
};
// :: Conference -> List[Person] -> Type -> List[Person]
let personsByType = (conference, persons, type) =>
personIdsByType(conference, persons.map(personId), type).map(pi =>
personById(persons, pi));
// :: Conference -> List[PersonId] -> Language -> List[PersonId]
let personIdsByLanguage = (conference, personIds, language) => {
let evs = eventsByLanguage(conferenceEvents(conference), language);
let pids = evs.flatMap(eventPersons).map(personId);
return distinct(personIds.filter(pi => pids.includes(pi)));
};
// :: Conference -> List[Person] -> Language -> List[Person]
let personsByLanguage = (conference, persons, language) =>
personIdsByLanguage(conference, persons.map(personId), language).map(pi =>
personById(persons, pi));
// :: Conference -> List[DayIndex] -> RoomName -> List[DayIndex]
let dayIndicesByRoomName = (conference, dayIndices, roomName) => {
let evs = eventsByRoomName(conferenceEvents(conference), roomName);
let dis = distinct(evs.map(eventDayIndex));
return distinct(dayIndices.filter(di => dis.includes(di)));
};
// :: Conference -> List[DayIndex] -> Room -> List[DayIndex]
let dayIndicesByRoom = (conference, dayIndices, room) =>
dayIndicesByRoomName(conference, dayIndices, roomName(room));
// :: Conference -> List[Day] -> RoomName -> List[Day]
let daysByRoomName = (conference, days, roomName) =>
dayIndicesByRoomName(conference, days.map(dayIndex), roomName).map(di =>
dayByIndex(days, di));
// :: Conference -> List[Day] -> Room -> List[Day]
let daysByRoom = (conference, days, room) =>
daysByRoomName(conference, days, roomName(room));
// :: Conference -> List[DayIndex] -> PersonId -> List[DayIndex]
let dayIndicesByPersonId = (conference, dayIndices, id) => {
let evs = eventsByPersonId(conferenceEvents(conference), id);
let dis = distinct(evs.map(eventDayIndex));
return distinct(dayIndices.filter(di => dis.includes(di)));
};
// :: Conference -> List[DayIndex] -> Person -> List[DayIndex]
let dayIndicesByPerson = (conference, dayIndices, person) =>
dayIndicesByPersonId(conference, dayIndices, personId(person));
// :: Conference -> List[Day] -> PersonId -> List[Day]
let daysByPersonId = (conference, days, id) =>
dayIndicesByPersonId(conference, days.map(dayIndex), id).map(di =>
dayByIndex(days, di));
// :: Conference -> List[Day] -> Person -> List[Day]
let daysByPerson = (conference, days, person) =>
daysByPersonId(conference, days, personId(person));
// :: Conference -> List[DayIndex] -> Track -> List[DayIndex]
let dayIndicesByTrack = (conference, dayIndices, track) => {
let evs = eventsByTrack(conferenceEvents(conference), track);
let dis = evs.map(eventDayIndex);
return distinct(dayIndices.filter(di => dis.includes(di)));
};
// :: Conference -> List[Day] -> Track -> List[Day]
let daysByTrack = (conference, days, track) =>
dayIndicesByTrack(conference, days.map(dayIndex), track).map(di =>
dayByIndex(days, di));
// :: Conference -> List[DayIndex] -> Type -> List[DayIndex]
let dayIndicesByType = (conference, dayIndices, type) => {
let evs = eventsByType(conferenceEvents(conference), type);
let dis = evs.map(eventDayIndex);
return distinct(dayIndices.filter(di => dis.includes(di)));
};
// :: Conference -> List[Day] -> Type -> List[Day]
let daysByType = (conference, days, type) =>
dayIndicesByType(conference, days.map(dayIndex), type).map(di =>
dayByIndex(days, di));
// :: Conference -> List[DayIndex] -> Language -> List[DayIndex]
let dayIndicesByLanguage = (conference, dayIndices, language) => {
let evs = eventsByLanguage(conferenceEvents(conference), language);
let dis = evs.map(eventDayIndex);
return distinct(dayIndices.filter(di => dis.includes(di)));
};
// :: Conference -> List[Day] -> Language -> List[Day]
let daysByLanguage = (conference, days, language) =>
dayIndicesByLanguage(conference, days.map(dayIndex), language).map(di =>
dayByIndex(days, di));
// :: Conference -> List[Track] -> DayIndex -> List[Track]
let tracksByDayIndex = (conference, tracks, dayIndex) =>
tracksOfEvents(eventsByDayIndex(conferenceEvents(conference), dayIndex));
// :: Conference -> List[Track] -> Day -> List[Track]
let tracksByDay = (conference, tracks, day) =>
tracksOfEvents(eventsByDay(conferenceEvents(conference), day));
// :: Conference -> List[Track] -> RoomName -> List[Track]
let tracksByRoomName = (conference, tracks, roomName) =>
tracksOfEvents(eventsByRoomName(conferenceEvents(conference), roomName));
// :: Conference -> List[Track] -> Room -> List[Track]
let tracksByRoom = (conference, tracks, room) =>
tracksOfEvents(eventsByRoom(conferenceEvents(conference), room));
// :: Conference -> List[Type] -> DayIndex -> List[Type]
let typesByDayIndex = (conference, types, dayIndex) =>
typesOfEvents(eventsByDayIndex(conferenceEvents(conference), dayIndex));
// :: Conference -> List[Type] -> Day -> List[Type]
let typesByDay = (conference, types, day) =>
typesOfEvents(eventsByDay(conferenceEvents(conference), day));
// :: Conference -> List[Type] -> RoomName -> List[Type]
let typesByRoomName = (conference, types, roomName) =>
typesOfEvents(eventsByRoomName(conferenceEvents(conference), roomName));
// :: Conference -> List[Type] -> Room -> List[Type]
let typesByRoom = (conference, types, room) =>
typesOfEvents(eventsByRoom(conferenceEvents(conference), room));
// :: Conference -> List[Language] -> DayIndex -> List[Language]
let languagesByDayIndex = (conference, languages, dayIndex) =>
languagesOfEvents(eventsByDayIndex(conferenceEvents(conference), dayIndex));
// :: Conference -> List[Language] -> Day -> List[Language]
let languagesByDay = (conference, languages, day) =>
languagesOfEvents(eventsByDay(conferenceEvents(conference), day));
// :: Conference -> List[Language] -> RoomName -> List[Language]
let languagesByRoomName = (conference, languages, roomName) =>
languagesOfEvents(eventsByRoomName(conferenceEvents(conference), roomName));
// :: Conference -> List[Language] -> Room -> List[Language]
let languagesByRoom = (conference, languages, room) =>
languagesOfEvents(eventsByRoom(conferenceEvents(conference), room));
// ---------------------------------------------------------
// Timing of Events and Days
// :: List[Event] -> luxon.DateTime -> List[Event]
let futureEvents = (events, now) =>
events.filter(e => now.toMillis() < eventStartDate(e).toMillis());
// :: List[Event] -> luxon.DateTime -> List[Event]
let currentEvents = (events, now) =>
events.filter(e =>
(eventStartDate(e).toMillis() <= now.toMillis() &&
now.toMillis() <= eventEndDate(e).toMillis()));
// :: List[Event] -> luxon.DateTime -> List[Event]
let pastEvents = (events, now) =>
events.filter(e => eventEndDate(e).toMillis() < now.toMillis());
// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event]
let startingEvents = (events, now, dt) =>
events.filter(e =>
(eventStartDate(e).minus(dt).toMillis() <= now.toMillis() &&
now.toMillis() < eventStartDate(e).toMillis()));
// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event]
let startedEvents = (events, now, dt) =>
events.filter(e =>
(eventStartDate(e).toMillis() <= now.toMillis() &&
now.toMillis() <= eventStartDate(e).plus(dt).toMillis()));
// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event]
let endingEvents = (events, now, dt) =>
events.filter(e =>
(eventEndDate(e).minus(dt).toMillis() <= now.toMillis() &&
now.toMillis() <= eventEndDate(e).toMillis()));
// :: List[Event] -> luxon.DateTime -> luxon.Duration -> List[Event]
let endedEvents = (events, now, dt) =>
events.filter(e =>
(eventEndDate(e).toMillis() < now.toMillis() &&
now.toMillis() <= eventStartDate(e).plus(dt).toMillis()));
// :: List[Event] -> List[Event]
let sortEventsByStartDate = (events) =>
events.sort((e1, e2) =>
eventStartDate(e1).toMillis() - eventStartDate(e2).toMillis());
// :: List[Event] -> List[Event]
let sortEventsByEndDate = (events) =>
events.sort((e1, e2) =>
eventEndDate(e1).toMillis() - eventEndDate(e2).toMillis());
// :: List[Event] -> List[Event]
let sortEventsByDuration = (events) =>
events.sort((e1, e2) =>
eventDuration(e1).toMillis() - eventDuration(e2).toMillis());
// :: List[Day] -> luxon.DateTime -> List[Day]
let futureDays = (days, now) =>
days.filter(d => now.toMillis() < dayStartDate(d).toMillis());
// :: List[Day] -> luxon.DateTime -> List[Day]
let currentDays = (days, now) =>
days.filter(d =>
(dayStartDate(d).toMillis() <= now.toMillis() &&
now.toMillis() <= dayEndDate(d).toMillis()));
// :: List[Day] -> luxon.DateTime -> List[Day]
let pastDays = (days, now) =>
days.filter(d => dayEndDate(d).toMillis() < now.toMillis());
// :: List[Day] -> List[Day]
let sortDaysByStartDate = (days) =>
days.sort((d1, d2) =>
dayStartDate(d1).toMillis() - dayStartDate(d2).toMillis());
// :: List[Day] -> List[Day]
let sortDaysByEndDate = (days) =>
days.sort((d1, d2) =>
dayEndDate(d1).toMillis() - dayEndDate(d2).toMillis());
// :: List[Day] -> List[Day]
let sortDaysByDuration = (days) =>
days.sort((d1, d2) =>
dayDuration(d1).toMillis() - dayDuration(d2).toMillis());
// ---------------------------------------------------------
// Extractors: Shortcut entry points
// :: Schedule -> List[Day]
let allDays = (schedule) => conferenceDays(conference(schedule));
// :: Schedule -> List[Room]
let allRooms = (schedule) => conferenceRooms(conference(schedule));
// :: Schedule -> List[Event]
let allEvents = (schedule) => conferenceEvents(conference(schedule));
// :: Schedule -> List[Person]
let allPersons = (schedule) => conferencePersons(conference(schedule));
// :: Schedule -> List[TrackName]
let allTracks = (schedule) => conferenceTracks(conference(schedule));
// :: Schedule -> List[EventType]
let allTypes = (schedule) => conferenceTypes(conference(schedule));
// :: Schedule -> List[Language]
let allLanguages = (schedule) => conferenceLanguages(conference(schedule));
// ---------------------------------------------------------
// Public API Exports
export {
optional,
defined,
withDefined,
distinct,
intersection,
processScheduleFile,
scheduleVersion,
scheduleBaseUrl,
conferenceAcronym,
conferenceTitle,
conferenceStartDate,
conferenceEndDate,
conferenceDuration,
conferenceDaysCount,
conferenceTimeslotDuration,
conferenceTimezoneName,
dayIndex,
dayDate,
dayStartDate,
dayEndDate,
dayDuration,
roomName,
roomGuid,
roomDescription,
roomCapacity,
eventId,
eventGuid,
eventLogo,
eventStartDate,
eventEndDate,
eventDuration,
eventDayIndex,
eventRoomName,
eventSlug,
eventUrl,
eventTitle,
eventSubtitle,
eventTrack,
eventType,
eventLanguage,
eventAbstract,
eventDescription,
eventRecordingLicense,
eventDoNotRecord,
eventPersons,
eventPersonCount,
eventAnswers,
personId,
personCode,
personName,
personBiography,
eventsByDayIndex,
eventsByDay,
eventsByRoomName,
eventsByRoom,
eventsByPersonId,
eventsByPersonName,
eventsByPerson,
eventsByTrack,
eventsByType,
eventsByLanguage,
roomById,
roomsByName,
dayByIndex,
personById,
personsByName,
eventById,
distinctRooms,
distinctDays,
distinctEvents,
distinctPersons,
sortPersonsByName,
sortRoomsByName,
sortEventsByTitle,
eventsOfDay,
eventsOfDays,
tracksOfEvents,
typesOfEvents,
languagesOfEvents,
conferenceDays,
conferenceRooms,
conferenceEvents,
conferencePersons,
conferenceTracks,
conferenceTypes,
conferenceLanguages,
conference,
roomNamesByDayIndex,
roomNamesByDay,
roomsByDayIndex,
roomsByDay,
roomNamesByPersonId,
roomNamesByPerson,
roomsByPersonId,
roomsByPerson,
roomNamesByTrack,
roomsByTrack,
roomNamesByType,
roomsByType,
roomNamesByLanguage,
roomsByLanguage,
personIdsByDayIndex,
personIdsByDay,
personsByDayIndex,
personsByDay,
personIdsByRoomName,
personIdsByRoom,
personsByRoomName,
personsByRoom,
personIdsByTrack,
personsByTrack,
personIdsByType,
personsByType,
personIdsByLanguage,
personsByLanguage,
dayIndicesByRoomName,
dayIndicesByRoom,
daysByRoomName,
daysByRoom,
dayIndicesByPersonId,
dayIndicesByPerson,
daysByPersonId,
daysByPerson,
dayIndicesByTrack,
daysByTrack,
dayIndicesByType,
daysByType,
dayIndicesByLanguage,
daysByLanguage,
tracksByDayIndex,
tracksByDay,
tracksByRoomName,
tracksByRoom,
typesByDayIndex,
typesByDay,
typesByRoomName,
typesByRoom,
languagesByDayIndex,
languagesByDay,
languagesByRoomName,
languagesByRoom,
futureEvents,
currentEvents,
pastEvents,
startingEvents,
startedEvents,
endingEvents,
endedEvents,
sortEventsByStartDate,
sortEventsByEndDate,
sortEventsByDuration,
futureDays,
currentDays,
pastDays,
sortDaysByStartDate,
sortDaysByEndDate,
sortDaysByDuration,
allDays,
allRooms,
allEvents,
allPersons,
allTracks,
allTypes,
allLanguages
};
// Command to generate API exports:
// grep -A 1 -e '// :: ' sol.js | sed -e '/^--$/d' -e '/ :: /d' -e 's/^let / /g' -e 's/ = .*$/,/g' > names.txt
// Note: Type signatures starting with '//-:: ' instead of '// :: ' denote unexported internal functions.