Created
March 17, 2023 04:26
-
-
Save CristianCantoro/4cb3ca3944ac202fed18ebc2b341ddb9 to your computer and use it in GitHub Desktop.
Automated Munroe geohashing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
# | |
# == Author == | |
# Cristian Consonni | |
# This script was generated making extensive use of ChatGPT v3.5 | |
# | |
# == License == | |
# | |
# MIT License | |
# | |
# Copyright (c) 2023 Cristian Consonni | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in all | |
# copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
# SOFTWARE. | |
import argparse | |
import geocoder | |
import hashlib | |
import requests | |
import webbrowser | |
import yfinance as yf | |
from datetime import datetime, timedelta | |
def get_current_date(): | |
# Get the current date and format it as YYYY-MM-DD | |
return datetime.now().strftime('%Y-%m-%d') | |
def get_dow_jones(date=None): | |
dow = yf.Ticker('^DJI') | |
# Get the earliest and latest dates for which data is available | |
earliest_date = dow.history(period='max').index[0] | |
latest_date = dow.history(period='max').index[-1] | |
# Convert the input date to datetime object | |
if date is None: | |
end_date = datetime.now() | |
elif isinstance(date, str): | |
end_date = datetime.strptime(date, '%Y-%m-%d').date() | |
elif isinstance(date, datetime): | |
end_date = date.date() | |
# If the input date is outside the available range, | |
# get the closest available date | |
if end_date < earliest_date: | |
end_date = earliest_date | |
elif end_date > datetime.today().date(): | |
end_date = latest_date | |
start_date = end_date - timedelta(days=1) | |
# Get the Dow Jones index for the selected date | |
dow_data = dow.history(start=start_date, end=end_date) | |
if len(dow_data) == 0: | |
retries = 1 | |
while (len(dow_data) == 0) and (retries < 5): | |
retries += 1 | |
# if no data is available for the selected date, get the day before | |
new_end_date = end_date - timedelta(days=1) | |
new_start_date = new_end_date - timedelta(days=1) | |
dow_data = dow.history(start=new_start_date, end=new_end_date) | |
start_date = new_start_date | |
end_date = new_end_date | |
# if nothing yet, pick a random date | |
if len(dow_data) == 0: | |
dow_data = dow.history(period='max').sample(n=1) | |
# Return the Dow Jones index for the selected date and the actual date used | |
return dow_data['Open'][-1], end_date | |
def get_city_coordinates(city): | |
# Use the geocoder module to get the latitude and longitude of the city | |
g = geocoder.osm(city) | |
latitude = g.lat | |
longitude = g.lng | |
# Return the latitude and longitude as a tuple | |
return (latitude, longitude) | |
def get_current_location(): | |
# Make a request to the IP Geolocation API | |
response = requests.get('https://ipgeolocation.abstractapi.com/v1/' | |
'?api_key=<my_api_key>') | |
# Parse the JSON response to get the latitude, longitude, and city name | |
data = response.json() | |
latitude = data['latitude'] | |
longitude = data['longitude'] | |
city = data['city'] | |
# Return the latitude, longitude, and city as a tuple | |
return (latitude, longitude, city) | |
def geohash(latitude, longitude, datedow): | |
'''Compute geohash() using the Munroe algorithm. | |
>>> geohash(37.421542, -122.085589, b'2005-05-26-10458.68') | |
37.857713 -122.544543 | |
''' | |
# https://xkcd.com/426/ | |
h = hashlib.md5(datedow, usedforsecurity=False).hexdigest() | |
p, q = [('%f' % float.fromhex('0.' + x)) for x in (h[:16], h[16:32])] | |
newlat = float('%d%s' % (latitude, p[1:])) | |
newlon = float('%d%s' % (longitude, q[1:])) | |
return (newlat, newlon) | |
def gmaps(latitude, longitude): | |
url = ("https://www.google.com/maps/search/" | |
f"?api=1&query={latitude},{longitude}&zoom=5") | |
webbrowser.open(url) | |
def main(): | |
parser = argparse.ArgumentParser( | |
description='Generate geohash and display on Google Maps' | |
) | |
parser.add_argument( | |
'--city', | |
help='The name of the city to generate the geohash for' | |
) | |
parser.add_argument( | |
'--date', | |
help='The date to fetch the Dow Jones opening value for ' | |
'in the format YYYY-MM-DD' | |
) | |
args = parser.parse_args() | |
if args.city: | |
latitude, longitude = get_city_coordinates(args.city) | |
print(f"The coordinates of {args.city} are ({latitude}, {longitude})") | |
else: | |
latitude, longitude, city = get_current_location() | |
print(f"Your current location is ({latitude}, {longitude}) in {city}") | |
if args.date: | |
date = args.date | |
print(f"Using date {date}") | |
else: | |
date = get_current_date() | |
print(f"The current date is {date}") | |
dow_value, actual_date = get_dow_jones(date) | |
print(f"The opening value for the Dow Jones index on {date} was " | |
f"{dow_value}") | |
# combine values in datedow | |
datedow = f'{date}-{dow_value}'.encode('utf-8') | |
newlatitude, newlongitude = geohash(latitude, longitude, datedow) | |
print(f"Munrow geohash: ({newlatitude}, {newlongitude})") | |
gmaps(newlatitude, newlongitude) | |
if __name__ == '__main__': | |
main() | |
exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment