README.md
# measurement_server
A Simple JSON REST API for a database of scientific measurements taken at various locations.
## Execution
1. Install dependencies
```bash
pip install Flask Flask-Jsonpify Flask-RESTful SQLAlchemy
```
2. Start server
```bash
python measurement_server.py
```
## API reference
### `/area` - List all areas
Returns an array of every Area in the database.
#### Example usage
```json
[
{"area_id": 1, "name": "Grand Canyon", "lat": 30, "long": 20},
{"area_id": 2, "name": "Boca Raton", "lat": 50, "long": 40},
{"area_id": 3, "name": "Kennesaw", "lat": 70, "long": 60},
{"area_id": 4, "name": "Mount Hood", "lat": 90, "long": 80},
{"area_id": 5, "name": "Mount Rainer", "lat": 121.5, "long": 46.5},
{"area_id": 6, "name": "Saint Olaf", "lat": 93, "long": 44},
{"area_id": 7, "name": "Mount St. Helens", "lat": 122, "long": 46}
]
```
#### Area object
| --------- | ------- | --------------------------------------- |
| `area_id` | integer | Id |
| `name` | string | The name of the area |
| `lat` | number | The latitude (in degrees) of this area |
| `long` | number | The longitude (in degrees) of this area |
### `/area/<area_id>/location` - List locations in area
Returns an array of Locations which match the given `area_id`.
#### Example usage
```json
[
{"loc_id": 11, "name": "South rim", "alt": 200, "area_id": 1},
{"loc_id": 12, "name": "North rim", "alt": 300, "area_id": 1},
{"loc_id": 13, "name": "Phantom Ranch", "alt": 100, "area_id": 1}
]
```
#### Location object
| --------- | ------- | ------------------------------------- |
| `loc_id` | integer | Unique ID |
| `name` | string | Name of the location |
| `alt` | number | Altitude (in feet??) |
| `area_id` | integer | The ID of the area the location is in |
### `/location/<loc_id>/measurement` - List measurements for location
Returns an array of Measurements taken in the given location.
#### Example usage
```json
[
{"m_id": 1100, "loc_id": 11, "val": 44.82004560587978},
{"m_id": 1101, "loc_id": 11, "val": 38.91602608079564},
{"m_id": 1102, "loc_id": 11, "val": 44.178163488614025},
{"m_id": 1103, "loc_id": 11, "val": 46.41919904550956},
{"m_id": 1104, "loc_id": 11, "val": 46.345502885760894},
{"m_id": 1105, "loc_id": 11, "val": 43.1501772579135},
{"m_id": 1106, "loc_id": 11, "val": 44.31037965295677},
{"m_id": 1107, "loc_id": 11, "val": 41.692298340629186},
{"m_id": 1108, "loc_id": 11, "val": 43.28018622019225},
{"m_id": 1109, "loc_id": 11, "val": 39.07856683302732}
]
```
#### Measurement object
| -------- | ------- | ------------------------------------------------------ |
| `m_id` | integer | A unique ID for the measurement |
| `loc_id` | integer | The ID of the location where the measurement was taken |
| `val` | number | The value of the measurement |
### `/area/AREA_ID/category` - Get categories for area
#### Example usage
```json
[
{"cat_id": 31, "name": "Volcanos", "description": "Areas that are on volcanoes"},
{"cat_id": 33, "name": "West", "description": "Areas that are in the west"}
]
```
#### Category object
| ------------ | ------- | ------------------------------ |
| `cat_id` | integer | A unique ID for this category |
| `name` | string | The name of this category |
| `descripton` | string | A description of that category |
### `/area/AREA_ID/average_measurement` - Get the average measurement for area
#### Example usage
```json
46.26524716693247
```
### `/area/AREA_ID/number_locations` Get the number of locations for area
#### Example usage
```json
3
```
measurement_server.py
from flask import Flask, request
from flask_restful import Resource, Api
from flask_jsonpify import jsonify
from sqlalchemy import create_engine, text
from json import dumps
SQLITE_FILE = "measures.db"
SERVER_PORT = 9000
db_connect = create_engine(f'sqlite:///{SQLITE_FILE}')
app = Flask(__name__)
api = Api(app)
class Areas(Resource):
def get(self):
with db_connect.connect() as conn:
result = conn.execute(text("select area_id, name, latitude as lat, longitude as long from area"))
return [dict(zip(tuple(row._fields), row)) for row in result.all()]
class AreaLocations(Resource):
def get(self, area_id):
with db_connect.connect() as conn:
result = conn.execute(
text("select location_id as loc_id, name, altitude as alt, location_area as area_id from location where location_area = %d" %int(area_id)))
return [dict(zip(tuple(row._fields), row)) for row in result.all()]
class LocationMeasurements(Resource):
def get(self, loc_id):
with db_connect.connect() as conn:
result = conn.execute(
text("select measurement_id as m_id, measurement_location as loc_id, value as val from measurement where measurement_location = %d" % int(loc_id)))
return [dict(zip(tuple(row._fields), row)) for row in result.all()]
class AreaCategories(Resource):
def get(self, area_id):
with db_connect.connect() as conn:
result = conn.execute(
text("SELECT category_id AS cat_id, name, description FROM category WHERE category_id IN (SELECT category_id FROM category_area WHERE area_id = %d)" % int(area_id)))
return [dict(zip(tuple(row._fields), row)) for row in result.all()]
class AreaAverageMeasurement(Resource):
def get(self, area_id):
with db_connect.connect() as conn:
result = conn.execute(
text("SELECT AVG(value) AS avg FROM measurement WHERE measurement_location IN (SELECT location_id FROM location WHERE location_area = %d)" % int(area_id)))
return result.all()[0]["avg"]
class AreaNumberLocations(Resource):
def get(self, area_id):
with db_connect.connect() as conn:
result = conn.execute(
text("SELECT COUNT(*) AS count FROM location WHERE location_area = %d" % int(area_id)))
return result.all()[0]["count"]
api.add_resource(Areas, '/area')
api.add_resource(AreaLocations, '/area/<area_id>/location')
api.add_resource(LocationMeasurements, '/location/<loc_id>/measurement')
api.add_resource(AreaCategories, '/area/<area_id>/category')
api.add_resource(AreaAverageMeasurement, '/area/<area_id>/average_measurement')
api.add_resource(AreaNumberLocations, '/area/<area_id>/number_locations')
if __name__ == '__main__':
app.run(port=SERVER_PORT)