-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
98 lines (86 loc) · 3.98 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import os
from flask import Flask, jsonify, render_template, request
from flask.ext.bower import Bower
from sqlalchemy.orm import joinedload
from models import db
from datetime import datetime
app = Flask(__name__, instance_relative_config=True)
# Load environment-specific settings from config.py
env = os.environ.get('BUSMAP_ENV', 'prod')
app.config.from_object('config.{0}Config'.format(env.capitalize()))
# Load deployment-specific settings from instance/config.cfg
app.config.from_pyfile('config.py', silent=True)
# Database init
db.init_app(app)
Bower(app)
# Flask Web Routes
@app.route('/')
def map():
from models import Agency
# TODO: serve different agency depending on cookie (or special domain)
agency_tag = app.config['AGENCIES'][0]
agency = db.session.query(Agency).filter(Agency.tag==agency_tag).one()
return render_template('map.html', agency=agency, config=app.config)
@app.route('/embed')
def map_embed():
from models import Agency
# TODO: serve different agency depending on cookie (or special domain)
agency_tag = app.config['AGENCIES'][0]
agency = db.session.query(Agency).filter(Agency.tag==agency_tag).one()
return render_template('map.html', agency=agency, config=app.config, embed=True)
@app.route('/ajax')
def ajax():
# TODO: OPTIMIZE THIS SHIT.
# Over 1sec/request just to get predictions? Fuck that noise.
dataset = request.args.get('dataset')
agency = request.args.get('agency')
def routes():
from models import Agency, Route, RouteStop, Stop
routes = db.session.query(Route).join(Agency)\
.filter(Agency.tag==agency).all()
stops = db.session.query(Stop).options(joinedload(Stop.routes))\
.filter(Stop.routes.any(Route.id.in_([r.id for r in routes]))).all()
return {
"routes": {r.tag: r.serialize() for r in routes},
"stops": {s.id: s.serialize() for s in stops}
}
def vehicles():
from models import Agency, Route, VehicleLocation, Prediction
# TODO: Somehow bundle these queries into the object model definitions? So messy :(
# 1. Select the latest vehicle locations for each vehicle. (The DB may have old ones too).
v_inner = db.session.query(VehicleLocation.vehicle,
db.func.max(VehicleLocation.time).label("time"))\
.group_by(VehicleLocation.vehicle).subquery()
vehicle_locations = db.session.query(VehicleLocation).join(v_inner, db.and_(
v_inner.c.vehicle == VehicleLocation.vehicle,
v_inner.c.time == VehicleLocation.time
)).filter(Agency.tag==agency).all()
# 2. Select the predictions for each vehicle:stop pair which came from the most recent
# API call for that vehicle:stop pair. Old predictions may be stored but we don't want them.
now = datetime.now()
p_inner = db.session.query(Prediction.vehicle, Prediction.stop_id,
db.func.max(Prediction.api_call_id).label("api_call_id"))\
.group_by(Prediction.vehicle, Prediction.stop_id)\
.subquery()
predictions = db.session.query(Prediction).join(p_inner, db.and_(
p_inner.c.api_call_id == Prediction.api_call_id,
p_inner.c.vehicle == Prediction.vehicle,
p_inner.c.stop_id == Prediction.stop_id
)).filter(
Agency.tag==agency,
Prediction.prediction >= now)\
.group_by(Prediction.id, Prediction.vehicle, Prediction.stop_id)\
.all()
z = {
"locations": {v.vehicle: v.serialize() for v in vehicle_locations},
"predictions": {p.id: p.serialize() for p in predictions}
}
return z
if dataset == "routes":
r = jsonify(routes())
elif dataset == "vehicles":
r = jsonify(vehicles())
return r
if __name__ == '__main__':
# Run Flask
app.run(host='0.0.0.0')