Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

indicate when prices are cheap #24

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 83 additions & 9 deletions lib/calendar/calendar.js
Original file line number Diff line number Diff line change
@@ -11,26 +11,102 @@ const helpers = require('../helpers')
const sortBy = require('lodash').sortBy

const timeoutTime = 10*1000
const ChartjsNode = require('chartjs-node');



// format output (only price and duration)
const formatDayResult = (result) => {
return result ? {
price: helpers.formatPrice(result.price.amount),
duration: formatDuration(result.duration)
duration: formatDuration(result.duration),
graph: result.graph
} : null
}


function createGraph(day,max,min) {
var chartNode = new ChartjsNode(128, 40);
var heights = [];
var colors=[];
for (var i = 0; i < 24; i++) {
heights.push(0);
colors.push('rgba(0,0,0,0)');
}
for(let journey of day) {
var hour = new Date(journey.legs[0].departure).getHours();
if (heights[hour] > journey.price.amount || heights[hour] == 0){
heights[hour] = journey.price.amount;
var factor = 1- (journey.price.amount - min) /(max-min);
colors[hour] = 'hsla('+Math.floor(factor*122)+', 50%, 50%,0.4)';
}

}
console.log(heights)
console.log(colors)
return chartNode.drawChart({
type: 'bar',
data: {
labels: ['','','','','','','','','','','','','','','','','','','','','','','',''],
datasets: [{
label: '',
data: heights,
backgroundColor: colors,
borderWidth: 0
}]
},
options: {
legend: {
display: false
},
responsive: false,
width: 128,
height: 40,
animation: false,
scales:{
xAxes: [{
categoryPercentage: 1.0,
barPercentage: 1.0,
display: false //this will remove all the x-axis grid lines
}],yAxes: [{
display: false, //this will remove all the x-axis grid lines
ticks: {
suggestedMax: max
}}]
}
}
})
.then(() => {
return chartNode.getImageDataUrl("image/png").then(data=>{for(let journey of day)journey.graph = data;});
}).catch(err => {
console.error('Error : ', err);
return false;
})
}
// add handy short-hand attributes like "duration"
const addAttributes = (journeysPerDay) => {
const addAttributes = (journeysPerDay)=> {
var promises = []
var max = 0;
var min = 100000;
for(let day of journeysPerDay) {
for (let journey of day) {
if (max < journey.price.amount) max = journey.price.amount;
if (min > journey.price.amount) min = journey.price.amount;
}
}

for(let day of journeysPerDay){
for(let journey of day){
const departure = new Date(journey.legs[0].departure)
const arrival = new Date(journey.legs[journey.legs.length-1].arrival)
const duration = +arrival - (+departure)
journey.duration = duration

promises.push(createGraph(day,max,min))
}

}
return journeysPerDay
return Promise.all(promises).then(()=>{return journeysPerDay})
}

// only keep journeys with price information
@@ -104,12 +180,10 @@ const calendar = (params) => {
)
)
}

