Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def create_app(config_name):
root = CONFIG[config_name].APPLICATION_ROOT

# flask migrate doesn't recognize the tables without this import
from app.models import Application, Genre, ApplicationType
from app.models import Application, Genre, ApplicationType, Session, Questionnaire

# Set up extensions
db.init_app(app)
Expand All @@ -33,4 +33,10 @@ def create_app(config_name):
from app.routes.v1 import application as application_blueprint
app.register_blueprint(application_blueprint, url_prefix=root + '/application')

from app.routes.v1 import session as session_blueprint
app.register_blueprint(session_blueprint, url_prefix=root + '/session')

from app.routes.v1 import questionnaire as questionnaire_blueprint
app.register_blueprint(questionnaire_blueprint, url_prefix=root + '/questionnaire')

return app
2 changes: 2 additions & 0 deletions app/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
from .application import * # noqa
from .application_type import * # noqa
from .genre import * # noqa
from .session import * # noqa
from .questionnaire import * # noqa
17 changes: 14 additions & 3 deletions app/models/application.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from marshmallow import fields, validate
from .application_type import ApplicationTypeSchema
from .genre import GenreSchema
from .. import db, ma


Expand All @@ -13,17 +15,26 @@ class Application(db.Model):
description = db.Column(db.String(250), nullable=False)
creation_date = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), nullable=False)
genre_id = db.Column(db.Integer, db.ForeignKey('genre.id', use_alter=True, name='fk_genre_id'), nullable=False)
sessions = db.relationship('Session', backref='app', lazy='dynamic')

def __init__(self, name, identifier, developer, type, description, genre):
self.name = name
self.identifier = identifier
self.developer = developer
self.type = type
self.description = description
self.genre = genre

def __repr__(self):
return self.name
return '<Application %r>' % self.id


class ApplicationSchema(ma.Schema):
id = fields.Integer(dump_only=True)
name = fields.String(required=True, validate=validate.Length(1, 100))
identifier = fields.String()
developer = fields.String(required=True, validate=validate.Length(1, 100))
type = fields.String(required=True)
type = fields.Nested(ApplicationTypeSchema, dump_only=True)
description = fields.String(required=True, validate=validate.Length(1, 250))
creation_date = fields.DateTime()
genre = fields.String(required=True)
genre = fields.Nested(GenreSchema, dump_only=True)
7 changes: 6 additions & 1 deletion app/models/application_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ class ApplicationType(db.Model):
display_name_full = db.Column(db.String(250), nullable=False)
applications = db.relationship('Application', backref='type', lazy='dynamic')

def __init__(self, name, display_name, display_name_full):
self.name = name
self.display_name = display_name
self.display_name_full = display_name_full

@classmethod
def seed(cls):
if cls.is_table_empty(cls):
Expand All @@ -41,7 +46,7 @@ def is_table_empty(self):
return False

def __repr__(self):
return self.display_name_full
return '<ApplicationType %r>' % self.id


class ApplicationTypeSchema(ma.Schema):
Expand Down
6 changes: 5 additions & 1 deletion app/models/genre.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class Genre(db.Model):
display_name = db.Column(db.String(250), nullable=False)
applications = db.relationship('Application', backref='genre', lazy='dynamic')

def __init__(self, name, display_name):
self.name = name
self.display_name = display_name

@classmethod
def seed(cls):
if cls.is_table_empty(cls):
Expand All @@ -40,7 +44,7 @@ def is_table_empty(self):
return False

def __repr__(self):
return self.display_name
return '<Genre %r>' % self.id


class GenreSchema(ma.Schema):
Expand Down
32 changes: 32 additions & 0 deletions app/models/questionnaire.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from marshmallow import fields, validate
from .. import db, ma


class Questionnaire(db.Model):
__tablename__ = 'questionnaire'

id = db.Column(db.Integer, primary_key=True)
pre = db.Column(db.JSON, nullable=False)
post = db.Column(db.JSON, nullable=False, default={})
creation_date = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), nullable=False)
session = db.relationship("Session", uselist=False, backref="questionnaire")

def __init__(self, pre, post):
self.pre = pre
self.post = post

def __repr__(self):
return '<Questionnaire %r>' % self.id


class SymptomSchema(ma.Schema):
name = fields.String(required=False)
display_name = fields.String(required=False)
score = fields.String(required=False)


class QuestionnaireSchema(ma.Schema):
id = fields.Integer(dump_only=True)
pre = fields.List(fields.Nested(SymptomSchema), dump_only=True)
post = fields.List(fields.Nested(SymptomSchema), dump_only=True)
creation_date = fields.DateTime()
37 changes: 37 additions & 0 deletions app/models/session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from marshmallow import fields, validate
from .. import db, ma
from .application import ApplicationSchema
from .questionnaire import QuestionnaireSchema


class Session(db.Model):
__tablename__ = 'session'

id = db.Column(db.Integer, primary_key=True)
app_id = db.Column(db.Integer, db.ForeignKey('application.id', use_alter=True, name='fk_app_id'), nullable=False)
creation_date = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), nullable=False)
expected_emotions = db.Column(db.JSON, nullable=False)
questionnaire_id = db.Column(db.Integer, db.ForeignKey('questionnaire.id', use_alter=True, name='fk_questionnaire_id'), nullable=False)
cssi_score = db.Column(db.Float, nullable=False, default=0)
latency_scores = db.Column(db.JSON, nullable=False, default={})
total_latency_score = db.Column(db.Float, nullable=False, default=0)
sentiment_scores = db.Column(db.JSON, nullable=False, default={})
total_sentiment_score = db.Column(db.Float, nullable=False, default=0)
questionnaire_scores = db.Column(db.JSON, nullable=True, default={})
total_questionnaire_score = db.Column(db.Float, nullable=False, default=0)

def __init__(self, app, expected_emotions, questionnaire):
self.app = app
self.expected_emotions = expected_emotions
self.questionnaire = questionnaire

def __repr__(self):
return '<Session %r>' % self.id


class SessionSchema(ma.Schema):
id = fields.Integer(dump_only=True)
creation_date = fields.DateTime()
expected_emotions = fields.List(fields.String(), dump_only=True)
app = fields.Nested(ApplicationSchema, dump_only=True)
questionnaire = fields.Nested(QuestionnaireSchema, dump_only=True)
2 changes: 2 additions & 0 deletions app/routes/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
from app.routes.v1.application import application # noqa
from app.routes.v1.main import main # noqa
from app.routes.v1.session import session # noqa
from app.routes.v1.questionnaire import questionnaire # noqa
12 changes: 6 additions & 6 deletions app/routes/v1/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def get_application(id):
@application.route('/', methods=['POST'])
def create_application():
"""Create a new Application"""

json_data = request.get_json(force=True)

if not json_data:
Expand All @@ -55,14 +56,13 @@ def create_application():
if errors:
return jsonify({'status': 'error', 'message': 'Incorrect format of data provided.', 'data': errors}), 422

name = data['name']
name = request.json['name']
identifier = str(uuid.uuid4().hex)
developer = data['developer']
type = ApplicationType.query.filter_by(name=data['type']).first()
description = data['description']
genre = Genre.query.filter_by(name=data['genre']).first()
developer = request.json['developer']
type = ApplicationType.query.filter_by(id=request.json['type']).first()
description = request.json['description']
genre = Genre.query.filter_by(id=request.json['genre']).first()

print(identifier)
# validate application type
if not type:
return {'status': 'error', 'message': 'Invalid Application Type'}, 400
Expand Down
58 changes: 58 additions & 0 deletions app/routes/v1/questionnaire.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# (c) Copyright 2019 Brion Mario.
# (c) This file is part of the CSSI REST API and is made available under MIT license.
# (c) For more information, see https://github.com/brionmario/cssi-api/blob/master/LICENSE.txt
# (c) Please forward any queries to the given email address. email: brion@apareciumlabs.com

"""Application routes module

This modules contains all the different routes to interact with applications.

Authors:
Brion Mario

"""

import uuid
from flask import Blueprint, jsonify, request
from app.models import Questionnaire, ApplicationType, QuestionnaireSchema, Genre
from app import db

questionnaire = Blueprint('questionnaire', __name__)

questionnaire_schema = QuestionnaireSchema(strict=True)
questionnaires_schema = QuestionnaireSchema(many=True, strict=True)


@questionnaire.route('/', methods=['GET'])
def get_questionnaire_list():
"""Get a list of all the Questionnaire"""
questionnaires = Questionnaire.query.all()
result = questionnaires_schema.dump(questionnaires).data
return jsonify({'status': 'success', 'message': None, 'data': result}), 200


