Skip to content

Instantly share code, notes, and snippets.

@timaschew
Last active August 14, 2018 12:07
Show Gist options
  • Save timaschew/496994f0f86a29753881d230509e6bd3 to your computer and use it in GitHub Desktop.
Save timaschew/496994f0f86a29753881d230509e6bd3 to your computer and use it in GitHub Desktop.
GTFS alert feed generator for NEB
<!DOCTYPE html>
<html lang="de">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta charset="utf-8">
<meta name="viewport" content="width = device-width, initial-scale = 1.0">
<title>GTFS alert feed Generator for NEB</title>
<meta name="description" content="Offline Formular um GTFS Alert Feeds zu generieren">
<meta name="author" content="Anton Wilhelm">
<meta name="url" content="https://github.com/timaschew">
<style>
div {
padding: 10px;
}
* {
font-size: 1.0em;
}
textarea {
width: 100%;
height: 100vw;
}
input {
border: 1px solid #888;
padding: 5px;
}
input:invalid, select.invalid {
border: 1px dashed red;
}
select {
height: 34px;
}
input.header, input.description, input.url {
width: 100%;
}
.resources {
float: right;
}
.resources * {
display: block;
}
</style>
</head>
<body>
<div class="resources">
<strong>Resourcen</strong>
<a href="https://developers.google.com/transit/gtfs/reference/" target="_blank">GTFS Specification</a>
<a href="http://gtfs.org/de/" target="_blank">GTFS Specification (de)</a>
<a href="https://www.vbb.de/unsere-themen/vbbdigital/api-entwicklerinfos/datensaetze" target="_blank">VBB GTFS Daten</a>
<a href=""></a>
<a href="https://support.google.com/transitpartners/answer/6159841?hl=de&ref_topic=6159819" target="_blank">Praktische Empfehlungen für GTFS-realtime</a>
<a href="https://developers.google.com/transit/gtfs-realtime/examples/alerts" target="_blank">Service Alert Example</a>
</div>
<form>
<!--
VBB GTFS routes.txt
17564_100,596,"RB12","",100,"","",""
16910_100,596,"RB25","",100,"","",""
16339_100,596,"RB26","",100,"","",""
16334_100,596,"RB27","",100,"","",""
16911_100,596,"RB35","",100,"","",""
16924_100,596,"RB36","",100,"","",""
17566_100,596,"RB54","",100,"","",""
16914_100,596,"RB60","",100,"","",""
16916_100,596,"RB61","",100,"","",""
16917_100,596,"RB62","",100,"","",""
16919_100,596,"RB63","",100,"","",""
-->
<div>
<label>Linie</label>
<select class="route invalid">
<option value="-1" disabled selected>Bitte wählen</option>
<option value="17564_100">RB12</option>
<option value="16910_100">RB25</option>
<option value="16339_100">RB26</option>
<option value="16334_100">RB27</option>
<option value="16911_100">RB35</option>
<option value="16924_100">RB36</option>
<option value="17566_100">RB54</option>
<option value="16914_100">RB60</option>
<option value="16916_100">RB61</option>
<option value="16917_100">RB62</option>
<option value="16919_100">RB63</option>
</select>
</div>
<div>
<label>Grund</label>
<select class="cause invalid">
<option value="-1" disabled selected>Bitte wählen</option>
<option value="UNKNOWN_CAUSE">unbekannter Grund</option>
<option value="OTHER_CAUSE">sonstiger Grund</option>
<option value="TECHNICAL_PROBLEM">technische Störung</option>on>
<option value="STRIKE">Streik</option>
<option value="DEMONSTRATION">Demonstration</option>
<option value="ACCIDENT">Unfall</option>
<option value="HOLIDAY">Urlaub</option>
<option value="WEATHER">Wetter</option>
<option value="MAINTENANCE">Wartung</option>
<option value="CONSTRUCTION">Bauarbeiten</option>
<option value="POLICE_ACTIVITY">Polizeieinsatz</option>
<option value="MEDICAL_EMERGENCY">Notfall</option>
</select>
</div>
<div>
<label>Auswirkung</label>
<select class="effect invalid">
<option value="-1" disabled selected>Bitte wählen</option>
<option value="NO_SERVICE">❗️kein Verkehr</option>
<option value="SIGNIFICANT_DELAYS">❗️erhebliche Verspätungen</option>
<option value="DETOUR">⚠️Umleitung</option>
<option value="STOP_MOVED">⚠️Haltestelle verlegt</option>
<option value="REDUCED_SERVICE">⚠️weniger Fahrten</option>
<option value="MODIFIED_SERVICE">⚠️Fahrplan wird nicht eingehalten</option>
<option value="ADDITIONAL_SERVICE">ℹ️zusätzlicher Fahrten</option>
<option value="OTHER_EFFECT">ℹ️andere Auswirkung</option>
<option value="UNKNOWN_EFFECT">ℹ️unbekannte Auswirkung</option>
</select>
</div>
<div>
<label>Begin</label>
<input class="start-date" type="date" required />
<input class="start-time" type="time" required />
</div>
<div>
<label>Ende</label>
<input class="end-date" type="date" required />
<input class="end-time" type="time" required />
</div>
<div><input class="header" placeholder="Titel" required /></div>
<div><input class="description" placeholder="Beschreibung" required /></div>
<div><input class="url" placeholder="Link mit mehr Infos" required /></div>
<br>
<div><button type="submit" class="render">GTFS Alert generieren</button></div>
<div><textarea class="output" placeholder="Alert wird in dieses Textfeld automatisch generiert"></textarea></div>
</form>
<script>
const button = document.querySelector(".render")
document.querySelector(".route").addEventListener('change', function(e) {
e.target.value == -1 ? e.target.classList.add('invalid') : e.target.classList.remove('invalid')
}, false)
document.querySelector(".cause").addEventListener('change', function(e) {
e.target.value == -1 ? e.target.classList.add('invalid') : e.target.classList.remove('invalid')
}, false)
document.querySelector(".effect").addEventListener('change', function(e) {
e.target.value == -1 ? e.target.classList.add('invalid') : e.target.classList.remove('invalid')
}, false)
button.addEventListener('click', function(event){
event.preventDefault()
const routeId = document.querySelector(".route").value
const cause = document.querySelector(".cause").value
const effect = document.querySelector(".effect").value
const startDate = document.querySelector(".start-date").value
const endDate = document.querySelector(".end-date").value
const startTime = document.querySelector(".start-time").value
const endTime = document.querySelector(".end-time").value
const header = document.querySelector(".header").value
const description = document.querySelector(".description").value
const url = document.querySelector(".url").value
const agencyId = 596 // NEB
const langKey = 'de'
const timestamp = parseInt(Date.now() / 1000)
const start = new Date(startDate + 'T' + startTime).getTime() / 1000
const end = new Date(endDate + 'T' + endTime) / 1000
const entityId = routeId + '__' + startDate.replace(/-/g, '_')
const result = renderGtfsRealtimeAlert(timestamp, entityId, start, end, routeId, cause, effect, header, description, url, langKey)
document.querySelector(".output").value = result
}, false)
function renderGtfsRealtimeAlert(timestamp, entityId, start, end, routeId, cause, effect, header, description, url, langKey) {
console.log(arguments)
return `# header information
header {
# version of speed specification. Currently "2.0"
gtfs_realtime_version: "2.0"
# determines whether dataset is incremental or full
incrementality: FULL_DATASET
# the time where this dataset was generated on server
# for determining the sequence of alert feeds
timestamp: ${timestamp}
}
# multiple entities can be included in the feed
entity {
# unique identifier for the entity
id: "${entityId}"
# "type" of the entity
alert {
# multiple periods can be defined when alert is active
active_period {
# start time in POSIX epoch format
start: ${start}
# end time in POSIX epoch format
end: ${end}
}
# selects which GTFS entities will be affected
informed_entity {
# valid parameters:
# agency_id, route_id, route_type, stop_id, trip (see TripDescriptor)
route_id: "${routeId}"
}
# cause of the alert - see gtfs-realtime.proto for valid values
cause: ${cause}
# effect of the alert - see gtfs-realtime.proto for valid values
effect: ${effect}
# the given url provides additional information
url {
# multiple languages/translations supported
translation {
# page hosted outside of Google (at provider/agency, etc.)
text: "${url}"
language: "${langKey}"
}
}
# header for the alert will be highlighted
header_text {
# multiple languages/translations supported
translation {
text: "${header}"
language: "${langKey}"
}
}
# Alert description. Additional info to the header text
description_text {
# multiple languages/translations supported
translation {
text: "${description}"
language: "${langKey}"
}
}
}
}`
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment