diff --git a/.env.example b/.env.example index 45f410b..5ae28bc 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,7 @@ USERNAME= PASSWORD= SESSION_COOKIE_NAME= +MAX_RECORD_DAYS= # NEW DATABASE URI -SQLALCHEMY_DATABASE_URI='mysql+mysqlconnector://user:pass@host/database' \ No newline at end of file +SQLALCHEMY_DATABASE_URI='mysql+mysqlconnector://user:pass@host/database' diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml new file mode 100644 index 0000000..48ce960 --- /dev/null +++ b/.github/workflows/python-app.yml @@ -0,0 +1,24 @@ +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: Python application + +on: [ push, pull_request ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Run tests + run: | + python -m unittest discover diff --git a/README.md b/README.md index b66c025..8b76563 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,20 @@ Server is based on **Flask** and few extensions: Database: **MySQL** +## Executing + +First of all, activate virtual environment with: + +`source venv/bin/activate` + +To start the server run: + +`python run.py` + +To start tests run: + +`python -m unittest tests` + ## Credits All credits to @andrew4ever diff --git a/common/AQICalculator.py b/common/AQICalculator.py index 7731d47..f23a6cf 100644 --- a/common/AQICalculator.py +++ b/common/AQICalculator.py @@ -2,6 +2,9 @@ # In future old backend will be replaced by this new project and aqi calculator will be refactored import math +from os import environ +from datetime import datetime + import mysql.connector @@ -34,13 +37,19 @@ def calculate_aqi(self): continue self.cursor.execute( - "SELECT * FROM `sensor_record` WHERE `sensor_id` = {}".format( + "SELECT * FROM `sensor_record` WHERE `sensor_id` = {} ORDER BY `created_at` DESC".format( sensor[0]) ) record = self.cursor.fetchone() - if record: + if not record: + continue + + timedelta = datetime.now() - record[2] + + if timedelta.days < int(environ.get('MAX_RECORD_DAYS')): records.append(record) + print(sensor[0], record) # arrange records to squares squares = {} @@ -52,6 +61,12 @@ def calculate_aqi(self): squares[square_center].append(record) + self.cursor.execute("SELECT * FROM `sensor_value_type`") + types = self.cursor.fetchall() + used_ids = [value_type[0] + for value_type in types if value_type[-2] == 1] + types = {value_type[0]: value_type for value_type in types} + # get aqi for each square for center, records in squares.items(): # prepare dataset @@ -61,12 +76,6 @@ def calculate_aqi(self): "SELECT * FROM `sensor_value` WHERE `record_id` = {}".format(record[0])) values = self.cursor.fetchall() - self.cursor.execute("SELECT * FROM `sensor_value_type`") - types = self.cursor.fetchall() - used_ids = [value_type[0] - for value_type in types if value_type[-2] == 1] - types = {value_type[0]: value_type for value_type in types} - for value in values: if value[2] not in used_ids: continue diff --git a/models/area.py b/models/area.py index 3abfd6b..1871a65 100644 --- a/models/area.py +++ b/models/area.py @@ -36,9 +36,9 @@ class AreaModel(db.Model): ) def __repr__(self): - return ''.format(self._string_coords()) + return ''.format(self.string_coords()) - def _string_coords(self): + def string_coords(self): return str(self.latitude) + '-' + str(self.longitude) def as_dict(self): diff --git a/resources/area.py b/resources/area.py index 727fcb5..3b3a5a1 100644 --- a/resources/area.py +++ b/resources/area.py @@ -12,7 +12,7 @@ def get(self): areas = AreaModel.query \ .filter_by(latitude=latitude) \ .filter_by(longitude=longitude) \ - .limit(10).order_by(desc(AreaModel.created)).all() + .order_by(desc(AreaModel.created)).all() if not areas: return {'code': 404, 'message': 'Area not found'}, 404 diff --git a/resources/map.py b/resources/map.py index 8e1206a..7592d99 100644 --- a/resources/map.py +++ b/resources/map.py @@ -1,3 +1,6 @@ +from datetime import datetime +from os import environ + from flask_restful import Resource from sqlalchemy import desc @@ -17,6 +20,12 @@ def get(self): if (a['latitude'], a['longitude']) in areas_coords: continue + timedelta = datetime.now() - \ + datetime.strptime(a['created'], '%Y-%m-%d %H:%M:%S') + + if timedelta.days >= int(environ.get('MAX_RECORD_DAYS')): + continue + areas_coords.append((a['latitude'], a['longitude'])) areas_list.append(area.as_dict()) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..1b3bd4c --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,3 @@ +from tests.models.area import AreaModelTest +from tests.resources.area import AreaResourceTest +from tests.resources.map import MapResourceTest diff --git a/tests/models/area.py b/tests/models/area.py new file mode 100644 index 0000000..184c2b3 --- /dev/null +++ b/tests/models/area.py @@ -0,0 +1,43 @@ +import unittest + +from models import AreaModel + + +class AreaModelTest(unittest.TestCase): + def test_as_dict(self): + data = { + 'aqi': 42, + 'latitude': '50.442', + 'longitude': '30.91' + } + + result = AreaModel(**data).as_dict() + del result['created'] + del result['id'] + + self.assertEqual(result, data) + + def test_string_coords(self): + data = { + 'aqi': 42, + 'latitude': '50.442', + 'longitude': '30.91' + } + + result = AreaModel(**data).string_coords() + + self.assertEqual(result, self.string_coords(data)) + + def test_repr(self): + data = { + 'aqi': 42, + 'latitude': '50.442', + 'longitude': '30.91' + } + + result = str(AreaModel(**data)) + + self.assertEqual(result, ''.format(self.string_coords(data))) + + def string_coords(self, data): + return data['latitude'] + '-' + data['longitude'] diff --git a/tests/resources/area.py b/tests/resources/area.py new file mode 100644 index 0000000..5f1ec31 --- /dev/null +++ b/tests/resources/area.py @@ -0,0 +1,7 @@ +import unittest + +from resources import AreaResource + + +class AreaResourceTest(unittest.TestCase): + pass diff --git a/tests/resources/map.py b/tests/resources/map.py new file mode 100644 index 0000000..2dd1fb6 --- /dev/null +++ b/tests/resources/map.py @@ -0,0 +1,7 @@ +import unittest + +from resources import Map + + +class MapResourceTest(unittest.TestCase): + pass