summaryrefslogtreecommitdiff
path: root/src/main.py
blob: 6dae3228fc29e41ab4de12ede011195c7f63e98d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import os
import random
import json
import sqlite3
from contextlib import closing # with close sqlite

import flask
from PIL import Image as PIL_Image # Image file exif data for GPS coordinate extraction
import PIL.ExifTags as PIL_ExifTags
import geopy.distance

app = flask.Flask(__name__)

def decimal_coords(coords, ref):
    decimal_degrees = coords[0] + coords[1] / 60 + coords[2] / 3600
    if ref == "S" or ref =='W' :
        decimal_degrees = -decimal_degrees
    return decimal_degrees

def get_exif(image_path: os.PathLike) -> dict:
    # Extract EXIF metadata as a dictionary with readable tags
    image = PIL_Image.open(image_path)  # Load the image from the specified path
    exif = {
        PIL_ExifTags.TAGS[k]: v
        for k, v in image._getexif().items()
        if k in PIL_ExifTags.TAGS
    }
    return exif


def image_coordinates(exif: dict) -> (float, float):
    # Extract raw GPS data for latitude (north) and longitude (east)
    north = exif['GPSInfo'][2]  # Latitude data in degrees, minutes, and seconds
    east = exif['GPSInfo'][4]   # Longitude data in degrees, minutes, and seconds

    # Convert latitude and longitude from degrees-minutes-seconds to decimal format
    lat = ((((north[0]*60) + north[1])*60) + north[2]) / 60 / 60
    lng = ((((east[0]*60) + east[1])*60) + east[2]) / 60 / 60
    return float(lat),float(lng)

@app.route('/favicon.ico')
def favicon():
    return flask.send_from_directory(os.path.join(app.root_path, 'static'),
                                     'favicon.ico', mimetype='image/vnd.microsoft.icon')

@app.route('/get_random_image.json')
def get_random_image():
    return random.choice(pics)

@app.route("/guess.json", methods=['POST'])
def guess():
    data = json.loads(flask.request.data)
    exif = get_exif(os.path.join(pic_root_path, data['image_name']))

    correct_coordinates = image_coordinates(exif)
    guess_coordinates   = (data['coordinates']['lat'], data['coordinates']['lng'])

    distance = geopy.distance.geodesic(correct_coordinates, guess_coordinates)
    distance_meters = round(distance.meters)

    image_unique_id = exif['ImageUniqueID']
    with closing(sqlite3.connect("guess_where.db")) as connection:
        with closing(connection.cursor()) as cursor:
            cursor.execute("""INSERT INTO guesses(
                                                picture_name,
                                                image_unique_id,
                                                correct_coordinates,
                                                guess_coordinates,
                                                distance_meters
                                                )
                           VALUES (?, ?, ?, ?, ?)
                           """, (
                                                data['image_name'],
                                                image_unique_id,
                                                f"{correct_coordinates[0]}, {correct_coordinates[1]}",
                                                f"{data['coordinates']['lat']}, {data['coordinates']['lng']}",
                                                distance_meters
                               ))
            connection.commit()

    return {'correct_coordinates': correct_coordinates, 'distance_meters': distance_meters}

@app.route("/")
def game():
    return  flask.render_template('game.html')



pic_root_path = 'src/static/pics/mine'
pics_original = os.listdir(pic_root_path)
pics = []

# Check if all images have GPS coordinates on application start
for pic in pics_original:
    img_path = os.path.join(pic_root_path, pic)
    try:
        exif = get_exif(img_path)
        correct_coordinates = image_coordinates(exif)
        pics.append(pic)
    except Exception as ex:
        print(f'Error loading GPS coordinates for: {img_path}')
        raise ex


with closing(sqlite3.connect("guess_where.db")) as connection:
    with closing(connection.cursor()) as cursor:
        rows = cursor.execute("""
                              CREATE TABLE IF NOT EXISTS guesses (
                                  picture_name        TEXT,
                                  image_unique_id     TEXT,
                                  correct_coordinates TEXT,
                                  guess_coordinates   TEXT,
                                  distance_meters     INT,
                                  timestamp           DATETIME DEFAULT CURRENT_TIMESTAMP
                                  )
                              """).fetchall()