Permalink
Browse files

Merge branch 'master' of github.com:mjschultz/cse521s-wsn-project

  • Loading branch information...
2 parents 981d8d5 + 12a62c5 commit 1cc53b0dccb8ef1f862357fee02e1575d7002697 Michael Schultz committed Dec 10, 2010
View
@@ -8,5 +8,7 @@ handlers:
script: media/usage.py
- url: /media/js/
static_dir: media/js/
+- url: /media/css/
+ static_dir: media/css/
- url: /.*
script: main.py
View
@@ -5,6 +5,7 @@
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp.util import run_wsgi_app
+from datetime import datetime, timedelta
def makeLot(lot_id, space_count, lat, lon) :
lot = ParkingLot(key_name=lot_id)
@@ -21,6 +22,45 @@ def makeLot(lot_id, space_count, lat, lon) :
lot.unknown_count = space_count
lot.put()
+def viewRange(lot_id, min_datetime=None, max_datetime=None, nbuckets=15) :
+ lot = ParkingLot.get_by_key_name(lot_id)
+ log = LotLog.all()
+ log.filter('lot =', lot)
+ if min_datetime :
+ log.filter('timestamp >=', min_datetime)
+ if max_datetime :
+ log.filter('timestamp <=', max_datetime)
+
+ buckets = [{'count':0,'n':0,'min':None,'max':None} for i in range(nbuckets)]
+ min_time = min_datetime.time()
+ max_time = max_datetime.time()
+ min_dt = datetime.combine(datetime.now(), min_time)
+ max_dt = datetime.combine(datetime.now(), max_time)
+ td = max_dt - min_dt
+ delta = td / nbuckets
+ delta = delta.seconds
+ for e in log :
+ e_time = e.timestamp.time()
+ e_dt = datetime.combine(datetime.now(), e_time)
+ if min_time <= e_time <= max_time :
+ d = e_dt - min_dt
+ t = d.seconds / delta
+ bucket = buckets[t]
+ bucket['count'] += e.full_count
+ bucket['n'] += 1
+ if bucket['min'] == None or bucket['min'] > e.full_count :
+ bucket['min'] = e.full_count
+ if bucket['max'] == None or bucket['max'] < e.full_count :
+ bucket['max'] = e.full_count
+
+ for (i, b) in enumerate(buckets) :
+ if b['n'] != 0 :
+ b['average'] = b['count']/b['n']
+ else :
+ b['average'] = 0
+ b['label'] = min_dt + timedelta(seconds=delta*i)
+ return buckets
+
def getSpaces(lot_id) :
lot = ParkingLot.get_by_key_name(lot_id)
spaces = ParkingSpace.all()
View
@@ -10,6 +10,11 @@ indexes:
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.
+- kind: LotLog
+ properties:
+ - name: lot
+ - name: timestamp
+
- kind: ParkingSpace
properties:
- name: is_empty
View
@@ -9,6 +9,8 @@
('/', views.MainPage),
('/lot/?', views.LotPage),
('/lot/([A-Za-z0-9-_]+)(/.*)?', views.LotHandler),
+ ('/chart/?', views.ChartPage),
+ ('/chart/([A-Za-z0-9-_]+)(/.*)?', views.ChartHandler),
]
application = webapp.WSGIApplication(pages, debug=True)

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -4,6 +4,7 @@
<title>{{ title }}</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
+ <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script>
{% block head %}{% endblock %}
</head>
<body {{ body_actions }}>
@@ -0,0 +1,78 @@
+{% extends "base.html" %}
+{% block head %}
+<link rel="stylesheet" href="/media/css/jquery-ui.css" type="text/css" />
+<script>
+ $(function() {
+ $( "#mindate" ).datepicker();
+ $( "#maxdate" ).datepicker();
+ });
+</script>
+{% endblock head %}
+{% block content %}
+<h2>Chart Lot Usage</h2>
+<form method="post">
+ <fieldset>
+ <legend>Date Range to view</legend>
+ <label for="mindate">Begin Date</label>
+ <input id="mindate" type="text" name="mindate" value="{{ min_date }}"/>
+ <label for="maxdate">End Date</label>
+ <input id="maxdate" type="text" name="maxdate" value="{{ max_date }}" />
+ </fieldset>
+ <fieldset>
+ <legend>Time Range for each day</legend>
+ <label for="minhour">Begin Hour</label>
+ <select id="minhour" name="minhour">
+ <option>00</option> <option>01</option>
+ <option>02</option> <option>03</option>
+ <option>04</option> <option>05</option>
+ <option>06</option> <option>07</option>
+ <option>08</option> <option>09</option>
+ <option>10</option> <option>11</option>
+ <option>12</option> <option>13</option>
+ <option>14</option> <option>15</option>
+ <option>16</option> <option>17</option>
+ <option>18</option> <option>19</option>
+ <option>20</option> <option>21</option>
+ <option>22</option> <option>23</option>
+ </select>
+ <label for="minminute">Begin Minute</label>
+ <select id="minminute" name="minminute">
+ <option>00</option>
+ <option>15</option>
+ <option>30</option>
+ <option>45</option>
+ </select>
+
+ <label for="maxhour">End Hour</label>
+ <select id="maxhour" name="maxhour">
+ <option>00</option> <option>01</option>
+ <option>02</option> <option>03</option>
+ <option>04</option> <option>05</option>
+ <option>06</option> <option>07</option>
+ <option>08</option> <option>09</option>
+ <option>10</option> <option>11</option>
+ <option>12</option> <option>13</option>
+ <option>14</option> <option>15</option>
+ <option>16</option> <option>17</option>
+ <option>18</option> <option>19</option>
+ <option>20</option> <option>21</option>
+ <option>22</option> <option>23</option>
+ </select>
+ <label for="maxminute">End Minute</label>
+ <select id="maxminute" name="maxminute">
+ <option>00</option>
+ <option>15</option>
+ <option>30</option>
+ <option>45</option>
+ </select>
+ </fieldset>
+ <input type="submit" name="submit" value="Submit" />
+</form>
+{% if buckets %}
+<hr />
+<p style="text-align:center;">
+<img src="http://chart.apis.google.com/chart?chxl=1:{% for bucket in buckets %}|{{ bucket.label|date:"H:i" }}{% endfor %}&chxr=0,0,{{ max_count }}&chxs=0,676767,11.5,-1,l,676767&chxt=y,x&chbh=a,4,9&chs=600x225&cht=bvg&chco=A2C180&chds=0,{{ max_count }}&chd=t:{% for bucket in buckets %}{{ bucket.average }}{% if not forloop.last %},{% endif %}{% endfor %}&chma=0,0,0,7&chtt=Usage for {{ lot_id }}" />
+</p>
+{% endif %}
+
+{% endblock content %}
@@ -0,0 +1,10 @@
+{% extends "base.html" %}
+{% block head %}
+{% endblock head %}
+{% block content %}
+<ul>
+ {% for lot in lots %}
+ <li><a href="/chart/{{ lot.lot_id }} ">{{ lot.lot_id }}</a></li>
+ {% endfor %}
+</ul>
+{% endblock content %}
View
@@ -4,6 +4,7 @@
import geo.geotypes
from model import ParkingLot, ParkingSpace, LotGeoPoint
import os.path
+from datetime import datetime, time as dttime
from google.appengine.api import users
from google.appengine.ext import webapp
@@ -47,6 +48,27 @@ def post(self) :
self.redirect('/lot/')
class LotHandler(webapp.RequestHandler) :
+ def show_json(self, spaces, lot) :
+ if lot.geo_point :
+ geo_pt = lot.geo_point.location
+ geo_point = str(geo_pt.lat)+','+str(geo_pt.lon)
+ else :
+ geo_point = None
+
+ spaces_out = []
+ for s in spaces :
+ space_out = {}
+ space_out['space_id'] = s.key().name()
+ space_out['is_empty'] = s.is_empty
+ space_out['extra_info'] = s.extra_info
+ space_out['timestamp'] = time.mktime(s.timestamp.timetuple())
+ spaces_out.append(space_out)
+ json_out = {'lot_id':lot.key().name(),
+ 'geo_pt':geo_point,
+ 'timestamp':time.mktime(lot.timestamp.timetuple()),
+ 'spaces':spaces_out}
+ self.response.out.write(json.dumps(json_out))
+
def get(self, lot_id, type) :
(spaces, lot) = controller.getSpaces(lot_id)
if lot == None :
@@ -65,6 +87,10 @@ def get(self, lot_id, type) :
view = 'html'
else :
view = type.strip('/.')
+
+ if view == 'json' :
+ self.show_json(spaces, lot)
+ return
if lot.geo_point :
geo_pt = lot.geo_point.location
@@ -94,21 +120,7 @@ def get(self, lot_id, type) :
if self.request.get('nomap') == 'true' :
values['nomap'] = True
- if view == 'json' :
- spaces_out = []
- for s in spaces :
- space_out = {}
- space_out['space_id'] = s.key().name()
- space_out['is_empty'] = s.is_empty
- space_out['extra_info'] = s.extra_info
- space_out['timestamp'] = time.mktime(s.timestamp.timetuple())
- spaces_out.append(space_out)
- json_out = {'lot_id':lot_id,
- 'geo_pt':geo_point,
- 'timestamp':time.mktime(lot.timestamp.timetuple()),
- 'spaces':spaces_out}
- self.response.out.write(json.dumps(json_out))
- elif view == 'html' :
+ if view == 'html' :
path = os.path.join(base_path, 'templates/lot.html')
self.response.out.write(template.render(path, values))
else :
@@ -131,3 +143,54 @@ def put(self, lot_id, type) :
else :
self.response.set_status(400)
+class ChartPage(webapp.RequestHandler) :
+ def get(self) :
+ lots = ParkingLot.all()
+ lots.order('-timestamp')
+
+ values = {
+ 'title': 'Parking Lots',
+ 'lots': lots,
+ }
+ path = os.path.join(base_path, 'templates/chart_main.html')
+ self.response.out.write(template.render(path, values))
+
+class ChartHandler(webapp.RequestHandler) :
+ def get(self, lot_id, type) :
+ path = os.path.join(base_path, 'templates/chart.html')
+ values = {}
+ self.response.out.write(template.render(path, values))
+
+ def post(self, lot_id, type) :
+ min_date = self.request.get('mindate')
+ max_date = self.request.get('maxdate')
+ min_hour = self.request.get('minhour')
+ min_minute = self.request.get('minminute')
+ max_hour = self.request.get('maxhour')
+ max_minute = self.request.get('maxminute')
+
+ if min_date != '' :
+ min_datetime = datetime.strptime(min_date, '%m/%d/%Y')
+ else :
+ min_datetime = datetime.min
+ if max_date != '' :
+ max_datetime = datetime.strptime(max_date, '%m/%d/%Y')
+ else :
+ max_datetime = datetime.max
+
+ min_time = dttime(int(min_hour), int(min_minute))
+ max_time = dttime(int(max_hour), int(max_minute))
+ if int(max_hour) == 0 and int(max_minute) == 0 :
+ # special case, we want end-of-day
+ max_time = dttime.max
+ min_datetime = datetime.combine(min_datetime.date(), min_time)
+ max_datetime = datetime.combine(max_datetime.date(), max_time)
+
+ # controller query
+ buckets = controller.viewRange(lot_id, min_datetime, max_datetime)
+ max_count = max(e['average'] for e in buckets)
+
+ values = {'min_date':min_date, 'max_date':max_date,
+ 'buckets':buckets, 'max_count':max_count, 'lot_id':lot_id}
+ path = os.path.join(base_path, 'templates/chart.html')
+ self.response.out.write(template.render(path, values))

0 comments on commit 1cc53b0

Please sign in to comment.