# Polyphemus & Callimachus
## Rearquitecturación de la DB
### Sample edition
Para la realización de las tareas, hemos pasado las tablas (a partir de exportaciones parciales desde phpmyadmin) a Sqlite.
Siguen procesos de rearquitecturación a partir de scripts SQL nativos + programas python conectándose a la base de datos para interactuar con ella.
**Packages python:**
- ==***`sqlite3`***==
- ==***`greek_accentuation`***==
- ==***`tqdm`***==
**Campos tratados para Callimachus** (crear medias para siglos):
- `ID_PAPYRUS text`,
- `PAPYRUS_NAME_2 text`,
- `NU_CENTURY text`,
- `NU_EARLIER_CENTURY text`,
- `NU_LATER_CENTURY text`
**Campos tratados para WORDS (Polyphemus)** (con fin de optimizar el sistema de request por el servidor a la DB):
- `ID_WORD integer`,
- `ID_PAPYRUS text`,
- `WORD_ORIG text`,
- `LEMMA text`,
- `POS text`,
- `PERSON text`,
- `NUMBER text`,
- `TENSE text`,
- `MOOD text`,
- `VOICE text`,
- `GENDER text`,
- `GRAM_CASE text`,
- `DEGREE text`,
- `TRANSLATION text`
### 1. CALLIMACHUS: Cálculo de medias
**python script:** ==**1_CenturyAverage.py**==
**desc:**
- Crea una table de trabajo PAPYRUS_CENTURY_AVERAGE:
- `ID_PAPYRUS integer`
- `CENTURY_AVERAGE integer`
- `AVERAGE_PRECISION text`
- Takes NU_EARLIER_CENTURY y NU_LATER_CENTURY from CALLIMACHUS y calcula el average + average_precision (ver buggs en comentarios del programa).
- Inserta los datos en PAPYRUS_CENTURY_AVERAGE.
### 2. POLYPHEMUS: Primera fase
**==`2_RearquitecturaPOLYPHEMUS.txt`== :** Serie de scripts SQL.
**comando desde el terminal** (posicionarse en la carpeta *`Pretratamiento/`* desde el terminal):
==**`sqlite3 DUMMYTEST.db <2_RearquitecturaPolyphemus.txt`**==
Lo que sigue (apartados 2.1, 2.2 etc.) es una descripción de las tareas efectuadas por los scripts contenidos en `2_RearquitecturaPOLYPHEMUS.txt`
#### 2.1 Creación de la nueva tabla WORDS
**Objetivo:** Añadir una primary key.
```#sql=
ALTER TABLE WORDS RENAME TO WORDS_OLD;
`CREATE TABLE WORDS(
ID_WORD INTEGER PRIMARY KEY,
ID_PAPYRUS text,
WORD_ORIG text,
LEMMA text,
POS text,
PERSON text,
NUMBER text,
TENSE text,
MOOD text,
VOICE text,
GENDER text,
GRAM_CASE text,
DEGREE text,
TRANSLATION text,
FOREIGN KEY(ID_PAPYRUS) REFERENCES CALLIMACHUS(ID_PAPYRUS)
);
INSERT INTO WORDS
SELECT ID_WORD, ID_PAPYRUS, WORD_ORIG, LEMMA, POS, PERSON, NUMBER, TENSE, MOOD, VOICE, GENDER, GRAM_CASE, DEGREE, TRANSLATION
FROM WORDS_OLD;
```
#### 2.2 División en TABLA DE IDs + TABLA DE VALUES per instancia en palabras
**¿Para qué?** Para permitir la construcción en la app de una ruta `query_form/` (client) `/query_form` (server) y automatizar el despliegue de las opciones que tiene la DB al usuario.
También permite ya tener registro los IDs correspondientes (desde le input del usuario) a la petición para construír peticiones mucho más complejas en la seguida.
**OUTPUT:** Las siguientes tablas de IDs están creadas:
* `FLEXTYPE_IDs`: cada `ID_FLEXTYPE` posible, compuesto de cada configuración única, dentro de las configuraciones atestiguadas, de IDs de las tablas siguientes:
* `DEGREE_IDS`
* `GENDER_IDS`
* `GRAM_CASE_IDS`
* `VOICE_IDS`
* `MOOD_IDS`
* `TENSE_IDS`
* `NUMBER_IDS`
* `PERSON_IDS`
* `POS_IDS`
* `LEMMA_IDS` : cada `ID_LEMMA` posible, compuesto de cada configuración única, dentro de las configuraciones atestiguadas, de valores de las tablas siguientes:
* `WORDS.LEMMA`
* `POS_IDS.ID_POS`
* `WORDS.TRANSLATION`
##### A - Modelo de script SQL para las subtablas `{DEGREE/GENDER/GRAM_CASE/VOICE/MOOD/TENSE/NUMBER/PERSON/POS}_IDS`
ej. de `DEGREE` :
Tabla para acceder a los posibles valores que se encuentran en la columna `DEGREE` de `WORDS` :
```sql=
CREATE TABLE DEGREE_IDS(
ID_DEGREE INTEGER PRIMARY KEY AUTOINCREMENT,
DEGREE_VALUE TEXT
);
INSERT INTO DEGREE_IDS(DEGREE_VALUE)
SELECT DISTINCT WORDS.DEGREE
FROM WORDS;
```
##### B - Script SQL para la tabla `FLEXTYPE_IDS`
```sql=
CREATE TABLE FLEXTYPE_IDS(
ID_FLEXTYPE INTEGER PRIMARY KEY AUTOINCREMENT,
ID_POS INTEGER NOT NULL,
ID_PERSON INTEGER NOT NULL,
ID_NUMBER INTEGER NOT NULL,
ID_TENSE INTEGER NOT NULL,
ID_MOOD INTEGER NOT NULL,
ID_VOICE INTEGER NOT NULL,
ID_GENDER INTEGER NOT NULL,
ID_GRAM_CASE INTEGER NOT NULL,
ID_DEGREE INTEGER NOT NULL,
FOREIGN KEY (ID_POS) REFERENCES POS_IDS(ID_POS)
FOREIGN KEY (ID_PERSON) REFERENCES PERSON_IDS(ID_PERSON)
FOREIGN KEY (ID_NUMBER) REFERENCES NUMBER_IDS(ID_NUMBER)
FOREIGN KEY (ID_TENSE) REFERENCES TENSE_IDS(ID_TENSE)
FOREIGN KEY (ID_MOOD) REFERENCES MOOD_IDS(ID_MOOD)
FOREIGN KEY (ID_VOICE) REFERENCES VOICE_IDS(ID_VOICE)
FOREIGN KEY (ID_GENDER) REFERENCES GENDER_IDS(ID_GENDER)
FOREIGN KEY (ID_GRAM_CASE) REFERENCES GRAM_CASE_IDS(ID_GRAM_CASE)
FOREIGN KEY (ID_DEGREE) REFERENCES DEGREE_IDS(ID_DEGREE)
);
INSERT INTO FLEXTYPE_IDS(ID_POS, ID_PERSON, ID_NUMBER, ID_TENSE, ID_MOOD, ID_VOICE, ID_GENDER, ID_GRAM_CASE, ID_DEGREE)
SELECT DISTINCT POS_IDS.ID_POS, PERSON_IDS.ID_PERSON, NUMBER_IDS.ID_NUMBER, TENSE_IDS.ID_TENSE, MOOD_IDS.ID_MOOD, VOICE_IDS.ID_VOICE, GENDER_IDS.ID_GENDER, GRAM_CASE_IDS.ID_GRAM_CASE, DEGREE_IDS.ID_DEGREE
FROM WORDS
JOIN POS_IDS ON POS_IDS.POS_VALUE = WORDS.POS
JOIN PERSON_IDS ON PERSON_IDS.PERSON_VALUE = WORDS.PERSON
JOIN NUMBER_IDS ON NUMBER_IDS.NUMBER_VALUE = WORDS.NUMBER
JOIN TENSE_IDS ON TENSE_IDS.TENSE_VALUE = WORDS.TENSE
JOIN MOOD_IDS ON MOOD_IDS.MOOD_VALUE = WORDS.MOOD
JOIN VOICE_IDS ON VOICE_IDS.VOICE_VALUE = WORDS.VOICE
JOIN GENDER_IDS ON GENDER_IDS.GENDER_VALUE = WORDS.GENDER
JOIN GRAM_CASE_IDS ON GRAM_CASE_IDS.GRAM_CASE_VALUE = WORDS.GRAM_CASE
JOIN DEGREE_IDS ON DEGREE_IDS.DEGREE_VALUE = WORDS.DEGREE;
```
##### C - Script SQL para la tabla `LEMMA_IDS`
```sql=
CREATE TABLE LEMMA_IDS(
ID_LEMMA INTEGER PRIMARY KEY AUTOINCREMENT,
LEMMA_STR TEXT,
ID_POS INTEGER NOT NULL,
TRANSLATION TEXT,
FOREIGN KEY (ID_POS) REFERENCES POS_IDS(ID_POS)
);
INSERT INTO LEMMA_IDS(LEMMA_STR, ID_POS, TRANSLATION)
SELECT DISTINCT WORDS.LEMMA, POS_IDS.ID_POS, WORDS.TRANSLATION
FROM WORDS
JOIN POS_IDS ON POS_IDS.POS_VALUE = WORDS.POS;
```
#### 2.3 Creación de las tablas `WORD_TYPES` y `WORD_TOKENS`
**¿Para qué?** Para limitar el ruido de los procesos de peticiones a la base de datos desde el servidor de la app.
Por ejemplo, el servidor podrá efectuar la petición de tipo 'TODOS LOS `WORD_TOKENS` QUE SON PARTICIPIOS FEMENINOS AL DATIVO' utilizando la cadena de búsqueda siguiente:
```flow
in=>start: Input ID_MOOD [x], ID_GENDER [y], ID_GRAM_CASE[z]
out=>end: WORD_TOKENS with predefined WORD_TYPES (2298 results)
op1=>operation: Gets corresponding ID_FLEXTYPES (31 results)
op2=>operation: Gets WORD_TYPES with these ID_FLEXTYPES (771 results)
in->op1->op2->out
```
##### A - Creación de WORD_TYPES
```sql=
CREATE TABLE WORD_TYPES(
ID_WORDTYPE INTEGER PRIMARY KEY AUTOINCREMENT,
WORD_STR TEXT,
ID_FLEXTYPE INTEGER NOT NULL,
ID_LEMMA INTEGER NOT NULL,
FOREIGN KEY (ID_FLEXTYPE) REFERENCES FLEXTYPE_IDS(ID_FLEXTYPE)
FOREIGN KEY (ID_LEMMA) REFERENCES LEMMA_IDS(ID_LEMMA)
);
INSERT INTO WORD_TYPES(WORD_STR, ID_FLEXTYPE, ID_LEMMA)
SELECT DISTINCT WORDS.WORD_ORIG, FLEXTYPE_IDS.ID_FLEXTYPE, LEMMA_IDS.ID_LEMMA
FROM WORDS
JOIN LEMMA_IDS ON (LEMMA_IDS.LEMMA_STR = WORDS.LEMMA AND LEMMA_IDS.TRANSLATION = WORDS.TRANSLATION)
JOIN POS_IDS ON POS_IDS.POS_VALUE = WORDS.POS
JOIN PERSON_IDS ON PERSON_IDS.PERSON_VALUE = WORDS.PERSON
JOIN NUMBER_IDS ON NUMBER_IDS.NUMBER_VALUE = WORDS.NUMBER
JOIN TENSE_IDS ON TENSE_IDS.TENSE_VALUE = WORDS.TENSE
JOIN MOOD_IDS ON MOOD_IDS.MOOD_VALUE = WORDS.MOOD
JOIN VOICE_IDS ON VOICE_IDS.VOICE_VALUE = WORDS.VOICE
JOIN GENDER_IDS ON GENDER_IDS.GENDER_VALUE = WORDS.GENDER
JOIN GRAM_CASE_IDS ON GRAM_CASE_IDS.GRAM_CASE_VALUE = WORDS.GRAM_CASE
JOIN DEGREE_IDS ON DEGREE_IDS.DEGREE_VALUE = WORDS.DEGREE
JOIN FLEXTYPE_IDS ON (FLEXTYPE_IDS.ID_DEGREE= DEGREE_IDS.ID_DEGREE
AND FLEXTYPE_IDS.ID_GRAM_CASE = GRAM_CASE_IDS.ID_GRAM_CASE
AND FLEXTYPE_IDS.ID_GENDER = GENDER_IDS.ID_GENDER
AND FLEXTYPE_IDS.ID_VOICE = VOICE_IDS.ID_VOICE
AND FLEXTYPE_IDS.ID_MOOD = MOOD_IDS.ID_MOOD
AND FLEXTYPE_IDS.ID_TENSE = TENSE_IDS.ID_TENSE
AND FLEXTYPE_IDS.ID_NUMBER = NUMBER_IDS.ID_NUMBER
AND FLEXTYPE_IDS.ID_PERSON = PERSON_IDS.ID_PERSON
AND FLEXTYPE_IDS.ID_POS = POS_IDS.ID_POS);
```
##### B - Creación de WORD_TOKENS
```sql=
CREATE TABLE WORD_TOKENS(
ID_WORDTOKEN INTEGER PRIMARY KEY,
ID_WORDTYPE INTEGER NOT NULL,
ID_PAPYRUS INTEGER NOT NULL,
FOREIGN KEY (ID_WORDTYPE) REFERENCES WORD_TYPES(ID_WORDTYPE)
FOREIGN KEY (ID_PAPYRUS) REFERENCES CALLIMACHUS(ID_PAPYRUS)
);
INSERT INTO WORD_TOKENS
SELECT W_FLEX_LEM.IDWORD, WORD_TYPES.ID_WORDTYPE, W_FLEX_LEM.IDPAPYRUS
FROM (SELECT W_FLEX.ID_WORD as IDWORD, W_FLEX.ID_PAPYRUS AS IDPAPYRUS, W_FLEX.WORD_ORIG AS WORDORIG, W_FLEX.ID_FLEXTYPE AS IDFLEXTYPE, LEMMA_IDS.ID_LEMMA AS IDLEMMA
FROM (SELECT WORDS.ID_WORD as ID_WORD, WORDS.ID_PAPYRUS as ID_PAPYRUS, WORDS.WORD_ORIG as WORD_ORIG, FLEXTYPE_VALUES.ID_FLEXTYPE as ID_FLEXTYPE, WORDS.LEMMA AS LEMMA, WORDS.TRANSLATION as TRANSLATION
FROM WORDS
JOIN FLEXTYPE_VALUES ON (FLEXTYPE_VALUES.POS_VALUE = WORDS.POS
AND FLEXTYPE_VALUES.PERSON_VALUE = WORDS.PERSON
AND FLEXTYPE_VALUES.NUMBER_VALUE = WORDS.NUMBER
AND FLEXTYPE_VALUES.TENSE_VALUE = WORDS.TENSE
AND FLEXTYPE_VALUES.MOOD_VALUE = WORDS.MOOD
AND FLEXTYPE_VALUES.VOICE_VALUE = WORDS.VOICE
AND FLEXTYPE_VALUES.GENDER_VALUE = WORDS.GENDER
AND FLEXTYPE_VALUES.GRAM_CASE_VALUE = WORDS.GRAM_CASE
AND FLEXTYPE_VALUES.DEGREE_VALUE = WORDS.DEGREE) ) AS W_FLEX
JOIN FLEXTYPE_IDS ON FLEXTYPE_IDS.ID_FLEXTYPE = W_FLEX.ID_FLEXTYPE
JOIN LEMMA_IDS ON (LEMMA_IDS.LEMMA_STR = W_FLEX.LEMMA AND LEMMA_IDS.TRANSLATION = W_FLEX.TRANSLATION AND LEMMA_IDS.ID_POS = FLEXTYPE_IDS.ID_POS)) AS W_FLEX_LEM
JOIN WORD_TYPES ON (WORD_TYPES.WORD_STR = W_FLEX_LEM.WORDORIG AND WORD_TYPES.ID_FLEXTYPE = W_FLEX_LEM.IDFLEXTYPE AND WORD_TYPES.ID_LEMMA = W_FLEX_LEM.IDLEMMA);
```
### 3. POLYPHEMUS: Segunda Fase
#### 3.1 Descripción de las tareas
**Objetivos:**
* Crear una columna en `LEMMA_IDS` que permita efectuar un autocomplete a partir del input del usuario en el front-end de la applicación (ruta `lemma_autocomplete/`).
* Crear las tablas de IDs para las diferentes unidades de traducción que pueden entrar en el sistema de petición por el servidor.
**OUTPUT:** Las siguientes tablas de IDs (para los elementos de traducción) están creadas:
* `TABLE TRANSLATION_IDS` : crea un ID único per traducción (dentro de los valores de `WORDS.TRANSLATION`)
* `TRANSLAT_GROUPWORD_TYPES` : crea un ID único per grupo de traducción(split por `||` en las cadenas de traducción)
* `TRANSLATWORD_TYPES` : crea un ID único per palabra de traducción (dentro de los grupos de traducción)
* `TRANSLATWORD_ID_TRANSLAT_GROUPWORD` : JOIN TABLE para correspondencia entre ID de una palabra con los IDs de los grupos de traducción donde figura.
* `TRANSLATWORD_TOKENS` : JOIN TABLE para correspondencia entre ID de un grupo de traducción con los IDs de las traducciones donde se encuentra.
**Procesos**:
* **python script:** ==**3_NormalizingGreek.py**==
* **comando desde el terminal** (posicionarse en la carpeta *`Pretratamiento/`* desde el terminal):
==**`sqlite3 DUMMYTEST.db <4_TranslationTables.txt`**==
* **python script:** ==**5_TranslationWords.py**==
* **comando desde el terminal** (posicionarse en la carpeta *`Pretratamiento/`* desde el terminal):
==**`sqlite3 DUMMYTEST.db <6_ActualizarLEMMAS_IDs.txt`**==
#### 3.2 Estructura SQL de las nuevas tablas
```sql=
CREATE TABLE IF NOT EXISTS TRANSLAT_GROUPWORD_TYPES(
ID_GROUPWORD_TYPE INTEGER PRIMARY KEY AUTOINCREMENT,
GROUPWORD_STR TEXT,
GROUPWORD_SEARCH TEXT);
CREATE TABLE IF NOT EXISTS TRANSLATWORD_TYPES(
ID_TRANSLATWORD_TYPE INTEGER PRIMARY KEY AUTOINCREMENT,
TRANSLATWORD_STR TEXT,
TRANSLATWORD_SEARCH TEXT);
CREATE TABLE IF NOT EXISTS TRANSLATWORD_ID_TRANSLAT_GROUPWORD(
ID_TRANSLATWORD_TYPE INTEGER NOT NULL,
ID_GROUPWORD_TYPE INTEGER NOT NULL,
FOREIGN KEY (ID_TRANSLATWORD_TYPE) REFERENCES TRANSLATWORD_TYPES(ID_TRANSLATWORD_TYPE)
FOREIGN KEY (ID_GROUPWORD_TYPE) REFERENCES TRANSLAT_GROUPWORD_TYPES(ID_GROUPWORD_TYPE));
CREATE TABLE IF NOT EXISTS TRANSLATWORD_TOKENS(
ID_GROUPWORD_TYPE INTEGER NOT NULL,
ID_TRANSLATION INTEGER NOT NULL,
FOREIGN KEY (ID_GROUPWORD_TYPE) REFERENCES TRANSLAT_GROUPWORD_TYPES(ID_GROUPWORD_TYPE)
FOREIGN KEY (ID_TRANSLATION) REFERENCES TRANSLATION_IDS(ID_TRANSLATION)
);
```
## Desarollo de la aplicación
### 1. Descripción general
A partir de la nueva arquitectura de la base de datos, hemos desarrollado una aplicación web, utilizando el entorno Express para Node.js.
Con Node.js, la parte servidor tal como la parte cliente se desarrolla en javascript.
Para el despliegue de la app (en local primero y luego en un servidor exterior), son necesarias las instalaciones siguientes.
**Instalación de Node.js y NPM**
- Seguir las instrucciones en [Node.js](https://https://nodejs.org/en). La instalación de Node.js viene con NPM (Node Package Manager) que permite instalar los paquetes necesarios.
**Packages necesarios para la app de DEMO**
- [express](https://expressjs.com/es/)
- [sqlite3](https://www.npmjs.com/package/sqlite3)
- [greek-utils](https://www.npmjs.com/package/greek-utils)
Dado que se importa la app directamente con la lista de node_modules y el package.json actualizados en función de las instalaciones en la máquina de origen, procederemos primero a la purgación de los paquetes necesarios, con el comando siguiente (a partir del directorio `.../Polyphemus-app$` donde está la app):
==**`sudo npm uninstall <nombredelpaquete>`**==
Y, una vez desinstalados estos paquetes, procederemos otra vez a su instalación con el comando :
==**`sudo npm install <nombredelpaquete>`**==
**Arrancar la app localmente**
==**`sudo node server.js`**==
Y ya se puede abrir en un browser el port determinado (configuración por defecto : `localhost:4000`)

### 1. Front-end (cliente)
#### 1.1 Setup()
Cuando un cliente se conecta al PORT (por defecto 4000) donde está escuchando el servidor, ese último le sirve el archivo `index.html` así como la hoja de estilo `polyphemus.css` y el script `index.js` enlazados a aquello.
La función inicial `setup()` del javascript cliente modifical el html de base para crear una primera línea de atributo (parametro de la búsqueda del usuario) configurada por defecto en el parametro *Part-of-Speech*:

Esta inicialización incluye la configuración del elemento correspondiente al parametro que recibe automáticamente un id `query_attr_<número del atributo>` (el número del atributo corresponde a la variable `qid_num`, inicializada en 1 y que va cambiando según las acciones del usuario).
#### 1.2 Configuración de las líneas de atributos
Cada línea de atributo consiste primero en un campo `table_attr_<qid_num>` (iniciado por `MakeAttributeLine()`) donde el usuario puede elegir la categoría que concierne el parametro de su búsqueda y en un campo dedicado al valor que el usuario desea hacerle corresponder (id `value_list_<qid_num>`).
En función de la categoría elegida en el campo `table_attr_<qid_num>`, la configuración de su campo de valor varia, tal como explicitado en lo que sigue.
Cada línea de atributo termina por un elemento `button` (con id `delete-attr-<qid_num>`)que permita suprimir la línea entera. A este botón, creado a lo largo de la ejecución de `MakeValueField()`, corresponde la función `DeleteAttrButton()` que le añade un EventListener para suprimir la línea de atributo correspondiente cuando el usuario pincha y que llama a la función `ReoderingAttribute()` para poner en buena forma la nueva lista de atributos así modificada (ordenamiento de los números de id, reconfiguración de `qid_num`, etc.).
La lista de atributos siempre termina por una línea para añadir un nuevo atributo/parametro de búsqueda (id `paragraph-add-attr`) que consta de un botón (id `button-add-attribute`) y de un botón para ver los resultados cuya acción se describe más abajo. Al botón `paragraph-add-attr`, creado a lo largo de la ejecución de `MakeValueField()`, corresponde la función `ChangeAttrButtonToField()` que le añade un EventListener para añadir un nuevo atributo/parametro (llamando otra vez a `MakeNewLine()`) a la lista y reiniciar la línea `paragraph-add-attr`.
##### 1.2.1 Valores de la parte `table_attr_<qid_num>` del parametro
El usuario puede elegir las siguientes categorías de información para cada parametro de su búsqueda:
* Part-of-Speech (`value = 'POS_IDS'`)
* Lemma (`value = 'LEMMA_IDS'`)
* Translation (`value = 'TRANSLATWORD_TYPES'`)
* Datation (`value = 'PAPYRUS_CENTURY_AVERAGE_IDS'`)
* Verbal Flexion
* Tense(`value = 'TENSE_IDS'`)
* Mood (`value = 'MOOD_IDS'`)
* Voice (`value = 'VOICE_IDS'`)
* Person (`value = 'PERSON_IDS'`)
* Nominal Flexion
* Grammatical Case (`value = 'GRAM_CASE_IDS'`)
* Gender (`value = 'GENDER_IDS'`)
* Number (`value = 'NUMBER_IDS'`)
* Degree (`value = 'DEGREE_IDS'`)
Cada uno representa un elemento `option` dentro de un `select` cuyo attributo `value` corresponde a una tabla de IDs de la base de datos mencionada entre paréntesis en la lista anterior. De este `value` depende la configuración de la parte `value_list_<qid_num>`.
##### 1.2.1 Valores de la parte `value_list_<qid_num>` del parametro
Función de referencia : `MakeValueField()`
Los parametros de búsqueda llaman a tres tipos de procesos para configurar la parte `value_list_<qid_num>`, que corresponden a tres tipos de elementos que aparecen en la página:
1. un menú desplegable (elemento `select`) donde el usuario puede elegir el valor que desea (categorías PART-OF-SPEECH, TENSE, MOOD, VOICE, PERSON, GRAMMATICAL CASE, GENDER, NUMBER, DEGREE),
2. un elemento `input` en el cual el usuario puede empezar a escribir el valor que quiere y que reacciona por un proceso de autocompletion (cat. LEMMA y TRANSLATION),
3. un elemento `div` que contiene varios subelementos para la configuración del parametro (cat. DATATION).
Para el tipo 1., los valores posibles, cada uno correspondiendo a una opción cuyo attributo `value` corresponde a la primary key de la tabla correspondiente en la DB, se generan a partir de una request de método POST hacia el servidor por la ruta `query_form/` (ver el detalle en la apartado 2. dedicado al servidor), contenida en la función `GetTableFieldValues()`
Para el tipo 2., las funciones `ChangingLemmaInput()` y `ChangingTranslationInput()` crean un EventListener para el input concernado que llama respectivamente a la función `GetLemmaValues()` o la función `GetTranslationValues()` que efectuan una request de método POST hacia el servidor por la ruta `lemma_autocomplete` o `translation_autocomplete` para obtener todos los lemas o traducciones de la base de datos que puedan corresponder al input del usuario en cada una de sus actualizaciones.
El tipo 3. es un derivado del tipo 1., dado que funciona sobre menús deplegables de opciones determinadas en función de que siglos interesan al usuarios, incluso si desea estudiar un intervalo de siglos o un siglo en concreto. Función de referencia : `SetCenturyOption()` que pone un EventListener para llamar, en función del deseo del usuario, a la función CreateOneCentOption() o CreateSeveralCentOption().
### 2. Back-end (servidor)