1+ import zoneinfo
2+
13import requests
2- from bs4 import BeautifulSoup
3- from dateutil import parser
4+ from django .conf import settings
45from django .core .management .base import BaseCommand
5- from django .utils import timezone
6+ from django .utils .dateparse import parse_datetime
7+ from django .utils .timezone import make_aware
68
79from penndata .models import FitnessRoom , FitnessSnapshot
810
@@ -12,77 +14,59 @@ def cap_string(s):
1214
1315
1416def get_usages ():
15-
16- # count/capacities default to 0 since spreadsheet number appears blank if no one there
17- locations = [
18- "4th Floor Fitness" ,
19- "3rd Floor Fitness" ,
20- "2nd Floor Strength" ,
21- "Basketball Courts" ,
22- "MPR" ,
23- "Climbing Wall" ,
24- "1st Floor Fitness" ,
25- "Pool-Shallow" ,
26- "Pool-Deep" ,
27- ]
28- usages = {location : {"count" : 0 , "capacity" : 0 } for location in locations }
29-
30- date = timezone .localtime () # default if can't get date from spreadsheet
31-
3217 try :
3318 resp = requests .get (
34- (
35- "https://docs.google.com/spreadsheets/u/0/d/e/"
36- "2PACX-1vSX91_MlAjJo5uVLznuy7BFnUgiBOI28oBCReLRKKo76L"
37- "-k8EFgizAYXpIKPBX_c76wC3aztn3BogD4"
38- "/pubhtml/sheet?headers=false&gid=0"
39- )
19+ "https://goboardapi.azurewebsites.net/api/FacilityCount/GetCountsByAccount" ,
20+ params = {"AccountAPIKey" : settings .FITNESS_TOKEN },
4021 )
22+ data = resp .json ()
4123 except ConnectionError :
4224 return None
43-
44- html = resp .content .decode ("utf8" )
45- soup = BeautifulSoup (html , "html5lib" )
46- if not (embedded_spreadsheet := soup .find ("tbody" )):
25+ except requests .exceptions .JSONDecodeError :
4726 return None
4827
49- table_rows = embedded_spreadsheet .findChildren ("tr" )
50- for i , row in enumerate (table_rows ):
51- cells = row .findChildren ("td" )
52- if i == 0 :
53- date = timezone .make_aware (parser .parse (cells [1 ].getText ()))
54- elif (location := cap_string (cells [0 ].getText ())) in usages :
55- try :
56- count = int (cells [1 ].getText ())
57- capacity = float (cells [2 ].getText ().strip ("%" ))
58- usages [location ] = {"count" : count , "capacity" : capacity }
59- except ValueError :
60- pass
61- else :
62- print (f"Unknown location: { location } " )
63- return usages , date
28+ def location_aware_datetime (time_str ):
29+ date = parse_datetime (time_str )
30+ timezone = zoneinfo .ZoneInfo ("America/New_York" )
31+ return make_aware (date , timezone = timezone )
32+
33+ usages = {
34+ location ["LocationName" ]: {
35+ "count" : location ["LastCount" ],
36+ "capacity" : location ["TotalCapacity" ],
37+ "last_updated" : location_aware_datetime (location ["LastUpdatedDateAndTime" ]),
38+ }
39+ for location in data
40+ }
41+ return usages
6442
6543
6644class Command (BaseCommand ):
67- help = "Captures a new Fitness Snapshot for every Laundry room."
45+ help = "Captures a new Fitness Snapshot for every Fitness room."
6846
6947 def handle (self , * args , ** kwargs ):
70- usage_by_location , date = get_usages ()
71-
72- # prevent double creating FitnessSnapshots
73- if FitnessSnapshot .objects .filter (date = date ).exists ():
74- self .stdout .write ("FitnessSnapshots already exist for this date!" )
75- return
76-
48+ def exists (record ):
49+ (name , usage ) = record
50+ try :
51+ room = FitnessRoom .objects .get (name = name )
52+ except FitnessRoom .DoesNotExist :
53+ return False
54+ return not FitnessSnapshot .objects .filter (
55+ date = usage ["last_updated" ], room = room
56+ ).exists ()
57+
58+ # Don't update locations for which we already have a room with a matching last_updated date.
59+ # This is also O(n^2), idk how we feel about that chat
60+ usage_by_location = filter (exists , get_usages ().items ())
7761 FitnessSnapshot .objects .bulk_create (
7862 [
7963 FitnessSnapshot (
8064 room = FitnessRoom .objects .get_or_create (name = room_name )[0 ],
81- date = date ,
65+ date = room_usage [ "last_updated" ] ,
8266 count = room_usage ["count" ],
8367 capacity = room_usage ["capacity" ],
8468 )
85- for room_name , room_usage in usage_by_location . items ()
69+ for ( room_name , room_usage ) in usage_by_location
8670 ]
8771 )
8872
0 commit comments