3 from google
.appengine
.ext
import db
4 from google
.appengine
.ext
.db
import djangoforms
21 'Wednesday': 'hr_weds',
22 'Thursday': 'hr_thurs',
27 def _make_hours(store_hours
):
28 """Store hours is a dictionary that maps a DOW to different open/close times
29 Since it's easy to represent disjoing hours, we'll do this by default
30 Such as, if a store is open from 11am-2pm and then 5pm-10pm
31 We'll slice the times in to a list of floats representing 30 minute intevals
32 So for monday, let's assume we have the store hours from 10am - 3pm
34 monday = [10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5]
37 for dow
in store_hours
.keys():
39 for hour_set
in store_hours
[dow
]:
44 open_hr
= float(hour_set
[0])
45 close_hr
= float(hour_set
[1])
46 if close_hr
< open_hr
:
50 current_hr_it
= open_hr
51 while((close_hr
- current_hr_it
) >= .5):
52 dow_hours
.append(current_hr_it
)
54 week_hrs
[dow
] = dow_hours
57 def _earth_distance(lat1
, lon1
, lat2
, lon2
):
58 lat1
, lon1
= math
.radians(float(lat1
)), math
.radians(float(lon1
))
59 lat2
, lon2
= math
.radians(float(lat2
)), math
.radians(float(lon2
))
60 return RADIUS
* math
.acos(math
.sin(lat1
) * math
.sin(lat2
) +
61 math
.cos(lat1
) * math
.cos(lat2
) * math
.cos(lon2
- lon1
))
63 class Store(db
.Model
):
64 name
= db
.StringProperty()
65 pretty_address
= db
.TextProperty()
66 pretty_description
= db
.TextProperty()
67 pretty_hours
= db
.TextProperty()
68 location
= db
.GeoPtProperty()
69 geoboxes
= db
.StringListProperty()
70 hr_mon
= db
.ListProperty(float)
71 hr_tues
= db
.ListProperty(float)
72 hr_weds
= db
.ListProperty(float)
73 hr_thurs
= db
.ListProperty(float)
74 hr_fri
= db
.ListProperty(float)
75 hr_sat
= db
.ListProperty(float)
76 hr_sun
= db
.ListProperty(float)
77 holidays
= db
.StringListProperty()
78 categories
= db
.StringListProperty()
79 phone_numbers
= db
.StringProperty()
82 def add(self
, **kwargs
):
83 lat
= kwargs
.pop('lat')
84 lon
= kwargs
.pop('lon')
85 location
= db
.GeoPt(lat
, lon
)
87 new_store
= Store(name
=name
, location
=location
)
89 new_store
.pretty_address
= kwargs
['address']
90 for (resolution
, slice, use_set
) in GEOBOX_CONFIGS
:
92 all_boxes
.extend(geobox
.compute_set(lat
, lon
, resolution
, slice))
94 all_boxes
.append(geobox
.compute(lat
, lon
, resolution
, slice))
95 new_store
.geoboxes
= all_boxes
96 store_hour_dict
= _make_hours(kwargs
['store_hours'])
97 for day
, prop
in _DAY_DICTIONARY
.iteritems():
98 setattr(new_store
, prop
, store_hour_dict
[day
])
100 new_store
.categories
= kwargs
['categories']
101 new_store
.pretty_description
= kwargs
['description']
105 def query(self
, time
, dow
, lat
, lon
, max_results
, min_params
):
106 """Queries for Muni stops repeatedly until max results or scope is reached.
108 system: The transit system to query.
109 lat, lon: Coordinates of the agent querying.
110 max_results: Maximum number of stops to find.
111 min_params: Tuple (resolution, slice) of the minimum resolution to allow.
114 List of (distance, MuniStop) tuples, ordered by minimum distance first.
115 There will be no duplicates in these results. Distance is in meters.
117 # Maps stop_ids to MuniStop instances.
120 # Do concentric queries until the max number of results is reached.
121 dow_query_string
= _DAY_DICTIONARY
[dow
] + ' ='
122 for params
in GEOBOX_CONFIGS
:
123 if len(found_stores
) >= max_results
:
125 if params
< min_params
:
128 resolution
, slice, unused
= params
129 box
= geobox
.compute(lat
, lon
, resolution
, slice)
130 logging
.info("Searching for box=%s at resolution=%s, slice=%s",
131 box
, resolution
, slice)
132 query
= self
.all().filter("geoboxes =", box
).filter(dow_query_string
, time
)
133 results
= query
.fetch(50)
134 logging
.info("Found %d results", len(results
))
137 for result
in results
:
138 if result
.name
not in found_stores
:
139 found_stores
[result
.name
] = result
141 # Now compute distances and sort by distance.
142 stores_by_distance
= []
143 for store
in found_stores
.itervalues():
144 distance
= _earth_distance(lat
, lon
, store
.location
.lat
, store
.location
.lon
)
145 stores_by_distance
.append((distance
, store
))
146 stores_by_distance
.sort()
148 return stores_by_distance
150 class UserProfile(db
.Model
):
151 user
= db
.UserProperty(required
=True)
153 class CommentIndex(db
.Model
):
154 max_index
= db
.IntegerProperty(default
=0, required
=True)
156 class Comment(db
.Model
):
157 index
= db
.IntegerProperty(required
=True)
158 reviewer
= db
.ReferenceProperty(UserProfile
, required
=True)
159 store
= db
.ReferenceProperty(Store
, required
=True)
160 review
= db
.TextProperty(required
=True)
161 rating
= db
.IntegerProperty(choices
=set([1,2,3,4,5]))
162 posted_on
= db
.DateTimeProperty(auto_now_add
=True)
163 disabled
= db
.BooleanProperty(default
=False)