/* Social program for Ramaskrik. Copyright (C) 2019 Harald Eilertsen This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ function load_screenings(data_done) { let req = new XMLHttpRequest() req.addEventListener("load", data_done) req.open("GET", "ravenheart-2019.json") req.responseType = "json" req.send() } function date_f(d) { let opts = { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' } return new Intl.DateTimeFormat('nb-NO', opts).format(d) } window.addEventListener("load", function() { let screenings_by_date = new Map() function _add(screening) { let d = Date.parse(screening.date) if (!screenings_by_date.has(d)) screenings_by_date.set(d, new Array()) let s = screenings_by_date.get(d) s.push(screening) }; function _end_time(screening) { if (screening.end_time < screening.start_time) { return screening.end_time .split(':') // Add 24 to the hour component of the time string .map( (v, i) => i == 0 ? (parseInt(v) + 24).toString() : v) .join(':') } else { return screening.end_time } } function _time_to_sec(t) { let expl = t.split(':').map( v => parseInt(v) ) return expl[0] * 3600 + expl[1] * 60 + expl[2] } function _sec_to_time(v) { let hour = Math.floor(v / 3600) v = v % 3600 let min = Math.floor(v / 60) let f = Intl.NumberFormat('nb-NO', { minimumIntegerDigits: 2 }) return [ f.format(hour), f.format(min) ].join(':') } function time_f(t) { _sec_to_time(_time_to_sec(t)) } function break_text(c, text, x, y, width) { let len = c.measureText(text).width if (len < width) { c.fillText(text, x, y) return } let expl = text.split(' ') let space = c.measureText(' ').width let llen = 0 let lpos = 0 for (let frag of expl) { flen = c.measureText(frag).width llen += flen if (llen > width) { llen = 0 lpos = 0 y += 15 } c.fillText(frag, x + lpos, y) lpos += flen + space } } function center_text(c, text, x, y, width) { let len = c.measureText(text).width let xpos = Math.ceil((width - len) / 2) c.fillText(text, x + xpos, y) } let margin = 30; let xmargin = 50; function draw_timescale(c, start, end) { let dur = Math.ceil((end - start) / 30) c.font = '10px sans-serif' c.lineWidth = 'thin' c.strokeStyle = '#ccc' for (let y = 0; y <= dur; y += 30) { let ypos = y + margin; c.beginPath() c.moveTo(35, ypos) c.lineTo(510, ypos) c.stroke() c.fillText(_sec_to_time(y * 30 + start + margin), 5, ypos + 3) } } function draw_room_headers(c, rooms) { let x = 0; c.font = 'bold 15px sans-serif' for (let r of [...rooms]) { center_text(c, r, 50 + x, 15, 100) x += 150 } } function draw_screenings(c, screenings, start_time, rooms) { let r = [...rooms] c.strokeStyle = '#cfc' for (let s of screenings) { let stt = _time_to_sec(s.start_time) let ett = _time_to_sec(_end_time(s)) let ystart = Math.ceil((stt - start_time) / 30) + margin; let height = Math.ceil((ett - start_time ) / 30) + margin - ystart; let ri = s.room.id - 1 let xstart = xmargin + ri * 150 c.fillStyle = '#eca' c.fillRect(xstart, ystart, 100, height) c.strokeRect(xstart, ystart, 100, height) c.fillStyle = '#000' c.font = '10px sans-serif' c.fillText(_sec_to_time(stt) + " - " + _sec_to_time(ett), xstart + 5, ystart + 10) c.font = '12px sans-serif' break_text(c, s.film.title, xstart + 5, ystart + 25, 90) } } load_screenings(function() { this.response.forEach(_add) console.log("Screenings in " + screenings_by_date.size + " days: ") for (let date of screenings_by_date.keys()) { let date_str = date_f(date) console.log(date_str) let s = screenings_by_date.get(date) let start_time = s .map( el => _time_to_sec(el.start_time) ) .reduce( (acc, cur) => cur < acc ? cur : acc, _time_to_sec('23:59:59') ) let end_time = s .map( el => _time_to_sec(_end_time(el))) .reduce( (acc, cur) => cur > acc ? cur : acc, 0 ) console.log(" Start time: " + _sec_to_time(start_time)) console.log(" End time : " + _sec_to_time(end_time)) let dur = end_time - start_time console.log(" Duration : " + _sec_to_time(dur)) // Each line in the canvas equals half a minute let canvas_height = Math.ceil(dur / 30) + 60 let p = document.querySelector('#program') let day = document.createElement('section') day.id = "program-" + date_str day.innerHTML = '

' + date_str + '

' + '' + '' p.appendChild(day) let canvas = document.getElementById('canvas-' + date_str) let c = canvas.getContext('2d'); c.fillStyle = '#000' c.fillRect(0, 0, 350, canvas_height); let rooms = new Set(s.map( el => el.room.name )) c.fillStyle = '#fff' draw_room_headers(c, rooms) draw_timescale(c, start_time, end_time) draw_screenings(c, s, start_time, rooms) } }) })