archive/SmearcarDB/server.py

355 lines
12 KiB
Python
Raw Normal View History

2018-01-16 14:13:19 -05:00
from flask import Flask
from flask import render_template, jsonify, request
2018-01-28 23:27:09 -05:00
from flask_sqlalchemy import SQLAlchemy
2018-05-25 19:30:45 -04:00
from numpy.polynomial.polynomial import polyfit
from numpy import corrcoef
import numpy as np
import tkinter
import matplotlib.pyplot as plt
2018-04-28 23:04:34 -04:00
from flask import send_file
2018-04-16 21:41:01 -04:00
import datetime
2018-04-28 19:40:30 -04:00
import os
2018-05-27 01:55:30 -04:00
from scipy import stats
2018-01-21 16:39:19 -05:00
2018-01-16 14:13:19 -05:00
app = Flask(__name__)
2018-01-28 23:27:09 -05:00
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config.update(
DEBUG=True,
TEMPLATES_AUTO_RELOAD=True
)
2018-01-28 23:27:09 -05:00
db = SQLAlchemy(app)
2018-04-28 21:48:37 -04:00
working_dir = os.path.dirname(__file__)
2018-01-28 23:27:09 -05:00
class Frequency(db.Model):
language_id = db.Column(db.Integer, db.ForeignKey('language.id'), primary_key=True)
phoneme_id = db.Column(db.Integer, db.ForeignKey('phoneme.id'), primary_key=True)
value = db.Column(db.Float(6), nullable=False)
phoneme = db.relationship('Phoneme')
class Language(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(100), nullable=False)
2018-04-19 21:24:00 -04:00
# source = db.Column(db.LargeBinary)
2018-01-28 23:27:09 -05:00
phonemes = db.relationship('Frequency')
class Phoneme(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
2018-01-29 16:35:37 -05:00
name = db.Column(db.String(5), nullable=False, unique=True)
2018-01-28 23:27:09 -05:00
class Update(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
author = db.Column(db.String(30), nullable=False)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
date = db.Column(db.DateTime, nullable=False,
default=datetime.datetime.now())
2018-02-05 21:22:12 -05:00
class Editor(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
authority = db.Column(db.Integer, nullable=False, default=1)
# 0: Full Access
2018-04-16 20:01:05 -04:00
# 1: Below + create Updates
# 2: Edit values and Add files
2018-02-05 21:22:12 -05:00
# 3: No Access
2018-04-16 20:01:05 -04:00
username = db.Column(db.String(32), nullable=False)
password = db.Column(db.String(32), nullable=False)
2018-02-05 21:22:12 -05:00
2018-05-25 19:30:45 -04:00
def rand_jitter(arr):
stdev = .01*(max(arr)-min(arr))
return arr + np.random.randn(len(arr)) * stdev
2018-05-27 01:55:30 -04:00
def uniqueness(title="Figure 1"):
2018-05-25 19:30:45 -04:00
x = []
y = []
languages = Language.query.all()
for phoneme in Phoneme.query.all():
frequencies = Frequency.query.filter_by(phoneme_id=phoneme.id).all()
values = [x.value for x in frequencies]
x.append(len(frequencies) / len(languages))
y.append(sum(values) / len(frequencies))
print(corrcoef(x, y))
b, m = polyfit(x, y, 1)
plt.scatter(rand_jitter(x), y, s=7)
bestfit = [b + m * number for number in x]
plt.plot(x, bestfit, '-')
plt.xlabel("Phoneme Presence in Studied Languages")
plt.ylabel("Average Frequency / %")
2018-05-27 01:55:30 -04:00
plt.title(title)
2018-05-25 19:30:45 -04:00
plt.show()
def phoneme_rank(scatter=False, detail=1000, textOutput=False, title="Figure 2"):
speakers = {
'Spanish (Castillian)': 46.4,
'English (American)': 308.9,
'Spanish (American)': 435.7,
'Japanese': 128,
'German': 76,
'Arabic': 315,
'Mandarin': 909,
'Portuguese (Brazilian)': 194,
'French': 76.8,
'Hindi': 260,
'Polish': 40.3,
'Samoan': 0.40742,
'Kaiwa': 0.0021,
'Bengali': 243,
'Swedish': 12.8,
'Malay': 60.7,
'Italian': 64.8
}
2018-05-29 00:16:19 -04:00
total = sum(speakers.values())
calculation = sorted([(phoneme.name, sum([frequency.value * speakers[Language.query.filter_by(id=frequency.language_id).first().name] / (total * len(Language.query.filter_by(name=Language.query.filter_by(id=frequency.language_id).first().name).all()) ) for frequency in Frequency.query.filter_by(phoneme_id=phoneme.id).all()])) for phoneme in Phoneme.query.limit(detail).all()], key=lambda x:-x[1])
2018-05-25 19:30:45 -04:00
labels, data = zip(*calculation)
if textOutput:
return labels
if scatter:
plt.yscale("log")
plt.plot(range(len(data)), data)
else:
plt.bar(range(len(data)), data)
plt.xlabel("Phoneme Rank")
plt.ylabel("Frequency weighted by Number of Speakers / %")
plt.title(title)
plt.show()
def phoible_compare():
# lang_id = Language.query.filter_by(name=lang).first().id
with open("phoible", "r") as f:
phoible = f.read().splitlines()
phonemes = [phoneme.name for phoneme in Phoneme.query.all()]
return [x for x in phoible if x in phonemes]
2018-02-05 21:22:12 -05:00
2018-05-27 01:55:30 -04:00
def rank_compare(textOutput=True, title="Rank Comparison"):
phoible = phoible_compare()
original = phoneme_rank(textOutput=True)
2018-05-27 01:55:30 -04:00
phoible_ranks = list(range(len(phoible)+1))[1:]
original_ranks = [original.index(phoneme) + 1 for phoneme in phoible]
if textOutput:
return {"kendall": stats.kendalltau(phoible_ranks, original_ranks),
"spearman": stats.spearmanr(phoible_ranks, original_ranks),
"wilcoxon": stats.wilcoxon(phoible_ranks, original_ranks, zero_method="pratt")}
plt.scatter(phoible_ranks, original_ranks)
plt.xlabel("Phoible Rank")
plt.ylabel("Weighted Rank")
plt.title(title)
plt.show()
2018-01-28 23:27:09 -05:00
def database():
final = {'values': []}
2018-04-15 23:47:12 -04:00
final['languages'] = [f.name for f in Language.query.order_by(Language.name).all()]
2018-01-28 23:27:09 -05:00
final['phonemes'] = [f.name for f in Phoneme.query.all()]
2018-04-15 23:47:12 -04:00
for language in Language.query.order_by(Language.name).all():
2018-02-24 23:00:18 -05:00
languageobject = {'id': language.id,
'name': language.name,
2018-04-19 21:33:09 -04:00
# 'source': language.source,
2018-01-28 23:27:09 -05:00
'phonemes': {}}
for frequency in language.phonemes:
languageobject['phonemes'][frequency.phoneme.name] = frequency.value
final['values'].append(languageobject)
return final
2018-01-16 14:13:19 -05:00
2018-04-16 20:01:05 -04:00
def check_privelege(doer, privelege):
if Editor.query.filter_by(username=doer['username'], password=doer['password']).first().authority <= privelege:
return True
else:
return False
2018-01-29 16:35:37 -05:00
def phoneme_add(info):
"""Add or edit value associated with phoneme."""
# info = {
# language_id: language_id,
# phoneme: phoneme_name,
# value: phoneme_value
# }
phoneme = Phoneme.query.filter_by(name=info['phoneme']).first()
language = Language.query.filter_by(id=info['language_id']).first()
2018-05-25 19:30:45 -04:00
if not phoneme:
phoneme = Phoneme(name=info['phoneme'])
db.session.add(phoneme)
2018-04-28 22:39:38 -04:00
link = Frequency.query.filter_by(
language_id=language.id,
phoneme_id=phoneme.id).first()
2018-05-25 19:30:45 -04:00
if not link:
2018-01-29 16:35:37 -05:00
link = Frequency(value=info['value'])
link.phoneme = phoneme
language.phonemes.append(link)
2018-05-25 19:30:45 -04:00
db.session.add(link)
else:
link.value = info['value']
2018-01-29 16:35:37 -05:00
def phoneme_remove(info):
"""Remove a phoneme from a language."""
# info = {
# language_id: language_id,
2018-04-15 22:03:14 -04:00
# phoneme: phoneme_name
2018-01-29 16:35:37 -05:00
# }
2018-04-15 22:03:14 -04:00
phoneme = Phoneme.query.filter_by(name=info['phoneme']).first()
language = Language.query.filter_by(id=info['language_id']).first()
frequency = Frequency.query.filter_by(
2018-04-15 22:03:14 -04:00
phoneme_id=phoneme.id, language_id=info['language_id']).first()
2018-04-15 22:03:14 -04:00
if Frequency.query.filter_by(phoneme_id=phoneme.id).count() == 1:
# Delete phoneme
db.session.delete(phoneme)
language.phonemes = [frequency for frequency in language.phonemes
2018-04-15 22:03:14 -04:00
if frequency.phoneme_id != phoneme.id]
db.session.delete(frequency)
def language_name_edit(info):
"""Edit the name of a Language."""
# info = {
# language_id: language_id,
# language_name: name
# }
2018-02-05 21:22:12 -05:00
language = Language.query.filter_by(id=info['language_id']).first()
language.name = info['language_name']
2018-01-29 16:35:37 -05:00
2018-04-19 21:13:03 -04:00
# def language_source_add(info):
# """Add or replace a source"""
# # info = {
# # language_id: language_id,
# # language_source = source
# # }
# language = Language.query.filter_by(id=info['language_id']).first()
# language.source = info['language_source']
patch_functions = {
"phoneme_add": phoneme_add, # Add and edit value
"phoneme_remove": phoneme_remove, # Remove association and/or phoneme
"language_name_edit": language_name_edit, # Change language name
2018-04-19 21:13:03 -04:00
# "language_source_add": language_source_add # Add/edit source
}
2018-01-29 16:35:37 -05:00
2018-01-16 14:13:19 -05:00
# Render the client at the default URL
@app.route("/")
def initial():
return render_template('index.html')
2018-01-28 23:27:09 -05:00
2018-01-29 16:35:37 -05:00
# GET method for files
2018-04-19 21:13:03 -04:00
@app.route("/server/<lang_id>", methods=["GET"])
2018-01-29 16:35:37 -05:00
def file_return(lang_id):
2018-04-28 23:37:28 -04:00
extensions = dict(x.split(".") for x in os.listdir("files/"))
2018-04-19 21:24:00 -04:00
try:
2018-04-28 23:34:45 -04:00
return send_file('files/' + lang_id+"."+extensions[str(lang_id)])
2018-04-19 21:24:00 -04:00
except Exception as e:
return str(e)
2018-01-29 16:35:37 -05:00
2018-04-19 21:13:03 -04:00
# POST files
@app.route("/source", methods=["POST"])
def source_add():
"""Add or replace a source"""
2018-04-28 19:40:30 -04:00
if check_privelege({
"username": request.form["username"],
"password": request.form["password"]
}, 2):
2018-04-19 21:14:43 -04:00
f = request.files['file']
2018-04-28 23:34:45 -04:00
write_path = os.path.join(working_dir, "files", request.form['lang_id']+"."+f.filename.split(".")[-1])
2018-04-28 21:48:37 -04:00
# with open(write_path, 'w') as a:
# a.write()
f.save(write_path)
2018-04-19 21:13:03 -04:00
return "nice"
2018-04-28 19:40:30 -04:00
2018-04-19 21:13:03 -04:00
return "Error"
2018-01-29 16:35:37 -05:00
2018-04-19 21:13:03 -04:00
# Add and Edit data
2018-01-21 16:39:19 -05:00
@app.route("/server", methods=["GET", "POST", "PATCH"])
2018-01-16 14:13:19 -05:00
def backend():
2018-01-29 16:35:37 -05:00
# # GET method returns the latest database
# if request.method == "GET":
# return jsonify(database())
2018-01-16 14:13:19 -05:00
2018-01-21 16:41:27 -05:00
# POST method appends input to database['values']
2018-04-16 20:01:05 -04:00
2018-01-29 16:35:37 -05:00
if request.method == "POST":
2018-02-24 23:00:18 -05:00
received = request.get_json()
2018-04-16 20:01:05 -04:00
if check_privelege(received['editor'], 2):
2018-04-28 19:40:30 -04:00
language = Language(name=received['name'])
2018-04-16 20:01:05 -04:00
db.session.add(language)
for phoneme, value in received['phonemes'].items():
with db.session.no_autoflush:
search = Phoneme.query.filter_by(name=phoneme).first()
if not search:
search = Phoneme(name=phoneme)
db.session.add(search)
link = Frequency(value=value, phoneme=search)
language.phonemes.append(link)
db.session.add(link)
db.session.commit()
2018-01-29 16:35:37 -05:00
# return jsonify(database())
2018-01-28 23:27:09 -05:00
2018-01-29 16:35:37 -05:00
# PATCH method inputs edited language and returns updated database
elif request.method == "PATCH":
2018-02-24 23:00:18 -05:00
received = request.get_json()
2018-04-16 20:01:05 -04:00
if check_privelege(received['editor'], 2):
patch_functions[received['action']](received['data'])
db.session.commit()
2018-01-29 16:35:37 -05:00
return jsonify(database())
2018-01-28 23:27:09 -05:00
2018-01-16 14:13:19 -05:00
# Manipulate Updates
@app.route("/updates", methods=["GET", "POST", "PATCH"])
def updates():
2018-01-31 17:12:54 -05:00
if request.method == "POST":
2018-02-24 23:00:18 -05:00
received = request.get_json()
2018-04-16 20:01:05 -04:00
if check_privelege(received['editor'], 1):
update = Update(author=received['author'],
title=received['title'],
content=received['content'])
db.session.add(update)
2018-01-31 17:12:54 -05:00
elif request.method == "PATCH":
2018-02-24 23:00:18 -05:00
received = request.get_json()
2018-04-16 20:01:05 -04:00
if check_privelege(received['editor'], 1):
update = Update.query.filter_by(id=received['id']).first()
update.name = received['author']
update.title = received['title']
update.content = received['content']
2018-01-31 17:12:54 -05:00
db.session.commit()
return jsonify([{"author": update.author,
"id": update.id,
"title": update.title,
"content": update.content,
"date": update.date.strftime("%m/%d/%Y | %A, %B %d, %Y")}
for update in Update.query.all()])
2018-04-16 20:01:05 -04:00
# Manipulate Editor
@app.route("/editors", methods=["POST"])
def editors():
if request.method == "POST":
received = request.get_json()
2018-04-16 22:50:11 -04:00
if Editor.query.filter_by(username=received['username']).count() == 0 and check_privelege(received['editor'], 0):
2018-04-16 20:54:58 -04:00
user = Editor(authority = received['authority'],
username = received['username'],
password = received['password'])
2018-04-16 20:47:36 -04:00
db.session.add(user)
db.session.commit()
2018-04-16 22:50:11 -04:00
return "Success"
2018-04-16 20:01:05 -04:00
else:
return "Bad Request"
else:
return "Bad Request"
2018-01-31 17:12:54 -05:00
2018-04-16 22:52:28 -04:00
if __name__ == "__main__":
app.run(host="0.0.0.0")