#!/usr/bin/python # -*- coding: UTF-8 -*- from _collections import defaultdict from uuid import uuid4 import json from flask import Blueprint from flask import session, request, jsonify, current_app import config from const import pfsp import utils from utils.decorator import trainer_has_access from utils.template import my_render_template from MDmisc.RecursiveDefaultDict import edefaultdict, defDict trainer_view = Blueprint( "trainer", __name__, template_folder = "templates" ) @trainer_view.route( "/marks/search" ) @trainer_has_access def search(): """ Provide the search page. """ sql = """ SELECT files.id, files.uuid, mark_info.pfsp, mark_info.detection_technic, mark_info.surface, files.note, submissions.uuid AS submission_uuid, users.username, users.id AS userid FROM files LEFT JOIN mark_info ON mark_info.uuid = files.uuid LEFT JOIN submissions ON files.folder = submissions.id LEFT JOIN users ON submissions.donor_id = users.id WHERE ( files.type = 3 OR files.type = 4 ) ORDER BY files.id ASC """ marks = config.db.query_fetchall( sql ) sql = """ SELECT submissions.uuid AS submissions_uuid, segments_locations.fpc, segments_locations.tenprint_id FROM segments_locations INNER JOIN files ON segments_locations.tenprint_id = files.uuid LEFT JOIN submissions ON files.folder = submissions.id ORDER BY fpc """ ref_list = config.db.query_fetchall( sql ) refs = defDict() for ref in ref_list: refs[ ref[ "submissions_uuid" ] ][ ref[ "fpc" ] ] = ref[ "tenprint_id" ] sql = """ SELECT donor_fingers_gp.donor_id AS id, donor_fingers_gp.fpc, gp.name FROM donor_fingers_gp LEFT JOIN gp ON donor_fingers_gp.gp = gp.id """ donors_gp = config.db.query_fetchall( sql ) all_detection_technics = config.db.query_fetchall( "SELECT * FROM detection_technics ORDER BY name ASC" ) surfaces = config.db.query_fetchall( "SELECT * FROM surfaces ORDER BY name ASC" ) for _, v in enumerate( marks ): for col in [ "detection_technic", "surface", "note" ]: for old, new in [ ( "{", "" ), ( "}", "" ), ( "\n", "; " ) ]: try: v[ col ] = v[ col ].replace( old, new ) except: pass v[ "username" ] = v[ "username" ].replace( "_", " " ) # Current working folder current_exercise_folder = session.get( "current_exercise_folder", "" ) sql = "SELECT * FROM exercises WHERE trainer_id = %s ORDER BY name ASC" all_exercises_list = config.db.query_fetchall( sql, ( session[ "user_id" ], ) ) # PFSP zones to fpc pfsp2fpc = defaultdict( list ) for pfc in xrange( 1, 11 ): for loc in [ "tip", "distal" ]: pfsp2fpc[ "F{}-{}".format( pfc, loc ) ].append( pfc ) pfsp2fpc[ "F1-tip" ].append( 11 ) pfsp2fpc[ "F1-distal" ].append( 11 ) pfsp2fpc[ "F6-tip" ].append( 12 ) pfsp2fpc[ "F6-distal" ].append( 12 ) for fpc in xrange( 2, 6 ): for z in [ "tip", "distal" ]: pfsp2fpc[ "F{}-{}".format( fpc, z ) ].append( 13 ) for fpc in xrange( 6, 11 ): for z in [ "tip", "distal" ]: pfsp2fpc[ "F{}-{}".format( fpc, z ) ].append( 14 ) for side, fpc in [ ( "Right", 25 ), ( "Left", 27 ) ]: for z in [ "grasp", "carpal_delta_area", "wrist_bracelet", "thenar", "hypothenar", "interdigital", "writer_palm" ]: pfsp2fpc[ "{}-{}".format( side, z ) ].append( fpc ) pfsp2fpc[ "Right-writer_palm" ].append( 22 ) pfsp2fpc[ "Left-writer_palm" ].append( 24 ) # PFSP code friendly name pfspdesc = {} n = 1 for laterality in [ "right", "left" ]: for finger in [ "thumb", "index", "middel", "ring", "little" ]: for zone in [ "tip", "distal", "medial", "proximal" ]: pfspdesc[ "F{}-{}".format( n, zone ) ] = "{} {} {}".format( laterality, finger, zone ) n += 1 # PFSP to donor general pattern search pfsp_fpc_search = {} n = 1 for laterality in [ "right", "left" ]: for finger in [ "thumb", "index", "middel", "ring", "little" ]: for zone in [ "tip", "distal" ]: pfsp_fpc_search[ "F{}-{}".format( n, zone ) ] = "{}".format( n ) n += 1 # return my_render_template( "trainer/search.html", marks = marks, refs = refs, donors_gp = donors_gp, current_exercise_folder = current_exercise_folder, all_exercises_list = all_exercises_list, pfsp2fpc = pfsp2fpc, pfspdesc = pfspdesc, pfsp_fpc_search = pfsp_fpc_search, all_detection_technics = all_detection_technics, surfaces = surfaces, all_pfsp = pfsp.zones ) @trainer_view.route( "/exercises/list" ) @trainer_has_access def exercises_list(): if session[ "account_type_name" ] == "Administrator": sql = """ SELECT exercises.*, users.username FROM exercises LEFT JOIN users ON exercises.trainer_id = users.id ORDER BY name ASC """ data = () else: sql = "SELECT * FROM exercises WHERE trainer_id = %s AND active = true ORDER BY name ASC" data = ( session[ "user_id" ], ) ex_list = config.db.query_fetchall( sql, data ) marks_count = {} sql = "SELECT folder AS uuid, count( * ) AS nb FROM exercises_folder GROUP BY folder" for c in config.db.query_fetchall( sql ): marks_count[ c[ "uuid" ] ] = c[ "nb" ] return my_render_template( "trainer/exercises.html", ex_list = ex_list, marks_count = marks_count ) @trainer_view.route( "/exercises/new", methods = [ "POST" ] ) @trainer_has_access def exercises_new(): try: name = request.form.get( "name" ) uuid = str( uuid4() ) trainer_id = session[ "user_id" ] sql = utils.sql.sql_insert_generate( "exercises", [ "name", "uuid", "trainer_id" ], "id" ) config.db.query_fetchone( sql, ( name, uuid, trainer_id, ) ) config.db.commit() return jsonify( { "error": False, "data": uuid } ) except: return jsonify( { "error": True, "msg": "Error while creating the exercises list" } ) @trainer_view.route( "/exercises/rename", methods = [ "POST" ] ) @trainer_has_access def exercises_rename(): try: new_name = request.form.get( "name" ) uuid = request.form.get( "uuid" ) sql = "UPDATE exercises SET name = %s WHERE uuid = %s AND trainer_id = %s" config.db.query( sql, ( new_name, uuid, session[ "user_id" ], ) ) config.db.commit() return jsonify( { "error": False } ) except: return jsonify( { "error": True } ) @trainer_view.route( "/exercises/add_to_list", methods = [ "POST" ] ) @trainer_has_access def add_mark_to_list(): try: folder = session[ "current_exercise_folder" ] except: try: sql = "SELECT uuid FROM exercises WHERE trainer_id = %s ORDER BY creationtime" folder = config.db.query_fetchone( sql, ( session[ "user_id" ], ) )[ "uuid" ] except: sql = utils.sql.sql_insert_generate( "exercises", [ "uuid", "trainer_id", "name" ], "uuid" ) data = ( str( uuid4() ), session[ "user_id" ], "no name", ) folder = config.db.query_fetchone( sql, data )[ "uuid" ] try: mark = request.form.get( "mark", False ) current_app.logger.info( "Add {} to {}".format( mark, folder ) ) sql = "SELECT count(*) FROM exercises_folder WHERE mark = %s AND folder = %s" c = config.db.query_fetchone( sql, ( mark, folder, ) )[ "count" ] if c == 0: sql = utils.sql.sql_insert_generate( "exercises_folder", [ "mark", "folder" ], "id" ) r = config.db.query_fetchone( sql, ( mark, folder, ) )[ "id" ] config.db.commit() return jsonify( { "error": False } ) except: return jsonify( { "error": True } ) @trainer_view.route( "/exercises/remove_from_list", methods = [ "POST" ] ) @trainer_has_access def remove_mark_from_list(): try: mark = request.form.get( "mark", False ) folder_id = request.form.get( "folder_id", False ) sql = "DELETE FROM exercises_folder WHERE mark = %s AND folder = %s" config.db.query( sql, ( mark, folder_id, ) ) config.db.commit() return jsonify( { "error": False } ) except: return jsonify( { "error": True } ) @trainer_view.route( "/exercises//show" ) @trainer_has_access def show_folder_content( folder_id ): sql = """ SELECT files_v.* FROM files_v INNER JOIN exercises_folder ON exercises_folder.mark = files_v.uuid WHERE exercises_folder.folder = %s ORDER BY id ASC """ mark_list = config.db.query_fetchall( sql, ( folder_id, ) ) sql = "SELECT name FROM exercises WHERE uuid = %s" folder_name = config.db.query_fetchone( sql, ( folder_id, ) )[ "name" ] return my_render_template( "trainer/folder_show.html", folder = folder_id, folder_name = folder_name, mark_list = mark_list ) @trainer_view.route( "/exercises//trainee" ) @trainer_has_access def show_folder_trainee( folder_id ): sql = "SELECT name FROM exercises WHERE uuid = %s" folder_name = config.db.query_fetchone( sql, ( folder_id, ) )[ "name" ] sql = """ SELECT * FROM users INNER JOIN exercises_trainee_list ON users.id = exercises_trainee_list.user_id WHERE exercises_trainee_list.folder = %s AND users.type = 7 """ trainee_list = config.db.query_fetchall( sql, ( folder_id, ) ) return my_render_template( "trainer/trainee.html", folder = folder_id, folder_name = folder_name, trainee_list = trainee_list ) @trainer_view.route( "/exercises//trainee/add", methods = [ "POST" ] ) @trainer_has_access def add_users_to_folder( folder_id ): try: users_email_list = request.form.get( "users", None ) users_email_list = users_email_list.replace( "\n", ";" ).split( ";" ) for user_email in users_email_list: if user_email == "": continue try: sql = """ SELECT count( email ) AS nb FROM users LEFT JOIN exercises_trainee_list ON users.id = exercises_trainee_list.user_id WHERE exercises_trainee_list.folder = %s AND email = %s GROUP BY email """ nb = config.db.query_fetchone( sql, ( folder_id, user_email, ) )[ "nb" ] except TypeError: nb = 0 if nb == 0: userid = config.db.query_fetchone( "SELECT nextval( 'username_trainee_seq' ) as id" )[ "id" ] username = "trainee_{}".format( userid ) sql = utils.sql.sql_insert_generate( "users", [ "username", "email", "type" ], "id" ) data = ( username, user_email, 7 ) trainee_user_id = config.db.query_fetchone( sql, data )[ "id" ] sql = utils.sql.sql_insert_generate( "exercises_trainee_list", [ "user_id", "folder" ], "id" ) data = ( trainee_user_id, folder_id, ) config.db.query_fetchone( sql, data ) else: continue config.db.commit() return jsonify( { "error": False } ) except: return jsonify( { "error": True } ) @trainer_view.route( "/exercises//trainee/remove", methods = [ "POST" ] ) @trainer_has_access def remove_user_from_folder( folder_id ): user_id = request.form.get( "user_id", None ) try: sql = "DELETE FROM exercises_trainee_list WHERE user_id = %s AND folder = %s" config.db.query( sql, ( user_id, folder_id, ) ) config.db.commit() return jsonify( { "error": False, } ) except: return jsonify( { "error": True } ) @trainer_view.route( "/exercises/get/current_folder_id" ) @trainer_has_access def get_current_folder_id(): folder = session.get( "current_exercise_folder", None ) return jsonify( { "error": False, "folder_id": folder } ) @trainer_view.route( "/exercises/set/current_folder_id", methods = [ "POST" ] ) @trainer_has_access def set_current_folder_id(): folder = request.form.get( "current_folder_id", None ) if folder != None: session[ "current_exercise_folder" ] = folder return jsonify( { "error": False, } )