This commit is contained in:
Alexander Munch-Hansen 2019-04-06 17:38:23 +02:00
commit 6a0d0863b2
8 changed files with 119 additions and 40 deletions

4
.gitignore vendored
View file

@ -519,3 +519,7 @@ tags
.history .history
# End of https://www.gitignore.io/api/vim,emacs,android,pycharm+all,androidstudio,visualstudiocode,python,java,angular # End of https://www.gitignore.io/api/vim,emacs,android,pycharm+all,androidstudio,visualstudiocode,python,java,angular
# Custom
requests_cache.sqlite

View file

@ -1,4 +1,5 @@
import inspect import inspect
import logging
import statistics import statistics
from dataclasses import asdict from dataclasses import asdict
from datetime import timedelta from datetime import timedelta
@ -7,21 +8,24 @@ from typing import List
import requests_cache import requests_cache
from flask import Flask, jsonify from flask import Flask, jsonify
from .strategies import dmi, steam, miloStrats from .strategies import miloStrats, iss, cars_in_traffic, tide_strat, upstairs_neighbour
from .util import Context from .util import Context
logger = logging.getLogger(__name__)
app = Flask(__name__) app = Flask(__name__)
requests_cache.install_cache("requests_cache.sqlite", expire_after=timedelta(minutes=10)) requests_cache.install_cache("requests_cache", expire_after=timedelta(minutes=10))
strategies = { strategies = {
# name: (weight, probability function) # name: (weight, probability function)
"dmi": (0.5, dmi.probability), "tv2news": miloStrats.tv2newsStrat,
"steam": (1.0, steam.probability), "australia": miloStrats.australiaStrat,
"australia": (1.0, miloStrats.australiaStrat), "camera": miloStrats.camImgStrat,
"camera": (1.0, miloStrats.camImgStrat), "iss": iss.night_on_iss,
"tv2news": (1.0, miloStrats.tv2newsStrat) "cars_in_traffic": cars_in_traffic.cars_in_traffic,
"tide": tide_strat.is_tide,
"upstairs_neighbour": upstairs_neighbour.check_games,
} }
@ -31,17 +35,18 @@ def probabilities():
context = Context(**phone_data) context = Context(**phone_data)
predictions: List[dict] = [] predictions: List[dict] = []
for name, (weight, strategy) in strategies.items(): for name, strategy in strategies.items():
try: try:
prediction = strategy(context) prediction = strategy(context)
except Exception as e: except Exception as e:
print(f"Strategy {name} failed: {e}") logger.warning("Strategy %s failed: %s", name, e)
logger.exception(e)
continue continue
predictions.append({ predictions.append({
"name": name, "name": name,
"description": inspect.getdoc(strategy), "description": inspect.getdoc(strategy),
"weight": weight, "weight": prediction.weight,
"weighted_probability": prediction.probability * weight, "weighted_probability": prediction.probability * prediction.weight,
"night": prediction.probability > 0.5, "night": prediction.probability > 0.5,
**asdict(prediction), **asdict(prediction),
}) })

View file

@ -1,12 +0,0 @@
from ..util import Context, Prediction
def probability(context: Context) -> Prediction:
"""
The data from DMI.
"""
p = Prediction()
p.probability = 0.7
p.reasons.append("It is raining in Tønder")
return p

View file

