var http = require('http')
var Stack = require('stack')
var route = require('tiny-route')
var db = require('./db')
var pull = require('pull-stream')
var toPull = require('stream-to-pull-stream')
var pl = require('pull-level')
var stringify = require('pull-stringify')
var urls = require('./urls')
var marked = require('marked')
function render(data, format, md) {
if(format === '.json')
return JSON.stringify(data, null, 2) + '\n\n'
if(format === '.md') return md(data)
return '
'+marked(md(data))+'
'
}
function capitalize (n) {
return n[0].toUpperCase() + n.substring(1).toLowerCase()
}
function log (e) {
console.log(e)
return e
}
function sections (text) {
return log(text.split(/([\w,\s]+):/).map(function (e, i) {
if(!(i%2)) return e + '\n\n'
if(/\s/.test(e.trim())) return '### ' + e
else return '#### ' + e
})).join('\n')
}
function renderTides(tides) {
return tides.map(function (e) {
return '### ' + capitalize(e.location) + '\n' +
e.tides.map(function (tide) {
return '* ' + tide.height + 'm at ' + tide.time
}).join('\n')
}).join('\n\n')
}
function get(key, format, res, next) {
db.sublevel('raw').get(key, function (err, value) {
if(err) return next(err)
if(value.forecast) //render a weather forecast
res.end(render(value, format, function (e) {
return [
'# ' + capitalize(value.name),
'issued at: [' + value.issued +'](/ls/'+value.name+')',
'## Situation',
e.situation,
'## Forecast',
sections(e.forecast),
'## Outlook',
sections(e.outlook),
e.swell ? '## Swell\n\n' + e.swell : '',
e.tides ? '## Tides\n\n' + renderTides(e.tides) : '',
//oceanic forecasts
e.warnings ? '## Warnings\n\n' +
e.warnings.map(function (e) {
return '### warning: '+e.name + ' (Analysis ' + e.analysis+')\n\n' +
e.warning.replace(/
/g, '\n\n') + '\n\n issued at:' + e.issued
}).join('\n\n') : ''
].join('\n')
}))
else if(value.imageData)
res.end(render(value, format, function (e) {
return e.imageData.map(function (e) {
return '## ' + e.description + '\n\n'
+ '![e.description](http://metservice.com' + e.url + ')\n'
+ '\nissued at:' + e.issuedTime + ' valid from:' + e.validFromTime
}).join('\n\n\n')
}))
})
}
http.createServer(Stack(
route(/^\/summary.json$/, function (req, res) {
db.summary(function (err, data) {
res.end(JSON.stringify(data, null, 2))
})
}),
route(/^\/([0-9a-f]{64})(\.\w+)?$/, function (req, res, next) {
get(req.params[0], req.params[1], res, next)
}),
route(/^\/([a-z\-_]+)(\.\w+)?$/, function (req, res, next) {
db.get(req.params[0], function (err, value) {
if(err) return next(err)
get(value, req.params[1], res, next)
})
}),
route(/^\/ls\/([a-z\-_]+)(\.\w+)?$/, function (req, res, next) {
var place = req.params[0]
pull(
pl.read(db.sublevel('sample'), {gte: [place, null], lt: [place, undefined], reverse: true}),
pull.collect(function (err, data) {
res.end(render(data, req.params[1], function (e) {
return '# history for:' + capitalize(e[0].key[0]) + '\n\n' +
e.map(function (e) {
return '* [' + new Date(e.key[1]) + '](/'+e.value+')'
}).join('\n')
}))
})
)
}),
route(/^\/_admin\/update$/, function (req, res, next) {
db.update(function (err, data) {
if(err) return next(err)
return res.end(JSON.stringify(data, null, 2))
})
}),
route(/^\/(\.\w+)?$/, function (req, res) {
res.end(render(Object.keys(urls), req.params[0], function (data) {
return data.map(function (e) {
return '* ['+e+'](/'+e+')'
}).join('\n')
}))
})
)).listen(8000)
//every hour, update.
var HOUR = 1000*60*60, MIN = 1000*60
;(function poll () {
db.getLast(function (err, ts) {
if(Date.now() > (+ts || 0) + HOUR) {
console.log('updating...', Date.now() > ts + HOUR)
db.update(function (err, data) {
console.log(err, data)
setTimeout(poll, MIN)
})
}
else {
console.log('last update:', (Date.now() - ts)/MIN)
console.log('next poll in:', (HOUR - (Date.now() - ts)) / MIN, 'minutes')
setTimeout(poll, HOUR - (Date.now() - ts))
}
})
})()