Skip to content

Instantly share code, notes, and snippets.

@alextremblay
Created March 15, 2021 15:09
Show Gist options
  • Save alextremblay/087810b572c50a9981e16d3ad44833be to your computer and use it in GitHub Desktop.
Save alextremblay/087810b572c50a9981e16d3ad44833be to your computer and use it in GitHub Desktop.
Ontario Parks Availability
from pathlib import Path
import pickle
from typing import Union
import csv
from uuid import uuid4
import requests
import arrow
target = 'Aug 15 2021'
days = 7
start = arrow.get(target, 'MMM DD YYYY')
end = start.shift(days=days)
def timecode(time: arrow.Arrow, date_only=True):
if date_only:
return f'{time.format("YYYY-MM-DD")}T00:00:00.000Z'
#else:
return time.format("YYYY-MM-DDTHH:mm:ss.SSS[Z]")
def fetch_map_id(map_id):
url = 'https://reservations.ontarioparks.com/api/maps/mapdatabyid'
payload = {
"mapId": map_id,
"cartUid": str(uuid4()),
"bookingUid": str(uuid4()),
"cartTransactionUid": str(uuid4()),
"bookingCategoryId": 0,
"startDate": f'{start.format("YYYY-MM-DD")}T00:00:00.000Z',
"endDate": f'{end.format("YYYY-MM-DD")}T00:00:00.000Z',
"isReserving": True,
"getDailyAvailability": False,
"partySize": 4,
"filterData": "[]",
"equipmentCategoryId": -32768,
"subEquipmentCategoryId": -32768,
"boatLength": None,
"boatDraft": None,
"boatWidth": None,
"generateBreadcrumbs": False,
"resourceAccessPointId": None
}
current_time = arrow.utcnow().format("YYYY-MM-DDTHH:mm:ss.SSS[Z]")
res = requests.post(
f'{url}?seed={current_time}',
json=payload
)
data = res.json()
return data
availability_map = {
0:"Available",
1:"Unavailable",
2:"Unavailable",
3:"Unavailable",
4:"Unavailable",
6:"No Availability For Selected Booking Category",
7:"Partially Available",
}
def get_info(map_id, names = None):
"fetch a map by map_id, recursively fetch every mapped linked to by that map, and availability counts for every campsite linked to in any of those maps"
data = fetch_map_id(map_id)
res = {}
sub_sections = data.get('mapLinkLocalizedValues')
sites = data.get('resourceAvailabilityMap')
if sub_sections:
for sub_id in sub_sections:
name = sub_sections[sub_id][0]['title']
if names:
new_names = names + [name]
else:
new_names = [name]
res[name] = get_info(sub_id, new_names)
elif sites:
total = len(sites)
avail = 0
partial = 0
for site in sites.values():
if site and site[0]['availability'] == 0:
avail += 1
if site and site[0]['availability'] == 7:
partial += 1
print('fetched', ' > '.join(names))
return (avail, partial, total)
else:
raise Exception("How did we get here?")
return res
def get_count(sub: Union[dict, tuple]):
if isinstance(sub, tuple):
return sub
#else:
avail, partial, total = 0,0,0
for k, v in sub.items():
subavail, subpartial, subtotal = get_count(v)
avail += subavail
partial += subpartial
total += subtotal
return avail, partial, total
def get_pairs(regions_: dict):
for region_name, region in regions_.items():
for park_name, park in region.items():
avail, partial, total = get_count(park)
yield f'{region_name} > {park_name}', avail, partial, total
def summary(regions_: dict):
avail_symbol = '#'
partial_symbol = '-'
unavail_symbol = ' '
print(f'Legend: "{avail_symbol}" = Available, "{partial_symbol}" = Partially available, "{unavail_symbol}" = Unavailable')
for name, avail, partial, total in get_pairs(regions_):
avail_per = avail / total
bar_length = 50
avail_per = avail / total
partial_per = partial / total
bar = int(avail_per*bar_length)*avail_symbol
bar += int(partial_per*bar_length)*partial_symbol
bar = bar.ljust(bar_length, unavail_symbol)
print(f'[{bar}] {name}: Available: {avail}/{total}, Partially Available: {partial}/{total}')
def write_csv(regions_):
with Path('res.csv').open('w') as f:
writer = csv.writer(f)
writer.writerow(['Park Name', 'Available Campsites', 'Partially Available Campsites', 'Total Campsites'])
for row in get_pairs(regions_):
writer.writerow(row)
print("Results written to res.csv")
regions = get_info(-2147483464)
Path('res.pkl').write_bytes(pickle.dumps(regions))
#regions = pickle.loads(Path('res.pkl').read_bytes())
summary(regions)
write_csv(regions)
print("Done!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment