"use strict"; (() => { // ns-hugo:/home/raoul-web/rc3_2021/html-infobeamer-content/assets/js/services.js var delay = 3 * 5 * 60 * 1e3; var hereRoom = "Chaos-West TV"; var postsLimit = 20; var postMaxAge = 32 * 24 * 60 * 60 * 1e3; var defaultUrlSet = [ "https://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png", "https://chaos.social/avatars/original/missing.png" ]; var socialFilters = [ RegExp("http.://bit.ly/.*\\w+") ]; var socialReplacement = "\u2588\u2588\u2588\u2588\u2588"; var default_profile_image_url = () => "./nounicorn.png"; var social_limiter = (tweets, toots) => { let posts = tweets.concat(toots); let maxAge = (p) => Date.parse(p.time) >= Date.now() - postMaxAge; let recentPosts = posts.filter(maxAge); let byDate = (fst, snd) => Date.parse(fst.time) - Date.parse(snd.time); let postsSorted = recentPosts.sort(byDate); console.log("Number distinct social posts in loop: " + postsSorted.length); if (postsSorted.length > 0) { while (postsSorted.length < postsLimit) { postsSorted = postsSorted.concat(postsSorted); } } let postsLimited = postsSorted.reverse().slice(0, postsLimit); return postsLimited; }; var replace_default_image_url = (url) => defaultUrlSet.includes(url) === true ? default_profile_image_url() : url; var censorship = (text) => { socialFilters.forEach((f) => { text = text.replace(f, socialReplacement); }); return text; }; var html_plainify = (html2) => { let span = document.createElement("span"); span.innerHTML = html2; let children = span.querySelectorAll("*"); children.forEach((child) => { child.textContent += " "; }); return span.textContent.toString().replace(/ +/g, " "); }; var tweet_author = (data, tweet) => { let authorId = tweet.author_id; let users = data.includes.users; let author = users.find((item) => item.id === authorId); let userName = author !== void 0 ? author.username : "NoOne"; return userName; }; var tweet_profile_image = (data, tweet) => { let authorId = tweet.author_id; let users = data.includes.users; let author = users.find((item) => item.id === authorId); let profileImageUrl = replace_default_image_url(author.profile_image_url); return profileImageUrl; }; var tweet_text = (tweet) => tweet.text; var tweet_time = (tweet) => tweet.created_at; var twitter_filter = (inputData) => { let tweets; inputData.forEach((d) => tweets = d.data.map((t) => { return { author: tweet_author(d, t), image: tweet_profile_image(d, t), text: censorship(html_plainify(tweet_text(t))), time: tweet_time(t), source: "twitter" }; })); return tweets; }; var toot_author = (toot) => toot.account.username; var toot_profile_image = (toot) => replace_default_image_url(toot.account.avatar_static); var toot_text = (toot) => toot.content; var toot_time = (toot) => toot.created_at; var mastodon_filter = (idata) => { let toots; idata.forEach((d) => { toots = d.map((t) => { return { author: toot_author(t), image: toot_profile_image(t), text: censorship(html_plainify(toot_text(t))), time: toot_time(t), source: "mastodon" }; }); }); return toots; }; var schedule_filter = (data) => { let dataDays = data.schedule.conference.days; let talksData = dataDays.map((d) => { let rooms = Object.values(d.rooms); rooms.flat().forEach((t) => { t.day = d.index; }); return rooms; }).flat(2); let byDate = (fst, snd) => Date.parse(fst.date) - Date.parse(snd.date); let talksDataSorted = talksData.sort(byDate); return talksDataSorted; }; var is_own_event = (event) => event.room === hereRoom; var future_events = (schedule, now) => schedule.filter((e) => Date.parse(e.date) >= now - delay); var running_event = (schedule, now) => { const preDelay = 5 * 60 * 1e3; const postDelay = 3 * 5 * 60 * 1e3; let talk_duration = (durationString) => { const timeFormat = "hh:mm"; let dt = moment(durationString, timeFormat); let minutes = 60 * dt.hours() + dt.minutes(); return minutes * 60 * 1e3; }; let is_running = (e) => { let start = Date.parse(e.date); let end = start + talk_duration(e.duration); return start - preDelay <= now && now <= end + postDelay === true; }; return schedule.filter(is_own_event).filter(is_running).slice(0, 1); }; var same_music_track = (track1, track2) => track1.artist === track2.artist && track1.title === track2.title; var is_new_music = (musicA, musicB) => { let isNewMusic; if (musicA.length !== 0 && musicB.length !== 0) { isNewMusic = same_music_track(musicA[0], musicB[0]); } else if (musicA.length === 0 && musicB.length === 0) { isNewMusic = true; } else { isNewMusic = false; } return !isNewMusic; }; var music_update = (musicA, musicB) => { if (is_new_music(musicA, musicB) === true) { musicB.forEach((mb) => mb.since = Date.now()); } else { musicA.forEach((ma) => { musicB.forEach((mb) => mb.since = ma.since); }); } return musicB; }; // ns-hugo:/home/raoul-web/rc3_2021/html-infobeamer-content/assets/js/dom.js var html = htm.bind(preact.h); var hereRoom2 = "Chaos-West TV"; var number_events_all = 8; var musicAge = 5 * 1e3; var urgent = 5 * 60 * 1e3; var stale = 3 * 5 * 60 * 1e3; var lapse = 5 * 1e3; var talk_day = (talk) => { const lut = { 1: "I", 2: "II", 3: "III", 4: "IV" }; return lut[talk.day]; }; var is_own_talk = (talk) => talk.room === hereRoom2; var talk_start_time = (talk) => Date.parse(talk.date); var is_urgent = (talk, time) => { let timeDelta = talk_start_time(talk) - time; return timeDelta >= 0 && timeDelta <= urgent; }; var is_stale = (talk, time) => { let timeDelta = talk_start_time(talk) - time; return timeDelta < 0; }; var is_lapse = (talk, time) => { let timeDelta = talk_start_time(talk) - time; return timeDelta <= -(stale - lapse); }; var urgent_class = (talk, time) => is_urgent(talk, time) ? "urgent" : ""; var stale_class = (talk, time) => is_stale(talk, time) ? "stale" : ""; var lapse_class = (talk, time) => is_lapse(talk, time) ? "lapse" : ""; var speaker_names = (talk) => talk.persons.map((p) => p.public_name); var speaker_dom = (talk) => { const separator = ", "; let names = speaker_names(talk); let inner; if (names.length > 0) { let string = names.join(separator); inner = html`
${string}:
`; } else { inner = html``; } return inner; }; var starting_dom = (talk, time) => { const hrs3 = 3 * 60 * 60 * 1e3; const min15 = 3 * 5 * 60 * 1e3; const min2 = 2 * 60 * 1e3; const min1 = 60 * 1e3; let timeDelta = talk_start_time(talk) - time; let minutes = Math.ceil(Math.abs(timeDelta / 1e3 / 60)); let inner; if (timeDelta > hrs3) { inner = html`Day ${talk_day(talk)} at ${talk.start}`; } else if (timeDelta > min15) { inner = html`Starting at ${talk.start}`; } else if (timeDelta <= min15 && timeDelta > min1) { inner = html`Starting in ${minutes} minutes`; } else if (timeDelta <= min1 && timeDelta >= 0) { inner = html`Starting now!`; } else if (timeDelta < 0 && timeDelta >= -min1) { inner = html`Just started!`; } else if (timeDelta < -min1 && timeDelta >= -min15) { inner = html`Started ${minutes} minutes ago`; } else if (timeDelta < -min15) { inner = html`Seriously missed`; } return inner; }; var to_minutes = (duration) => { const timeFormat = "hh:mm"; let dt = moment(duration, timeFormat); let minutes = 60 * dt.hours() + dt.minutes(); return minutes; }; var duration_dom = (talk) => { return html`${to_minutes(talk.duration)} minutes`; }; var meta_here_dom = (schedule, time) => { let inner = html`${schedule.map((talk) => html`
${speaker_dom(talk)}
${talk.title}
${starting_dom(talk, time)} ${duration_dom(talk)}
`)}`; return inner; }; var abstract_text_dom = (talk) => { const placeHolder = "\xAF_(\u30C4)_/\xAF"; let inner; if (talk.abstract !== null) { let lang = talk.language !== void 0 ? talk.language : "en"; inner = html`
${talk.abstract}
`; } else { inner = html``; } return inner; }; var track_dom = (talk) => { let inner; if (talk.track !== null) { inner = html`
Track: ${talk.track}
`; } else { inner = html``; } return inner; }; var abstract_here_dom = (schedule) => { let inner = html``; schedule.forEach((talk) => { inner = html` ${abstract_text_dom(talk)} ${track_dom(talk)}`; }); return inner; }; var talk_day_dom = (talk) => html`Day ${talk_day(talk)}`; var highlight_class = (talk) => is_own_talk(talk) === true ? "highlight" : ""; var do_not_record_dom = (talk) => { let icon = "fa-microphone-slash"; let inner; if (talk.do_not_record === true) { inner = html``; } else { inner = html``; } return inner; }; var list_all_dom = (schedule, time) => { let inner = html` ${schedule.map((talk) => html`
${talk.title}
${talk.start} ${talk_day_dom(talk)} ${do_not_record_dom(talk)} ${talk.room}
`)}`; return inner; }; var next_up_here_dom = (talks, time) => { let inner; if (talks.length > 0) { inner = html`
Next Up Here
${meta_here_dom(talks, time)}
`; } else { inner = html`
Next Up Here
`; } return inner; }; var next_up_abstract_dom = (talks, time) => { let inner; if (talks.length > 0) { inner = html`
Abstract
${abstract_here_dom(talks)}
`; } else { inner = html``; } return inner; }; var next_up_list_all_dom = (talks, time) => { let inner; if (talks.length > 0) { inner = html`
Next Up at rC3
${list_all_dom(talks, time)}
`; } else { inner = html`
Next Up at rC3
`; } return inner; }; var schedule_dom = (schedule, time) => { let allTalks = schedule.slice(0, number_events_all); let nextTalkHere = schedule.filter(is_own_talk).slice(0, 1); return html`
${next_up_here_dom(nextTalkHere, time)} ${next_up_abstract_dom(nextTalkHere, time)}
${next_up_list_all_dom(allTalks, time)}
`; }; var music_changed = (current, time) => time - current.since <= musicAge; var changed_music_class = (current, time) => music_changed(current, time) ? "changed" : ""; var music_license_dom = (current) => current.license !== void 0 ? html`(${current.license})` : html``; var music_title_dom = (current) => current.license !== void 0 ? html`«${current.title}»` : html``; var music_artist_dom = (current) => current.license !== void 0 ? html`by${current.artist}` : html``; var music_playing_now_dom = (music, time) => { return html`
${music.map((current) => html`
Now playing: ${music_license_dom(current)}
${music_title_dom(current)} ${music_artist_dom(current)}
`)}
`; }; var post_time = (date) => moment(date).format("H:mm, D. MMMM YYYY"); var social_network_dom = (post) => { let icon = ""; if (post.source === "twitter") { icon = "fa-twitter"; } else if (post.source === "mastodon") { icon = "fa-mastodon"; } return html``; }; var single_post_dom = (post) => { let inner = html`
${social_network_dom(post)} @${post.author} ${post_time(post.time)}
${post.text}
`; return inner; }; var social_container_dom = (posts) => { let inner = html`
${posts.map((p) => single_post_dom(p))}
`; return inner; }; var hastag_talk_title_dom = (talk) => { let inner = html`:`; talk.forEach((t) => { inner = html` regarding the talk «${t.title}»:`; }); return inner; }; var hashtag_dom = (talk) => { let inner = html`
For Questions:
Please use the Hashtag #rc3cwtv or join our IRC Channel #rc3-cwtv
For Questions${hastag_talk_title_dom(talk)}
Please use the Hashtag #rc3cwtv on Twitter or Mastodon, or join our IRC channel #rc3-cwtv:irc.hackint.org
`; return inner; }; function update_main_slide(data, time) { let schedule = data.futureSchedule; let runningEvent = data.runningEvent; let music = data.music; let postings = data.posts; let inner = html` ${schedule_dom(schedule, time)} ${hashtag_dom(runningEvent)} ${music_playing_now_dom(music, time)} ${social_container_dom(postings)} `; const anchorElId = "main"; const el = document.getElementById(anchorElId); preact.render(inner, el); } // var scheduleData = []; var musicData = []; var twitterData = []; var mastodonData = []; if (window.Worker) { const workerBaseURL = window.infoBeamerConfig.get("workerBaseURL"); const fetchWorkerCode = workerBaseURL + "js/generic_fetch_worker.js"; const scheduleWorker = new Worker(fetchWorkerCode); const scheduleType = "Schedule"; const scheduleURL = window.infoBeamerConfig.get("scheduleURL"); const scheduleFetchInterval = window.infoBeamerConfig.get("scheduleFetchInterval"); scheduleWorker.postMessage({ fetchType: scheduleType, fetchURL: scheduleURL, fetchInterval: scheduleFetchInterval }); scheduleWorker.onmessage = function(e) { if (e.data.msgType === scheduleType) { scheduleData = schedule_filter(e.data.json); update_screen(); } }; const musicWorker = new Worker(fetchWorkerCode); const musicType = "Music"; const musicURL = window.infoBeamerConfig.get("musicURL"); const musicFetchInterval = window.infoBeamerConfig.get("musicFetchInterval"); musicWorker.postMessage({ fetchType: musicType, fetchURL: musicURL, fetchInterval: musicFetchInterval }); musicWorker.onmessage = function(e) { if (e.data.msgType === musicType) { let musicDataUpdate = [e.data.json]; musicData = music_update(musicData, musicDataUpdate); update_screen(); } }; const twitterWorker = new Worker(fetchWorkerCode); const twitterType = "Twitter"; const twitterURL = window.infoBeamerConfig.get("twitterURL"); const twitterFetchInterval = window.infoBeamerConfig.get("twitterFetchInterval"); twitterWorker.postMessage({ fetchType: twitterType, fetchURL: twitterURL, fetchInterval: twitterFetchInterval }); twitterWorker.onmessage = function(e) { if (e.data.msgType === twitterType) { twitterData = [e.data.json]; twitterData = twitter_filter(twitterData); update_screen(); } }; const mastodonWorker = new Worker(fetchWorkerCode); const mastodonType = "Mastodon"; const mastodonURL = window.infoBeamerConfig.get("mastodonURL"); const mastodonFetchInterval = window.infoBeamerConfig.get("mastodonFetchInterval"); mastodonWorker.postMessage({ fetchType: mastodonType, fetchURL: mastodonURL, fetchInterval: mastodonFetchInterval }); mastodonWorker.onmessage = function(e) { if (e.data.msgType === mastodonType) { mastodonData = [e.data.json]; mastodonData = mastodon_filter(mastodonData); update_screen(); } }; } else { console.log("Your browser doesn't support web workers."); } var fakeTimeDelta = 0; function update_screen() { let realTime = new Date(); let now = Date.now() + fakeTimeDelta; update_main_slide({ futureSchedule: future_events(scheduleData, now), runningEvent: running_event(scheduleData, now), music: musicData, posts: social_limiter(twitterData, mastodonData) }, now); } function main_loop() { update_screen(); setTimeout(main_loop, 1 * 1e3); } main_loop(); })();