import { normalizeId } from './client.ts'
import type {
EventSchedule,
EventSummary,
ScheduleSlot,
SessionizeAllResult,
SessionizeAllSession,
SessionizeAllSpeaker,
SessionizeListedSession,
SessionizeListedSpeaker,
SessionizeScheduleDay,
SessionizeSessionGroup,
SessionizeSpeakerRef,
SlimSession,
SlimSpeaker,
} from './types.ts'
function roomNameById(
rooms: Array<{ id: number; name: string }>,
): Map<number, string> {
return new Map(rooms.map((room) => [room.id, room.name]))
}
function categoryValues(
session: SessionizeAllSession,
categories: SessionizeAllResult['categories'],
): Array<{ name: string; values: Array<string> }> {
const selected = new Set(session.categoryItems)
return categories
.map((category) => ({
name: category.title,
values: category.items
.filter((item) => selected.has(item.id))
.map((item) => item.name),
}))
.filter((category) => category.values.length > 0)
}
function listedCategoryValues(
session: SessionizeListedSession,
): Array<{ name: string; values: Array<string> }> {
return session.categories
.map((category) => ({
name: category.name,
values: category.categoryItems.map((item) => item.name),
}))
.filter((category) => category.values.length > 0)
}
export function slimSessionFromAll(
session: SessionizeAllSession,
speakersById: Map<string, SessionizeAllSpeaker>,
rooms: Array<{ id: number; name: string }>,
categories: SessionizeAllResult['categories'],
): SlimSession {
const roomsById = roomNameById(rooms)
return {
id: normalizeId(session.id),
title: session.title,
startsAt: session.startsAt,
endsAt: session.endsAt,
roomId: session.roomId,
room: session.roomId == null ? null : (roomsById.get(session.roomId) ?? null),
speakers: session.speakers.map((speakerId) => {
const speaker = speakersById.get(normalizeId(speakerId))
return {
id: normalizeId(speakerId),
name: speaker?.fullName ?? normalizeId(speakerId),
}
}),
categories: categoryValues(session, categories),
isServiceSession: session.isServiceSession,
isPlenumSession: session.isPlenumSession,
status: session.status,
}
}
export function slimSessionFromListed(
session: SessionizeListedSession,
): SlimSession {
return {
id: normalizeId(session.id),
title: session.title,
startsAt: session.startsAt,
endsAt: session.endsAt,
roomId: session.roomId,
room: session.room,
speakers: session.speakers.map((speaker) => ({
id: normalizeId(speaker.id),
name: speaker.name,
})),
categories: listedCategoryValues(session),
isServiceSession: session.isServiceSession,
isPlenumSession: session.isPlenumSession,
status: session.status,
}
}
export function flattenSessionGroups(
groups: Array<SessionizeSessionGroup>,
): Array<SlimSession> {
const byId = new Map<string, SlimSession>()
for (const group of groups) {
for (const session of group.sessions) {
const slim = slimSessionFromListed(session)
const existing = byId.get(slim.id)
if (existing) {
const alreadyHasGroup = existing.categories.some(
(category) =>
category.values.includes(group.groupName) ||
category.name === group.groupName,
)
if (!alreadyHasGroup && group.groupName) {
existing.categories = [
...existing.categories,
{ name: 'Group', values: [group.groupName] },
]
}
continue
}
byId.set(slim.id, slim)
}
}
return [...byId.values()]
}
export function slimSpeakerFromAll(
speaker: SessionizeAllSpeaker,
sessionsById: Map<string, SessionizeAllSession>,
): SlimSpeaker {
const sessionIds = speaker.sessions.map((id) => normalizeId(id))
return {
id: normalizeId(speaker.id),
fullName: speaker.fullName,
firstName: speaker.firstName,
lastName: speaker.lastName,
tagLine: speaker.tagLine,
isTopSpeaker: speaker.isTopSpeaker,
profilePicture: speaker.profilePicture,
links: speaker.links,
sessionIds,
sessionTitles: sessionIds
.map((id) => sessionsById.get(id)?.title)
.filter((title): title is string => Boolean(title)),
}
}
export function slimSpeakerFromListed(
speaker: SessionizeListedSpeaker,
): SlimSpeaker {
return {
id: normalizeId(speaker.id),
fullName: speaker.fullName,
firstName: speaker.firstName,
lastName: speaker.lastName,
tagLine: speaker.tagLine,
isTopSpeaker: speaker.isTopSpeaker,
profilePicture: speaker.profilePicture,
links: speaker.links,
sessionIds: speaker.sessions.map((session) => normalizeId(session.id)),
sessionTitles: speaker.sessions.map((session) => session.name),
}
}
export function projectEvent(
endpointId: string,
data: SessionizeAllResult,
): EventSummary {
const speakersById = new Map(
data.speakers.map((speaker) => [normalizeId(speaker.id), speaker]),
)
const sessionsById = new Map(
data.sessions.map((session) => [normalizeId(session.id), session]),
)
return {
endpointId,
sessionCount: data.sessions.length,
speakerCount: data.speakers.length,
roomCount: data.rooms.length,
categoryCount: data.categories.length,
rooms: data.rooms.map((room) => ({ id: room.id, name: room.name })),
categories: data.categories.map((category) => ({
id: category.id,
title: category.title,
type: category.type,
items: category.items.map((item) => ({ id: item.id, name: item.name })),
})),
sessions: data.sessions.map((session) =>
slimSessionFromAll(session, speakersById, data.rooms, data.categories),
),
speakers: data.speakers.map((speaker) =>
slimSpeakerFromAll(speaker, sessionsById),
),
}
}
function scheduleSessionToSlot(
session: SessionizeScheduleDay['rooms'][number]['sessions'][number],
room: { id: number; name: string },
): ScheduleSlot {
const speakers: Array<SessionizeSpeakerRef> = session.speakers.map(
(speaker) => ({
id: normalizeId(speaker.id),
name: speaker.name,
}),
)
return {
startsAt: session.startsAt,
endsAt: session.endsAt,
roomId: session.roomId ?? room.id,
room: session.room ?? room.name,
session: {
id: normalizeId(session.id),
title: session.title,
isServiceSession: session.isServiceSession,
isPlenumSession: session.isPlenumSession,
speakers,
},
}
}
export function projectSchedule(
endpointId: string,
days: Array<SessionizeScheduleDay>,
): EventSchedule {
return {
endpointId,
days: days.map((day) => {
const slotsByKey = new Map<string, ScheduleSlot>()
for (const room of day.rooms) {
for (const session of room.sessions ?? []) {
const slot = scheduleSessionToSlot(session, room)
slotsByKey.set(`${slot.session.id}:${slot.roomId}:${slot.startsAt}`, slot)
}
}
const slots = [...slotsByKey.values()].sort((left, right) => {
const start = (left.startsAt ?? '').localeCompare(right.startsAt ?? '')
if (start !== 0) return start
return (left.room ?? '').localeCompare(right.room ?? '')
})
return {
date: day.date,
rooms: day.rooms.map((room) => ({ id: room.id, name: room.name })),
slots,
}
}),
}
}
export function matchSession(
session: SlimSession,
query: string,
): boolean {
const q = query.trim()
if (!q) return false
if (normalizeId(session.id) === normalizeId(q)) return true
if (session.title.toLocaleLowerCase() === q.toLocaleLowerCase()) return true
return (
session.title.toLocaleLowerCase().includes(q.toLocaleLowerCase()) ||
session.speakers.some((speaker) =>
speaker.name.toLocaleLowerCase().includes(q.toLocaleLowerCase()),
)
)
}
export function matchSpeaker(speaker: SlimSpeaker, query: string): boolean {
const q = query.trim()
if (!q) return false
if (normalizeId(speaker.id) === normalizeId(q)) return true
const haystacks = [
speaker.fullName,
speaker.firstName,
speaker.lastName,
speaker.tagLine ?? '',
...speaker.sessionTitles,
]
return haystacks.some((value) =>
value.toLocaleLowerCase().includes(q.toLocaleLowerCase()),
)
}