Testing the final product

This commit is contained in:
Viktor Søndergaard 2019-04-07 04:36:11 +02:00
commit 29b066b836
14 changed files with 92 additions and 52 deletions

View File

@ -1,4 +1,4 @@
<ActionBar title="Home" class="action-bar"></ActionBar> <ActionBar title="Nightr" class="action-bar"></ActionBar>
<ScrollView class="page"> <ScrollView class="page">
<AbsoluteLayout> <AbsoluteLayout>

View File

@ -4,6 +4,7 @@ import { GestureEventData } from 'tns-core-modules/ui/gestures'
import { Switch } from "tns-core-modules/ui/switch"; import { Switch } from "tns-core-modules/ui/switch";
import * as appSettings from "tns-core-modules/application-settings"; import * as appSettings from "tns-core-modules/application-settings";
import { isEnabled, enableLocationRequest, getCurrentLocation, watchLocation, distance, clearWatch, Location } from "nativescript-geolocation";
import { MyHttpPostService } from '../services/my-http-post-service'; import { MyHttpPostService } from '../services/my-http-post-service';
@Component({ @Component({

View File

@ -1,11 +1,26 @@
.title-container .h2
{ {
font-family: sans-serif; font-family: sans-serif;
font-size: 30px; font-size: 35px;
padding: 5px;
color: white; color: white;
text-align: center; text-align: center;
} }
.h1
{
font-family: sans-serif;
font-size: 100px;
color: white;
text-align: center;
}
.h3
{
font-family: sans-serif;
font-style: italic;
font-size: 20px;
color: white;
text-align: center;
}
.page { .page {
background-color: lightskyblue; background-color: lightskyblue;
} }

View File

@ -1,11 +1,12 @@
<ActionBar title="Result" class="action-bar"></ActionBar> <ActionBar title="Nightr" class="action-bar"></ActionBar>
<StackLayout class="page" height="100%"> <StackLayout class="page" height="100%">
<StackLayout height="20%" class="title-container"> <StackLayout height="45%" class="title-container">
<Label text="{{night}}"></Label> <Label text="{{itis}}" class="h3"></Label>
<Label text="{{percentage}}" textWrap="true"></Label> <Label text="{{night}}" class="h1"></Label>
<Label text="{{percentage}}" textWrap="true" class="h2"></Label>
<Label text="{{hereswhy}}" class="h3"></Label>
</StackLayout> </StackLayout>
<ScrollView height='80%'> <ScrollView height='55%'>
<ListView [items]="reasons" class="list-group"> <ListView [items]="reasons" class="list-group">
<ng-template let-reason="item" let-i="index" let-odd="odd" let-even="even"> <ng-template let-reason="item" let-i="index" let-odd="odd" let-even="even">
<StackLayout orientation="vertical" class="list-group-item"> <StackLayout orientation="vertical" class="list-group-item">
@ -16,3 +17,4 @@
</ListView> </ListView>
</ScrollView> </ScrollView>
</StackLayout> </StackLayout>
<ActivityIndicator #activityIndicator [busy]="isBusy" originX ="0.5" originY="0.5" width="100" height="100" class="activity-indicator"></ActivityIndicator>

View File

@ -1,9 +1,9 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { MyHttpPostService } from '../services/my-http-post-service' import { MyHttpPostService } from '../services/my-http-post-service';
import { MyGeoLocationService} from '../services/my-geo-location.service'; import { MyGeoLocationService} from '../services/my-geo-location.service';
import { MyBatteryInfoService } from '../services/my-battery-info.service'; import { MyBatteryInfoService } from '../services/my-battery-info.service';
import { MyCameraService } from '../services/my-camera-service' import { MyCameraService } from '../services/my-camera-service';
import { RouterExtensions } from 'nativescript-angular/router'; import { RouterExtensions } from 'nativescript-angular/router';
import { Location } from 'nativescript-geolocation'; import { Location } from 'nativescript-geolocation';
import * as appSettings from "tns-core-modules/application-settings"; import * as appSettings from "tns-core-modules/application-settings";
@ -23,6 +23,7 @@ class Reason {
}) })
export class ResultPageComponent implements OnInit { export class ResultPageComponent implements OnInit {
returnMessage: string = ""; returnMessage: string = "";
isBusy: boolean;
myReturnJSON: Object; myReturnJSON: Object;
locationData: Location; locationData: Location;
myPicture: String; myPicture: String;
@ -30,9 +31,12 @@ export class ResultPageComponent implements OnInit {
flat_earth: boolean; flat_earth: boolean;
in_australia: boolean; in_australia: boolean;
night: string = ""; night: string = "";
percentage: string = ""; percentage: string = "Calculating...";
hereswhy: string = "";
itis: string = "";
reasons: Array<Reason>;
JSONObject; JSONObject;
public reasons: Array<Reason>;
constructor(private myHttpPostSerivce: MyHttpPostService, constructor(private myHttpPostSerivce: MyHttpPostService,
private routerExtensions: RouterExtensions, private routerExtensions: RouterExtensions,
@ -41,6 +45,8 @@ export class ResultPageComponent implements OnInit {
private cameraService: MyCameraService,){ } private cameraService: MyCameraService,){ }
ngOnInit(): Promise<void> { ngOnInit(): Promise<void> {
this.isBusy = true;
this.reasons = new Array<Reason>();
return this.cameraService.takePicture(). return this.cameraService.takePicture().
then(picture => { then(picture => {
this.image = JSON.stringify(picture); this.image = JSON.stringify(picture);
@ -62,13 +68,15 @@ public submit(): void {
} }
private makePostRequest(): void { private makePostRequest(): void {
this.isBusy = true;
this.myHttpPostSerivce this.myHttpPostSerivce
.postData({ position: this.locationData, image: this.image, .postData({ position: this.locationData, image: this.image,
flat_earth: appSettings.getBoolean("applicationIsEarthFlat", false), flat_earth: appSettings.getBoolean("applicationIsEarthFlat", false),
in_australia: appSettings.getBoolean("applicationinAustralia", false), }) in_australia: appSettings.getBoolean("applicationinAustralia", false), })
.subscribe(res => { .subscribe(res => {
//console.log('This is res', res); console.log('This is res', res);
this.JSONObject = res; this.JSONObject = res;
this.isBusy = false;
this.addToArray(); this.addToArray();
//console.log('THis is myreturnJSON', this.myReturnJSON); //console.log('THis is myreturnJSON', this.myReturnJSON);
}); });
@ -77,17 +85,19 @@ private makePostRequest(): void {
public addToArray(): void { public addToArray(): void {
if (this.JSONObject.night) { if (this.JSONObject.night) {
this.night = "It is night"; this.night = "NIGHT";
} else { } else {
this.night = "It is day"; this.night = "DAY";
} }
this.percentage = "At least we are "+Math.floor(this.JSONObject.weighted_probabilities_mean*100)+"% sure, here's why" this.percentage = "At least we are "+Math.floor(this.JSONObject.weighted_probabilities_mean*100)+"% sure"
for (let i = 0; i < this.JSONObject.predictions.length; i++) { for (let i = 0; i < this.JSONObject.predictions.length; i++) {
var causestring = "" var causestring = ""
for (let j = 0; j < this.JSONObject.predictions[i].reasons.length; j++) { for (let j = 0; j < this.JSONObject.predictions[i].reasons.length; j++) {
causestring = causestring + " - " + this.JSONObject.predictions[i].reasons[j] + "\n"; causestring = causestring + " - " + this.JSONObject.predictions[i].reasons[j] + "\n";
} }
this.itis = "It is"
this.hereswhy = "Here's why:"
this.reasons.push(new Reason(""+Math.round(this.JSONObject.predictions[i].contribution*100)+"% - " + this.JSONObject.predictions[i].name, causestring)); this.reasons.push(new Reason(""+Math.round(this.JSONObject.predictions[i].contribution*100)+"% - " + this.JSONObject.predictions[i].name, causestring));
} }
} }

View File

@ -11,4 +11,4 @@ var app_module_1 = require("./app/app.module");
// so we provide a wrapper platform object, platformNativeScriptDynamic, // so we provide a wrapper platform object, platformNativeScriptDynamic,
// that sets up a NativeScript application and can bootstrap the Angular framework. // that sets up a NativeScript application and can bootstrap the Angular framework.
platform_1.platformNativeScriptDynamic().bootstrapModule(app_module_1.AppModule); platform_1.platformNativeScriptDynamic().bootstrapModule(app_module_1.AppModule);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1haW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwwR0FBMEc7QUFDMUcsMERBQTRFO0FBRTVFLCtDQUE2QztBQUU3QyxnRkFBZ0Y7QUFDaEYsMEVBQTBFO0FBQzFFLHNFQUFzRTtBQUN0RSx5REFBeUQ7QUFDekQseUVBQXlFO0FBQ3pFLHdFQUF3RTtBQUN4RSxtRkFBbUY7QUFDbkYsc0NBQTJCLEVBQUUsQ0FBQyxlQUFlLENBQUMsc0JBQVMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdGhpcyBpbXBvcnQgc2hvdWxkIGJlIGZpcnN0IGluIG9yZGVyIHRvIGxvYWQgc29tZSByZXF1aXJlZCBzZXR0aW5ncyAobGlrZSBnbG9iYWxzIGFuZCByZWZsZWN0LW1ldGFkYXRhKVxyXG5pbXBvcnQgeyBwbGF0Zm9ybU5hdGl2ZVNjcmlwdER5bmFtaWMgfSBmcm9tIFwibmF0aXZlc2NyaXB0LWFuZ3VsYXIvcGxhdGZvcm1cIjtcclxuXHJcbmltcG9ydCB7IEFwcE1vZHVsZSB9IGZyb20gXCIuL2FwcC9hcHAubW9kdWxlXCI7XHJcblxyXG4vLyBBIHRyYWRpdGlvbmFsIE5hdGl2ZVNjcmlwdCBhcHBsaWNhdGlvbiBzdGFydHMgYnkgaW5pdGlhbGl6aW5nIGdsb2JhbCBvYmplY3RzLFxyXG4vLyBzZXR0aW5nIHVwIGdsb2JhbCBDU1MgcnVsZXMsIGNyZWF0aW5nLCBhbmQgbmF2aWdhdGluZyB0byB0aGUgbWFpbiBwYWdlLlxyXG4vLyBBbmd1bGFyIGFwcGxpY2F0aW9ucyBuZWVkIHRvIHRha2UgY2FyZSBvZiB0aGVpciBvd24gaW5pdGlhbGl6YXRpb246XHJcbi8vIG1vZHVsZXMsIGNvbXBvbmVudHMsIGRpcmVjdGl2ZXMsIHJvdXRlcywgREkgcHJvdmlkZXJzLlxyXG4vLyBBIE5hdGl2ZVNjcmlwdCBBbmd1bGFyIGFwcCBuZWVkcyB0byBtYWtlIGJvdGggcGFyYWRpZ21zIHdvcmsgdG9nZXRoZXIsXHJcbi8vIHNvIHdlIHByb3ZpZGUgYSB3cmFwcGVyIHBsYXRmb3JtIG9iamVjdCwgcGxhdGZvcm1OYXRpdmVTY3JpcHREeW5hbWljLFxyXG4vLyB0aGF0IHNldHMgdXAgYSBOYXRpdmVTY3JpcHQgYXBwbGljYXRpb24gYW5kIGNhbiBib290c3RyYXAgdGhlIEFuZ3VsYXIgZnJhbWV3b3JrLlxyXG5wbGF0Zm9ybU5hdGl2ZVNjcmlwdER5bmFtaWMoKS5ib290c3RyYXBNb2R1bGUoQXBwTW9kdWxlKTtcclxuIl19 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1haW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwwR0FBMEc7QUFDMUcsMERBQTRFO0FBRTVFLCtDQUE2QztBQUU3QyxnRkFBZ0Y7QUFDaEYsMEVBQTBFO0FBQzFFLHNFQUFzRTtBQUN0RSx5REFBeUQ7QUFDekQseUVBQXlFO0FBQ3pFLHdFQUF3RTtBQUN4RSxtRkFBbUY7QUFDbkYsc0NBQTJCLEVBQUUsQ0FBQyxlQUFlLENBQUMsc0JBQVMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdGhpcyBpbXBvcnQgc2hvdWxkIGJlIGZpcnN0IGluIG9yZGVyIHRvIGxvYWQgc29tZSByZXF1aXJlZCBzZXR0aW5ncyAobGlrZSBnbG9iYWxzIGFuZCByZWZsZWN0LW1ldGFkYXRhKVxuaW1wb3J0IHsgcGxhdGZvcm1OYXRpdmVTY3JpcHREeW5hbWljIH0gZnJvbSBcIm5hdGl2ZXNjcmlwdC1hbmd1bGFyL3BsYXRmb3JtXCI7XG5cbmltcG9ydCB7IEFwcE1vZHVsZSB9IGZyb20gXCIuL2FwcC9hcHAubW9kdWxlXCI7XG5cbi8vIEEgdHJhZGl0aW9uYWwgTmF0aXZlU2NyaXB0IGFwcGxpY2F0aW9uIHN0YXJ0cyBieSBpbml0aWFsaXppbmcgZ2xvYmFsIG9iamVjdHMsXG4vLyBzZXR0aW5nIHVwIGdsb2JhbCBDU1MgcnVsZXMsIGNyZWF0aW5nLCBhbmQgbmF2aWdhdGluZyB0byB0aGUgbWFpbiBwYWdlLlxuLy8gQW5ndWxhciBhcHBsaWNhdGlvbnMgbmVlZCB0byB0YWtlIGNhcmUgb2YgdGhlaXIgb3duIGluaXRpYWxpemF0aW9uOlxuLy8gbW9kdWxlcywgY29tcG9uZW50cywgZGlyZWN0aXZlcywgcm91dGVzLCBESSBwcm92aWRlcnMuXG4vLyBBIE5hdGl2ZVNjcmlwdCBBbmd1bGFyIGFwcCBuZWVkcyB0byBtYWtlIGJvdGggcGFyYWRpZ21zIHdvcmsgdG9nZXRoZXIsXG4vLyBzbyB3ZSBwcm92aWRlIGEgd3JhcHBlciBwbGF0Zm9ybSBvYmplY3QsIHBsYXRmb3JtTmF0aXZlU2NyaXB0RHluYW1pYyxcbi8vIHRoYXQgc2V0cyB1cCBhIE5hdGl2ZVNjcmlwdCBhcHBsaWNhdGlvbiBhbmQgY2FuIGJvb3RzdHJhcCB0aGUgQW5ndWxhciBmcmFtZXdvcmsuXG5wbGF0Zm9ybU5hdGl2ZVNjcmlwdER5bmFtaWMoKS5ib290c3RyYXBNb2R1bGUoQXBwTW9kdWxlKTtcbiJdfQ==

View File

@ -11,7 +11,7 @@ def clock(context: Context) -> Prediction:
It's nighttime if Bing says it's daytime. It's nighttime if Bing says it's daytime.
""" """
p = Prediction() p = Prediction()
p.weight = 0.02 p.weight = 0.01
headers = { headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'} 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'}

View File

@ -1,15 +1,11 @@
import itertools import operator
from datetime import datetime from datetime import datetime, timezone
from math import pi, sqrt, sin, cos, atan2 from math import pi, sqrt, sin, cos, atan2
import pytz
import requests import requests
from timezonefinder import TimezoneFinder
from ..util import Context, Prediction from ..util import Context, Prediction
tf = TimezoneFinder(in_memory=True)
def night_on_iss(context: Context) -> Prediction: def night_on_iss(context: Context) -> Prediction:
""" """
@ -20,34 +16,43 @@ def night_on_iss(context: Context) -> Prediction:
if not context.flat_earth: if not context.flat_earth:
iss_position = requests.get("http://api.open-notify.org/iss-now.json").json()["iss_position"] iss_position = requests.get("http://api.open-notify.org/iss-now.json").json()["iss_position"]
the_iss = "The ISS" the_iss = "The ISS"
at_iss_location = "at the ISS's location"
iss_position_description = "on board the ISS" iss_position_description = "on board the ISS"
else: else:
p.reasons.append("The ISS is (obviously) located in Hollywood") p.reasons.append('The "ISS" is obviously a studio in Hollywood')
the_iss = "Hollywood" the_iss = "Hollywood"
iss_position = {'latitude': 34.092808, 'longitude': -118.328659} # Hollywood iss_position = {'latitude': 34.092808, 'longitude': -118.328659} # Hollywood
at_iss_location = "in Hollywood"
iss_position_description = "in the Hollywood studio" iss_position_description = "in the Hollywood studio"
phone_position = context.position sun_times = requests.get(f"https://api.sunrise-sunset.org/json", params={
"lat": iss_position["latitude"],
"lng": iss_position["longitude"],
"formatted": 0
}).json()["results"]
iss_position_sunrise = datetime.strptime(sun_times["sunrise"], "%Y-%m-%dT%H:%M:%S%z")
iss_position_sunset = datetime.strptime(sun_times["sunset"], "%Y-%m-%dT%H:%M:%S%z")
p.reasons.append(f"The sun rises and sets at UTC {iss_position_sunrise.strftime('%H:%M')} and {iss_position_sunset.strftime('%H:%M')}, respectively, {at_iss_location}.")
utcnow = datetime.now(timezone.utc)
p.reasons.append(f"It is currently {utcnow.strftime('%H:%M')} UTC")
iss_night = utcnow < iss_position_sunrise or iss_position_sunset < utcnow
iss_time_description = "nighttime" if iss_night else "daytime"
p.reasons.append(f"Therefore, it is {iss_time_description} {iss_position_description}.")
# Calculate ratio: a number between 0 and 1 saying how close we are to the ISS # Calculate ratio: a number between 0 and 1 saying how close we are to the ISS
phone_position = context.position
distance = haversine(iss_position, phone_position) 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 max_distance = 40075 / 2 # the furthest you can be from any position is half of the earth's circumference
ratio = distance / max_distance ratio = distance / max_distance
# We're in the same "timezone" as the ISS if we're on the same half of the earth # 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 on_iss_time = ratio < 0.5
side = "same" if on_iss_time else "other" 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.") 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 = iss_time.hour < 6 or iss_time.hour >= 22
# iss_night on_iss_time night # iss_night on_iss_time night
# 0 0 1 # 0 0 1
@ -56,11 +61,10 @@ def night_on_iss(context: Context) -> Prediction:
# 1 1 1 # 1 1 1
night = iss_night == on_iss_time night = iss_night == on_iss_time
iss_time_description = "nighttime" if iss_night else "daytime"
time_description = "nighttime" if night else "daytime" time_description = "nighttime" if night else "daytime"
p.probability = float(night) op = operator.add if night else operator.sub
p.reasons.append(f"It is {iss_time_description} {iss_position_description}.") p.probability = op(0.5, ratio * 0.5)
p.reasons.append(f"Therefore, it must be {time_description} where we are.") p.reasons.append(f"So it must be {time_description} where we are.")
return p return p

View File

@ -34,7 +34,7 @@ def is_restaurant_open(name, open, close) -> Prediction:
else: else:
p.reasons.append(f"Our favorite pizza place, {name}, is closed.") 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)}% chance of it currently being night outside!")
p.probability = 1 - (1 / 11) p.probability = round(1 - (1 / 11), 2)
return p return p

View File

@ -35,12 +35,20 @@ def australiaStrat(context : Context) -> Prediction:
hour = t.hour hour = t.hour
p = Prediction() p = Prediction()
if hour > 22 or hour < 6: if context.in_australia:
p.probability = 0.0 if hour > 22 or hour < 6:
p.reasons.append('It\'s night-time in Australia, so it must be day-time here.') p.probability = 1.0
p.reasons.append('It\'s night-time in Australia, and that\'s where we\'re at.')
else:
p.probability = 0.0
p.reasons.append('It\'s day-time in Australia, and that\'s where we\'re at.')
else: else:
p.probability = 1.0 if hour > 22 or hour < 6:
p.reasons.append('It\'s day-time in Australia, so it must be night-time here.') p.probability = 0.0
p.reasons.append('It\'s night-time in Australia, so it must be day-time here.')
else:
p.probability = 1.0
p.reasons.append('It\'s day-time in Australia, so it must be night-time here.')
return p return p

View File

@ -55,7 +55,7 @@ def perform_svm_pred(context: Context) -> Prediction:
X = [min(x, 1) for x in X] X = [min(x, 1) for x in X]
p.reasons.append("We only have two data points") p.reasons.append("We only have two data points")
p.reasons.append("Our only two data points have 11 dimensions") p.reasons.append("Our only two data points have 11 dimensions")
p.reasons.append("We are using a SVM") p.reasons.append("We are using a SVM. Apparently that's a poor idea.")
p.probability = float(predict(X)) p.probability = float(predict(X))
return p return p

View File

@ -11,7 +11,7 @@ from ..util import Context, Prediction
def is_tide(context: Context) -> Prediction: def is_tide(context: Context) -> Prediction:
""" """
Determine whether or not it is night in Aarhus based no the current water level and which month we are in, based Determine whether or not it is night in Aarhus based on the current water level and which month we are in, based
on number of cars driving across The Storbæltsbro. on number of cars driving across The Storbæltsbro.
""" """

View File

@ -1,4 +1,5 @@
import base64 import base64
import random
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import List, Dict from typing import List, Dict
@ -9,7 +10,7 @@ import numpy as np
@dataclass @dataclass
class Context: class Context:
battery: int = 55 battery: int = field(default_factory=lambda: random.randint(0, 100))
position: Dict[str, float] = field(default_factory=lambda: {'latitude': 53.0, 'longitude': 9.0}) # Denmark somewhere position: Dict[str, float] = field(default_factory=lambda: {'latitude': 53.0, 'longitude': 9.0}) # Denmark somewhere
image: np.ndarray = None image: np.ndarray = None

View File

@ -5,7 +5,6 @@ pytz
beautifulsoup4 beautifulsoup4
pandas pandas
opencv-python opencv-python
timezonefinder
scikit-learn scikit-learn
html5lib html5lib
xlrd xlrd