Add level
This commit is contained in:
parent
a760e2fabc
commit
3e80e68da7
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
venv
|
venv
|
||||||
config.py
|
config.py
|
||||||
__pycache__
|
__pycache__
|
||||||
data/
|
src_audio/
|
27
app.py
27
app.py
@ -62,17 +62,29 @@ def home():
|
|||||||
@app.route("/signup", methods=["GET", "POST"])
|
@app.route("/signup", methods=["GET", "POST"])
|
||||||
def signup():
|
def signup():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
message = ""
|
||||||
username = request.form['username']
|
username = request.form['username']
|
||||||
|
if username == "":
|
||||||
|
message += gettext("Username empty. Try to find one.")
|
||||||
email = request.form['email']
|
email = request.form['email']
|
||||||
|
if email == "":
|
||||||
|
message += gettext("Email empty. Please give me one.")
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
registered_user = User.query.filter_by(user_name=username).first()
|
if password == "":
|
||||||
if registered_user is None:
|
message += gettext("You should not use an empty password")
|
||||||
|
registered_user_by_username = User.query.filter_by(user_name=username).first()
|
||||||
|
registered_user_by_email = User.query.filter_by(user_email=email).first()
|
||||||
|
if registered_user_by_username is None and registered_user_by_email is None:
|
||||||
password_hash = generate_password_hash(password)
|
password_hash = generate_password_hash(password)
|
||||||
registered_user = User(user_name=username, user_email=email, user_password=password_hash)
|
registered_user = User(user_name=username, user_email=email, user_password=password_hash)
|
||||||
db.session.add(registered_user)
|
db.session.add(registered_user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
return render_template("auth/signup.html", message="Username already used. Try with an other.")
|
if not registered_user_by_email is None:
|
||||||
|
message += gettext("Email already used by a user.")
|
||||||
|
else:
|
||||||
|
message += gettext("Username already used by a user.")
|
||||||
|
return render_template("auth/signup.html", message=message)
|
||||||
return redirect(url_for("login"))
|
return redirect(url_for("login"))
|
||||||
elif request.method == "GET":
|
elif request.method == "GET":
|
||||||
return render_template("auth/signup.html")
|
return render_template("auth/signup.html")
|
||||||
@ -109,7 +121,14 @@ def game():
|
|||||||
|
|
||||||
@app.route("/game/new")
|
@app.route("/game/new")
|
||||||
def new_game():
|
def new_game():
|
||||||
question = Game.new_question()
|
if not "username" in session:
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
user = User.query.filter_by(user_name = session['username']).first()
|
||||||
|
if user is None:
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
else:
|
||||||
|
level = str(user.user_level)
|
||||||
|
question = Game.new_question(level)
|
||||||
session["question"] = question
|
session["question"] = question
|
||||||
return render_template("game/question.html", question=question)
|
return render_template("game/question.html", question=question)
|
||||||
|
|
||||||
|
120
data/level_species_cleaned.json
Normal file
120
data/level_species_cleaned.json
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
{
|
||||||
|
"1": [
|
||||||
|
"Buse variable",
|
||||||
|
"Merle noir",
|
||||||
|
"Pic vert",
|
||||||
|
"Rougegorge familier",
|
||||||
|
"Mouette rieuse",
|
||||||
|
"Canard colvert",
|
||||||
|
"Pinson des arbres",
|
||||||
|
"Moineau domestique",
|
||||||
|
"Pie bavarde",
|
||||||
|
"Corneille noire",
|
||||||
|
"Faisan de Colchide"
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"Grive draine",
|
||||||
|
"Grande Aigrette",
|
||||||
|
"Grand Cormoran",
|
||||||
|
"Foulque macroule",
|
||||||
|
"Hirondelle rustique",
|
||||||
|
"Fauvette grisette",
|
||||||
|
"Troglodyte mignon",
|
||||||
|
"Bergeronnette grise",
|
||||||
|
"Choucas des tours",
|
||||||
|
"Pigeon ramier",
|
||||||
|
"Rougequeue noir",
|
||||||
|
"Tourterelle turque"
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"Aigrette garzette",
|
||||||
|
"Grive litorne",
|
||||||
|
"Accenteur mouchet",
|
||||||
|
"Bernache du Canada",
|
||||||
|
"Pipit farlouse",
|
||||||
|
"Tourterelle des bois",
|
||||||
|
"Sittelle torchepot",
|
||||||
|
"Alouette des champs",
|
||||||
|
"Coucou gris",
|
||||||
|
"Corbeau freux",
|
||||||
|
"Martinet noir",
|
||||||
|
"Bruant zizi"
|
||||||
|
],
|
||||||
|
"4": [
|
||||||
|
"Grimpereau des jardins",
|
||||||
|
"Grive musicienne",
|
||||||
|
"Bruant jaune",
|
||||||
|
"Bergeronnette des ruisseaux",
|
||||||
|
"Sterne pierregarin",
|
||||||
|
"Bruant des roseaux",
|
||||||
|
"Milan noir",
|
||||||
|
"Grand Corbeau",
|
||||||
|
"Fuligule morillon"
|
||||||
|
],
|
||||||
|
"5": [
|
||||||
|
"Gobemouche gris",
|
||||||
|
"Cigogne blanche",
|
||||||
|
"Alouette lulu",
|
||||||
|
"Grive mauvis",
|
||||||
|
"Tarin des aulnes",
|
||||||
|
"Chouette hulotte",
|
||||||
|
"Traquet motteux",
|
||||||
|
"Milan royal",
|
||||||
|
"Monticole bleu",
|
||||||
|
"Canard chipeau"
|
||||||
|
],
|
||||||
|
"6": [
|
||||||
|
"Fuligule milouin",
|
||||||
|
"Chevalier guignette",
|
||||||
|
"Bouscarle de Cetti",
|
||||||
|
"Tadorne de Belon",
|
||||||
|
"Cisticole des joncs",
|
||||||
|
"Pic noir",
|
||||||
|
"Nette rousse",
|
||||||
|
"Petit Gravelot",
|
||||||
|
"Fauvette des jardins",
|
||||||
|
"Serin cini"
|
||||||
|
],
|
||||||
|
"7": [
|
||||||
|
"Pic mar",
|
||||||
|
"Perdrix grise",
|
||||||
|
"Pinson du Nord",
|
||||||
|
"Bruant proyer",
|
||||||
|
"Phragmite des joncs",
|
||||||
|
"Rousserolle effarvatte",
|
||||||
|
"Pouillot fitis",
|
||||||
|
"Faucon hobereau"
|
||||||
|
],
|
||||||
|
"8": [
|
||||||
|
"Fauvette pitchou",
|
||||||
|
"Busard des roseaux",
|
||||||
|
"Canard mandarin",
|
||||||
|
"Spatule blanche",
|
||||||
|
"Bernache nonnette",
|
||||||
|
"Torcol fourmilier",
|
||||||
|
"Effraie des clochers",
|
||||||
|
"Sittelle corse",
|
||||||
|
"Perdrix rouge",
|
||||||
|
"Hirondelle de rochers",
|
||||||
|
"Hirondelle de rivage"
|
||||||
|
],
|
||||||
|
"9": [
|
||||||
|
"Moineau friquet",
|
||||||
|
"Bernache cravant",
|
||||||
|
"Plongeon imbrin",
|
||||||
|
"Fuligule nyroca",
|
||||||
|
"Pigeon colombin",
|
||||||
|
"Grimpereau des bois"
|
||||||
|
],
|
||||||
|
"10": [
|
||||||
|
"Petit-duc scops",
|
||||||
|
"Chevalier sylvain",
|
||||||
|
"Chevalier gambette",
|
||||||
|
"Pipit spioncelle",
|
||||||
|
"Canard souchet",
|
||||||
|
"Accenteur alpin",
|
||||||
|
"Sterne naine",
|
||||||
|
"Chevalier aboyeur",
|
||||||
|
"Gobemouche noir"
|
||||||
|
]
|
||||||
|
}
|
22
game.py
22
game.py
@ -1,31 +1,33 @@
|
|||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
import json
|
||||||
|
|
||||||
bird_species_folders = list(map(os.path.basename, glob("static/data/src_audio/*")))
|
with open("./data/level_species_cleaned.json", "r") as f:
|
||||||
|
LEVEL_SPECIES_LIST = json.load(f)
|
||||||
|
|
||||||
format_name = lambda folder_name : folder_name.replace('_', ' ')
|
format_name = lambda folder_name : folder_name.replace('_', ' ')
|
||||||
|
to_folder_name = lambda species_name : species_name.replace(' ', '_').replace('\'', '').lower()
|
||||||
|
|
||||||
def get_proposals(question_species_name, n):
|
def get_proposals(question_species_name, available_species, n):
|
||||||
proposals = [question_species_name]
|
proposals = [question_species_name]
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
proposition = format_name(random.choice(bird_species_folders))
|
proposition = random.choice(available_species)
|
||||||
while proposition == question_species_name:
|
while proposition == question_species_name:
|
||||||
proposition = format_name(random.choice(bird_species_folders))
|
proposition = random.choice(available_species)
|
||||||
proposals.append(proposition)
|
proposals.append(proposition)
|
||||||
random.shuffle(proposals)
|
random.shuffle(proposals)
|
||||||
return proposals
|
return proposals
|
||||||
|
|
||||||
def new_question():
|
def new_question(level):
|
||||||
question_species_folder = random.choice(bird_species_folders)
|
available_species = LEVEL_SPECIES_LIST[level]
|
||||||
question_species_name = format_name(question_species_folder)
|
question_species_name = random.choice(available_species)
|
||||||
print(question_species_folder)
|
question_species_folder = to_folder_name(question_species_name)
|
||||||
question = {}
|
question = {}
|
||||||
audio_paths = list(map(os.path.basename, glob(f"static/data/src_audio/{question_species_folder}/*.mp3")))
|
audio_paths = list(map(os.path.basename, glob(f"static/data/src_audio/{question_species_folder}/*.mp3")))
|
||||||
print(audio_paths)
|
|
||||||
audio_path = random.choice(audio_paths)
|
audio_path = random.choice(audio_paths)
|
||||||
question["species"] = question_species_name
|
question["species"] = question_species_name
|
||||||
question["species_folder"] = question_species_folder
|
question["species_folder"] = question_species_folder
|
||||||
question["audio_path"] = audio_path
|
question["audio_path"] = audio_path
|
||||||
question["proposals"] = get_proposals(question_species_name, 5)
|
question["proposals"] = get_proposals(question_species_name, available_species, 5)
|
||||||
return question
|
return question
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<audio src="/static/data/src_audio/{{ question['species_folder'] }}/{{ question['audio_path'] }}" controls></audio>
|
<audio src="/static/data/src_audio/{{ question['species_folder'] }}/{{ question['audio_path'] }}" controls autoplay></audio>
|
||||||
<form action="/game/answer" method="POST">
|
<form action="/game/answer" method="POST">
|
||||||
<select name="answer" id="answer">
|
<select name="answer" id="answer">
|
||||||
{% for item in question['proposals'] %}
|
{% for item in question['proposals'] %}
|
||||||
|
33
utils/convert_levels.py
Normal file
33
utils/convert_levels.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Update levels species folowing the folder names"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
|
||||||
|
SPECIES_FOLDER_NAMES = list(map(os.path.basename, glob.glob("./static/data/src_audio/*")))
|
||||||
|
|
||||||
|
def filter(species, condition):
|
||||||
|
keeped = []
|
||||||
|
for name in species:
|
||||||
|
if condition(name):
|
||||||
|
keeped.append(name)
|
||||||
|
return keeped
|
||||||
|
|
||||||
|
def only_matched_folder(species_name):
|
||||||
|
folder_like_name = species_name.replace(' ', '_').replace('\'', '')
|
||||||
|
folder_like_name = folder_like_name.lower()
|
||||||
|
return folder_like_name in SPECIES_FOLDER_NAMES
|
||||||
|
|
||||||
|
def main():
|
||||||
|
with open("./data/level_species.json", "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
for level in data:
|
||||||
|
species_list = data[level]
|
||||||
|
species_list = filter(species_list, only_matched_folder)
|
||||||
|
data[level] = species_list
|
||||||
|
with open("./data/level_species_cleaned.json", "w") as f:
|
||||||
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
46
utils/generate_levels.py
Normal file
46
utils/generate_levels.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Generate species list for each levels"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
|
||||||
|
LEVELS = 10
|
||||||
|
|
||||||
|
def load_species_sightings(file):
|
||||||
|
species_sightings = {}
|
||||||
|
with open(file, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
sightings = data['data']['sightings']
|
||||||
|
counter = 0
|
||||||
|
for sighting in sightings:
|
||||||
|
species = sighting["species"]["name"]
|
||||||
|
if species in species_sightings:
|
||||||
|
species_sightings[species] += 1
|
||||||
|
else:
|
||||||
|
species_sightings[species] = 1
|
||||||
|
counter += 1
|
||||||
|
for species in species_sightings:
|
||||||
|
species_sightings[species] /= counter * 0.01
|
||||||
|
return species_sightings
|
||||||
|
|
||||||
|
def split_species_list(species_sightings):
|
||||||
|
level_lists = { level: [] for level in range(1, LEVELS + 1)}
|
||||||
|
species_sorted = sorted(species_sightings, key = lambda species: -species_sightings[species])
|
||||||
|
species_number = len(species_sorted)
|
||||||
|
species_per_level = species_number // LEVELS
|
||||||
|
species_splitted = [species_sorted[i:i+species_per_level] for i in range(0, species_number, species_per_level)]
|
||||||
|
for level in range(1, LEVELS + 1):
|
||||||
|
level_lists[level] = species_splitted[level - 1]
|
||||||
|
return level_lists
|
||||||
|
|
||||||
|
def main():
|
||||||
|
file = "./data/export_26052022_150619.json"
|
||||||
|
species_frequency = load_species_sightings(file)
|
||||||
|
level_species = split_species_list(species_frequency)
|
||||||
|
with open("./data/level_species.json", "w") as f:
|
||||||
|
json.dump(level_species, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
x
Reference in New Issue
Block a user