Started boopbox implementation
|
@ -0,0 +1,86 @@
|
|||
from sanic import Blueprint, exceptions, response
|
||||
from time import time
|
||||
from asyncio import Future
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from asyncio import Queue
|
||||
from random import randint
|
||||
from boop_process import boop_process
|
||||
|
||||
bp = Blueprint("boop", url_prefix="/boop")
|
||||
|
||||
bp.ctx.boopbox_queue = {'a': Queue(), 'b': Queue(), 'c': Queue()}
|
||||
bp.ctx.busy = {'a': False, 'b': False, 'c': False}
|
||||
bp.ctx.last_tag = {'a': None, 'b': None, 'c': None}
|
||||
bp.ctx.repeats = {'a': None, 'b': None, 'c': None}
|
||||
|
||||
def enable_nfc(enable, boopbox_id):
|
||||
log.info('NFC is ' + ('enabled' if enable else 'disabled'))
|
||||
app.ctx.queue.put_nowait({'_': 'nfc', 'enabled': enable})
|
||||
app.ctx.nfc_enabled = enable;
|
||||
|
||||
@bp.get("/refresh")
|
||||
async def refresh_boops(request):
|
||||
await boop_process(request.app.ctx.om.cache.values(), request.app.ctx.boop)
|
||||
return response.text('ok')
|
||||
|
||||
@bp.get("/")
|
||||
async def show_boopbox(request):
|
||||
tpl = request.app.ctx.tpl.get_template('boopbox.html')
|
||||
return response.html(tpl.render())
|
||||
|
||||
@bp.get("/getqueue/<boopbox_id>")
|
||||
async def boop_queue(request, boopbox_id):
|
||||
|
||||
items = []
|
||||
queue = bp.ctx.boopbox_queue[boopbox_id]
|
||||
while 1:
|
||||
try:
|
||||
item = queue.get_nowait()
|
||||
except asyncio.queues.QueueEmpty:
|
||||
if items:
|
||||
break
|
||||
|
||||
# Try one last time to get a task, then fail.
|
||||
bp.ctx.busy[boopbox_id] = False
|
||||
try:
|
||||
item = await asyncio.wait_for(queue.get(), timeout=5)
|
||||
except asyncio.exceptions.TimeoutError:
|
||||
break
|
||||
|
||||
items.append(item)
|
||||
|
||||
if len(items):
|
||||
bp.ctx.busy[boopbox_id] = True
|
||||
return response.json(items)
|
||||
|
||||
@bp.post("/read")
|
||||
async def handle_boop(request):
|
||||
payload = request.json
|
||||
queue = bp.ctx.boopbox_queue[payload['boopbox_id']]
|
||||
|
||||
if bp.ctx.busy[payload['boopbox_id']]: return response.text('busy')
|
||||
|
||||
|
||||
await queue.put({'_': 'play', 'src': f"/res/snd/error.wav"})
|
||||
|
||||
if bp.ctx.last_tag[payload['boopbox_id']] == payload['id']:
|
||||
bp.ctx.repeats[payload['boopbox_id']] += 1
|
||||
else:
|
||||
bp.ctx.last_tag[payload['boopbox_id']] = payload['id']
|
||||
bp.ctx.repeats[payload['boopbox_id']] = 0
|
||||
|
||||
if bp.ctx.repeats[payload['boopbox_id']] > 5:
|
||||
await queue.put({'_': 'play', 'src': f"/res/snd/ratelimit.wav"})
|
||||
await queue.put({'_': 'bye'})
|
||||
return response.text('ok')
|
||||
|
||||
if bp.ctx.repeats[payload['boopbox_id']] > 10:
|
||||
await queue.put({'_': 'talk', 'who': 'tiger', 'msg': f"Hey! Stop that! You're not the only one here!"})
|
||||
await queue.put({'_': 'bye'})
|
||||
return response.text('ok')
|
||||
|
||||
request.app.ctx.boop.execute('INSERT INTO boop(tag_id, station, ts) VALUES (?,?,?)', (payload['id'], payload['boopbox_id'], int(time())))
|
||||
request.app.ctx.boop.commit()
|
||||
|
||||
return response.text('ok')
|
|
@ -0,0 +1,42 @@
|
|||
from datetime import datetime
|
||||
from random import randint
|
||||
from hashlib import md5
|
||||
from base64 import b16encode
|
||||
|
||||
fibonacci = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
|
||||
current_date = datetime.today()
|
||||
|
||||
async def boop_process(orders, db):
|
||||
print(f'Processing {len(orders)} orders')
|
||||
db.execute('DELETE FROM player')
|
||||
|
||||
for o in orders:
|
||||
|
||||
tags = []
|
||||
code = o.code
|
||||
tag_id = o.nfc_id or b16encode(md5(code.encode()).digest()).decode()[:14]
|
||||
birthday = o.birth_date
|
||||
badge_id = o.badge_id or randint(0,200)
|
||||
room = o.actual_room or randint(100,400)
|
||||
country = o.country
|
||||
name = o.first_name.lower().strip()
|
||||
|
||||
birth_date = datetime.strptime(birthday, "%Y-%m-%d").date()
|
||||
|
||||
age = current_date.year - birth_date.year
|
||||
if (current_date.month, current_date.day) < (birth_date.month, birth_date.day):
|
||||
age -= 1
|
||||
|
||||
# Check if the birthday is today
|
||||
if (current_date.month, current_date.day) == (birth_date.month, birth_date.day):
|
||||
tags.append('birthday')
|
||||
|
||||
# Check if the badge is a fib number
|
||||
if badge_id in fibonacci:
|
||||
tags.append('fibonacci')
|
||||
|
||||
db.execute('INSERT INTO player(tag_id, code, tags, birthday, badge_id, age, name, room, country) VALUES (?,?,?,?,?,?,?,?,?)',
|
||||
(tag_id, code, ','.join(tags), birthday, badge_id, age, name, room, country)
|
||||
)
|
||||
|
||||
db.commit()
|
After Width: | Height: | Size: 1.2 MiB |
|
@ -0,0 +1,95 @@
|
|||
/* Fonts */
|
||||
@font-face {font-family: 'Alegreya';src: url("font/alegreya-latin-600-normal.woff2") format('woff2');}
|
||||
@font-face {font-family: 'Nexa Rust Sans'; src: url("font/NexaRustSans-Black.otf");}
|
||||
@font-face {font-family: 'Ticketing'; src: url("font/ticketing.otf");}
|
||||
@font-face {font-family: 'Trade Winds'; src: url("font/TradeWinds-Regular.ttf");}
|
||||
|
||||
* {margin:0;padding:0;border:0;box-sizing:border-box;}
|
||||
body {font-family: 'Alegreya', serif;background:#000;color:#fff;overflow:hidden; /*cursor: none;*/}
|
||||
em {color:#fc0;}
|
||||
#border {border:red 1px dotted;position:absolute;top:50%;left:50%;transform:translateX(-640px) translateY(-400px);width:1280px;height:800px;z-index:1000;}
|
||||
#main {position:absolute;top:50%;left:50%;transform:translateX(-640px) translateY(-400px);background:linear-gradient(
|
||||
rgba(0, 0, 0, 0.5),
|
||||
rgba(0, 0, 0, 0.5)
|
||||
),url('bg.png');background-size:cover;background-repeat:no-repeat;width:1280px;height:800px;border:1px solid #000;overflow:hidden;}
|
||||
#commands a {color:#fff;display:inline-block;padding:0.2em;margin:0 0.25em;background:#009;font-family:monospace;font-size:2em;line-height:1.2em;}
|
||||
|
||||
#debug {font-family:monospace;}
|
||||
|
||||
#error {font-family:'Ticketing';font-size:2em;position:absolute;top:50%;left:50%;transform:translateX(-640px) translateY(-400px);background:#333;width:1280px;height:800px;background:rgba(0,0,0,0.75);z-index:200;box-sizing:border-box;}
|
||||
#error p {display:block;margin-top:10em;text-align:center;background:#00c;padding:0.5em 0;}
|
||||
|
||||
/* Personaggi */
|
||||
.char {position:absolute;transform:translateX(0px);transition: all 0.3s;z-index:500;}
|
||||
#wolf {width:400px;left:880px;top:240px;}
|
||||
#tiger {width:500px;left:-60px;top:90px;}
|
||||
#wolf[disabled] {transform:translateX(398px);}
|
||||
#tiger[disabled] {transform:translateX(-440px);}
|
||||
|
||||
/* Nfc status in basso a dx */
|
||||
#nfcstat {background:#090;position:absolute;right:32px;width:320px;top:716px;font-size:1.7em;padding: 8px 16px;text-align:center;border-radius:8px}
|
||||
#nfcstat[disabled] {background:#a00;}
|
||||
#nfcstat img {margin-left:0.2em;margin-top:-4px;height:0.9em;display:inline-block;vertical-align:middle; filter: invert(100%);}
|
||||
|
||||
.hidden {opacity: 0;}
|
||||
.welcome-back {transition: all .25s;}
|
||||
|
||||
/* Message box */
|
||||
#msgbox {backdrop-filter: blur(3px);position:absolute;width:1180px;height:190px;background:rgba(0.7,0,0,0.5);padding:26px;left:20px;bottom:20px;border-radius:8px;color:#fff;font-weight:bold;font-size:32px;opacity:1;transition: opacity .3s;z-index:600;}
|
||||
#msgbox[disabled] {opacity:0;}
|
||||
#msgbox img {height:60px;display:inline-block;vertical-align:middle; filter: invert(100%)}
|
||||
#msgbox span {display:block;}
|
||||
|
||||
@keyframes touch {from{opacity:0.3;} to{opacity:0.9;}}
|
||||
#touch {animation-name:touch;animation-duration:0.7s;animation-iteration-count:infinite;animation-direction:alternate;}
|
||||
#touch[disabled] {display:none;}
|
||||
|
||||
/* Events */
|
||||
|
||||
#events > p {margin-bottom:1em;}
|
||||
#events > p > a {display:inline-block;border-radius:16px;padding:0.1em 0.7em;margin-right:0.3em;text-decoration: none;color:#fff;font-size:1.3em;background:rgba(100,0,200,0.2);border:4px solid rgba(0,0,0,0);}
|
||||
#events > p > a:hover {border:4px solid darkorchid;}
|
||||
|
||||
#eventsbox div, #column {backdrop-filter: blur(6px);background:rgba(0,0,0,0.2);border-radius:16px;text-shadow: 0 0 5px rgba(0,0,0,0.5);}
|
||||
|
||||
#events {transition: all .25s;position:absolute;left:32px;height:740px;width:870px;top:32px;}
|
||||
|
||||
#eventsbox span {float:right;background:#300;border-radius:6px;font-size:0.9em;padding:0.3em 0.5em;}
|
||||
#eventsbox span[data-location~="Reception"] {background:#613583;}
|
||||
#eventsbox span[data-location~="Restaurant"] {background:#26a269;}
|
||||
#eventsbox span[data-location~="Disco"] {background:#e5a50a;}
|
||||
#eventsbox span[data-location~="Dealers"] {background:#1a5fb4;}
|
||||
#eventsbox span[data-location~="Tent"] {background:#a51d2d;}
|
||||
#eventsbox span[data-location~="Stage"] {background:#63452c;}
|
||||
|
||||
#eventsbox > div {padding:1em 1em 0.5em 1em;font-size:1.5em;margin-bottom:1em;border-bottom:5px solid;border-radius:8px 8px 0 0;border-image: linear-gradient(to right, darkblue, darkorchid 50%, rgba(0,0,0,0) 50.1%) 1;transition:all 0.5s;}
|
||||
|
||||
#eventsbox {height:690px;overflow:auto;overflow:auto;scrollbar-width: none;-webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 5%, #000 95%, transparent);}
|
||||
|
||||
.eventmeter {box-sizing:border-box;display:inline-block;background:#090;height:4px;width:100%;margin-left:-1em;}
|
||||
|
||||
/* Side column and tv */
|
||||
#tv {position:absolute;background:#000;right:32px;width:320px;height:180px;top:32px;border-radius:16px;}
|
||||
#column {transition: all .25s;text-align:center;position:absolute;right:32px;width:320px;height:460px;top:230px;padding:1em;}
|
||||
#column p {font-size:1.3em;}
|
||||
|
||||
h1,h2,h3 {font-family: 'Trade Winds';}
|
||||
h1 {text-align:center;font-size:2em;}
|
||||
|
||||
hr {border: 1px solid white;opacity:0.2;width:320px;max-width:60%;margin:0.5em auto;}
|
||||
|
||||
@keyframes shake {
|
||||
0% { transform: translate(1px, 1px); }
|
||||
10% { transform: translate(-1px, -2px); }
|
||||
20% { transform: translate(-3px, 0px); }
|
||||
30% { transform: translate(3px, 2px); }
|
||||
40% { transform: translate(1px, -1px); }
|
||||
50% { transform: translate(-1px, 2px); }
|
||||
60% { transform: translate(-3px, 1px); }
|
||||
70% { transform: translate(3px, 1px); }
|
||||
80% { transform: translate(-1px, -1px); }
|
||||
90% { transform: translate(1px, 2px); }
|
||||
100% { transform: translate(1px, -2px); }
|
||||
}
|
||||
|
||||
.yell {line-height:1.1em;font-size:2.5em;animation: shake 0.5s;animation-iteration-count: infinite; }
|
|
@ -0,0 +1,246 @@
|
|||
const box = document.getElementById("msgbox");
|
||||
const msgbox = document.getElementById("msgcontent");
|
||||
const wolf = document.getElementById("wolf");
|
||||
const tiger = document.getElementById("tiger");
|
||||
const touch = document.getElementById("touch");
|
||||
const bye_elements = document.getElementsByClassName('bye');
|
||||
const welcome_back_elements = document.getElementsByClassName('welcome-back');
|
||||
|
||||
const apiUrl = "/manage/api/events.json";
|
||||
let currentTime = new Date();
|
||||
|
||||
const searchParams = new URL(window.location.href).searchParams;
|
||||
const boopboxId = searchParams.get('id');
|
||||
|
||||
if(!boopboxId) {
|
||||
alert("Boopbox id is not set!");
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
updateEvents();
|
||||
loop();
|
||||
clock();
|
||||
//fastForward();
|
||||
}
|
||||
|
||||
let cachedData = null;
|
||||
|
||||
function updateEvents() {
|
||||
fetch(apiUrl)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
cachedData = data;
|
||||
updateDivs(data);
|
||||
})
|
||||
.catch(error => {
|
||||
if (cachedData) {
|
||||
updateDivs(cachedData);
|
||||
} else {
|
||||
console.error('Request failed and no cached data available:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateDivs(data) {
|
||||
const eventsContainer = document.getElementById("eventsbox");
|
||||
const tenMinutesFromNow = new Date(currentTime.getTime() + 10 * 60000);
|
||||
const tenMinutesAgo = new Date(currentTime.getTime() - 10 * 60000);
|
||||
let visibleEvents = 0;
|
||||
|
||||
data.forEach(event => {
|
||||
const eventStart = new Date(event.start);
|
||||
const eventEnd = new Date(event.end);
|
||||
|
||||
const eventPercent = Math.max(0, Math.min(100, ((currentTime - eventStart) / (eventEnd - eventStart)) * 100));
|
||||
|
||||
if (eventStart <= tenMinutesFromNow && eventEnd >= tenMinutesAgo) {
|
||||
|
||||
visibleEvents++;
|
||||
let eventDiv = document.getElementById(`event-${event.id}`);
|
||||
|
||||
if (!eventDiv) {
|
||||
eventDiv = document.createElement('div');
|
||||
eventDiv.id = `event-${event.id}`;
|
||||
eventsContainer.appendChild(eventDiv);
|
||||
}
|
||||
|
||||
eventDiv.innerHTML = `
|
||||
<span data-location="${event.location}">${event.location}</span>
|
||||
<h2>${event.title}</h2>
|
||||
<p>${event.about}</p>
|
||||
<p style="text-align:right;">${Math.ceil(Math.max(0, (eventEnd - currentTime) / 60000))} minutes left</p>
|
||||
`;
|
||||
|
||||
eventDiv.style.borderImage = `linear-gradient(to right, darkblue, darkorchid ${eventPercent}%, rgba(0,0,0,0) ${eventPercent+0.1}%) 1`;
|
||||
|
||||
} else {
|
||||
const eventDiv = document.getElementById(`event-${event.id}`);
|
||||
|
||||
if (eventDiv) {
|
||||
eventDiv.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(visibleEvents == 0) {
|
||||
document.getElementById("nothing-happening").style.display = 'block';
|
||||
} else {
|
||||
document.getElementById("nothing-happening").style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function clock() {
|
||||
setInterval(() => {
|
||||
currentTime = new Date();
|
||||
let ts = currentTime.toString();
|
||||
ts = ts.replace("GMT+0200 (Central European Summer Time)", "");
|
||||
ts = ts.replace("2023", "<br />");
|
||||
document.getElementById("clock").innerHTML = ts;
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function fastForward() {
|
||||
currentTime = new Date("2023-05-29T18:00Z");
|
||||
setInterval(() => {
|
||||
updateDivs(cachedData);
|
||||
currentTime.setMinutes(currentTime.getMinutes()+1);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
async function loop() {
|
||||
while (true) {
|
||||
try {
|
||||
document.getElementById("nfcstat").removeAttribute('disabled');
|
||||
const response = await fetch("/boop/getqueue/"+boopboxId);
|
||||
const json = await response.json();
|
||||
document.getElementById("nfcstat").setAttribute('disabled', 'true');
|
||||
for(i = 0; i < json.length; i++) {
|
||||
console.log(json[i]);
|
||||
document.getElementById('debug').innerHTML = JSON.stringify(json[i]);
|
||||
try {
|
||||
await window[json[i]["_"]](json[i]);
|
||||
} catch (e) {
|
||||
document.getElementById('debug').innerHTML = e;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*window.oncontextmenu = function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
};*/
|
||||
|
||||
async function talk(dict) {
|
||||
|
||||
for (const c of welcome_back_elements) {
|
||||
c.classList.add('hidden');
|
||||
}
|
||||
|
||||
character = document.getElementById(dict.who);
|
||||
character.removeAttribute('disabled');
|
||||
box.removeAttribute('disabled');
|
||||
for(j = 0;j < dict.msg.length; j++) {
|
||||
to = 20;
|
||||
msgbox.innerHTML += dict.msg[j];
|
||||
|
||||
if(dict.msg[j] == '.') {to = 400;}
|
||||
if(dict.msg[j] == ',') {to = 200;}
|
||||
|
||||
await new Promise(r => setTimeout(r, to));
|
||||
}
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
}
|
||||
|
||||
async function bye(dict) {
|
||||
|
||||
msgbox.innerHTML = '';
|
||||
|
||||
for (const c of bye_elements) {
|
||||
c.setAttribute('disabled', 'true');
|
||||
}
|
||||
|
||||
for (const c of welcome_back_elements) {
|
||||
c.classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
async function play(dict) {
|
||||
const audio = new Audio(dict.src);
|
||||
await audio.play();
|
||||
}
|
||||
|
||||
async function wait(dict) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, dict.time * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
async function orchestrate(thing) {
|
||||
for(var i = 0; i < msg.length; i++) {
|
||||
task = msg[i]
|
||||
|
||||
// It's a command
|
||||
if(task.length == 3) {
|
||||
switch(task) {
|
||||
case '!w-':
|
||||
wolf.setAttribute('disabled', 'true');
|
||||
break;
|
||||
case '!t-':
|
||||
tiger.setAttribute('disabled', 'true');
|
||||
break;
|
||||
case '!w+':
|
||||
wolf.removeAttribute('disabled');
|
||||
break;
|
||||
case '!t+':
|
||||
tiger.removeAttribute('disabled');
|
||||
break;
|
||||
case '!s+':
|
||||
msgbox.classList.add('yell');
|
||||
break;
|
||||
case '!s-':
|
||||
msgbox.classList.remove('yell');
|
||||
break;
|
||||
default:
|
||||
alert('Invalid command received.' + task);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
touch.setAttribute("disabled", "true");
|
||||
|
||||
// It's a text message
|
||||
if (task.startsWith('!w:') || task.startsWith('!t:')) {
|
||||
|
||||
if(task[1] == 'w' && wolf.getAttribute('disabled') == 'true') {
|
||||
wolf.removeAttribute('disabled');
|
||||
}
|
||||
|
||||
if(task[1] == 't' && tiger.getAttribute('disabled') == 'true') {
|
||||
tiger.removeAttribute('disabled');
|
||||
}
|
||||
|
||||
msgbox.style.color = (task[1] == 'w')?'#FAEBD7':'#ADD8E6';
|
||||
|
||||
txt = task.substr(3);
|
||||
|
||||
|
||||
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
//touch.removeAttribute("disabled");
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
msgbox.innerHTML = '';
|
||||
|
||||
console.log(task);
|
||||
}
|
||||
}
|
||||
|
||||
box.setAttribute('disabled', 'true');
|
||||
}
|
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 204 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><svg height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><title/><rect height="96" rx="8" ry="8" width="96" x="80" y="16"/><rect height="96" rx="8" ry="8" width="96" x="208" y="16"/><rect height="96" rx="8" ry="8" width="96" x="336" y="16"/><rect height="96" rx="8" ry="8" width="96" x="80" y="144"/><rect height="96" rx="8" ry="8" width="96" x="208" y="144"/><rect height="96" rx="8" ry="8" width="96" x="336" y="144"/><rect height="96" rx="8" ry="8" width="96" x="80" y="272"/><rect height="96" rx="8" ry="8" width="96" x="208" y="272"/><rect height="96" rx="8" ry="8" width="96" x="208" y="400"/><rect height="96" rx="8" ry="8" width="96" x="336" y="272"/></svg>
|
After Width: | Height: | Size: 717 B |
|
@ -1,46 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
id="Icons"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
sodipodi:docname="lock.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#999999"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="35.416667"
|
||||
inkscape:cx="9.2611765"
|
||||
inkscape:cy="12"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1035"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="21"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Icons" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<style
|
||||
id="style2">.cls-1{fill:#232323;}</style>
|
||||
</defs>
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M12,0A6,6,0,0,0,6,6V7H8V6a4,4,0,0,1,8,0V7h2V6A6,6,0,0,0,12,0Z"
|
||||
id="path6"
|
||||
style="fill:#000000" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M18,9H6a3,3,0,0,0-3,3v8a3,3,0,0,0,3,3H18a3,3,0,0,0,3-3V12A3,3,0,0,0,18,9Zm-5,7.73V19a1,1,0,0,1-2,0V16.73a2,2,0,1,1,2,0Z"
|
||||
id="path8"
|
||||
style="fill:#000000" />
|
||||
</svg>
|
||||
<?xml version="1.0" ?><svg height="24" version="1.1" width="24" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><g transform="translate(0 -1028.4)"><path d="m5 1037.4c-1.1046 0-2 0.9-2 2v1 6 1c0 1.1 0.8954 2 2 2h2 10 2c1.105 0 2-0.9 2-2v-7-1c0-1.1-0.895-2-2-2h-2-12z" fill="#f1c40f"/><path d="m5 1040.4c-1.1046 0-2 0.9-2 2v1 6 1c0 1.1 0.8954 2 2 2h2 10 2c1.105 0 2-0.9 2-2v-7-1c0-1.1-0.895-2-2-2h-2-12z" fill="#f39c12"/><path d="m12 1029.4c-3.866 0-7 3.1-7 7h3c0-2.2 1.7909-4 4-4 2.209 0 4 1.8 4 4h3c0-3.9-3.134-7-7-7z" fill="#bdc3c7"/><path d="m5 14v1h14v-1h-14zm0 2v1h14v-1h-14zm0 2v1h14v-1h-14zm0 2v1h14v-1h-14z" fill="#e67e22" transform="translate(0 1028.4)"/><path d="m5 1037.4v1c0 0.5 0.6716 1 1.5 1s1.5-0.5 1.5-1v-1c0 0.5-0.6716 1-1.5 1s-1.5-0.5-1.5-1z" fill="#7f8c8d"/><path d="m16 1037.4v1c0 0.5 0.672 1 1.5 1s1.5-0.5 1.5-1v-1c0 0.5-0.672 1-1.5 1s-1.5-0.5-1.5-1z" fill="#7f8c8d"/><path d="m12 2.4375c-0.351 0-0.699 0.0338-1.031 0.0937-0.247 0.0446-0.487 0.1129-0.719 0.1876-0.217 0.0698-0.4229 0.1561-0.625 0.25-0.106 0.0492-0.2109 0.1008-0.3125 0.1562-0.1319 0.0719-0.2513 0.1682-0.375 0.25-0.1158 0.0765-0.2356 0.1342-0.3437 0.2188-0.1407 0.1097-0.2799 0.2211-0.4063 0.3437-0.0369 0.0362-0.0581 0.0878-0.0937 0.125-0.1684 0.1744-0.3313 0.3356-0.4688 0.5313-0.1402 0.1993-0.2704 0.4065-0.375 0.625-0.004 0.0084 0.004 0.0227 0 0.0312-0.1111 0.2359-0.2159 0.4959-0.2812 0.75-0.253 0.5844-0.9424 1-1.75 1-0.06 0-0.0832 0.0018-0.125 0-0.0105-0.0004-0.0168 0.0014-0.0313 0l-0.0625 1v1 1h3v-1-1c0-0.2761 0.0405-0.5521 0.0938-0.8125 0.3729-1.8227 1.9732-3.1875 3.9062-3.1875 2.209 0 4 1.7909 4 4v1 1h3v-1-1l-0.062-1c-0.015 0.0014-0.021-0.0004-0.032 0h-0.125c-0.807 0-1.497-0.4156-1.75-1-0.065-0.2541-0.17-0.5141-0.281-0.75-0.004-0.0085 0.004-0.0228 0-0.0312-0.105-0.2185-0.235-0.4257-0.375-0.625-0.138-0.1957-0.3-0.3569-0.469-0.5313-0.036-0.038-0.055-0.0881-0.094-0.125-0.126-0.1226-0.265-0.234-0.406-0.3437-0.104-0.0817-0.232-0.1448-0.344-0.2188-0.122-0.0809-0.244-0.1788-0.374-0.25-0.101-0.055-0.208-0.1074-0.313-0.1562-0.202-0.0939-0.408-0.1802-0.625-0.25-0.232-0.0747-0.472-0.143-0.719-0.1876-0.332-0.0599-0.68-0.0937-1.031-0.0937z" fill="#95a5a6" transform="translate(0 1028.4)"/></g></svg>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><svg viewBox="0 0 288 288" xmlns="http://www.w3.org/2000/svg"><path d="M228 12c27 0 48 22 48 48v168c0 26-22 48-48 48h-72c-45 0-66-12-66-126V77l70 70c11 11 28-6 16-18L87 40c-9-9-21-2-21 8v102c0 52 4 90 18 115 3 6 4 11-4 11H60c-27 0-48-22-48-48V60c0-26 21-48 48-48h72c45 0 66 12 66 126v73l-69-69c-12-12-29 5-17 17l89 89c9 9 21 2 21-8V138c0-52-3-88-18-115-4-8-3-11 4-11h20z"/></svg>
|
After Width: | Height: | Size: 401 B |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10 3v2a5 5 0 0 0-3.54 8.54l-1.41 1.41A7 7 0 0 1 10 3zm4.95 2.05A7 7 0 0 1 10 17v-2a5 5 0 0 0 3.54-8.54l1.41-1.41zM10 20l-4-4 4-4v8zm0-12V0l4 4-4 4z"/></svg>
|
After Width: | Height: | Size: 248 B |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="512px" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="Gesture_x2C__hand_x2C__hand_touch_x2C__touch"><path d="M446.937,360.598l-21.123-39.657c-5.226-9.797-17.397-13.51-27.202-8.288l-1.763,0.937 c-3.169-25.073,8.091-55.672-1.983-73.96l-46.898-85.132c-1.521-2.755-3.658-5.033-6.157-6.851 c-8.699-8.423-23.044-10.28-35.29-3.531c-2.048,1.122-3.876,2.449-5.561,3.891c-8.659-8.756-23.26-10.759-35.709-3.906 c-6.406,3.534-11.045,8.868-13.775,14.81c-0.35,0.07-0.7,0.145-1.057,0.219l-1.389-2.509c-7.308-13.269-25.165-17.448-39.89-9.332 c-9.729,5.359-15.534,14.733-16.34,24.303c-0.169,0.036-0.346,0.076-0.521,0.115l-26.598-49.215 c4.681-8.321,7.35-17.869,7.35-28.017c0-32.165-26.766-58.333-59.667-58.333S53.697,62.309,53.697,94.474 c0,18.958,9.477,36.8,25.35,47.726c9.94,6.842,21.615,10.496,33.795,10.598c8.919,16.505,17.32,32.05,25.882,47.891 c0.22,0.47,0.422,0.945,0.676,1.406c1.646,2.993,3.126,5.679,4.459,8.094c6.074,11.243,12.293,22.746,18.898,34.969l0.192-0.104 c4.724,8.598,13.152,23.919,28.596,51.953c0,0-57.87,14.669-82.033,27.975c-52.687,29.033-26.438,63.83-15.233,64.689 c95.239-39.039,116.045-31.486,156.024-0.686c0.512,0.389,1.176,1.066,1.956,1.96c-7.942,5.814-10.672,16.666-5.912,25.601 l21.129,39.655c5.224,9.808,17.396,13.515,27.195,8.293l143.977-76.697C448.443,382.579,452.161,370.4,446.937,360.598z M89.253,127.373c-10.993-7.566-17.556-19.865-17.556-32.899c0-22.24,18.692-40.333,41.667-40.333s41.667,18.093,41.667,40.333 c0,2.42-0.234,4.788-0.658,7.092l-5.033-9.313c-9.719-17.975-29.581-26.063-44.378-18.076 c-14.805,7.982-18.927,29.022-9.213,46.988c2.25,4.163,4.445,8.226,6.604,12.221C97.686,132.154,93.264,130.134,89.253,127.373z M416.674,368.771c-7.784,4.296-17.579,1.469-21.877-6.319c-4.295-7.783-1.465-17.58,6.32-21.876 c7.785-4.292,17.578-1.468,21.876,6.318C427.29,354.682,424.458,364.474,416.674,368.771z"/></g><g id="Layer_1"/></svg>
|
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 18 MiB |
After Width: | Height: | Size: 4.2 MiB |
After Width: | Height: | Size: 2.4 MiB |
After Width: | Height: | Size: 430 KiB |
After Width: | Height: | Size: 289 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 227 KiB |
After Width: | Height: | Size: 124 KiB |
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="/res/boopbox.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="commands">
|
||||
<a href="javascript:document.documentElement.requestFullscreen();">Fs</a>
|
||||
<a href="javascript:document.getElementById('wolf').setAttribute('disabled', 'true');">Wolf hide</a>
|
||||
<a href="javascript:document.getElementById('wolf').removeAttribute('disabled');">Wolf show</a>
|
||||
<a href="javascript:document.getElementById('tiger').setAttribute('disabled', 'true');">Tiger hide</a>
|
||||
<a href="javascript:document.getElementById('tiger').removeAttribute('disabled');">Tiger show</a>
|
||||
<a href="javascript:document.getElementById('msgbox').removeAttribute('disabled');">Chatbox show</a>
|
||||
<a href="javascript:document.getElementById('msgbox').setAttribute('disabled', 'true');">Chatbox hide</a>
|
||||
<span id="debug">Debug command</span>
|
||||
</div>
|
||||
|
||||
<!--<div id="error">
|
||||
<p>An unrecoverable error has happened. Please call foxo.</p>
|
||||
</div>-->
|
||||
|
||||
<!--<div id="border"></div>-->
|
||||
<div id="main">
|
||||
<img class="char bye" id="wolf" src="/res/wolf.png" disabled="true" />
|
||||
<img class="char bye" id="tiger" src="/res/tiger.png" disabled="true" />
|
||||
|
||||
<div id="msgbox" class="bye" disabled><span id="msgcontent"></span><span id="touch" disabled>(touch the screen to continue <img src="/res/touch.svg" />)</span></div>
|
||||
|
||||
<div id="events" class="welcome-back">
|
||||
<div id="eventsbox">
|
||||
<h1 style="margin-top:7em;display:none;" id="nothing-happening">It looks like nothing is happening now~<br />_-¯¯-¯_<br />See you later :)</h1>
|
||||
</div>
|
||||
<h1>See more events with our app!</h1>
|
||||
|
||||
</div>
|
||||
|
||||
<video id="tv" autoplay muted playsinline controls="false" poster="/res/tv.jpg" class="welcome-back">
|
||||
<!-- <source id="video-source" src="http://192.168.32.189:8000/tron.webm" type="video/mp4"> -->
|
||||
</video>
|
||||
|
||||
<script>
|
||||
var video = document.getElementById('tv');
|
||||
var source = document.getElementById('video-source');
|
||||
|
||||
video.controls = false; // Ensure controls are hidden
|
||||
|
||||
video.addEventListener('error', function() {
|
||||
video.style.display = 'none';
|
||||
});
|
||||
|
||||
function playVideo() {
|
||||
var cachebuster = Date.now(); // Generate a unique timestamp
|
||||
var videoUrl = 'http://192.168.32.189:8000/tron.webm?cachebuster=' + cachebuster;
|
||||
source.src = videoUrl;
|
||||
|
||||
video.load();
|
||||
video.play().catch(function() {
|
||||
fallbackImage.style.display = 'block'; // Show fallback image on playback failure
|
||||
});
|
||||
}
|
||||
|
||||
playVideo();
|
||||
</script>
|
||||
|
||||
<div id="column" class="welcome-back">
|
||||
<h1>Useful Info</h1>
|
||||
<h2>CALL SECURITY</h2>
|
||||
<p>Dial (+39) 375 732 4734</p>
|
||||
<hr />
|
||||
<h2>Reception Open</h2>
|
||||
<p>Every day 8:00~19:00</p>
|
||||
<hr />
|
||||
<h2>NFC issues?</h2>
|
||||
<p>Search for Foxo (Badge ID 3) or write to @unfoxo on Telegram</p>
|
||||
<hr />
|
||||
<h2 id="clock"></h2>
|
||||
</div>
|
||||
|
||||
<div id="nfcstat" class="welcome-back" disabled>Dealer's Den <img src="/res/icons/nfc.svg" /></div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/res/boopbox.js"></script>
|
||||
</body>
|
||||
</html>
|