321 lines
8.4 KiB
Lua
321 lines
8.4 KiB
Lua
gl.setup(1280, 720)
|
|
|
|
font = resource.load_font("Oswald-Medium.ttf")
|
|
|
|
node.alias("room")
|
|
|
|
local json = require "json"
|
|
|
|
-- Configure room here
|
|
local SAAL = "attraktor"
|
|
|
|
util.auto_loader(_G)
|
|
|
|
util.file_watch("schedule.json", function(content)
|
|
print("reloading schedule")
|
|
talks = json.decode(content)
|
|
end)
|
|
|
|
util.file_watch("config.json", function(content)
|
|
local config = json.decode(content)
|
|
if sys.get_env then
|
|
saal = config.devices[sys.get_env("SERIAL")]
|
|
end
|
|
if not saal then
|
|
print("using statically configured saal identifier")
|
|
saal = SAAL
|
|
end
|
|
print(saal)
|
|
rooms = config.rooms
|
|
room = config.rooms[saal]
|
|
end)
|
|
|
|
local base_time = N.base_time or 0
|
|
local current_talk
|
|
local all_talks = {}
|
|
local day = 0
|
|
|
|
function get_now()
|
|
return base_time + sys.now()
|
|
end
|
|
|
|
function check_next_talk()
|
|
local now = get_now()
|
|
local room_next = {}
|
|
for idx, talk in ipairs(talks) do
|
|
if rooms[talk.place] and not room_next[talk.place] and talk.unix + 25 * 60 > now then
|
|
room_next[talk.place] = talk
|
|
end
|
|
end
|
|
|
|
for room, talk in pairs(room_next) do
|
|
talk.lines = wrap(talk.title, 40)
|
|
end
|
|
|
|
if room_next[saal] then
|
|
current_talk = room_next[saal]
|
|
else
|
|
current_talk = nil
|
|
end
|
|
|
|
all_talks = {}
|
|
for room, talk in pairs(room_next) do
|
|
if current_talk and room ~= current_talk.place then
|
|
all_talks[#all_talks + 1] = talk
|
|
end
|
|
end
|
|
table.sort(all_talks, function(a, b)
|
|
if a.unix < b.unix then
|
|
return true
|
|
elseif a.unix > b.unix then
|
|
return false
|
|
else
|
|
return a.place < b.place
|
|
end
|
|
end)
|
|
end
|
|
|
|
function wrap(str, limit, indent, indent1)
|
|
limit = limit or 72
|
|
local here = 1
|
|
local wrapped = str:gsub("(%s+)()(%S+)()", function(sp, st, word, fi)
|
|
if fi-here > limit then
|
|
here = st
|
|
return "\n"..word
|
|
end
|
|
end)
|
|
local splitted = {}
|
|
for token in string.gmatch(wrapped, "[^\n]+") do
|
|
splitted[#splitted + 1] = token
|
|
end
|
|
return splitted
|
|
end
|
|
|
|
local clock = (function()
|
|
local base_time = N.base_time or 0
|
|
|
|
local function set(time)
|
|
base_time = tonumber(time) - sys.now()
|
|
end
|
|
|
|
util.data_mapper{
|
|
["clock/midnight"] = function(since_midnight)
|
|
set(since_midnight)
|
|
end;
|
|
}
|
|
|
|
local left = 0
|
|
|
|
local function get()
|
|
local time = (base_time + sys.now()) % 86400
|
|
return string.format("%d:%02d", math.floor(time / 3600), math.floor(time % 3600 / 60))
|
|
end
|
|
|
|
return {
|
|
get = get;
|
|
set = set;
|
|
}
|
|
end)()
|
|
|
|
check_next_talk()
|
|
|
|
util.data_mapper{
|
|
["clock/set"] = function(time)
|
|
base_time = tonumber(time) - sys.now()
|
|
N.base_time = base_time
|
|
check_next_talk()
|
|
print("UPDATED TIME", base_time)
|
|
end;
|
|
["clock/day"] = function(new_day)
|
|
print("DAY", new_day)
|
|
day = new_day
|
|
end;
|
|
}
|
|
|
|
function switcher(screens)
|
|
local current_idx = 1
|
|
local current = screens[current_idx]
|
|
local switch = sys.now() + current.time
|
|
local switched = sys.now()
|
|
|
|
local blend = 0.5
|
|
|
|
local function draw()
|
|
local now = sys.now()
|
|
|
|
local percent = ((now - switched) / (switch - switched)) * 3.14129 * 2 - 3.14129
|
|
progress:use{percent = percent}
|
|
white:draw(WIDTH-50, HEIGHT-50, WIDTH-10, HEIGHT-10)
|
|
progress:deactivate()
|
|
|
|
if now - switched < blend then
|
|
local delta = (switched - now) / blend
|
|
gl.pushMatrix()
|
|
gl.translate(WIDTH/2, 0)
|
|
gl.rotate(270-90 * delta, 0, 1, 0)
|
|
gl.translate(-WIDTH/2, 0)
|
|
current.draw()
|
|
gl.popMatrix()
|
|
elseif now < switch - blend then
|
|
current.draw(now - switched)
|
|
elseif now < switch then
|
|
local delta = 1 - (switch - now) / blend
|
|
gl.pushMatrix()
|
|
gl.translate(WIDTH/2, 0)
|
|
gl.rotate(90 * delta, 0, 1, 0)
|
|
gl.translate(-WIDTH/2, 0)
|
|
current.draw()
|
|
gl.popMatrix()
|
|
else
|
|
current_idx = current_idx + 1
|
|
if current_idx > #screens then
|
|
current_idx = 1
|
|
end
|
|
current = screens[current_idx]
|
|
switch = now + current.time
|
|
switched = now
|
|
end
|
|
end
|
|
return {
|
|
draw = draw;
|
|
}
|
|
end
|
|
|
|
content = switcher{
|
|
{
|
|
time = 20;
|
|
draw = function()
|
|
redU(400, 200, "Other rooms", 80)
|
|
white:draw(0, 300, WIDTH, 302, 0.6)
|
|
y = 320
|
|
local time_sep = false
|
|
if #all_talks > 0 then
|
|
for idx, talk in ipairs(all_talks) do
|
|
if not time_sep and talk.unix > get_now() then
|
|
if idx > 1 then
|
|
y = y + 5
|
|
white:draw(0, y, WIDTH, y+2, 0.6)
|
|
y = y + 20
|
|
end
|
|
time_sep = true
|
|
end
|
|
|
|
local alpha = 1
|
|
if not time_sep then
|
|
alpha = 0.3
|
|
end
|
|
blueU(30, y, talk.start, 50)
|
|
redU(190, y, talk.place, 50)
|
|
yellow(450, y, talk.lines[math.floor((sys.now()/2) % #talk.lines)+1], 50)
|
|
y = y + 60
|
|
end
|
|
else
|
|
yellow(400, 330, "No other talks.", 50, 1,1,1,1)
|
|
end
|
|
end
|
|
}, {
|
|
time = 30;
|
|
draw = function()
|
|
if not current_talk then
|
|
redU(400, 200, "Next session...", 80, 1,1,1,1)
|
|
white:draw(0, 300, WIDTH, 302, 0.6)
|
|
redU(400, 330, "Nope. That's it.", 80)
|
|
|
|
else
|
|
local delta = current_talk.unix - get_now()
|
|
if delta > 0 then
|
|
redU(400, 200, "Next session", 80)
|
|
else
|
|
redU(400, 200, "This session", 80)
|
|
end
|
|
white:draw(0, 300, WIDTH, 302, 0.6)
|
|
|
|
blue(130, 330, current_talk.start, 50, 1,1,1,1)
|
|
if delta > 0 then
|
|
blue(130, 330 + 60, string.format("in %d min", math.floor(delta/60)+1), 50)
|
|
end
|
|
for idx, line in ipairs(current_talk.lines) do
|
|
if idx >= 5 then
|
|
break
|
|
end
|
|
yellow(400, 330 - 60 + 60 * idx, line, 50)
|
|
end
|
|
for i, speaker in ipairs(current_talk.speakers) do
|
|
blue(400, 510 + 50 * i, speaker, 50)
|
|
end
|
|
end
|
|
end
|
|
}, {
|
|
time = 10;
|
|
draw = function(t)
|
|
redU(400, 200, "Info", 80)
|
|
|
|
white:draw(0, 300, WIDTH, 302, 0.6)
|
|
|
|
blueU(30, 320, "WC", 50)
|
|
yellow(400, 320, "Im Keller", 50)
|
|
|
|
blueU(30, 380, "Spenden", 50)
|
|
yellow(400, 380, "Box am Tresen für Frühstück & Co.", 50)
|
|
|
|
blueU(30, 480, "IRC", 50)
|
|
yellow(400, 480, room.irc, 50)
|
|
|
|
blueU(30, 540, "Twitter", 50)
|
|
yellow(400, 540, room.twitter, 50)
|
|
end
|
|
}, {
|
|
time = 10;
|
|
draw = function(t)
|
|
redU(110, 200, "PUBLIC SERVICE ANNOUNCEMENT", 80)
|
|
|
|
white:draw(0, 300, WIDTH, 302, 0.6)
|
|
|
|
yellowU(350, 400, "ESST MEHR BRÖTCHEN!!1ELF", 50)
|
|
end
|
|
},
|
|
}
|
|
|
|
function redU(x, y, text, size)
|
|
red(x, y, string.upper(text), size)
|
|
end
|
|
|
|
function red(x, y, text, size)
|
|
font:write(x, y, text, size, 0.894, 0.251, 0.506, 1)
|
|
end
|
|
|
|
function yellowU(x, y, text, size)
|
|
yellow(x, y, string.upper(text), size)
|
|
end
|
|
|
|
function yellow(x, y, text, size)
|
|
font:write(x, y, text, size, 1.0, 0.776, 0.251, 1)
|
|
end
|
|
|
|
function blueU(x, y, text, size)
|
|
blue(x, y, string.upper(text), size)
|
|
end
|
|
|
|
function blue(x, y, text, size)
|
|
font:write(x, y, text, size, 0.251, 0.714, 0.906, 1)
|
|
end
|
|
|
|
function node.render()
|
|
gl.clear(0.1, 0.1, 0.1, 1)
|
|
|
|
if base_time == 0 then
|
|
return
|
|
end
|
|
|
|
util.draw_correct(logo, 20, 20, 300, 120)
|
|
|
|
yellowU(310, 20, saal, 80)
|
|
blueU(730, 20, clock.get(), 80)
|
|
redU(WIDTH-300, 20, string.format("Day %d", day), 80)
|
|
|
|
local fov = math.atan2(HEIGHT, WIDTH*2) * 360 / math.pi
|
|
gl.perspective(fov, WIDTH/2, HEIGHT/2, -WIDTH,
|
|
WIDTH/2, HEIGHT/2, 0)
|
|
content.draw()
|
|
end
|