Commit 4ed27883 by Luciano Barletta

entregable

- terminada la compilacion del segundo pdf
- hecho el manual de usuario
- llenado el README para programadores
- pulido de comportamientos no deseados
1 parent b59686f2
# Generación de PDF
## Instalación
El server corre en `python3` y cuenta con las siguientes dependencias:
- pip3 (para instalar cosas en python3)
- Flask
- Selenium
Para instalar estos paquetes se deben correr estos comandos siendo administrador:
```sh
apt-get install python3-pip
pip3 install flask
pip3 install selenium
```
## Inicialización
Para comenzar a usar el servidor, correr el siguiente comando en la carpeta del código (siendo administrador):
```sh
python3 deploy.py
```
## Uso
El servidor cuenta con dos direcciones:
### X.X.X.X:5000
Esta es la dirección principal. Aquí se tomarán usuario, contraseña y dominio a buscar. Además se tomarán los rendimientos de los ejes de suspensión. Todos los campos son obligatorios y no se puede avanzar sin ellos. Una vez que se hayan completado el formulario, presionar Buscar.
Luego de una espera de entre 10 y 20 segundos se mostrará un formulario con los datos recolectados. Aquí se pueden cambiar o llenar todos los datos que se quiera. Si ha habido un error, el mismo se mostrará y el formulario detrás estará vacío, disponible para ser llenado de todos modos.
Al fondo de la página habrá un campo "Por defecto" que contiene el texto que tendrán los campos vacíos o con un signo de pregunta '?'*. El valor por defecto puede ser modificado.
Al terminar de escribir los datos, se pueden convertir a PDF con los dos botones del final. La conversión a PDF se puede realizar tantas veces como se quiera, modificando datos cada vez si hubo un error. Tener en cuenta que realizar la recolección de datos de la misma patente cambiará algunos datos generados automáticamente.
El botón 1 genera el documento simplificado, el botón 2 genera el documento complejo. Cualquiera (o los dos) pueden ser generados. Luego de generados se pueden guardar o imprimir.
*Nota: El signo de pregunta significa que no se pudo recoletar el dato de la página.
### X.X.X.X:5000/manual
En esta dirección se saltea el paso de recolectar datos, simplemente muestra un formulario vacío para llenar manualmente.
Se recomienda que al llenar los campos, se alterne entre ellos rápidamente con el botón TAB para avanzar y SHIFT+TAB para retroceder.
## Detención
Para detener el servicio basta abrir la consola donde está corriendo y presionar CTRL+C.
\ No newline at end of file \ No newline at end of file
# Generación de PDF
## Python
Hay dos archivos de Python:
### deploy.py
[link](./deploy.py)
Contiene la aplicación y los procesos abstractos de recolección de datos y valores default. Cada parte del proceso puede fallar por algún motivo, en cuyo caso devolverá un string con el error. Sino, devolverá un JSON con los datos.
La app cuenta con 3 direcciones:
1. / \[GET] -> llama al form con bypass = false
2. /manual \[GET] -> llama al form con bypass = true
3. /pdf \[POST] -> dados los datos del form, recolecta los datos
### iselenium.py
[link](./iselenium.py)
Es la clase con utilidades para manejar Selenium con código corto, además cuenta con dos clases de Exception para dos casos:
1. NoSuchDriver -> el driver no está soportado por la interfaz
2. BadInterval -> error en el parsing de intervalos en las funciones find*
## HTML
Hay un solo [archivo](./templates/form.html), que cuenta con dos secciones:
1. form -> formulario que llama a /pdf y recolecta los datos
2. results -> muestra los datos y tiene botones para convertir a pdf
Hay una variable bypass que elige si mostrar el form o saltar a los resultados (vacíos)
## JavaScript
1. [Ajax](./static/src/ajax.js) -> utilidades de ajax
2. Sistema simil [html](./static/src/div.js) -> clases de para compilar posiciones relativas a padres de forma porcentual*
3. [Formularios](./static/src/forms.js) -> lee y llena formularios y hace consultas a /pdf
4. Compilación de [PDF1](./static/src/pdf1.js) y [PDF2](./static/src/pdf2.js) -> clases con métodos de dibujado que usan el punto 2 como interfaz
*Se forma un árbol y se llama recursivamente a los métodos draw(jsPDF pdf) de las clases
## Manual
[link](./Manual.md)
Manual de usuario para instalar, correr, usar y detener el servicio. Orientado a usuarios con experiencia en Linux y búsqueda por IP de páginas web
\ No newline at end of file \ No newline at end of file
#-*- coding: utf-8 -*- #-*- coding: utf-8 -*-
from flask import Flask, render_template, request, url_for from flask import Flask, render_template, request, url_for
from iselenium import SeleniumInterface as SI from iselenium import SeleniumInterface as SI
import random import random, json
app = Flask(__name__) app = Flask(__name__)
data = { @app.route('/')
"header" : { def main():
"patente" : "?", return render_template(
"fecha" : "?", "form.html",
"hora" : "?" bypass = False
}, )
"alineador" : {
"eje_delantero" : "?"
},
"suspension" : [
{
"rendimiento_izquierdo" : "?",
"peso_estatico" : "?",
"peso_dinamico" : "?",
"rendimiento_derecho" : "?"
},
{
"rendimiento_izquierdo" : "?",
"peso_estatico" : "?",
"peso_dinamico" : "?",
"rendimiento_derecho" : "?"
}
],
"frenos" : [
{
"fuerza_izquierda" : "?",
"resistencia_izquierda" : "?",
"ovalidad_izquierda" : "?",
"peso_estatico" : "?",
"peso_dinamico" : "?",
"fuerza_derecha" : "?",
"resistencia_derecha" : "?",
"ovalidad_derecha" : "?"
},
{
"fuerza_izquierda" : "?",
"resistencia_izquierda" : "?",
"ovalidad_izquierda" : "?",
"peso_estatico" : "?",
"peso_dinamico" : "?",
"fuerza_derecha" : "?",
"resistencia_derecha" : "?",
"ovalidad_derecha" : "?"
},
{
"fuerza_izquierda" : "?",
"resistencia_izquierda" : "?",
"ovalidad_izquierda" : "?",
"peso_estatico" : "?",
"peso_dinamico" : "?",
"fuerza_derecha" : "?",
"resistencia_derecha" : "?",
"ovalidad_derecha" : "?"
},
{
"fuerza_izquierda" : "?",
"resistencia_izquierda" : "?",
"ovalidad_izquierda" : "?",
"peso_estatico" : "?",
"peso_dinamico" : "?",
"fuerza_derecha" : "?",
"resistencia_derecha" : "?",
"ovalidad_derecha" : "?"
}
],
"trasero" : {
"fuerza_izquierda" : "?",
"fuerza_derecha" : "?",
"peso_estatico" : "?",
"peso_dinamico" : "?"
},
"gaseshumos" : {
"co" : "?",
"hc" : "?",
"opacidad_logaritmica" : "?"
}
}
@app.route('/manual') @app.route('/manual')
def pdf(): def manual():
return render_template( return render_template(
"resultados.html", "form.html",
data = data bypass = True
) )
@app.route('/') @app.route('/pdf', methods = ['POST'])
def main(): def pdf():
plate = "JPY149" d = request.json
plate = d['header']['patente']
s = SI(SI.Chrome) s = SI(SI.Chrome)
form = [
{
"rendimiento_izquierdo" : "0",
"rendimiento_derecho" : "0",
},
{
"rendimiento_izquierdo" : "0",
"rendimiento_derecho" : "0",
}
]
answer = { answer = {
"header" : {}, "header" : {},
"alineador" : {}, "alineador" : {},
"suspension" : [], "suspension" : d['suspension'],
"frenos" : [], "frenos" : {},
"trasero" : {}, "trasero" : {},
"gaseshumos" : {}, "gaseshumos" : {},
} }
...@@ -118,7 +37,12 @@ def main(): ...@@ -118,7 +37,12 @@ def main():
answer['header']['patente'] = plate.upper() answer['header']['patente'] = plate.upper()
try: try:
answer = login(s, answer) answer = login(
d['credenciales']['usuario'],
d['credenciales']['contrasena'],
s,
answer
)
except: except:
return "Error en el login." return "Error en el login."
try: try:
...@@ -130,30 +54,36 @@ def main(): ...@@ -130,30 +54,36 @@ def main():
except: except:
return f"Error leyendo datos de la patente '{plate}'." return f"Error leyendo datos de la patente '{plate}'."
try: try:
answer = extradata(form, answer) answer = rnddata(answer)
except: except:
return f"Error completando datos extra de la patente '{plate}'." return f"Error completando datos extra de la patente '{plate}'."
print(answer) print(answer)
del s return json.dumps(answer)
return render_template(
"resultados.html",
data = answer
)
def login(s, r): def login(u, p, s, r):
s.get("https://rto.cent.gov.ar/rto") s.get("https://rto.cent.gov.ar/rto")
login = s.find(SI.By.NAME, "j_username") login = s.find(SI.By.NAME, "j_username")
s.write(login, "salvatellih") s.write(login, u)
psw = s.find(SI.By.NAME, "j_password") psw = s.find(SI.By.NAME, "j_password")
s.write(psw, "3") s.write(psw, p)
button = s.find(SI.By.ID, "submit") button = s.find(SI.By.ID, "submit")
button.click() button.click()
return r reach = lambda s: s.find(SI.By.NAME, "j_username")
login = attempt_do(reach, default = "?")(s)
# login succeeded
if login == "?":
return r
# still in login page
else:
raise Exception("Fallo del login")
def gototec(s, r): def gototec(s, r):
s.get("https://rto.cent.gov.ar/rto/RTO/listaDePlanillas") s.get("https://rto.cent.gov.ar/rto/RTO/listaDePlanillas")
...@@ -191,27 +121,29 @@ def readdata(s, r): ...@@ -191,27 +121,29 @@ def readdata(s, r):
# suspension # suspension
for i in range(2): for i in range(2):
sus = {} sus = {}
sus['peso_estatico'] = empty_for_question(attempt_do(reach(f"pesoBascula-{i}"), default = "?")(s)) sus[f'peso_dinamico_{i + 1}'] = empty_for_question(attempt_do(reach(f"pesoBascula-{i}"), default = "?")(s))
sus[f'peso_estatico_{i + 1}'] = empty_for_question(attempt_do(reach(f"pesoMaximo-{i}"), default = "?")(s))
r['suspension'].append(sus) r['suspension'].update(sus)
# frenos # frenos
frenos = s.find(SI.By.XPATH, "//table[@class='tabla_ensayo']/tbody//tr[@class='odd' or @class='even']","1-4") frenos = s.find(SI.By.XPATH, "//table[@class='tabla_ensayo']/tbody//tr[@class='odd' or @class='even']","1-4")
for i in range(len(frenos)): for i in range(4):
fre = {} fre = {}
fre['peso_estatico'] = empty_for_question(attempt_do(reach(f"pesoBascula-{i}"), default = "?")(s)) fre[f'peso_dinamico_{i + 1}'] = empty_for_question(attempt_do(reach(f"pesoBascula-{i}"), default = "?")(s))
fre['peso_dinamico'] = empty_for_question(attempt_do(reach(f"pesoMaximo-{i}"), default = "?")(s)) fre[f'peso_estatico_{i + 1}'] = empty_for_question(attempt_do(reach(f"pesoMaximo-{i}"), default = "?")(s))
fre['fuerza_izquierda'] = empty_for_question(attempt_do(reach(f"fuerzaIzq-{i}"), default = "?")(s)) fre[f'fuerza_izquierda_{i + 1}'] = empty_for_question(attempt_do(reach(f"fuerzaIzq-{i}"), default = "?")(s))
fre['fuerza_derecha'] = empty_for_question(attempt_do(reach(f"fuerzaDer-{i}"), default = "?")(s)) fre[f'fuerza_derecha_{i + 1}'] = empty_for_question(attempt_do(reach(f"fuerzaDer-{i}"), default = "?")(s))
r['frenos'].append(fre) r['frenos'].update(fre)
# freno trasero # freno trasero
r['trasero']['peso_estatico'] = empty_for_question(attempt_do(reach(f"pesoBasculaEst-0"), default = "?")(s)) r['trasero']['peso_dinamico'] = empty_for_question(attempt_do(reach(f"pesoBasculaEst-0"), default = "?")(s))
r['trasero']['peso_dinamico'] = empty_for_question(attempt_do(reach(f"pesoMaximoEst-0"), default = "?")(s)) r['trasero']['peso_estatico'] = empty_for_question(attempt_do(reach(f"pesoMaximoEst-0"), default = "?")(s))
r['trasero']['fuerza_izquierda'] = empty_for_question(attempt_do(reach(f"fuerzaIzqEst-0"), default = "?")(s)) r['trasero']['fuerza_izquierda'] = empty_for_question(attempt_do(reach(f"fuerzaIzqEst-0"), default = "?")(s))
r['trasero']['fuerza_derecha'] = empty_for_question(attempt_do(reach(f"fuerzaDerEst-0"), default = "?")(s)) r['trasero']['fuerza_derecha'] = empty_for_question(attempt_do(reach(f"fuerzaDerEst-0"), default = "?")(s))
r['trasero']['eje'] = empty_for_question(attempt_do(reach(f"nroEjeEst-0"), default = "?")(s))
# gases y humos # gases y humos
...@@ -221,20 +153,21 @@ def readdata(s, r): ...@@ -221,20 +153,21 @@ def readdata(s, r):
return r return r
def extradata(form, r): def rnddata(r):
res = lambda: round(random.random() * 0.9 + 0.05, 2) res = lambda: round(random.random() * 0.9 + 0.05, 2)
ov = lambda: round(random.random() * 39 + 0.5, 2) ov = lambda: round(random.random() * 39 + 0.5, 2)
for i in range(len(r['suspension'])): for i in range(4):
r['suspension'][i]['rendimiento_izquierdo'] = form[i]['rendimiento_izquierdo'] f = r['frenos']; j = i+1; gen = False
r['suspension'][i]['rendimiento_derecho'] = form[i]['rendimiento_derecho'] # If any values were found, it means the axis exists, random values will be generated.
if f[f'fuerza_izquierda_{j}'] != "?" or f[f'fuerza_derecha_{j}'] != "?" or f[f'peso_estatico_{j}'] != "?":
for i in range(len(r['frenos'])): gen = True
r['frenos'][i]['resistencia_izquierda'] = res()
r['frenos'][i]['resistencia_derecha'] = res() f[f'resistencia_izquierda_{j}'] = res() if gen else "?"
r['frenos'][i]['ovalidad_izquierda'] = ov() f[f'resistencia_derecha_{j}'] = res() if gen else "?"
r['frenos'][i]['ovalidad_derecha'] = ov() f[f'ovalidad_izquierda_{j}'] = ov() if gen else "?"
f[f'ovalidad_derecha_{j}'] = ov() if gen else "?"
return r return r
......
...@@ -114,12 +114,4 @@ class BadInterval(Exception): ...@@ -114,12 +114,4 @@ class BadInterval(Exception):
self.interval = interval self.interval = interval
def __str__(self): def __str__(self):
return f"The interval '{self.interval}' is not valid"
class NotEditable(Exception):
def __init__(self, plate):
self.plate = plate
def __str__(self):
return f"The plate '{self.plate}' is not editable"
\ No newline at end of file \ No newline at end of file
return f"The interval '{self.interval}' is not valid"
\ No newline at end of file \ No newline at end of file
class Ajax {
constructor(object){
if (typeof object !== "object")
this.data = {};
else
this.data = object;
this.http = new XMLHttpRequest();
}
default(){
if (("url" in this.data) === false) {
throw "URL not set";
}
if (("async" in this.data) === false){
this.data.async = true;
}
if ( "success" in this.data ){
this.http.onload = () => {
if (this.http.status == 200)
this.data.success(this.http.response);
}
}
if ( "error" in this.data ){
this.http.onerror = () => this.data.error(this.http.response);
}
if (this.data.async === false && "timeout" in this.data){
this.http.timeout = this.data.timeout;
if ("ontimeout" in this.data)
this.http.ontimeout = (this.data.ontimeout).bind(this.http);
}
}
post(){
this.default();
this.http.open("POST", this.data.url, this.data.async);
if ("contentType" in this.data) {
this.http.setRequestHeader('Content-Type', this.data.contentType);
}
if ("data" in this.data) {
this.http.send(JSON.stringify(this.data.data));
}
else {
this.http.send();
}
}
get(){
this.default();
if ("contentType" in this.data) {
this.http.setRequestHeader('Content-Type', this.data.contentType);
}
if ("data" in this.data) {
this.http.open("GET", this.data.url + "?" + this.data.data, this.data.async);
}
else {
this.http.open("GET", this.data.url, this.data.async);
}
this.http.send();
}
}
\ No newline at end of file \ No newline at end of file
...@@ -44,12 +44,12 @@ class Vector { ...@@ -44,12 +44,12 @@ class Vector {
class Line { class Line {
/** /**
* @param {Vector} position * @param {Vector} beg
* @param {Vector} size * @param {Vector} end
*/ */
constructor(position, size) { constructor(beg, end) {
this.position = position; this.beg = beg;
this.size = size; this.end = end;
} }
/** /**
...@@ -57,10 +57,10 @@ class Line { ...@@ -57,10 +57,10 @@ class Line {
*/ */
draw(pdf) { draw(pdf) {
pdf.line( pdf.line(
this.position.x, this.beg.x,
this.position.y, this.beg.y,
this.size.x, this.end.x,
this.size.y this.end.y
); );
} }
} }
...@@ -152,11 +152,34 @@ class Div { ...@@ -152,11 +152,34 @@ class Div {
* @param {Vector} size * @param {Vector} size
* @param {bool} draw * @param {bool} draw
*/ */
constructor(position, size, draw = false) { constructor(position, size, draw = false, log = false) {
this.position = position; this.position = position;
this.size = size; this.size = size;
this.drawOutline = draw; this.drawOutline = draw;
this.logChildren = log;
this.children = []; this.children = [];
const t = this;
this.acceptedProperties = [
{
"prop" : "position",
"func" : (v) => t._getCoordinates(v)
},
{
"prop" : "size",
"func" : (v) => t._getSize(v)
},
{
"prop" : "beg",
"func" : (v) => t._getCoordinates(v)
},
{
"prop" : "end",
"func" : (v) => t._getCoordinates(v)
},
];
} }
/** Allows any position you want **/ /** Allows any position you want **/
...@@ -171,13 +194,12 @@ class Div { ...@@ -171,13 +194,12 @@ class Div {
addRelativeChild(child) { addRelativeChild(child) {
if ("draw" in child === false) if ("draw" in child === false)
console.error("the object passed needs to have a 'draw' method that takes a jsPDF object"); console.error("the object passed needs to have a 'draw' method that takes a jsPDF object");
if ("position" in child)
child.position = this._getDrawCoordinates(child.position);
if ("size" in child)
child.size = this._getSizeCoordinates(child.size);
this.acceptedProperties.forEach( (p) => {
if (p.prop in child)
child[ p.prop ] = p.func( child[ p.prop ] );
});
this.children.push(child); this.children.push(child);
return this.children[this.children.length - 1]; return this.children[this.children.length - 1];
} }
...@@ -195,44 +217,45 @@ class Div { ...@@ -195,44 +217,45 @@ class Div {
} }
/** Allows any position you want relative to the position of this Div. Percentage based **/ /** Allows any position you want relative to the position of this Div. Percentage based **/
getAbsoluteVector(vector) { getAbsoluteVector(v) {
return this.position.addxy( return this.position.addxy(
(this.size.x * vector.x / 100), (this.size.x * v.x / 100),
(this.size.y * vector.y / 100) (this.size.y * v.y / 100)
); );
} }
/** /**
* Compiles the true position coordinates based on percentage relative to parent element * Compiles the true position coordinates based on percentage relative to parent element
* Assumes the elements grow to the right and down * Assumes the elements grow to the right and down
* @param {Vector} position * @param {Vector} v
*/ */
_getDrawCoordinates(position) { _getCoordinates(v) {
if (position.x < 0 || position.x > 100 || position.y < 0 || position.y > 100) if (v.x < 0 || v.x > 100 || v.y < 0 || v.y > 100)
console.error("position components need to be real numbers in the range [0;100]"); console.error("position components need to be real numbers in the range [0;100]");
return this.position.addxy( return this.position.addxy(
(this.size.x * position.x / 100), (this.size.x * v.x / 100),
(this.size.y * position.y / 100) (this.size.y * v.y / 100)
); );
} }
/** /**
* Compiles the true size based on percentage relative to parent element * Compiles the size coordinates based on percentage relative to parent element
* Assumes the elements grow to the right and down * Assumes the elements grow to the right and down
* @param {Vector?} size * @param {Vector} s
*/ */
_getSizeCoordinates(size) { _getSize(s) {
if (size.x < 0 || size.x > 100 || size.y < 0 || size.y > 100) if (s.x < 0 || s.x > 100 || s.y < 0 || s.y > 100)
console.error("size components need to be real numbers in the range [0;100]"); console.error("position components need to be real numbers in the range [0;100]");
return new Vector ( return new Vector (
this.size.x * size.x / 100, (this.size.x * s.x / 100),
this.size.y * size.y / 100, (this.size.y * s.y / 100)
); );
} }
draw(pdf) { draw(pdf) {
/** Draw the confines of the div **/ /** Draw the confines of the div **/
if (this.drawOutline) { if (this.drawOutline) {
/** Upper **/ /** Upper **/
...@@ -257,8 +280,13 @@ class Div { ...@@ -257,8 +280,13 @@ class Div {
)); ));
} }
/** Log Children **/
if (this.logChildren) {
console.log(this.children);
}
/** Recursion **/ /** Recursion **/
this.children.forEach( child => child.draw(pdf) ); this.children.forEach( child => child.draw(pdf));
} }
} }
......
function collectToSearch() {
f = document.getElementById("form");
inputs = f.getElementsByTagName("input");
data = {};
function BadInputException(input) {
this.error = "badinput";
this.input = input;
}
Array.from(inputs).forEach( input => {
if (input.checkValidity() === false){
input.reportValidity("Por favor llene este campo");
throw BadInputException(input);
}
sub = input.getAttribute("sub");
if ( (sub in data) === false ) {
data[sub] = {}
}
data[sub][input.name] = input.value;
});
message("Espere...");
console.log(data);
const obj = {
"url" : "/pdf",
"contentType" : "application/json",
"async" : true,
"data" : data,
"success" : (response) => {
let r;
try {
r = JSON.parse(response);
document.getElementById("message").click();
} catch (error) {
message(response);
}
document.getElementById("results").style.display = "block";
document.getElementById("form").style.display = "none";
fillResults(r);
},
"error" : (response) => message(response),
"timeout" : 120000,
"ontimeout" : (response) => message("La conexión tardó demasiado.")
}
ajax = new Ajax(obj);
ajax.post();
}
function collectToConvert() {
r = document.getElementById("results")
inputs = r.getElementsByTagName("input");
data = {};
defecto = document.getElementsByName("defecto")[0].value;
Array.from(inputs).forEach(input => {
if (input.name == "defecto") return;
sub = input.getAttribute("sub");
if ((sub in data) === false) {
data[sub] = {}
}
data[sub][input.name] = (input.value == "?" || input.value == "" ? defecto : input.value);
});
return data;
}
function message(msg) {
let m = document.getElementById("message");
m.style.display = "block";
m = document.getElementById("msg");
m.innerHTML = msg;
}
function fillResults(results) {
r = document.getElementById("results")
inputs = r.getElementsByTagName("input");
Array.from(inputs).forEach(input => {
if (input.name == "defecto") return;
sub = input.getAttribute("sub");
input.value = results[sub][input.name];
});
}
\ No newline at end of file \ No newline at end of file
function getAncestorByAttribute(elem, attr, val) {
while (elem.getAttribute(attr) != val || elem == null) elem = elem.parentElement;
return elem;
}
function getDescendantByAttribute(elem, attr, val) {
if (elem == null || elem.getAttribute(attr) == val) return elem;
return Array.from(elem.children).reduce((a, b) => {
let x = getDescendantByAttribute(a, attr, val);
let y = getDescendantByAttribute(b, attr, val);
return x == null ? y : x;
}, null);
}
function getAncestorByTag(elem, val) {
while (elem.nodeName != val.toUpperCase() || elem == null) elem = elem.parentElement;
return elem;
}
function getDescendantByTag(elem, val) {
if (elem == null || elem.nodeName == val.toUpperCase()) return elem;
return Array.from(elem.children).reduce((a, b) => {
let x = getDescendantByTag(a, val);
let y = getDescendantByTag(b, val);
return x == null ? y : x;
}, null);
}
\ No newline at end of file \ No newline at end of file
...@@ -105,14 +105,13 @@ class PDF1 { ...@@ -105,14 +105,13 @@ class PDF1 {
]); ]);
}; };
for (let i = 0; i < ejes.length; i++) { for (let i = 0; i < 2; i++) {
const x = data[i];
table( table(
ejes[i], ejes[i],
i + 1, i + 1,
x["rendimiento_izquierdo"], data[`rendimiento_izquierdo_${i+1}`],
x["peso_estatico"], data[`peso_estatico_${i+1}`],
x["rendimiento_derecho"] data[`rendimiento_derecho_${i+1}`]
); );
} }
...@@ -169,18 +168,16 @@ class PDF1 { ...@@ -169,18 +168,16 @@ class PDF1 {
}; };
for (let i = 0; i < ejes.length; i++) { for (let i = 0; i < ejes.length; i++) {
const x = data[i];
if (x == undefined) continue;
table( table(
ejes[i], ejes[i],
i + 1, i + 1,
x["fuerza_izquierda"], data[`fuerza_izquierda_${i + 1}`],
x["resistencia_izquierda"], data[`resistencia_izquierda_${i + 1}`],
x["ovalidad_izquierda"], data[`ovalidad_izquierda_${i + 1}`],
x["peso_estatico"], data[`peso_estatico_${i + 1}`],
x["fuerza_derecha"], data[`fuerza_derecha_${i + 1}`],
x["resistencia_derecha"], data[`resistencia_derecha_${i + 1}`],
x["ovalidad_derecha"] data[`ovalidad_derecha_${i + 1}`]
); );
} }
......
...@@ -15,11 +15,6 @@ td{ ...@@ -15,11 +15,6 @@ td{
width: 33.33%; width: 33.33%;
} }
table {
width: 100%;
font-size: var(--FontSize);
}
.header { .header {
width: 50%; width: 50%;
} }
...@@ -35,12 +30,7 @@ table { ...@@ -35,12 +30,7 @@ table {
margin-bottom: 3%; margin-bottom: 3%;
width: 100%; width: 100%;
text-align: center; text-align: center;
} bottom: 0px;
#pdf {
border: dashed;
border-color: grey;
margin: 1%;
} }
.PDFButton { .PDFButton {
...@@ -71,13 +61,42 @@ input { ...@@ -71,13 +61,42 @@ input {
font-weight: normal; font-weight: normal;
} }
.Message { .MessageContainer {
font-size: 20; background-color: rgba(150, 150, 150, 0.5);
width: 100%;
height: 100%;
position: fixed; position: fixed;
right: 50; top: 0;
top: 50; left: 0;
}
.Message, .MessageFixed {
max-width: 33%;
padding: 1%; padding: 1%;
font-size: 20;
border: 2px solid gray; border: 2px solid gray;
background-color: rgba(200, 150, 250, 0.5); background-color: rgb(200, 150, 250);
width: 30%; }
.Message {
min-width: 10%;
min-height: 10%;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.MessageFixed {
position: absolute;
top: 50;
right: 50;
}
.X {
position: absolute;
top: 3;
right: 3;
font-weight: bolder;
font-family: Arial, Helvetica, sans-serif;
} }
\ No newline at end of file \ No newline at end of file
...@@ -4,108 +4,154 @@ ...@@ -4,108 +4,154 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script>
<script src="{{ url_for('static', filename = 'src/ajax.js') }}"></script>
<script src="{{ url_for('static', filename = 'src/div.js') }}"></script> <script src="{{ url_for('static', filename = 'src/div.js') }}"></script>
<script src="{{ url_for('static', filename = 'src/getters.js') }}"></script> <script src="{{ url_for('static', filename = 'src/getters.js') }}"></script>
<script src="{{ url_for('static', filename = 'src/pdf1.js') }}"></script> <script src="{{ url_for('static', filename = 'src/pdf1.js') }}"></script>
<script src="{{ url_for('static', filename = 'src/pdf2.js') }}"></script> <script src="{{ url_for('static', filename = 'src/pdf2.js') }}"></script>
<script src="{{ url_for('static', filename = 'src/forms.js') }}"></script>
<link rel="stylesheet" href="{{ url_for('static', filename = 'styles/general.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename = 'styles/general.css') }}">
<!--INCLUIMOS LA FUENTE--> <!--INCLUIMOS LA FUENTE-->
<link rel="stylesheet" media="screen" href="https://fontlibrary.org/face/cmu-typewriter" type="text/css" /> <link rel="stylesheet" media="screen" href="https://fontlibrary.org/face/cmu-typewriter" type="text/css" />
<title>Pruebas de Alineamiento</title> <title>Pruebas de Alineamiento</title>
</head> </head>
<body> <body>
<div class="Message"> <div id="results" style="display: {% if bypass %} block {% else %} none {% endif %};">
Los datos con signo de pregunta '?' son datos no encontrados o faltantes.<br> <div class="MessageFixed">
Pueden ser completados a mano antes de convertir a PDF.<br> Los datos con signo de pregunta '?' son datos no encontrados o faltantes.<br>
De no ser completados, se verán como lo que diga el campo 'Por defecto' al final de la página. Pueden ser completados a mano antes de convertir a PDF.<br>
</div> De no ser completados, se completaran automáticamente con el valor del campo 'Por defecto' al final de la página.
<h1>Datos Generales:</h1> </div>
Patente <input type="text" name="patente" value="{{ data['header']['patente'] }}"> <h1>Datos Generales:</h1>
<br> Patente <input sub="header" type="text" name="patente">
Fecha <input type="text" name="fecha" value="{{ data['header']['fecha'] }}"> <br>
<br> Fecha <input sub="header" type="text" name="fecha">
<h1>Alineador:</h1>
Eje Delantero <input type="text" name="eje_delantero" value="{{ data['alineador']['eje_delantero'] }}">
<br>
<h1>Suspensión:</h1>
{% for eje in data['suspension'] %}
Rendimiento Izquerdo <input type="text" name="rendimiento_izquierdo" value="{{ eje['rendimiento_izquierdo'] }}">
<br>
Rendimiento Derecho <input type="text" name="rendimiento_derecho" value="{{ eje['rendimiento_derecho'] }}">
<br>
Peso Estático (Total) <input type="text" name="peso_estatico" value="{{ eje['peso_estatico'] }}">
<br> <br>
<h1>Alineador:</h1>
Eje Delantero <input sub="alineador" type="text" name="eje_delantero">
<br> <br>
{% endfor %} <h1>Suspensión:</h1>
{% for eje in range(2) %}
<h1>Frenos:</h1>
{% for eje in data['frenos'] %} <h3>Eje {{ eje + 1 }}</h3>
Rendimiento Izquerdo <input sub="suspension" type="text" name="rendimiento_izquierdo_{{ eje + 1 }}">
<br>
Rendimiento Derecho <input sub="suspension" type="text" name="rendimiento_derecho_{{ eje + 1 }}">
<br>
Peso Estático (Total) <input sub="suspension" type="text" name="peso_estatico_{{ eje + 1 }}">
<br>
Peso Dinámico (Báscula) <input sub="suspension" type="text" name="peso_dinamico_{{ eje + 1 }}">
<br>
<br>
{% endfor %}
<h1>Frenos:</h1>
{% for eje in range(4) %}
<h3>Eje {{ eje + 1 }}</h3>
Fuerza Izquierda <input sub="frenos" type="text" name="fuerza_izquierda_{{ eje + 1 }}">
<br>
Fuerza Derecha <input sub="frenos" type="text" name="fuerza_derecha_{{ eje + 1 }}">
<br>
Resistencia Izquierda <input sub="frenos" type="text" name="resistencia_izquierda_{{ eje + 1 }}">
<br>
Resistencia Derecha <input sub="frenos" type="text" name="resistencia_derecha_{{ eje + 1 }}">
<br>
Ovalidad Izquierda <input sub="frenos" type="text" name="ovalidad_izquierda_{{ eje + 1 }}">
<br>
Ovalidad Derecha <input sub="frenos" type="text" name="ovalidad_derecha_{{ eje + 1 }}">
<br>
Peso Estático (Total) <input sub="frenos" type="text" name="peso_estatico_{{ eje + 1 }}">
<br>
Peso Dinámico (Báscula) <input sub="frenos" type="text" name="peso_dinamico_{{ eje + 1 }}">
<br>
<br>
{% endfor %}
Fuerza Izquierda <input type="text" name="fuerza_izquierda" value="{{ eje['fuerza_izquierda'] }}"> <h1>Freno Trasero:</h1>
Fuerza Izquierda <input sub="trasero" type="text" name="fuerza_izquierda">
<br> <br>
Fuerza Derecha <input type="text" name="fuerza_derecha" value="{{ eje['fuerza_derecha'] }}"> Fuerza Derecha <input sub="trasero" type="text" name="fuerza_derecha">
<br> <br>
Resistencia Izquierda <input type="text" name="resistencia_izquierda" value="{{ eje['resistencia_izquierda'] }}"> Eje Nº <input sub="trasero" type="text" name="eje">
<br> <br>
Resistencia Derecha <input type="text" name="resistencia_derecha" value="{{ eje['resistencia_derecha'] }}">
<h1>Gases y Humos</h1>
Opacidad Logarítmica <input sub="gaseshumos" type="text" name="opacidad_logaritmica">
<br> <br>
Ovalidad Izquierda <input type="text" name="ovalidad_izquierda" value="{{ eje['ovalidad_izquierda'] }}"> CO <input sub="gaseshumos" type="text" name="co">
<br> <br>
Ovalidad Derecha <input type="text" name="ovalidad_derecha" value="{{ eje['ovalidad_derecha'] }}"> HC <input sub="gaseshumos" type="text" name="hc">
<br> <br>
Peso Estático (Total) <input type="text" name="peso_estatico" value="{{ eje['peso_estatico'] }}">
<br> <br>
<br> <br>
Por defecto: <input type="text" name="defecto" value="0.00">
{% endfor %} <br>
<h1>Freno Trasero:</h1> <div class="PDFButtonContainer">
Fuerza Izquierda <input type="text" name="fuerza_izquierda" value="{{ data['trasero']['fuerza_izquierda'] }}"> <button class="PDFButton" onclick=
<br> "window.open(
Fuerza Derecha <input type="text" name="fuerza_derecha" value="{{ data['trasero']['fuerza_derecha'] }}"> compile(
<br> (new PDF1()).pdf( collectToConvert() ),
new jsPDF('portrait', 'pt', 'a4')
<h1>Gases y Humos</h1> )
Opacidad Logarítmica <input type="text" name="opacidad_logaritmica" value="{{ data['gaseshumos']['opacidad_logaritmica'] }}"> .output('bloburl')
<br> )";
CO <input type="text" name="co" value="{{ data['gaseshumos']['co'] }}"> >
<br> Convertir a PDF - 1
HC <input type="text" name="hc" value="{{ data['gaseshumos']['hc'] }}"> </button>
<br>
<br> <button class="PDFButton" onclick=
<br> "window.open(
Por defecto: <input type="text" name="defecto" value="0.000"> compile(
<br> (new PDF2()).pdf( collectToConvert() ),
new jsPDF('portrait', 'pt', 'a4')
)
.output('bloburl')
)";
>
Convertir a PDF - 2
</button>
<img id="maha" src="{{ url_for('static', filename = 'assets/maha.png') }}" style="display: none;">
</div>
</div>
<div class="PDFButtonContainer"> <div id="form" style="height: 100%; display: {% if bypass %} none {% else %} block {% endif %}">
<button class="PDFButton" onclick= <h1>Generación de PDF:</h1>
"window.open(
compile(
(new PDF1()).pdf( {{ data }} ),
new jsPDF('portrait', 'pt', 'a4')
)
.output('bloburl')
)";
>
Convertir a PDF - 1
</button>
<button class="PDFButton" onclick= Usuario <input required type="text" sub="credenciales" name="usuario">
"window.open( <br>
compile( Contraseña <input required type="password" sub="credenciales" name="contrasena">
(new PDF2()).pdf( {{ data }} ), <br>
new jsPDF('portrait', 'pt', 'a4') Patente <input required type="text" sub="header" name="patente">
) <br>
.output('bloburl')
)"; <h1>Datos Extra:</h1>
>
Convertir a PDF - 2 Rendimiento Izquierdo - Eje 1 <input required type="number" step="any" sub="suspension" name="rendimiento_izquierdo_1">
</button> <br>
<img id="maha" src="{{ url_for('static', filename = 'assets/maha.png') }}" style="display: none;"> Rendimiento Derecho - Eje 1 <input required type="number" step="any" sub="suspension" name="rendimiento_derecho_1">
<br>
Rendimiento Izquierdo - Eje 2 <input required type="number" step="any" sub="suspension" name="rendimiento_izquierdo_2">
<br>
Rendimiento Derecho - Eje 2 <input required type="number" step="any" sub="suspension" name="rendimiento_derecho_2">
<br>
<div class="PDFButtonContainer">
<button class="PDFButton" onclick="collectToSearch()">
Buscar
</button>
</div>
</div>
<div id="message" class="MessageContainer" onclick="this.style.display = 'none'" style="display: none;">
<div class="Message" style="text-align: center;">
<p id = "msg"></p>
<span class = "X">x<span>
</div>
</div> </div>
</body> </body>
</html> </html>
\ No newline at end of file \ No newline at end of file
{% macro header(dom,fecha) %}
<table class="header">
<tr>
<td>Dominio: {{ dom }}</td> <td>Fecha: {{ fecha }}</td>
</tr>
</table>
{% endmacro %}
{% macro alineador(eje_delan) %}
&ensp; Resultado Pruebas de Alineador al Paso
<br>
<br>
&ensp; Eje Delantero &ensp; {{ eje_delan }}
{% endmacro %}
{% macro suspension(eje, ren_izq, peso, ren_der) %}
&ensp; Resultado Pruebas en Banco de Suspensión - Eje {{ eje }}
<table>
<tr>
<td>Rendimiento Izquierdo</td> <td>Peso Total del Eje</td> <td>Rendimiento Derecho</td>
</tr>
<tr>
<td>{{ ren_izq }}</td> <td>{{ peso }}</td> <td>{{ ren_der }}</td>
</tr>
</table>
{% endmacro %}
{% macro frenos(eje , f_izq, res_izq, ov_izq, peso, f_der, res_der, ov_der) %}
&ensp; Diagnóstico de Frenos - Eje {{ eje }}
<table>
<tr>
<td>Fuerza IZ</td> <td>Peso del Eje</td> <td>Fuerza DE</td>
</tr>
<tr>
<td>{{ f_izq }}</td> <td>{{ peso }}</td> <td>{{ f_der }}</td>
</tr>
<tr>
<td>Res. Rodadura IZ</td> <td></td> <td>Res. Rodadura IZ</td>
</tr>
<tr>
<td>{{ res_izq }}</td> <td></td> <td>{{ res_der }}</td>
</tr>
<tr>
<td>Ovalidad IZ</td> <td></td> <td>Ovalidad DE</td>
</tr>
<tr>
<td>{{ ov_izq }}</td> <td></td> <td>{{ ov_der }}</td>
<tr>
</table>
{% endmacro %}
{% macro trasero(f_izq, f_der) %}
&ensp; Diagnóstico de Frenos - Eje Trasero - Freno de Mano
<table>
<tr>
<td>Fuerza IZ</td> <td></td> <td>Fuerza DE</td>
</tr>
<tr>
<td>{{ f_izq }}</td> <td></td> <td>{{ f_der }}</td>
</tr>
</table>
{% endmacro %}
{% macro gaseshumos(co, hc, med) %}
<table style="width: 60%; float: left;">
<tr>
<td style="width: 66%">
Resultado Analizador de Gases
</td>
</tr>
<tr>
<td>
CO {{ co }} %
</td>
<td>
HC {{ hc }} ppm
</td>
</tr>
</table>
<table style="width: 40%; float: left;">
<tr>
<td>
Resultado Analizador de Humos
</td>
</tr>
<tr>
<td>
Medición {{ med }}
</td>
</tr>
</table>
{% endmacro %}
\ No newline at end of file \ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!