/*
Social program for Ramaskrik.
Copyright (C) 2019 Harald Eilertsen <haraldei@anduin.net>
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 <https://www.gnu.org/licenses/>.
*/
function load_screenings(data_done) {
let req = new XMLHttpRequest()
req.addEventListener("load", data_done)
req.open("GET", "screenings")
req.responseType = "json"
req.send()
}
function pad(num) {
return num > 9 ? num.toString() : "0" + num
}
function time_f(t) {
return pad(t.getHours()) + ":" + pad(t.getMinutes())
}
function date_f(d) {
let opts = { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }
return new Intl.DateTimeFormat('nb-NO', opts).format(d)
}
function capitalize(s) {
return s.slice(0, 1).toUpperCase() + s.slice(1)
}
function isodate(d) {
return d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate())
}
window.addEventListener("load", function() {
let screenings_by_date = new Map()
function _add(screening) {
let d = new Date(screening.date || screening.start_time)
let key = isodate(d)
if (!screenings_by_date.has(key))
screenings_by_date.set(key, new Array())
let s = screenings_by_date.get(key)
s.push(screening)
};
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 + space + 5
if (lpos + 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 timestep = 30;
let timescale_font_size = 10;
let top_margin = 30;
let xmargin = 50;
function draw_timescale(c, start, end) {
let dur = Math.ceil((end - start) / 100)
c.font = timescale_font_size + 'px sans-serif'
c.lineWidth = 'thin'
c.strokeStyle = '#ccc'
let canvas = c.canvas
for (let y = 0; y <= dur; y += timestep) {
let ypos = y + top_margin;
c.beginPath()
c.moveTo(35, ypos)
c.lineTo(canvas.width, ypos)
c.stroke()
let label = time_f(new Date(start.valueOf() + y * 30000 + top_margin))
c.fillText(label, 5, ypos - 1 + Math.floor(timescale_font_size/2))
}
}
function draw_room_headers(c, rooms) {
let x = 0;
c.font = 'bold 15px sans-serif'
for (let r of [...rooms]) {
center_text(c, r, xmargin + x, 15, 100)
x += 150
}
}
function draw_screenings(c, screenings, start_time, rooms) {
let r = [...rooms]
c.strokeStyle = '#cc8'
for (let s of screenings) {
let stt = new Date(s.start_time)
let ett = new Date(s.end_time)
let ystart = Math.ceil((stt - start_time) / 30000) + top_margin;
let height = Math.ceil((ett - start_time ) / 30000) + top_margin - ystart;
let ri = r.findIndex(el => el == s.room.name)
let xstart = xmargin + ri * 150
c.fillStyle = '#cc8'
c.fillRect(xstart, ystart, 100, height)
c.strokeRect(xstart, ystart, 100, height)
c.fillStyle = '#000'
c.font = '10px sans-serif'
c.fillText(time_f(stt) + " - " + time_f(ett), xstart + 5, ystart + 10)
c.font = '12px sans-serif'
break_text(c, s.film.title, xstart + 5, ystart + 25, 95)
}
}
load_screenings(function() {
let ts = Date.now()
this.response.forEach(_add)
console.log("Screenings in " + screenings_by_date.size + " days: ")
for (let date of Array.from(screenings_by_date.keys()).sort()) {
console.log(date)
let s = screenings_by_date.get(date)
let start_time = new Date(s
.map( el => el.start_time )
.sort()
.shift())
let end_time = new Date(s
.map( el => el.end_time )
.sort()
.pop())
console.log(" Start time: " + start_time)
console.log(" End time : " + end_time)
let dur = (end_time - start_time) / 1000
console.log(" Duration : " + 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')
let rooms = new Set(s.map( el => el.room.name ))
let width = xmargin + 150 * rooms.size
let dateobj = new Date(date)
console.log("dateobj: " + dateobj)
day.id = "program-" + isodate(dateobj)
day.innerHTML = '<h2>' + capitalize(date_f(dateobj)) + '</h2>'
+ '<canvas id="canvas-' + isodate(dateobj) + '" height="' + canvas_height * 2 + '" width="' + width * 2 + '">'
+ '</canvas>'
p.appendChild(day)
let canvas = document.getElementById('canvas-' + isodate(dateobj))
let c = canvas.getContext('2d');
c.scale(2,2)
c.fillStyle = '#233'
c.fillRect(0, 0, width, canvas_height);
c.fillStyle = '#fff'
draw_room_headers(c, rooms)
draw_timescale(c, start_time, end_time)
draw_screenings(c, s, start_time, rooms)
}
console.log("Total elapsed time: " + (Date.now() - ts) + "ms.")
})
})