Commit e570f4b3 authored by Samuel Mergenthaler's avatar Samuel Mergenthaler
Browse files

add entry for bike sharing dashboard

parent 99cc083c
Pipeline #5868 passed with stages
in 15 seconds
export const pageMarginLeftRight = '2vw'
export const pageMarginLeftRightMobile = '2vw'
export const distance = {
verySmall: '0.3rem',
small: '0.6rem',
medium: '1rem',
large: '1.4rem',
veryLarge: '3rem'
}
export const maxScreenWidthMobile = 768
export const fontSizes = {
veryLarge: '2.3rem',
h1: '1.4rem',
h2: '1.3rem',
h3: '1.2rem',
h4: '1.1rem',
text: '1.0rem'
}
\ No newline at end of file
import { DefaultTheme } from 'styled-components'
export const darkTheme: DefaultTheme = {
colors: {
primary: '#f1edec',
secondary: '#f4ba8a',
backgroundPrimary: '#0c0c0c',
backgroundSecondary: '#161515',
backgroundInput: '#232323',
barChart: '#f4ba8a',
}
} as const
export const lightTheme: DefaultTheme = {
colors: {
primary: '#0c0c0c',
secondary: '#885d39',
backgroundPrimary: '#f9f6f5',
backgroundSecondary: '#e4e8ee',
backgroundInput: '#d0d0d0',
barChart: '#885d39',
}
} as const
\ No newline at end of file
{
"compilerOptions": {
"noImplicitAny": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"target": "es2015",
"jsx": "react-jsx",
"types": [
"react",
"jest"
],
"module": "esNext",
"moduleResolution": "node",
"experimentalDecorators": true,
"declaration": false,
"removeComments": true,
"noImplicitReturns": true,
"noUnusedLocals": false,
"strict": true,
"outDir": "dist",
"baseUrl": "src",
"typeRoots": [
"src/customTypings",
"node_modules/@types"
],
"strictNullChecks": true,
"allowJs": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"skipLibCheck": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"noFallthroughCasesInSwitch": true
},
"exclude": [
"dist",
"build",
"node_modules"
],
"include": [
"src"
]
}
# Santander bike-sharing trip data in London
Available in CSV-format [here](https://cycling.data.tfl.gov.uk/), starting at 2015.
The relevant files are in the folder 'usage-stats'.
node_modules
input
bike-sharing-trip-data.json
\ No newline at end of file
# Preprocess santander bike-sharing data
## CSV trip data to json
The script 'convert-csv-to-json' reads all CSV files in the 'input' directory and converts them it to a single json named 'bike-sharing-trip-data'.
The CSV files must contain London cycling trip data from Santander, available [here](https://cycling.data.tfl.gov.uk/).
Make sure your folder structure inside the input directory looks as follows:
```
├── 2015TripData
│ ├── 1a.JourneyDataExtract04Jan15-17Jan15.csv
│ ├── ...
├── 2016TripData
│ ├── 01aJourneyDataExtract10Jan16-23Jan16.csv
│ ├── ...
```
Install dependencies with `npm intall`.
Then you can run the script with `npm start`.
If you process a lot of files, the script might take a few minutes, don't abort the process, wait till the script finishes!
The file size of the final json will be twice as high as the original CSV files.
/**
* Reads all CSV files in subdirectories of 'input' directory and converts them it to a single json named 'bike-sharing-trip-data'.
*
* Make sure you your folder structure inside the input directory looks like:
*
* ├── 2015TripData
* │ ├── 1a.JourneyDataExtract04Jan15-17Jan15.csv
* │ ├── ...
* ├── 2016TripData
* │ ├── 01aJourneyDataExtract10Jan16-23Jan16.csv
* │ ├── ...
*
*/
// main script is wrapped in async function in order to use 'await' syntax
(async () => {
const csv = require('csvtojson')
const fs = require('fs')
const fileStream = fs.createWriteStream('bike-sharing-trip-data.json')
const inputDirectory = 'input'
const dirs = fs.readdirSync(inputDirectory).filter(path => !path.startsWith('.'))
let isFirstTrip = true
fileStream.write('[')
await asyncForEach(dirs, async dirName => {
const files = fs.readdirSync(`${inputDirectory}/${dirName}`)
await asyncForEach(files, async fileName => {
const trips = await csv({
headers: ['_id', 'duration', 'bikeId', 'endDate', 'endStationId', 'endStationName', 'startDate', 'startStationId', 'startStationName']
}).fromFile(`${inputDirectory}/${dirName}/${fileName}`)
trips.map(trip => {
trip.startDate = toUnixTimestamp(trip.startDate)
trip.endDate = toUnixTimestamp(trip.endDate)
trip.duration = Number(trip.duration)
// return trip with unix timestamps instead of date-strings
return trip
})
// if first trip, remove it from list (shift) and write to filestream without trailing comma
if(isFirstTrip){
fileStream.write('\n' + JSON.stringify(trips.shift()))
isFirstTrip = false
}
trips.forEach(trip => fileStream.write(',\n' + JSON.stringify(trip)))
})
})
fileStream.write('\n]')
fileStream.end()
})()
// convert date string of form 'dd/MM/yyyy HH:mm' to unix timestamp
const toUnixTimestamp = dateTimeString => {
// split string by slash space and colon
const [day, month, year, hour, minute] = dateTimeString.split(/[/\s:]/).map(part => parseInt(part))
// month needs -1 offset because January = 0 in Javascript Date
return Date.UTC(year, month - 1, day, hour, minute) / 1000
}
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
\ No newline at end of file
{
"name": "pre-process-bike-sharing-data",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"csvtojson": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz",
"integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==",
"requires": {
"bluebird": "^3.5.1",
"lodash": "^4.17.3",
"strip-bom": "^2.0.0"
}
},
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
"requires": {
"is-utf8": "^0.2.0"
}
}
}
}
{
"name": "pre-process-bike-sharing-data",
"version": "1.0.0",
"description": "Preprocess CSV bike sharing trip data.",
"scripts": {
"start": "node convert-csv-to-json.js"
},
"license": "ISC",
"dependencies": {
"csvtojson": "^2.0.10"
}
}
......@@ -90,34 +90,29 @@
<!-- BEISPIEL 1 -->
<div class="col-md-4">
<div class="card mb-4 shadow-sm extension">
<h5>Titel Beispielprojekt</h5>
<!-- <svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">Thumbnail</text></svg> -->
<!-- BITTE QUELLCODE UND BILDER JEWEILS IN EINEM EIGENEN PROJEKTORDNER ABLEGEN -->
<img class="thumbimg" src="beispielprojekt/imgs/thumbnails/hft_beispielbild.jpg" alt="">
<!-- Beschreibungstext bitte möglichst kurz halten, bspw. 100 Zeichen -->
<div class="card-body">
<p class="card-text">Beschreibungstext hier einfügen...</p>
</div>
<!-- Hier die Links hinzufügen -->
<div class="d-flex justify-content-between align-items-center btnGroupDiv">
<div class="btn-group">
<form action="beispielprojekt/src/beispiel.html" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary">GIT</button>
</form>
&nbsp;
<form action="beispielprojekt/src/beispiel.html" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary">YouTube</button>
</form>
&nbsp;
<form action="beispielprojekt/src/beispiel.html" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary">Website</button>
</form>
</div>
<!-- <small class="text-muted">9 mins</small> -->
<div class="card mb-4 shadow-sm extension">
<h5>Bike-Sharing Dashboard</h5>
<!-- <svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: Thumbnail"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">Thumbnail</text></svg> -->
<!-- BITTE QUELLCODE UND BILDER JEWEILS IN EINEM EIGENEN PROJEKTORDNER ABLEGEN -->
<img class="thumbimg" src="bike-sharing-london-dashboard-nodejs-react/imgs/map-view.png" alt="">
<!-- Beschreibungstext bitte möglichst kurz halten, bspw. 100 Zeichen -->
<div class="card-body">
<p class="card-text">Londoner Bike-Sharing Daten, mit Node.js Server vorbereitet und in React-Frontend visualisiert.</p>
</div>
<div class="d-flex justify-content-between align-items-center btnGroupDiv">
<div class="btn-group">
<form action="https://transfer.hft-stuttgart.de/gitlab/hdastageeri/geovis21/-/blob/master/public/bike-sharing-london-dashboard-nodejs-react" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary">GIT</button>
</form>
<!--
<form action="beispielprojekt/src/beispiel.html" class="form-signin" method="GET">
<button type="submit" class="btn btn-sm btn-outline-secondary">YouTube</button>
</form>
-->
</div>
<!-- <small class="text-muted">9 mins</small> -->
</div>
</div>
</div>
</div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment