diff --git a/dota2players.png b/dota2players.png new file mode 100644 index 0000000..0574926 Binary files /dev/null and b/dota2players.png differ diff --git a/server/README.md b/server/README.md index f931c46..2d04e64 100644 --- a/server/README.md +++ b/server/README.md @@ -3,3 +3,30 @@ cd server/ source activate.sh run ``` + + +## Inspiration +We were tasked with the troubling assignment of coming up with a project to built throughout this weekend. We had a base at the bar, sitting inside all confused and slightly drunk, as we did in fact not know if it was dark outside. This bewilderment inspired us to try and figure out how we could efficiently determine if it was nighttime, to try and fight our confusion. + +## What it does +The application taps into all the open data that Denmark has to offer. We use the number of cars on the roads, the free parking spaces, the level of the water in the bay, the number of cars having driven across the great belt bridge and whether your favorite pizza place is currently open. We also realise that everything has to utilise Machine Learning, so naturally the application has a support vector machine using all of two data points in an attempt to determine if it's nighttime based on free parking spaces. This is not all though, we also look at where the ISS space station is and much more, we do, however, make sure to not trust the clock.. Or Bing. Furthermore, the application allows for you to live in Australia, thus inverting everything, or perhaps you're a flat-earther and do not recognize space as a thing, thus special effort has to be taken. + +## How we built it +Through the power of drunken ideas and mediocre at best skills at Python. +We have a backend server which is written in Python. This server is easily extendable with strategies for determining whether or not it is nighttime. Whenever a request is received, the context of the person asking the question is sent to each strategy, who then has to determine if they think it is nighttime. Each answer is pooled together and we determine a weighted average from this. How each strategy determines this, is heavily dependent on its focus area. Some strategies use advanced machine learning, some use open data which has to be scraped or some just figure out if Alexanders upstairs neighbour is playing League of Legends. +On the frontend side of things, we have built a cross-platform application in nativescript. This application is built using their frameworks in Javascript and is tested on an android phone. + +## Challenges we ran into +We had to figure out how nativescript worked. We also had to find all the required data and do a bunch of odd calculations, such that the strategies could fulfill their purpose. The most difficult part was definitely building the app to work on an android phone, as none of us had really used this framework before. We had a slight grasp on machine learning prior to this, so the primary struggle of this, was building the dataset. + +## Accomplishments that we're proud of +We have scraped thousands of lines of open data, scoured through it to find what could be correlated to whether or not it is nighttime. We have built an android phone from the bottom up, capable of displaying our results and talking to our backend server. We have had to look at and decipher what internal calls different websites perform, as they did not actually give an open API. All of this results in an app which can give an accurate guess on whether or not it is nighttime. + +## What we learned +How to use nativescript. +How to scrape data using various python frameworks. +A strange amount of information in regards to the flat earth society. +How many factors ACTUALLY have a direct correlation with whether or not it is nighttime. + +## What's next for Nightr +We're actively looking for investors for our series A funding. BlackRock, get in touch! \ No newline at end of file diff --git a/server/nightr/app.py b/server/nightr/app.py index 23bd1ae..5518050 100644 --- a/server/nightr/app.py +++ b/server/nightr/app.py @@ -10,7 +10,7 @@ from typing import List import requests_cache from flask import Flask, jsonify, logging, request -from .strategies import miloStrats, iss, cars_in_traffic, tide_strat, upstairs_neighbour, bing, svm_strat, battery, just_eat +from .strategies import miloStrats, iss, cars_in_traffic, tide_strat, upstairs_neighbour, bing, svm_strat, battery, just_eat, steam from .util import Context app = Flask(__name__) @@ -33,6 +33,7 @@ strategies = { "ML Parking": svm_strat.perform_svm_pred, "Phone Battery Level": battery.battery_level, "Pizza Availability": just_eat.do_just_eat_strat, + "Steam Players Online": steam.dota2_players, } diff --git a/server/nightr/strategies/just_eat.py b/server/nightr/strategies/just_eat.py index aa074e9..1f550e2 100644 --- a/server/nightr/strategies/just_eat.py +++ b/server/nightr/strategies/just_eat.py @@ -33,7 +33,7 @@ def is_restaurant_open(name, open, close) -> Prediction: p.probability = 1 / 11 else: p.reasons.append(f"Our favorite pizza place, {name}, is closed.") - p.reasons.append(f"We can conclude from this, that there is {1 - (1/11)}% chance of it currently being night outside!") + p.reasons.append(f"We can conclude from this, that there is {1 - (1/11):.1f}% chance of it currently being night outside!") p.probability = round(1 - (1 / 11), 2) return p diff --git a/server/nightr/strategies/steam.py b/server/nightr/strategies/steam.py new file mode 100644 index 0000000..266b7c2 --- /dev/null +++ b/server/nightr/strategies/steam.py @@ -0,0 +1,40 @@ +from datetime import datetime +from pathlib import Path + +import requests + +from ..util import Context, Prediction + + +def dota2_players(context: Context) -> Prediction: + """ + How many players are playing Dota 2? + """ + p = Prediction() + + # Find the historic data closest matching the current number of players. Lol yolo + current_players = get_dota2_players() + with Path(__file__).parent.joinpath("dotaplayers 2019-04-06 13:43:33.074496.csv").open() as csv: + best_players, best_dt = min(csv, key=lambda l: abs(int(l.rstrip().split(", ")[0]) - current_players)).rstrip().split(", ") + best_match_players = int(best_players) + best_match_datetime = datetime.strptime(best_dt, "%Y-%m-%d %H:%M:%S.%f") + + night = best_match_datetime.hour < 6 or best_match_datetime.hour >= 22 + night_description = "night" if night else "day" + + p.reasons.append(f"{current_players} people are currently playing Dota 2.") + p.reasons.append(f"On the {night_description} of {best_match_datetime.strftime('%B %d')}, {best_match_players} were playing Dota 2.") + p.reasons.append(f"Therefore, it must currently be {night_description}time.") + + p.probability = float(night) # TODO: actual float lol gg + + return p + + +def get_dota2_players(): + header = {"Client-ID": "F07D7ED5C43A695B3EBB01C28B6A18E5"} + appId = 570 + game_players_url = 'https://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/?format=json&appid=' + str(appId) + game_players = requests.get(game_players_url, headers=header) + players_str = str(game_players.json()['response']['player_count']) + return int(players_str) diff --git a/server/nightr/strategies/tide_strat.py b/server/nightr/strategies/tide_strat.py index ef13e8c..17aa996 100644 --- a/server/nightr/strategies/tide_strat.py +++ b/server/nightr/strategies/tide_strat.py @@ -19,9 +19,9 @@ def is_tide(context: Context) -> Prediction: month, cur_year_total_cars, last_year_total_cars = determine_month() month = int(month) - p.reasons.append(f"The month is {calendar.month_name[month]}") p.reasons.append(f"The number of cars having driven on the Storbæltsbro is {cur_year_total_cars}, in the current year") - p.reasons.append(f"The number of cars having driven over it in the last year is {last_year_total_cars}, thus the frequency is: {last_year_total_cars / cur_year_total_cars}") + p.reasons.append(f"The number of cars having driven over it in the last year is {last_year_total_cars}, thus the frequency is: {last_year_total_cars / cur_year_total_cars:.2f}") + p.reasons.append(f"The month is therefore {calendar.month_name[month]}") tide_data = requests.get('https://www.dmi.dk/fileadmin/user_upload/Bruger_upload/Tidevand/2019/Aarhus.t.txt') @@ -77,7 +77,7 @@ def is_tide(context: Context) -> Prediction: moments.append(time[0]) night = sum([1 for x in moments if 6 >= x.hour or x.hour >= 22]) - p.reasons.append(f"The water level is currently at {current_water_level}") + p.reasons.append(f"The water level is currently at {current_water_level} in the Aarhus Bay") p.reasons.append(f"The number of times the water is at the current level at nighttime is: {night}, compared to the total amount of times in {calendar.month_name[month]}, being {len(moments)}") p.probability = 1 - (night / len(moments))