@ -0,0 +1,89 @@
import itertools
import logging
from datetime import datetime
from math import pi, sqrt, sin, cos, atan2
import pytz
import requests
from timezonefinder import TimezoneFinder
from ..util import Context, Prediction
logger = logging.getLogger(__name__)
tf = TimezoneFinder(in_memory=True)
def night_on_iss(context: Context) -> Prediction:
"""
It is night if it is night on the ISS and it is currently orbiting above us.
"""
p = Prediction()
if not context.flat_earth:
iss_position = requests.get("http://api.open-notify.org/iss-now.json").json()["iss_position"]
the_iss = "The ISS"
iss_position_description = "on board the ISS"
else:
p.reasons.append("The ISS is (obviously) located in Hollywood")
the_iss = "Hollywood"
iss_position = {'latitude': 34.092808, 'longitude': -118.328659} # Hollywood
iss_position_description = "in the Hollywood studio"
phone_position = context.position
# Calculate ratio: a number between 0 and 1 saying how close we are to the ISS
distance = haversine(iss_position, phone_position)
max_distance = 40075 / 2 # the furthest you can be from any position is half of the earth's circumference
ratio = distance / max_distance
# We're in the same "timezone" as the ISS if we're on the same half of the earth
on_iss_time = ratio < 0.5
side = "same" if on_iss_time else "other"
p.reasons.append(f"{the_iss} is {int(distance)} km away, so we are on the {side} side of the earth.")
for i in itertools.count(1):
iss_tz = tf.closest_timezone_at(lng=float(iss_position["longitude"]),
lat=float(iss_position["latitude"]),
delta_degree=i)
if iss_tz is not None:
break
iss_time = datetime.now(pytz.timezone(iss_tz))
iss_night = 6 < iss_time.hour > 22
# iss_night on_iss_time night
# 0 0 1
# 0 1 0
# 1 0 0
# 1 1 1
night = iss_night == on_iss_time
iss_time_description = "nighttime" if iss_night else "daytime"
time_description = "nighttime" if night else "daytime"
p.probability = float(night)
p.reasons.append(f"It is {iss_time_description} {iss_position_description}.")
p.reasons.append(f"Therefore, it must be {time_description} where we are.")
return p
def haversine(pos1, pos2):
"""
Distance between two GPS coordinates.
https://stackoverflow.com/a/18144531
"""
lat1 = float(pos1["latitude"])
long1 = float(pos1["longitude"])
lat2 = float(pos2["latitude"])
long2 = float(pos2["longitude"])
degree_to_rad = float(pi / 180.0)
d_lat = (lat2 - lat1) * degree_to_rad
d_long = (long2 - long1) * degree_to_rad
a = pow(sin(d_lat / 2), 2) + cos(lat1 * degree_to_rad) * cos(lat2 * degree_to_rad) * pow(sin(d_long / 2), 2)
c = 2 * atan2(sqrt(a), sqrt(1 - a))
km = 6367 * c
return km

View file

@ -1,18 +1,18 @@
from datetime import datetime from datetime import datetime
from pathlib import Path
import requests import requests
import cv2 import cv2
from pytz import timezone from pytz import timezone
from ..util import Context, Prediction from ..util import Context, Prediction
#from server.nightr.util import Context, Prediction
def camImgStrat(context : Context) -> Prediction: def camImgStrat(context : Context) -> Prediction:
""" """
The contents of the camera image The contents of the camera image
""" """
img = cv2.imread('night.jpg',0) img = cv2.imread(str(Path(__file__).parent.joinpath("night.jpg")), 0)
average = img.mean(axis=0).mean(axis=0) average = img.mean(axis=0).mean(axis=0)
print(average) print(average)
p = Prediction() p = Prediction()

View file

@ -1,12 +0,0 @@
from ..util import Context, Prediction
def probability(context: Context) -> Prediction:
"""
How many players are currently online on Steam.
"""
p = Prediction()
p.probability = 0.2
p.reasons.append("CSGO has more than 10.000 online players")
return p

View file

@ -15,4 +15,5 @@ class Context:
@dataclass @dataclass
class Prediction: class Prediction:
probability: float = 0.5 probability: float = 0.5
weight: float = 1.0
reasons: List[str] = field(default_factory=list) reasons: List[str] = field(default_factory=list)

View file

@ -1,7 +1,11 @@
Flask==1.0.2 Flask
requests==2.21.0 requests
requests-cache==0.4.13 requests-cache
pytz pytz
beautifulsoup4 beautifulsoup4
pandas pandas
opencv-python opencv-python
timezonefinder
scikit-learn
html5lib
xlrd