var PX_PER_MINUTE = 5 var data = null; var names = document.querySelector('main #names') var times = document.querySelector('main #times') function exportCSV() { if (data == null) { alert('No data found.') return } var startInput = document.querySelector('input#start') var endInput = document.querySelector('input#end') var gameInput = document.querySelector('input#game') var startDate = new Date(startInput.value) var endDate = new Date(endInput.value) var gameRE = new RegExp(gameInput.value || '.*') csv = 'timestamp,name,game,checkpoint\n' for (var [name, list] of Object.entries(data)) { for (entry of list) { if (entry.game.match(gameRE) == null) continue var arrD = new Date(entry.arrival) if (arrD < startDate || arrD > endDate) continue var arrTS = localISOTimeSeconds(arrD) csv += `${arrTS},${name},${entry.game},${entry.checkpoint}\n` } } var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(csv)); element.setAttribute('download', 'schnitzeljagd-export.csv'); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } function renderData() { if (data == null) { alert('No data found.') return } names = document.querySelector('main #names') times = document.querySelector('main #times') names.innerHTML = '' times.innerHTML = '' var startInput = document.querySelector('input#start') var endInput = document.querySelector('input#end') var gameInput = document.querySelector('input#game') var startDate = new Date(startInput.value) var endDate = new Date(endInput.value) var gameRE = new RegExp(gameInput.value || '.*') // Clear everything below hours because that would lead to // misalignments with the day grid startDate.setMinutes(0,0,0) var tc = new Date(startDate.getTime()) var content = '' while (tc < endDate) { var h = tc.getHours() var m = tc.getMinutes() var t = (h == 0) ? ''+tc.getDate()+'.'+(tc.getMonth()+1)+'.' : h+':'+m.toString().padStart(2, "0") var left = ((tc - startDate) / (1000 * 60)) content += ''+t+'' tc.setTime(tc.getTime() + (15*60*1000)); } var timeheader = document.getElementById('timelabels') timeheader.innerHTML = content var viewwidth = ((endDate - startDate) / (1000 * 60)) timeheader.style.width = (PX_PER_MINUTE * viewwidth) + 'px' times.style.width = (PX_PER_MINUTE * viewwidth) + 'px' var rowCount = 0 for (var [name, list] of Object.entries(data)) { var row = document.createElement('div') row.classList.add('row') var rowHasBlock = false for (entry of list) { if (entry.game.match(game) == null) continue var arrD = new Date(entry.arrival) var depD = new Date(arrD) + 1000 * 60 * 5 if (depD < startDate || arrD > endDate) continue rowHasBlock = true // Minutes since start date / beginning var arr = (arrD - startDate) / (1000 * 60) var dep = (depD - startDate) / (1000 * 60) var dur = dep - arr var block = document.createElement('span') block.innerHTML = entry.checkpoint block.style.left = (PX_PER_MINUTE * arr) + 'px' // 1px/min block.style.width = (PX_PER_MINUTE * Math.max(0,(dur-14))) + 'px' // 1px/min if (entry.game == "zeitfahren") block.classList.add('blue') row.appendChild(block) } if (rowHasBlock) { var vname = name.replace(/-/g, ' ') names.innerHTML += '
'+vname+'
' times.appendChild(row) rowCount += 12 } } //var viewheight = rowCount * 32; //times.style.height = viewheight + 'px' var tw = document.querySelector('main .scroll') tw.scrollLeft = tw.scrollWidth } function saveData(rdata) { data = rdata.reduce((acc, entry) => { var name = entry.name delete entry.name acc[name] = [...acc[name] || [], entry]; return acc; }, {}); console.log(data) renderData() } function submitCredentials() { var cp = document.querySelector('#credprompt') var user = cp.querySelector('#user').value var pass = cp.querySelector('#pass').value cp.remove() var auth = btoa(user + ":" + pass) localStorage.setItem('dataauth', auth) loadData() } function loadData() { var auth = localStorage.getItem('dataauth') if (auth == null) { var prompt = document.createElement('div') prompt.id = 'credprompt' prompt.innerHTML = '

Credentials Required

\ \ \ ' document.body.appendChild(prompt) document.querySelector('#credprompt #user').focus() return // Abort load, wait for submit } var headers = new Headers() headers.append('Authorization', 'Basic ' + auth) var fetchopts = { method: 'GET', headers: headers } fetch('/game/data', fetchopts) .then(res => { if (Math.floor(res.status / 100) == 2) return res.json() else localStorage.removeItem('dataauth') res.text().then(function (text) { alert(text) location.reload() }) }) .then(rdata => saveData(rdata)) } function localISOTimeSeconds(date) { var tzoffset = date.getTimezoneOffset() * 60000; //offset in milliseconds var localISOTime = (new Date(date - tzoffset)).toISOString().slice(0, -1); return localISOTime } function localISOTimeMinutes(date) { return localISOTimeSeconds(date).split(':').slice(0,2).join(':') } var now = new Date() now.setHours(now.getHours()+1,0,0,0) now.setMinutes(0,0,0) var startDate = new Date() startDate.setDate(now.getDate()) startDate.setHours(8,0,0,0) document.querySelector('input#start').value = localISOTimeMinutes(startDate) document.querySelector('input#end').value = localISOTimeMinutes(now) var scrollbox = document.querySelector('.scroll') var timehead = document.querySelector('#timeheader') var namebox = document.querySelector('section.names') scrollbox.onscroll = function() { timehead.scrollLeft = scrollbox.scrollLeft namebox.scrollTop = scrollbox.scrollTop } loadData()