@questionnaire.route('/<int:id>', methods=['GET'])
def get_questionnaire(id):
"""Get questionnaire when an id is passed in"""
questionnaire = Questionnaire.query.get(id)
result = questionnaire_schema.dump(questionnaire).data
return jsonify({'status': 'success', 'message': None, 'data': result}), 200


@questionnaire.route('/', methods=['POST'])
def create_questionnaire():
"""Create a new Questionnaire"""
pre = request.json['pre']
post = request.json['post']

new_questionnaire = Questionnaire(pre=pre, post=post)

db.session.add(new_questionnaire)
db.session.commit()

result = questionnaire_schema.dump(new_questionnaire).data

return jsonify({'status': 'success', 'message': 'Created new questionnaire', 'data': result}), 201
65 changes: 65 additions & 0 deletions app/routes/v1/session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# (c) Copyright 2019 Brion Mario.
# (c) This file is part of the CSSI REST API and is made available under MIT license.
# (c) For more information, see https://github.com/brionmario/cssi-api/blob/master/LICENSE.txt
# (c) Please forward any queries to the given email address. email: brion@apareciumlabs.com

"""Session routes module

This modules contains all the different routes to interact with Sessions.

Authors:
Brion Mario

"""

from flask import Blueprint, jsonify, request
from app.models import Session, SessionSchema, Application, Questionnaire
from app import db

session = Blueprint('session', __name__)

session_schema = SessionSchema(strict=True)
sessions_schema = SessionSchema(many=True, strict=True)


@session.route('/', methods=['GET'])
def get_sessions_list():
"""Get a list of all the sessions"""
sessions = Session.query.all()
result = sessions_schema.dump(sessions).data
return jsonify({'status': 'success', 'message': None, 'data': result}), 200


@session.route('/<int:id>', methods=['GET'])
def get_session(id):
"""Get info on a session when an id is passed in"""
session = Session.query.get(id)
result = sessions_schema.dump(session).data
return jsonify({'status': 'success', 'message': None, 'data': result}), 200


@session.route('/', methods=['POST'])
def create_session():
"""Create a new Session"""

app = Application.query.filter_by(id=request.json['app']).first()
questionnaire = Questionnaire.query.filter_by(id=request.json['questionnaire_id']).first()
expected_emotions = request.json['expected_emotions']

print(questionnaire)

# validate application type
if not app:
return {'status': 'error', 'message': 'Invalid application.'}, 400

new_session = Session(app=app, expected_emotions=expected_emotions, questionnaire=questionnaire)

db.session.add(new_session)
db.session.commit()

result = session_schema.dump(new_session).data

return jsonify({'status': 'success', 'message': 'Created new session for application with id of {}.'.format(request.json['app']), 'data': result}), 201
42 changes: 42 additions & 0 deletions migrations/versions/89ee48680e79_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""empty message

Revision ID: 89ee48680e79
Revises: cb018c771a53
Create Date: 2019-04-16 04:22:10.614121

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = '89ee48680e79'
down_revision = 'cb018c771a53'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_foreign_key('fk_type_id', 'application', 'application_type', ['type_id'], ['id'], use_alter=True)
op.create_foreign_key('fk_genre_id', 'application', 'genre', ['genre_id'], ['id'], use_alter=True)
op.alter_column('questionnaire', 'post',
existing_type=mysql.TEXT(),
nullable=True)
op.drop_column('questionnaire', 'session_id')
op.create_foreign_key('fk_app_id', 'session', 'application', ['app_id'], ['id'], use_alter=True)
op.create_foreign_key('fk_questionnaire_id', 'session', 'questionnaire', ['questionnaire_id'], ['id'], use_alter=True)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('fk_questionnaire_id', 'session', type_='foreignkey')
op.drop_constraint('fk_app_id', 'session', type_='foreignkey')
op.add_column('questionnaire', sa.Column('session_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=False))
op.alter_column('questionnaire', 'post',
existing_type=mysql.TEXT(),
nullable=False)
op.drop_constraint('fk_genre_id', 'application', type_='foreignkey')
op.drop_constraint('fk_type_id', 'application', type_='foreignkey')
# ### end Alembic commands ###
Loading