return Promise.all(requests).then(journeysPerDay => {
// console.log(journeysPerDay)
// todo: this is insanely inefficient code, but easier to understand
// add handy short-hand attributes like "transfers" or "duration"
journeysPerDay = addAttributes(journeysPerDay)
// console.log(journeysPerDay)
// todo: this is insanely inefficient code, but easier to understand
// add handy short-hand attributes like "transfers" or "duration"
return Promise.all(requests).then(addAttributes).then((journeysPerDay)=>{
// only keep journeys with price information
journeysPerDay = filterPricelessJourneys(journeysPerDay)
// sort by price and duration
10 changes: 7 additions & 3 deletions lib/calendar/index.js
Original file line number Diff line number Diff line change
@@ -12,15 +12,19 @@ const forward = (req, next) => (code) => {
const main = (req, res, next) => {
const error = forward(req, next)
params(req.query).then(params => {
if(!params) error('1')
if(!params) {
console.error("no params")
error('1')
}
if(params.status==='error') error(params.msg ? 'noStations' : '1')
else
return calendar(params.data).then(data => {
console.log("template stage!")
if(data) return res.send(template({input: params.data, output: data}, null))
error('noResults')
}).catch(err => error('1'))
}).catch(err => {console.error("error2" + err);error('1')})
})
.catch(err => error('1'))
.catch(err => {console.error("error3");error('1')})
}

module.exports = main
32 changes: 18 additions & 14 deletions lib/calendar/template.js
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ const generateSubTitleOptions = (data) => {
return [html.span(null, result), changeLink]
}

const calendar = (data) => {
function calendar(data){
if(!data) return html.span()
const cal = data.output
let weeks = []
@@ -52,19 +52,23 @@ const calendar = (data) => {
]))
}
else{
days.push(html.td({class: day.cheapest ? 'cheapest' : ''}, [
html.a({class: 'cell', href: dayURL(data, day)}, [
html.span('.date', day.date.formatted.split(' ')[0]), // todo
html.div('.priceGroup', [
html.span('.price', [
html.span('.priceLong', [day.price.euros, html.sup(null, day.price.cents)]),
html.span('.priceShort', Math.round(+day.price.euros+(+day.price.cents/100))+'€')



days.push(html.td({class: day.cheapest ? 'cheapest' : '', style: " background-repeat: no-repeat; background-position: center bottom; background-image: url(\""+day.graph+"\");"}, [
html.a({class: 'cell', href: dayURL(data, day)}, [
html.span('.date', day.date.formatted.split(' ')[0]), // todo
html.div({class: '.priceGroup'}, [
html.span('.price', [
html.span('.priceLong', [day.price.euros, html.sup(null, day.price.cents)]),
html.span('.priceShort', Math.round(+day.price.euros + (+day.price.cents / 100)) + '€')
]),
html.span('.inlineDuration', day.duration)
]),
html.span('.inlineDuration', day.duration)
]),
html.span('.duration', '🕒 '+day.duration)
])
]))
html.span('.duration', '🕒 ' + day.duration)
])
]))

}
}
weeks.push(html.tr((counter++%2==0) ? '.even' : null, days))
@@ -116,7 +120,7 @@ const moreLink = (data) => {
return [html.a({id: 'later', href: `/calendar?origin=${data.input.origin.name}&destination=${data.input.destination.name}&${options.url(data.input).join('&')}&weeks=${weeks}&submit=Y#later`}, 'Mehr anzeigen...')]
}

const generate = (data, error) => {
function generate (data, error) {
let document = '<!doctype html>' + html.html(null, [
head(data),
html.body(null, [
133 changes: 67 additions & 66 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,68 +1,69 @@
{
"name": "bahn.guru",
"description": "DB Preiskalender",
"version": "0.15.0",
"keywords": [
"train",
"railway",
"hafas",
"fare",
"sparpreis",
"preis",
"DB",
"prices",
"preise",
"deutsch",
"allemand",
"german",
"bahn",
"calendar",
"kalender",
"preiskalender"
],
"main": "index.js",
"files": [
"index.js",
"lib/*",
"bahn/*",
"config/default.json",
"assets/*"
],
"author": "Julius Tens <[email protected]>",
"homepage": "https://bahn.guru",
"repository": "juliuste/bahn.guru",
"bugs": "https://github.com/juliuste/bahn.guru/issues",
"engines": {
"node": ">=8"
},
"dependencies": {
"apicache": "^1.2.3",
"compression": "^1.7.2",
"config": "^1.30.0",
"db-hafas": "^2.1.0",
"db-prices": "^3.0.0",
"express": "^4.16.3",
"fetch-ponyfill": "^6.0.2",
"flix": "^4.0.1",
"horsey": "^4.2.2",
"js-beautify": "^1.7.5",
"lodash": "^4.17.10",
"moment-duration-format": "^2.2.2",
"moment-timezone": "^0.5.21",
"morgan": "^1.9.0",
"ms": "^2.1.1",
"p-queue": "^2.4.2",
"p-retry": "^2.0.0",
"p-timeout": "^2.0.1",
"pithy": "0.0.4",
"shorthash": "0.0.2"
},
"devDependencies": {
"browserify": "^16.2.2"
},
"scripts": {
"build": "node build",
"deploy": "./deploy/_all"
},
"license": "ISC"
"name": "bahn.guru",
"description": "DB Preiskalender",
"version": "0.15.0",
"keywords": [
"train",
"railway",
"hafas",
"fare",
"sparpreis",
"preis",
"DB",
"prices",
"preise",
"deutsch",
"allemand",
"german",
"bahn",
"calendar",
"kalender",
"preiskalender"
],
"main": "index.js",
"files": [
"index.js",
"lib/*",
"bahn/*",
"config/default.json",
"assets/*"
],
"author": "Julius Tens <[email protected]>",
"homepage": "https://bahn.guru",
"repository": "juliuste/bahn.guru",
"bugs": "https://github.com/juliuste/bahn.guru/issues",
"engines": {
"node": ">=8"
},
"dependencies": {
"apicache": "^1.2.3",
"chartjs-node": "^1.7.1",
"compression": "^1.7.2",
"config": "^1.30.0",
"db-hafas": "^2.1.0",
"db-prices": "^3.0.0",
"express": "^4.16.3",
"fetch-ponyfill": "^6.0.2",
"flix": "^4.0.1",
"horsey": "^4.2.2",
"js-beautify": "^1.7.5",
"lodash": "^4.17.10",
"moment-duration-format": "^2.2.2",
"moment-timezone": "^0.5.21",
"morgan": "^1.9.0",
"ms": "^2.1.1",
"p-queue": "^2.4.2",
"p-retry": "^2.0.0",
"p-timeout": "^2.0.1",
"pithy": "0.0.4",
"shorthash": "0.0.2"
},
"devDependencies": {
"browserify": "^16.2.2"
},
"scripts": {
"build": "node build",
"deploy": "./deploy/_all"
},
"license": "ISC"
}