Este sitio sirve para hacer pruebas básicas de desarrollo.
+En este momento se despliega la información de los paraderos y recorridos de los archivos kmz
+diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..d43c1be
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,29 @@
+FROM ubuntu:22.04
+#FROM debian:buster-slim
+#FROM python:3
+
+RUN apt-get update -y
+RUN apt-get install -y python3-pip python3-bs4
+
+# set a directory for the app
+RUN groupadd app && useradd -m -g app app
+
+# copy all the files to the container
+#RUN git clone https://dev.ilab.cl/public/pythonweb.git /srv
+COPY app.py /srv
+COPY webinterface /srv/webinterface
+RUN chown -R app:app /srv
+
+
+# install dependencies
+WORKDIR /srv
+RUN pip3 install setuptools gunicorn
+RUN pip3 install --no-cache-dir -r webinterface/requirements.txt
+
+USER app
+# define the port number the container should expose
+EXPOSE 8000
+
+# run the command
+ENTRYPOINT ["gunicorn"]
+CMD ["-b", "0.0.0.0:8000", "app:iapp"]
\ No newline at end of file
diff --git a/Setup.sh b/Setup.sh
new file mode 100755
index 0000000..b0f00b3
--- /dev/null
+++ b/Setup.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+if [ "$EUID" -ne 0 ]; then
+ echo "Este script requiere permisos de root."
+ exit
+fi
+
+
+apt update
+apt install -y python3-pip
+
+pip3 install setuptools gunicorn
+pip3 install -r web-interface/requirements.txt
diff --git a/WebService.sh b/WebService.sh
new file mode 100644
index 0000000..984cd46
--- /dev/null
+++ b/WebService.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+if [ "$EUID" -ne 0 ]; then
+ echo "Este script requiere permisos de root."
+ exit
+fi
+
+
+apt-get update
+apt-get install -y python3-pip
+
+git clone https://dev.ilab.cl/public/pythonweb.git /srv
+
+cd /srv
+pip3 install setuptools gunicorn
+pip3 install -r web-interface/requirements.txt
+
+cp -f webinterface.service.sample /etc/systemd/system/webinterface.service
+
+systemctl unmask webinterface.service
+systemctl enable webinterface.service
+systemctl start webinterface.service
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..4356afd
--- /dev/null
+++ b/app.py
@@ -0,0 +1,6 @@
+from webinterface import create_app
+
+iapp = create_app()
+
+if __name__ == '__main__':
+ iapp.run()
diff --git a/bp.sh b/bp.sh
new file mode 100755
index 0000000..820b57d
--- /dev/null
+++ b/bp.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+die(){
+ echo "$1"
+ exit 1
+}
+
+# if not enough args displayed, display an error and die
+[ $# -eq 0 ] && die "Usage: $0 [devel|stable|tag]"
+
+docker build -t docker.ilab.cl/ilab-mtt:$1 .
+if [ $1 == "stable" ]; then
+ docker image push docker.ilab.cl/ilab-mtt:$1
+fi
+docker-compose up
diff --git a/crea_db.py b/crea_db.py
new file mode 100644
index 0000000..4613bc3
--- /dev/null
+++ b/crea_db.py
@@ -0,0 +1,21 @@
+from webinterface import create_app, Config, db
+
+import datetime
+
+config = Config()
+#config.SQLALCHEMY_DATABASE_URI = 'sqlite:///GranConcepcion-{}.db'.format(datetime.datetime.now().strftime("%Y%m%d%H%M"))
+config.SQLALCHEMY_DATABASE_URI = 'sqlite:///GranConcepcion-process.db'
+config.DEBUG = True
+
+iapp = create_app(config)
+
+
+with iapp.app_context():
+
+ from webinterface.models.cargamodelo import load_dataset, completa_dataset, agrega_paraderos
+# db.create_all()
+
+# load_dataset()
+ completa_dataset()
+
+ agrega_paraderos()
\ No newline at end of file
diff --git a/datos/ESTACIONES_BIOTREN.kmz b/datos/ESTACIONES_BIOTREN.kmz
new file mode 100644
index 0000000..795cafc
Binary files /dev/null and b/datos/ESTACIONES_BIOTREN.kmz differ
diff --git a/datos/PARADEROS_FORMALES.kmz b/datos/PARADEROS_FORMALES.kmz
new file mode 100644
index 0000000..8357ad8
Binary files /dev/null and b/datos/PARADEROS_FORMALES.kmz differ
diff --git a/datos/TRAZADOS/100 - 81SC.kmz b/datos/TRAZADOS/100 - 81SC.kmz
new file mode 100644
index 0000000..328a435
Binary files /dev/null and b/datos/TRAZADOS/100 - 81SC.kmz differ
diff --git a/datos/TRAZADOS/102 - 12QA.kmz b/datos/TRAZADOS/102 - 12QA.kmz
new file mode 100644
index 0000000..98ba637
Binary files /dev/null and b/datos/TRAZADOS/102 - 12QA.kmz differ
diff --git a/datos/TRAZADOS/103 - 12RB.kmz b/datos/TRAZADOS/103 - 12RB.kmz
new file mode 100644
index 0000000..5fc8bcf
Binary files /dev/null and b/datos/TRAZADOS/103 - 12RB.kmz differ
diff --git a/datos/TRAZADOS/104 - 80JQ.kmz b/datos/TRAZADOS/104 - 80JQ.kmz
new file mode 100644
index 0000000..6901314
Binary files /dev/null and b/datos/TRAZADOS/104 - 80JQ.kmz differ
diff --git a/datos/TRAZADOS/104 - 80KH.kmz b/datos/TRAZADOS/104 - 80KH.kmz
new file mode 100644
index 0000000..75b1c9f
Binary files /dev/null and b/datos/TRAZADOS/104 - 80KH.kmz differ
diff --git a/datos/TRAZADOS/105 - 10DM.kmz b/datos/TRAZADOS/105 - 10DM.kmz
new file mode 100644
index 0000000..de7a09e
Binary files /dev/null and b/datos/TRAZADOS/105 - 10DM.kmz differ
diff --git a/datos/TRAZADOS/105 - 10TK Variante Tumbes.kmz b/datos/TRAZADOS/105 - 10TK Variante Tumbes.kmz
new file mode 100644
index 0000000..4db72fb
Binary files /dev/null and b/datos/TRAZADOS/105 - 10TK Variante Tumbes.kmz differ
diff --git a/datos/TRAZADOS/106 - 10AN.kmz b/datos/TRAZADOS/106 - 10AN.kmz
new file mode 100644
index 0000000..9268065
Binary files /dev/null and b/datos/TRAZADOS/106 - 10AN.kmz differ
diff --git a/datos/TRAZADOS/106 - 10JL.kmz b/datos/TRAZADOS/106 - 10JL.kmz
new file mode 100644
index 0000000..a3cc276
Binary files /dev/null and b/datos/TRAZADOS/106 - 10JL.kmz differ
diff --git a/datos/TRAZADOS/107 - 10BO.kmz b/datos/TRAZADOS/107 - 10BO.kmz
new file mode 100644
index 0000000..7e97ff4
Binary files /dev/null and b/datos/TRAZADOS/107 - 10BO.kmz differ
diff --git a/datos/TRAZADOS/108 - 16HK.kmz b/datos/TRAZADOS/108 - 16HK.kmz
new file mode 100644
index 0000000..b54a8c5
Binary files /dev/null and b/datos/TRAZADOS/108 - 16HK.kmz differ
diff --git a/datos/TRAZADOS/108 - 16IV.kmz b/datos/TRAZADOS/108 - 16IV.kmz
new file mode 100644
index 0000000..b41feb9
Binary files /dev/null and b/datos/TRAZADOS/108 - 16IV.kmz differ
diff --git a/datos/TRAZADOS/109 - 14HT CHIGUAYANTE SUR.kmz b/datos/TRAZADOS/109 - 14HT CHIGUAYANTE SUR.kmz
new file mode 100644
index 0000000..f47e481
Binary files /dev/null and b/datos/TRAZADOS/109 - 14HT CHIGUAYANTE SUR.kmz differ
diff --git a/datos/TRAZADOS/110 - 10CP.kmz b/datos/TRAZADOS/110 - 10CP.kmz
new file mode 100644
index 0000000..25c0bdc
Binary files /dev/null and b/datos/TRAZADOS/110 - 10CP.kmz differ
diff --git a/datos/TRAZADOS/111 - 11CM.kmz b/datos/TRAZADOS/111 - 11CM.kmz
new file mode 100644
index 0000000..74ec0c1
Binary files /dev/null and b/datos/TRAZADOS/111 - 11CM.kmz differ
diff --git a/datos/TRAZADOS/111 - 11EQ.kmz b/datos/TRAZADOS/111 - 11EQ.kmz
new file mode 100644
index 0000000..f9aee96
Binary files /dev/null and b/datos/TRAZADOS/111 - 11EQ.kmz differ
diff --git a/datos/TRAZADOS/112 - 11FR.kmz b/datos/TRAZADOS/112 - 11FR.kmz
new file mode 100644
index 0000000..98ca78b
Binary files /dev/null and b/datos/TRAZADOS/112 - 11FR.kmz differ
diff --git a/datos/TRAZADOS/115 - 17AW EXPRESO PLAZA DEL MALL.kmz b/datos/TRAZADOS/115 - 17AW EXPRESO PLAZA DEL MALL.kmz
new file mode 100644
index 0000000..d4a7deb
Binary files /dev/null and b/datos/TRAZADOS/115 - 17AW EXPRESO PLAZA DEL MALL.kmz differ
diff --git a/datos/TRAZADOS/115 - 17MC Expresos Plaza del Mall.kmz b/datos/TRAZADOS/115 - 17MC Expresos Plaza del Mall.kmz
new file mode 100644
index 0000000..e4e9e0c
Binary files /dev/null and b/datos/TRAZADOS/115 - 17MC Expresos Plaza del Mall.kmz differ
diff --git a/datos/TRAZADOS/117 - 14ZU CHIGUAYANTE SUR.kmz b/datos/TRAZADOS/117 - 14ZU CHIGUAYANTE SUR.kmz
new file mode 100644
index 0000000..63c5d28
Binary files /dev/null and b/datos/TRAZADOS/117 - 14ZU CHIGUAYANTE SUR.kmz differ
diff --git a/datos/TRAZADOS/118 - 17OX EXPRESO PLAZA DEL MALL.kmz b/datos/TRAZADOS/118 - 17OX EXPRESO PLAZA DEL MALL.kmz
new file mode 100644
index 0000000..07a1dae
Binary files /dev/null and b/datos/TRAZADOS/118 - 17OX EXPRESO PLAZA DEL MALL.kmz differ
diff --git a/datos/TRAZADOS/119 - 72JW.kmz b/datos/TRAZADOS/119 - 72JW.kmz
new file mode 100644
index 0000000..0a4657f
Binary files /dev/null and b/datos/TRAZADOS/119 - 72JW.kmz differ
diff --git a/datos/TRAZADOS/120 - 72KZ PEDRO DE VALDIVIA.kmz b/datos/TRAZADOS/120 - 72KZ PEDRO DE VALDIVIA.kmz
new file mode 100644
index 0000000..230b2d6
Binary files /dev/null and b/datos/TRAZADOS/120 - 72KZ PEDRO DE VALDIVIA.kmz differ
diff --git a/datos/TRAZADOS/121 - 65DQ_C¢ndor.kmz b/datos/TRAZADOS/121 - 65DQ_C¢ndor.kmz
new file mode 100644
index 0000000..345c79f
Binary files /dev/null and b/datos/TRAZADOS/121 - 65DQ_C¢ndor.kmz differ
diff --git a/datos/TRAZADOS/122- 30MB RUTA LAS PLAYAS.kmz b/datos/TRAZADOS/122- 30MB RUTA LAS PLAYAS.kmz
new file mode 100644
index 0000000..462997c
Binary files /dev/null and b/datos/TRAZADOS/122- 30MB RUTA LAS PLAYAS.kmz differ
diff --git a/datos/TRAZADOS/123 - 30NC RUTA LAS PLAYAS.kmz b/datos/TRAZADOS/123 - 30NC RUTA LAS PLAYAS.kmz
new file mode 100644
index 0000000..b50ed18
Binary files /dev/null and b/datos/TRAZADOS/123 - 30NC RUTA LAS PLAYAS.kmz differ
diff --git a/datos/TRAZADOS/124 - 30RD RUTA LAS PLAYAS.kmz b/datos/TRAZADOS/124 - 30RD RUTA LAS PLAYAS.kmz
new file mode 100644
index 0000000..7cfdc42
Binary files /dev/null and b/datos/TRAZADOS/124 - 30RD RUTA LAS PLAYAS.kmz differ
diff --git a/datos/TRAZADOS/126 - 30QE RUTA LAS PLAYAS.kmz b/datos/TRAZADOS/126 - 30QE RUTA LAS PLAYAS.kmz
new file mode 100644
index 0000000..be34c96
Binary files /dev/null and b/datos/TRAZADOS/126 - 30QE RUTA LAS PLAYAS.kmz differ
diff --git a/datos/TRAZADOS/127 - 31DF RUTA DEL MAR S.A..kmz b/datos/TRAZADOS/127 - 31DF RUTA DEL MAR S.A..kmz
new file mode 100644
index 0000000..59fee3f
Binary files /dev/null and b/datos/TRAZADOS/127 - 31DF RUTA DEL MAR S.A..kmz differ
diff --git a/datos/TRAZADOS/128 - 32EG INMOBILIARIA DEL MAR.kmz b/datos/TRAZADOS/128 - 32EG INMOBILIARIA DEL MAR.kmz
new file mode 100644
index 0000000..20a4268
Binary files /dev/null and b/datos/TRAZADOS/128 - 32EG INMOBILIARIA DEL MAR.kmz differ
diff --git a/datos/TRAZADOS/128 - 32JK INMOBILIARIA DEL MAR.kmz b/datos/TRAZADOS/128 - 32JK INMOBILIARIA DEL MAR.kmz
new file mode 100644
index 0000000..2a3ace6
Binary files /dev/null and b/datos/TRAZADOS/128 - 32JK INMOBILIARIA DEL MAR.kmz differ
diff --git a/datos/TRAZADOS/129 - 62HM PRIMAVERA.kmz b/datos/TRAZADOS/129 - 62HM PRIMAVERA.kmz
new file mode 100644
index 0000000..5dbebd6
Binary files /dev/null and b/datos/TRAZADOS/129 - 62HM PRIMAVERA.kmz differ
diff --git a/datos/TRAZADOS/130 - 40GN.kmz b/datos/TRAZADOS/130 - 40GN.kmz
new file mode 100644
index 0000000..47315ad
Binary files /dev/null and b/datos/TRAZADOS/130 - 40GN.kmz differ
diff --git a/datos/TRAZADOS/131 - 20JL.kmz b/datos/TRAZADOS/131 - 20JL.kmz
new file mode 100644
index 0000000..e2f73f6
Binary files /dev/null and b/datos/TRAZADOS/131 - 20JL.kmz differ
diff --git a/datos/TRAZADOS/133 - 44AB.kmz b/datos/TRAZADOS/133 - 44AB.kmz
new file mode 100644
index 0000000..8281e22
Binary files /dev/null and b/datos/TRAZADOS/133 - 44AB.kmz differ
diff --git a/datos/TRAZADOS/133 - 44EU FLOTA CENTAURO.kmz b/datos/TRAZADOS/133 - 44EU FLOTA CENTAURO.kmz
new file mode 100644
index 0000000..725d249
Binary files /dev/null and b/datos/TRAZADOS/133 - 44EU FLOTA CENTAURO.kmz differ
diff --git a/datos/TRAZADOS/134 - 41QV.kmz b/datos/TRAZADOS/134 - 41QV.kmz
new file mode 100644
index 0000000..4d263ba
Binary files /dev/null and b/datos/TRAZADOS/134 - 41QV.kmz differ
diff --git a/datos/TRAZADOS/135 - 41CR.kmz b/datos/TRAZADOS/135 - 41CR.kmz
new file mode 100644
index 0000000..d7f7fac
Binary files /dev/null and b/datos/TRAZADOS/135 - 41CR.kmz differ
diff --git a/datos/TRAZADOS/136 - 42UH.kmz b/datos/TRAZADOS/136 - 42UH.kmz
new file mode 100644
index 0000000..5179e80
Binary files /dev/null and b/datos/TRAZADOS/136 - 42UH.kmz differ
diff --git a/datos/TRAZADOS/137 - 42FW.kmz b/datos/TRAZADOS/137 - 42FW.kmz
new file mode 100644
index 0000000..9762f69
Binary files /dev/null and b/datos/TRAZADOS/137 - 42FW.kmz differ
diff --git a/datos/TRAZADOS/138 - 90EJ.kmz b/datos/TRAZADOS/138 - 90EJ.kmz
new file mode 100644
index 0000000..fb9ae50
Binary files /dev/null and b/datos/TRAZADOS/138 - 90EJ.kmz differ
diff --git a/datos/TRAZADOS/139 - 70IF.kmz b/datos/TRAZADOS/139 - 70IF.kmz
new file mode 100644
index 0000000..3bfd754
Binary files /dev/null and b/datos/TRAZADOS/139 - 70IF.kmz differ
diff --git a/datos/TRAZADOS/140 - 70JG.kmz b/datos/TRAZADOS/140 - 70JG.kmz
new file mode 100644
index 0000000..9558a52
Binary files /dev/null and b/datos/TRAZADOS/140 - 70JG.kmz differ
diff --git a/datos/TRAZADOS/141 - 62ON.kmz b/datos/TRAZADOS/141 - 62ON.kmz
new file mode 100644
index 0000000..7c38f7d
Binary files /dev/null and b/datos/TRAZADOS/141 - 62ON.kmz differ
diff --git a/datos/TRAZADOS/141 - 62VS_Mi Expreso.kmz b/datos/TRAZADOS/141 - 62VS_Mi Expreso.kmz
new file mode 100644
index 0000000..2a13bea
Binary files /dev/null and b/datos/TRAZADOS/141 - 62VS_Mi Expreso.kmz differ
diff --git a/datos/TRAZADOS/143 - 90YX.kmz b/datos/TRAZADOS/143 - 90YX.kmz
new file mode 100644
index 0000000..4f7b8be
Binary files /dev/null and b/datos/TRAZADOS/143 - 90YX.kmz differ
diff --git a/datos/TRAZADOS/144 - 57YP.kmz b/datos/TRAZADOS/144 - 57YP.kmz
new file mode 100644
index 0000000..732ffe4
Binary files /dev/null and b/datos/TRAZADOS/144 - 57YP.kmz differ
diff --git a/datos/TRAZADOS/145 - 63IG.kmz b/datos/TRAZADOS/145 - 63IG.kmz
new file mode 100644
index 0000000..8f705cc
Binary files /dev/null and b/datos/TRAZADOS/145 - 63IG.kmz differ
diff --git a/datos/TRAZADOS/147 - 24MF.kmz b/datos/TRAZADOS/147 - 24MF.kmz
new file mode 100644
index 0000000..78be995
Binary files /dev/null and b/datos/TRAZADOS/147 - 24MF.kmz differ
diff --git a/datos/TRAZADOS/148 - 24TR.kmz b/datos/TRAZADOS/148 - 24TR.kmz
new file mode 100644
index 0000000..c164635
Binary files /dev/null and b/datos/TRAZADOS/148 - 24TR.kmz differ
diff --git a/datos/TRAZADOS/149 - 21QB.kmz b/datos/TRAZADOS/149 - 21QB.kmz
new file mode 100644
index 0000000..e6b9831
Binary files /dev/null and b/datos/TRAZADOS/149 - 21QB.kmz differ
diff --git a/datos/TRAZADOS/150 - 22RC.kmz b/datos/TRAZADOS/150 - 22RC.kmz
new file mode 100644
index 0000000..a1e4021
Binary files /dev/null and b/datos/TRAZADOS/150 - 22RC.kmz differ
diff --git a/datos/TRAZADOS/151 - 22SN.kmz b/datos/TRAZADOS/151 - 22SN.kmz
new file mode 100644
index 0000000..8fd50be
Binary files /dev/null and b/datos/TRAZADOS/151 - 22SN.kmz differ
diff --git a/datos/TRAZADOS/152 - 22XE.kmz b/datos/TRAZADOS/152 - 22XE.kmz
new file mode 100644
index 0000000..cbaecca
Binary files /dev/null and b/datos/TRAZADOS/152 - 22XE.kmz differ
diff --git a/datos/TRAZADOS/153 - 22JO.kmz b/datos/TRAZADOS/153 - 22JO.kmz
new file mode 100644
index 0000000..cc1ea27
Binary files /dev/null and b/datos/TRAZADOS/153 - 22JO.kmz differ
diff --git a/datos/TRAZADOS/154 - 23EV SAN PEDRO DEL MAR.kmz b/datos/TRAZADOS/154 - 23EV SAN PEDRO DEL MAR.kmz
new file mode 100644
index 0000000..048962a
Binary files /dev/null and b/datos/TRAZADOS/154 - 23EV SAN PEDRO DEL MAR.kmz differ
diff --git a/datos/TRAZADOS/154 - 23LP.kmz b/datos/TRAZADOS/154 - 23LP.kmz
new file mode 100644
index 0000000..e62cfd6
Binary files /dev/null and b/datos/TRAZADOS/154 - 23LP.kmz differ
diff --git a/datos/TRAZADOS/155 - 23AQ.kmz b/datos/TRAZADOS/155 - 23AQ.kmz
new file mode 100644
index 0000000..9fe4b9d
Binary files /dev/null and b/datos/TRAZADOS/155 - 23AQ.kmz differ
diff --git a/datos/TRAZADOS/156 - 52AD.kmz b/datos/TRAZADOS/156 - 52AD.kmz
new file mode 100644
index 0000000..40d2d0a
Binary files /dev/null and b/datos/TRAZADOS/156 - 52AD.kmz differ
diff --git a/datos/TRAZADOS/157 - 40BP.kmz b/datos/TRAZADOS/157 - 40BP.kmz
new file mode 100644
index 0000000..1c94871
Binary files /dev/null and b/datos/TRAZADOS/157 - 40BP.kmz differ
diff --git a/datos/TRAZADOS/160 - 71ZI.kmz b/datos/TRAZADOS/160 - 71ZI.kmz
new file mode 100644
index 0000000..afc6105
Binary files /dev/null and b/datos/TRAZADOS/160 - 71ZI.kmz differ
diff --git a/datos/TRAZADOS/161 - 60XK.kmz b/datos/TRAZADOS/161 - 60XK.kmz
new file mode 100644
index 0000000..c2a99cc
Binary files /dev/null and b/datos/TRAZADOS/161 - 60XK.kmz differ
diff --git a/datos/TRAZADOS/162 - 60YL.kmz b/datos/TRAZADOS/162 - 60YL.kmz
new file mode 100644
index 0000000..9e7e31f
Binary files /dev/null and b/datos/TRAZADOS/162 - 60YL.kmz differ
diff --git a/datos/TRAZADOS/163 - 65ER.kmz b/datos/TRAZADOS/163 - 65ER.kmz
new file mode 100644
index 0000000..6fbb8a0
Binary files /dev/null and b/datos/TRAZADOS/163 - 65ER.kmz differ
diff --git a/datos/TRAZADOS/163 - 65FS_C¢ndor.kmz b/datos/TRAZADOS/163 - 65FS_C¢ndor.kmz
new file mode 100644
index 0000000..9b9ab8d
Binary files /dev/null and b/datos/TRAZADOS/163 - 65FS_C¢ndor.kmz differ
diff --git a/datos/TRAZADOS/164 - 63KP.kmz b/datos/TRAZADOS/164 - 63KP.kmz
new file mode 100644
index 0000000..e1bdecd
Binary files /dev/null and b/datos/TRAZADOS/164 - 63KP.kmz differ
diff --git a/datos/TRAZADOS/165 - 43JT.kmz b/datos/TRAZADOS/165 - 43JT.kmz
new file mode 100644
index 0000000..280eb40
Binary files /dev/null and b/datos/TRAZADOS/165 - 43JT.kmz differ
diff --git a/datos/TRAZADOS/166 - 70KH LAS BAHÖAS.kmz b/datos/TRAZADOS/166 - 70KH LAS BAHÖAS.kmz
new file mode 100644
index 0000000..eb6319e
Binary files /dev/null and b/datos/TRAZADOS/166 - 70KH LAS BAHÖAS.kmz differ
diff --git a/datos/TRAZADOS/167 - 60ZM.kmz b/datos/TRAZADOS/167 - 60ZM.kmz
new file mode 100644
index 0000000..cde1c4f
Binary files /dev/null and b/datos/TRAZADOS/167 - 60ZM.kmz differ
diff --git a/datos/TRAZADOS/168 - 63FH.kmz b/datos/TRAZADOS/168 - 63FH.kmz
new file mode 100644
index 0000000..605f168
Binary files /dev/null and b/datos/TRAZADOS/168 - 63FH.kmz differ
diff --git a/datos/TRAZADOS/168 - 63LB VARIANTE SAN SEBASTIAN.kmz b/datos/TRAZADOS/168 - 63LB VARIANTE SAN SEBASTIAN.kmz
new file mode 100644
index 0000000..069314f
Binary files /dev/null and b/datos/TRAZADOS/168 - 63LB VARIANTE SAN SEBASTIAN.kmz differ
diff --git a/datos/TRAZADOS/169 - 56OV.kmz b/datos/TRAZADOS/169 - 56OV.kmz
new file mode 100644
index 0000000..3ad6dc7
Binary files /dev/null and b/datos/TRAZADOS/169 - 56OV.kmz differ
diff --git a/datos/TRAZADOS/173 - 22KD.kmz b/datos/TRAZADOS/173 - 22KD.kmz
new file mode 100644
index 0000000..b7c52c9
Binary files /dev/null and b/datos/TRAZADOS/173 - 22KD.kmz differ
diff --git a/datos/TRAZADOS/175 - 20TM NUEVA LLACOLEN (VAR LAS PLAYAS).kmz b/datos/TRAZADOS/175 - 20TM NUEVA LLACOLEN (VAR LAS PLAYAS).kmz
new file mode 100644
index 0000000..f4fe6a2
Binary files /dev/null and b/datos/TRAZADOS/175 - 20TM NUEVA LLACOLEN (VAR LAS PLAYAS).kmz differ
diff --git a/datos/TRAZADOS/175 - 20VA.kmz b/datos/TRAZADOS/175 - 20VA.kmz
new file mode 100644
index 0000000..b6c5951
Binary files /dev/null and b/datos/TRAZADOS/175 - 20VA.kmz differ
diff --git a/datos/TRAZADOS/176 - 80LZ.kmz b/datos/TRAZADOS/176 - 80LZ.kmz
new file mode 100644
index 0000000..0515919
Binary files /dev/null and b/datos/TRAZADOS/176 - 80LZ.kmz differ
diff --git a/datos/TRAZADOS/177 - 50SU.kmz b/datos/TRAZADOS/177 - 50SU.kmz
new file mode 100644
index 0000000..93c6e09
Binary files /dev/null and b/datos/TRAZADOS/177 - 50SU.kmz differ
diff --git a/datos/TRAZADOS/181 - 13GS.kmz b/datos/TRAZADOS/181 - 13GS.kmz
new file mode 100644
index 0000000..5f83818
Binary files /dev/null and b/datos/TRAZADOS/181 - 13GS.kmz differ
diff --git a/datos/TRAZADOS/183 - 18PY PALOMARES.kmz b/datos/TRAZADOS/183 - 18PY PALOMARES.kmz
new file mode 100644
index 0000000..7597a6b
Binary files /dev/null and b/datos/TRAZADOS/183 - 18PY PALOMARES.kmz differ
diff --git a/datos/TRAZADOS/183 - 18PY.kmz b/datos/TRAZADOS/183 - 18PY.kmz
new file mode 100644
index 0000000..b441c1d
Binary files /dev/null and b/datos/TRAZADOS/183 - 18PY.kmz differ
diff --git a/datos/TRAZADOS/185 - 20ZW.kmz b/datos/TRAZADOS/185 - 20ZW.kmz
new file mode 100644
index 0000000..4fda02e
Binary files /dev/null and b/datos/TRAZADOS/185 - 20ZW.kmz differ
diff --git a/datos/TRAZADOS/186 - 23BS SAN PEDRO DEL MAR.kmz b/datos/TRAZADOS/186 - 23BS SAN PEDRO DEL MAR.kmz
new file mode 100644
index 0000000..1997acf
Binary files /dev/null and b/datos/TRAZADOS/186 - 23BS SAN PEDRO DEL MAR.kmz differ
diff --git a/datos/TRAZADOS/186 - 23CH.kmz b/datos/TRAZADOS/186 - 23CH.kmz
new file mode 100644
index 0000000..a731878
Binary files /dev/null and b/datos/TRAZADOS/186 - 23CH.kmz differ
diff --git a/datos/TRAZADOS/186 - 23NT.kmz b/datos/TRAZADOS/186 - 23NT.kmz
new file mode 100644
index 0000000..6cfb618
Binary files /dev/null and b/datos/TRAZADOS/186 - 23NT.kmz differ
diff --git a/datos/TRAZADOS/190 - B01_BioBus.kmz b/datos/TRAZADOS/190 - B01_BioBus.kmz
new file mode 100644
index 0000000..870b4e3
Binary files /dev/null and b/datos/TRAZADOS/190 - B01_BioBus.kmz differ
diff --git a/datos/TRAZADOS/190 - B02.kmz b/datos/TRAZADOS/190 - B02.kmz
new file mode 100644
index 0000000..d8e17fb
Binary files /dev/null and b/datos/TRAZADOS/190 - B02.kmz differ
diff --git a/datos/TRAZADOS/202 - 02AC HUALPENSAN VAR.kmz b/datos/TRAZADOS/202 - 02AC HUALPENSAN VAR.kmz
new file mode 100644
index 0000000..e7275e6
Binary files /dev/null and b/datos/TRAZADOS/202 - 02AC HUALPENSAN VAR.kmz differ
diff --git a/datos/TRAZADOS/202 - 02KD HUALPENSAN.kmz b/datos/TRAZADOS/202 - 02KD HUALPENSAN.kmz
new file mode 100644
index 0000000..a2d9d6f
Binary files /dev/null and b/datos/TRAZADOS/202 - 02KD HUALPENSAN.kmz differ
diff --git a/datos/TRAZADOS/203 - 02AP HUALPENSAN.kmz b/datos/TRAZADOS/203 - 02AP HUALPENSAN.kmz
new file mode 100644
index 0000000..dbfcb40
Binary files /dev/null and b/datos/TRAZADOS/203 - 02AP HUALPENSAN.kmz differ
diff --git a/datos/TRAZADOS/203 - 02KL HUALPENSAN VAR.kmz b/datos/TRAZADOS/203 - 02KL HUALPENSAN VAR.kmz
new file mode 100644
index 0000000..dc9f23e
Binary files /dev/null and b/datos/TRAZADOS/203 - 02KL HUALPENSAN VAR.kmz differ
diff --git a/datos/TRAZADOS/401 - Tome - Concepci¢n.kmz b/datos/TRAZADOS/401 - Tome - Concepci¢n.kmz
new file mode 100644
index 0000000..b863aca
Binary files /dev/null and b/datos/TRAZADOS/401 - Tome - Concepci¢n.kmz differ
diff --git a/datos/TRAZADOS/411 - Dichato - Concepci¢n.kmz b/datos/TRAZADOS/411 - Dichato - Concepci¢n.kmz
new file mode 100644
index 0000000..228355f
Binary files /dev/null and b/datos/TRAZADOS/411 - Dichato - Concepci¢n.kmz differ
diff --git a/debug.py b/debug.py
new file mode 100644
index 0000000..a63b926
--- /dev/null
+++ b/debug.py
@@ -0,0 +1,26 @@
+import sys
+from webinterface import create_app, Config
+
+config = Config()
+config.SQLALCHEMY_DATABASE_URI = 'sqlite:///GC.db'
+config.DEBUG = True
+
+
+
+
+if __name__ == "__main__":
+ iapp = create_app(config)
+
+ if len(sys.argv) == 3:
+ host = sys.argv[1]
+ port = sys.argv[2]
+ elif len(sys.argv) == 2:
+ import random
+ host = sys.argv[1]
+ port = random.randrange(3000,9000,1)
+ else:
+ import random
+ host = '127.0.0.1'
+ port = random.randrange(3000,9000,1)
+
+ iapp.run(host=host, port=port)
diff --git a/debug.sh b/debug.sh
new file mode 100755
index 0000000..55d88cf
--- /dev/null
+++ b/debug.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+#HOST='0.0.0.0' # Permite la conexión remota
+HOST='127.0.0.1' #Permite solo conexiones locales
+
+PORT='8888' # Por defecto elige un puerto al azar.
+
+python3 web-interface/debug.py $HOST $PORT
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..84fd926
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,22 @@
+version: '2'
+
+services:
+
+ app-mtt-dev:
+# image: docker.ilab.cl/ilab-mtt:devel
+ build: .
+ restart: "no"
+ volumes:
+ - ./GranConcepcion-process.db:/srv/webinterface/GranConcepcion.db
+ environment:
+ - DEBUG=False
+ - SECRET_KEY=4d6f45a5fc12445dbac2f59c3b6c7cb2
+ - SQLALCHEMY_DATABASE_URI=sqlite:///GranConcepcion.db
+# - SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://docker:docker@db/docker
+# - COOKIE_DOMAIN=utad.ilab.cl
+# - SIGA_DB=postgresql+psycopg2:////docker:docker@localhost/docker
+# - MAIL_SERVER=maul.usm.cl
+# - MAIL_PORT=25
+# - TIMEOUT=1200
+ ports:
+ - 8000:8000
diff --git a/webinterface.service.sample b/webinterface.service.sample
new file mode 100644
index 0000000..c45e756
--- /dev/null
+++ b/webinterface.service.sample
@@ -0,0 +1,12 @@
+[Unit]
+Description=Sample-WebInterface
+After=network.target
+
+[Service]
+User=root
+WorkingDirectory=/srv/web-interface
+ExecStart=/usr/local/bin/gunicorn -b 0.0.0.0:80 wsgi:app --access-logfile /var/log/web-access.log --error-logfile /var/log/web-error.log
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/webinterface/__init__.py b/webinterface/__init__.py
new file mode 100644
index 0000000..879337a
--- /dev/null
+++ b/webinterface/__init__.py
@@ -0,0 +1,43 @@
+# coding: utf-8
+from flask import Flask
+from flask.logging import default_handler
+from flask_sqlalchemy import SQLAlchemy
+
+import logging
+import sys
+import os
+
+
+class Config:
+ SECRET_KEY = os.environ.get('SECRET_KEY')
+ SQLALCHEMY_TRACK_MODIFICATIONS = False
+ SQLALCHEMY_ECHO = False
+ DEBUG = os.environ.get('DEBUG')
+ SESSION_COOKIE_DOMAIN = os.environ.get('COOKIE_DOMAIN')
+
+ SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI')
+
+ MAIL_DEBUG = int(os.environ.get('DEBUG') == True)
+
+#if sys.version_info.major < 3:
+# reload(sys)
+#sys.setdefaultencoding('utf8')
+
+db = SQLAlchemy()
+
+def create_app(config_class=Config):
+ app = Flask(__name__)
+
+ app.config.from_object(config_class)
+
+ if app.debug:
+ app.logger.setLevel(logging.DEBUG)
+ else:
+ app.logger.setLevel(logging.INFO)
+
+ db.init_app(app)
+
+ from webinterface.content.main import main
+ app.register_blueprint(main)
+
+ return app
diff --git a/webinterface/content/main.py b/webinterface/content/main.py
new file mode 100644
index 0000000..9c75136
--- /dev/null
+++ b/webinterface/content/main.py
@@ -0,0 +1,214 @@
+# -*- coding: utf-8 -*-
+import os
+from flask import Flask, Blueprint, abort, current_app, request, render_template, send_from_directory, jsonify
+from webinterface.models.granconcepcion import Agencia, Servicio, Paradero, Parada, Ruta, Linea
+from webinterface import db
+from sqlalchemy import func
+from datetime import datetime, date
+from webinterface.models.modelodatos import load_paraderos, load_estaciones, load_recorrido, listado_recorridos
+from webinterface.content.utils import haversine
+
+
+main = Blueprint('main', __name__)
+
+@main.route('/listado_estaciones')
+def listado_estaciones():
+ return jsonify(load_estaciones())
+
+@main.route('/listado_paraderos')
+def listado_paraderos():
+ current_app.logger.debug('Funcion listado_paralelos <- inicia')
+
+ paradas = []
+
+ for item in Paradero.query.all():
+ data = {}
+
+ data['latitude'] = item.latitud
+ data['longitude'] = item.longitud
+
+ data['codigo'] = item.nombre
+ data['lineas'] = item.lineas
+ if item.codigo is not None:
+ data['mensaje'] = f"""Ubicación: {item.nombre} Este sitio sirve para hacer pruebas básicas de desarrollo. En este momento se despliega la información de los paraderos y recorridos de los archivos kmz
+ Lineas: {item.lineas}
+ Paradas dia de semana: {item.paradasl}
+ Paradas dia de sabado: {item.paradass}
+ Paradas dia de domingo: {item.paradasd}
+ Codigo paradero: {item.codigo}
+
+ Tamaño del paradero: {item.tamano}
+ Capacidad: {item.capacidad}
+ Techo: {item.techo}
+ Pared: {item.pared}
+ Piso: {item.piso}
+
+ RecorridosA: {item.recorridos}
+ RecorridosB: {item.recorridos2}"""
+ else:
+ data['mensaje'] = f"""Ubicación: {item.nombre}
+ Lineas: {item.lineas}
+ Paradas dia de semana: {item.paradasl}
+ Paradas dia de sabado: {item.paradass}
+ Paradas dia de domingo: {item.paradasd}
+
+ RecorridosA: {item.recorridos}"""
+
+
+ paradas.append(data)
+
+ current_app.logger.debug('Funcion listado_paralelos <- finaliza')
+ return jsonify(paradas)
+
+@main.route('/ruta_recorrido', methods=['POST'])
+def ruta_recorrido():
+
+ retval = {}
+
+ retval['recorrido'] = []
+ retval['paradas'] = []
+
+ servicio = Servicio.query.filter(Servicio.rutaid==request.form['rutaid']).first()
+ if servicio is not None:
+
+ lng = 0
+ lat = 0
+ points = 0
+
+ distancia = 0
+
+ prevpoint = (0,0)
+
+ for item in Ruta.query.filter(Ruta.rutaid==request.form['rutaid']).order_by(Ruta.secuencia.asc()).all():
+ points += 1
+ lng += item.longitud
+ lat += item.latitud
+ retval['recorrido'].append({ 'lat': item.latitud, 'lng': item.longitud })
+
+ if prevpoint != (0,0):
+ distancia += haversine(item.longitud, item.latitud, prevpoint[0], prevpoint[1])
+
+ prevpoint = (item.longitud, item.latitud)
+
+ distancia = round(distancia, 2)
+
+ retval['latitude'] = lat / points
+ retval['longitude'] = lng / points
+ retval['color'] = f"#{servicio.linea.color}"
+
+ salida = -1
+ llegada = 0
+
+ for item in Parada.query.filter(Parada.servicioid==servicio.id).order_by(Parada.secuencia.asc()).all():
+ data = {}
+
+ if salida == -1:
+ salida = item.salida
+ llegada = item.llegada
+ elif llegada < item.llegada:
+ llegada = item.llegada
+
+ data['latitude'] = item.paradero.latitud
+ data['longitude'] = item.paradero.longitud
+
+ data['codigo'] = item.paradero.nombre
+ data['lineas'] = item.paradero.lineas
+ if item.paradero.codigo is not None:
+ data['mensaje'] = f"""Ubicación: {item.paradero.nombre}
+ Lineas: {item.paradero.lineas}
+ Paradas dia de semana: {item.paradero.paradasl}
+ Paradas dia de sabado: {item.paradero.paradass}
+ Paradas dia de domingo: {item.paradero.paradasd}
+ Codigo paradero: {item.paradero.codigo}
+
+ Tamaño del paradero: {item.paradero.tamano}
+ Capacidad: {item.paradero.capacidad}
+ Techo: {item.paradero.techo}
+ Pared: {item.paradero.pared}
+ Piso: {item.paradero.piso}
+
+ RecorridosA: {item.paradero.recorridos}
+ RecorridosB: {item.paradero.recorridos2}"""
+ else:
+ data['mensaje'] = f"""Ubicación: {item.paradero.nombre}
+ Lineas: {item.paradero.lineas}
+ Paradas dia de semana: {item.paradero.paradasl}
+ Paradas dia de sabado: {item.paradero.paradass}
+ Paradas dia de domingo: {item.paradero.paradasd}
+
+ RecorridosA: {item.paradero.recorridos}"""
+ retval['paradas'].append(data)
+ delta = datetime.combine(date.today(), llegada) - datetime.combine(date.today(), salida)
+
+ deltah = delta.seconds /3600
+ vprom = round(distancia / deltah, 2)
+ deltah = round(deltah, 3)
+
+
+ paradas = len(retval['paradas'])
+
+ normal = Servicio.query.filter(Servicio.rutaid==request.form['rutaid'], Servicio.dotw=='L').count()
+ nomalsq = db.session.query(Servicio.id).filter(Servicio.rutaid==request.form['rutaid'], Servicio.dotw=='L')
+ nhoras = db.session.query(func.max(Parada.llegada), func.min(Parada.llegada)).filter(Parada.secuencia==1, Parada.servicioid.in_(nomalsq)).all()
+
+ sabado = Servicio.query.filter(Servicio.rutaid==request.form['rutaid'], Servicio.dotw=='S').count()
+ nomalsq = db.session.query(Servicio.id).filter(Servicio.rutaid==request.form['rutaid'], Servicio.dotw=='S')
+ shoras = db.session.query(func.max(Parada.llegada), func.min(Parada.llegada)).filter(Parada.secuencia==1, Parada.servicioid.in_(nomalsq)).all()
+
+ domingo = Servicio.query.filter(Servicio.rutaid==request.form['rutaid'], Servicio.dotw=='D').count()
+ nomalsq = db.session.query(Servicio.id).filter(Servicio.rutaid==request.form['rutaid'], Servicio.dotw=='D')
+ dhoras = db.session.query(func.max(Parada.llegada), func.min(Parada.llegada)).filter(Parada.secuencia==1, Parada.servicioid.in_(nomalsq)).all()
+
+ retval['mensaje'] = f"""La línea tiene una extensión de {distancia} Km, recorridos en {deltah} Horas (Promedio velocidad: {vprom} Km/h)
+ La línea tiene {paradas} paradas durante su extensión
+ La línea tiene {normal} servicios en día de semana(de {nhoras[0][1]} a {nhoras[0][0]}), {sabado} los sabados(de {shoras[0][1]} a {shoras[0][0]}) y {domingo} los domingos(de {dhoras[0][1]} a {dhoras[0][0]})."""
+
+ return jsonify(retval)
+ else:
+ return abort(404)
+
+
+@main.route('/about')
+def about():
+ return render_template('about.html')
+
+@main.route('/')
+def home():
+ paraderos = db.session.query(func.count(Paradero.id)).scalar()
+ lineas = db.session.query(func.count(Linea.id)).scalar()
+ servicios = db.session.query(func.count(Servicio.id)).scalar()
+ detenciones = db.session.query(func.count(Parada.id)).scalar()
+
+ return render_template('home.html', paraderos=paraderos, lineas=lineas, servicios=servicios, detenciones=detenciones)
+
+@main.route('/paraderos')
+def paraderos():
+ return render_template('paraderosdb.html')
+
+@main.route('/estaciones')
+def estaciones():
+ return render_template('estaciones.html')
+
+@main.route('/recorridos')
+def recorridos():
+ lineas = []
+ recorridos = {}
+ for item in Servicio.query.all():
+
+ linea = (item.lineaid, item.direccionid)
+
+ if linea in lineas:
+ continue
+
+ lineas.append(linea)
+
+ if item.direccionid == 0:
+ recorridos[item.rutaid] = f"{item.linea.codigo} ida: {item.destino}"
+ else:
+ recorridos[item.rutaid] = f"{item.linea.codigo} regreso: {item.destino}"
+
+ return render_template('lineas.html', recorridos=dict(sorted(recorridos.items(), key=lambda item: item[1])))
+
+@main.route('/favicon.ico')
+def favicon():
+ return send_from_directory(os.path.join(current_app.root_path, 'static'), 'public.ico', mimetype='image/vnd.microsoft.icon')
\ No newline at end of file
diff --git a/webinterface/content/utils.py b/webinterface/content/utils.py
new file mode 100644
index 0000000..bde5fdc
--- /dev/null
+++ b/webinterface/content/utils.py
@@ -0,0 +1,18 @@
+
+from math import radians, cos, sin, asin, sqrt
+
+def haversine(lon1, lat1, lon2, lat2):
+ """
+ Calculate the great circle distance in kilometers between two points
+ on the earth (specified in decimal degrees)
+ """
+ # convert decimal degrees to radians
+ lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
+
+ # haversine formula
+ dlon = lon2 - lon1
+ dlat = lat2 - lat1
+ a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
+ c = 2 * asin(sqrt(a))
+ r = 6371 # Radius of earth in kilometers. Use 3956 for miles. Determines return value units.
+ return c * r
\ No newline at end of file
diff --git a/webinterface/models/__init__.py b/webinterface/models/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/webinterface/models/cargamodelo.py b/webinterface/models/cargamodelo.py
new file mode 100644
index 0000000..4b95639
--- /dev/null
+++ b/webinterface/models/cargamodelo.py
@@ -0,0 +1,328 @@
+import os
+import io
+import csv
+import traceback
+from datetime import datetime
+from flask import current_app
+from webinterface import db
+from webinterface.models.granconcepcion import Agencia, Servicio, Paradero, Parada, Ruta, Linea
+
+def parse_time(strinput):
+ try:
+ h, m, s = strinput.split(":")
+ h = int(h)
+ d = 0
+ while h > 23:
+ d += 1
+ h -= 24
+
+ return datetime.strptime("{}:{}:{}".format(h,m,s), '%H:%M:%S').time(), d
+ except:
+ current_app.logger.debug('Traceback {}'.format(traceback.format_exc()))
+ current_app.logger.warning("Hora incorrecta => {}".format(strinput))
+ return datetime.strptime("01:01:01", '%H:%M:%S').time(), 0
+
+
+def parse_paraderoid(strinput):
+ primerodenero2022 = 44562
+
+ if strinput.find("-") > 0:
+ current_app.logger.error("Error en el dato de la parada: {}".format(strinput))
+ try:
+ whatdate= datetime.strptime('{}-{}'.format(strinput, 2022), '%d-%b-%Y').date()
+ idparadero = primerodenero2022 + whatdate.timetuple().tm_yday
+ current_app.logger.warning("Calculado el Identificador en base al año 2022 => {}".format(idparadero))
+ return idparadero
+ except:
+ return 0
+ else:
+ return int(strinput)
+
+
+def completa_dataset():
+ iparaderos = 0
+ for paradero in Paradero.query.all():
+ iparaderos += 1
+ cparadero = 0
+ lparadas = 0
+ sparadas = 0
+ dparadas = 0
+ lineas = []
+ lparada = []
+
+ for parada in Parada.query.filter(Parada.paraderoid==paradero.id).all():
+ cparadero += 1
+ if cparadero % 1000 == 0:
+ current_app.logger.debug("Paradero {}, {} detenciones. {} lineas".format(iparaderos, cparadero, len(lineas)))
+
+ elemento = (parada.servicio.lineaid, parada.servicio.direccionid)
+
+ if parada.servicio.dotw == 'S':
+ sparadas += 1
+ elif parada.servicio.dotw == 'D':
+ dparadas += 1
+ else:
+ lparadas += 1
+
+ if elemento in lineas:
+ continue
+
+ lineas.append(elemento)
+ if parada.servicio.direccionid:
+ lparada.append("{} ({} ida)".format(parada.servicio.linea.codigo, parada.secuencia))
+ else:
+ lparada.append("{} ({} regreso)".format(parada.servicio.linea.codigo, parada.secuencia))
+
+ lparada.sort()
+ paradero.recorridos = " - ".join(lparada)
+ paradero.paradas = 5*lparadas+sparadas+dparadas
+ paradero.resumen = "{} paradas a la semana, {} lineas".format(paradero.paradas, len(lineas))
+ paradero.paradasl = lparadas
+ paradero.paradass = sparadas
+ paradero.paradasd = dparadas
+ paradero.lineas = len(lineas)
+ current_app.logger.info("Paradero {}, {} detenciones a la semana en {} lineas".format(iparaderos, paradero.paradas, len(lineas)))
+ if iparaderos % 10 == 0:
+ db.session.commit()
+
+ db.session.commit()
+
+def agrega_paraderos():
+ from bs4 import BeautifulSoup
+ from zipfile import ZipFile
+
+# print(os.getcwd())
+
+ current_app.logger.info("Archivo de paraderos, kmz")
+ with ZipFile('webinterface/models/datos/PARADEROS_FORMALES.kmz', 'r') as kmz:
+ kml = kmz.open(kmz.filelist[0].filename, 'r').read()
+
+ soup = BeautifulSoup(kml, 'xml')
+ existen = 0
+ nuevo = 0
+
+
+ for paradero in soup.find_all("kml:Placemark"):
+ if (existen+nuevo) % 1000 == 0:
+ current_app.logger.debug("Leidos {} paraderos existentes y {} nuevos".format(existen, nuevo))
+
+
+ lat = int(paradero.find("kml:SimpleData", {"name": "LATITUDE"}).text)/1000000
+ lng = int(paradero.find("kml:SimpleData", {"name": "LONGITUDE"}).text)/1000000
+
+ codigo = paradero.find("kml:SimpleData", {"name": "CODIGO_INT"}).text
+ comuna = paradero.find("kml:SimpleData", {"name": "COMUNA"}).text
+ recorridos = paradero.find("kml:SimpleData", {"name": "RECORRIDOS"}).text
+ tamano = paradero.find("kml:SimpleData", {"name": "SUPERFICIE"}).text
+ capacidad = paradero.find("kml:SimpleData", {"name": "CAPACIDAD"}).text
+ materialpiso = paradero.find("kml:SimpleData", {"name": "RADIER_MAT"}).text
+ materialpared = paradero.find("kml:SimpleData", {"name": "PARED_POS2"}).text
+ materialtecho = paradero.find("kml:SimpleData", {"name": "TECHUMBRE2"}).text
+
+
+ match = None
+
+ for radio in [0.00000001, 0.00000002, 0.00000003, 0.00000004, 0.00000005, 0.000000075, 0.0000001, 0.0000002]:
+ match = Paradero.query.filter(((Paradero.latitud-lat)*(Paradero.latitud-lat)+(Paradero.longitud-lng)*(Paradero.longitud-lng)) < radio).first()
+
+ if match is not None:
+ break
+
+ if match is None:
+ nuevo += 1
+ nombre = "{} cerca {}".format(paradero.find("kml:SimpleData", {"name": "NOMBRE_DE_"}).text, paradero.find("kml:SimpleData", {"name": "CALLE_CERC"}).text)
+ match = Paradero(id=codigo, codigo=codigo, nombre=nombre, latitud=lat, longitud=lng)
+ db.session.add(match)
+ db.session.commit()
+ else:
+ existen += 1
+
+ match.codigo = codigo
+ match.comuna = comuna
+ match.recorridos2 = recorridos
+ match.tamano = tamano
+ match.capacidad = capacidad
+ match.techo = materialtecho
+ match.pared = materialpared
+ match.piso = materialpiso
+ db.session.commit()
+
+ current_app.logger.info("Cargados {} paraderos existentes y {} nuevos".format(existen, nuevo))
+
+
+
+
+
+def load_dataset():
+ from bs4 import BeautifulSoup
+ from zipfile import ZipFile
+
+ with ZipFile('GC.zip', 'r') as dataset:
+ current_app.logger.debug("Abriendo archivo GC.zip")
+
+ #Carga las agencias:
+ with io.TextIOWrapper(dataset.open('agency.txt'), encoding='utf8') as agencias_csv:
+ current_app.logger.debug("Leyendo agency.txt")
+ agencias = csv.reader(agencias_csv, delimiter=',')
+ elementos = 0
+
+ for item in agencias:
+ if elementos > 0:
+ agencia = Agencia.query.filter(Agencia.id==item[0]).one_or_none()
+
+ if agencia is None:
+ agencia = Agencia(id=item[0], nombre=item[1], url=item[2], fono=item[5])
+ db.session.add(agencia)
+ else:
+ agencia.nombre = item[1]
+ agencia.url = item[2]
+ agencia.fono = item[3]
+
+ elementos += 1
+
+ db.session.commit()
+ current_app.logger.info("Se cargaron {} agencias".format(elementos))
+
+
+ #Carga las agencias
+ with io.TextIOWrapper(dataset.open('stops.txt'), encoding='utf8') as paraderos_csv:
+ current_app.logger.debug("Leyendo stops.txt")
+ paraderos = csv.reader(paraderos_csv, delimiter=',')
+ elementos = 0
+
+ for item in paraderos:
+ if elementos > 0:
+
+ idparadero = item[0]
+
+ paradero = Paradero.query.filter(Paradero.id==idparadero).one_or_none()
+ if len(item[1]) > 0:
+ codigo = item[1]
+ else:
+ codigo = None
+
+ if paradero is None:
+
+ paradero = Paradero(id=idparadero, codigo=codigo, nombre=item[2], latitud=item[4], longitud=item[5])
+ db.session.add(paradero)
+ else:
+ paradero.codigo = codigo
+ paradero.nombre = item[2]
+ paradero.latitud = item[4]
+ paradero.longitud = item[5]
+
+ elementos += 1
+ if elementos % 1000 == 0:
+ current_app.logger.info("Se han cargado {} elementos".format(elementos))
+
+ db.session.commit()
+ current_app.logger.info("Se cargaron {} paradas".format(elementos))
+
+
+ with io.TextIOWrapper(dataset.open('routes.txt'), encoding='utf8') as lineas_csv:
+ current_app.logger.debug("Leyendo routes.txt")
+ lineas = csv.reader(lineas_csv, delimiter=',')
+ elementos = 0
+
+ for item in lineas:
+ if elementos > 0:
+ variante = Linea.query.filter(Linea.id==item[0]).one_or_none()
+
+ if variante is None:
+ variante = Linea(id=item[0], agenciaid=item[1], codigo=item[2], nombre=item[3], color=item[7])
+ db.session.add(variante)
+ else:
+ variante.agenciaid = item[1]
+ variante.codigo = item[2]
+ variante.nombre = item[3]
+ variante.color = item[7]
+
+ elementos += 1
+ if elementos % 1000 == 0:
+ current_app.logger.info("Se han cargado {} elementos".format(elementos))
+
+ db.session.commit()
+ current_app.logger.info("Se cargaron {} Linea".format(elementos))
+
+
+ with io.TextIOWrapper(dataset.open('trips.txt'), encoding='utf8') as rutas_csv:
+ current_app.logger.debug("Leyendo Servicios.txt")
+ rutas = csv.reader(rutas_csv, delimiter=',')
+ elementos = 0
+
+ for item in rutas:
+ if elementos > 0:
+
+ itinerario = Servicio.query.filter(Servicio.id==item[2], Servicio.lineaid==item[0]).one_or_none()
+
+ if itinerario is None:
+ itinerario = Servicio(id=item[2], lineaid=item[0], direccionid=item[5], destino=item[3], dotw=item[1], rutaid=item[7])
+ db.session.add(itinerario)
+ else:
+ itinerario.destino = item[3]
+ itinerario.direccionid = item[5]
+ itinerario.rutaid = item[7]
+ itinerario.dotw = item[1]
+
+ elementos += 1
+ if elementos % 1000 == 0:
+ db.session.commit()
+ current_app.logger.info("Se han cargado {} elementos".format(elementos))
+
+ db.session.commit()
+ current_app.logger.info("Se cargaron {} servicios".format(elementos))
+
+ with io.TextIOWrapper(dataset.open('shapes.txt'), encoding='utf8') as shapes_csv:
+ current_app.logger.debug("Leyendo rutas.txt")
+ shapes = csv.reader(shapes_csv, delimiter=',')
+ elementos = 0
+
+ for item in shapes:
+ if elementos > 0:
+ shape = Ruta.query.filter(Ruta.rutaid==item[0], Ruta.secuencia==item[3]).one_or_none()
+
+ if shape is None:
+ shape = Ruta(rutaid=item[0], secuencia=item[3], latitud=item[1], longitud=item[2])
+ db.session.add(shape)
+ else:
+ shape.latitud = item[1]
+ shape.longitud = item[2]
+
+ elementos += 1
+ if elementos % 1000 == 0:
+ db.session.commit()
+ current_app.logger.info("Se han cargado {} elementos".format(elementos))
+
+
+ db.session.commit()
+ current_app.logger.info("Se cargaron {} puntos".format(elementos))
+
+ with io.TextIOWrapper(dataset.open('stop_times.txt'), encoding='utf8') as paradas_csv:
+ current_app.logger.debug("Leyendo paradas.txt")
+ paradas = csv.reader(paradas_csv, delimiter=',')
+ elementos = 0
+
+ for item in paradas:
+ if elementos > 0:
+ idparadero = item[3]
+
+ parada = Parada.query.filter(Parada.servicioid==item[0], Parada.paraderoid==idparadero, Parada.secuencia==item[4]).one_or_none()
+ llegada, _ = parse_time(item[1])
+ salida, otrodia = parse_time(item[2])
+
+ if parada is None:
+ parada = Parada(servicioid=item[0], paraderoid=idparadero, secuencia=item[4], tipo=item[8], llegada=llegada, salida=salida, otrodia=otrodia)
+ db.session.add(parada)
+ else:
+ parada.llegada = llegada
+ parada.salida = salida
+ parada.otrodia = otrodia
+ parada.tipo = item[8]
+
+ elementos += 1
+ if elementos % 1000 == 0:
+ db.session.commit()
+ current_app.logger.info("Se han cargado {} elementos".format(elementos))
+
+ db.session.commit()
+ current_app.logger.info("Se cargaron {} paradas".format(elementos))
diff --git a/webinterface/models/granconcepcion.py b/webinterface/models/granconcepcion.py
new file mode 100644
index 0000000..c0ed6de
--- /dev/null
+++ b/webinterface/models/granconcepcion.py
@@ -0,0 +1,131 @@
+from sqlalchemy.sql import func
+from sqlalchemy.dialects import postgresql, sqlite
+from webinterface import db
+
+class Agencia(db.Model):
+ __tablename__ = 'agencias'
+
+ id = db.Column(db.String(20), primary_key=True, nullable=False)
+ nombre = db.Column(db.String(100))
+ url = db.Column(db.String(100))
+ fono = db.Column(db.String(100))
+
+class Paradero(db.Model):
+ __tablename__ = 'paraderos'
+
+ id = db.Column(db.String(20), primary_key=True, nullable=False)
+ codigo = db.Column(db.String(50), unique=True, nullable=True)
+ nombre = db.Column(db.Text)
+
+ longitud = db.Column(db.Float, nullable=False)
+ latitud = db.Column(db.Float, nullable=False)
+
+ comuna = db.Column(db.Text)
+ tamano = db.Column(db.Float)
+ capacidad = db.Column(db.Integer)
+ techo = db.Column(db.Text)
+ pared = db.Column(db.Text)
+ piso = db.Column(db.Text)
+
+ recorridos = db.Column(db.Text)
+ recorridos2 = db.Column(db.Text)
+ resumen = db.Column(db.Text)
+ paradas = db.Column(db.Integer, default=0)
+ paradasl = db.Column(db.Integer, default=0)
+ paradass = db.Column(db.Integer, default=0)
+ paradasd = db.Column(db.Integer, default=0)
+ lineas = db.Column(db.Integer, default=0)
+
+
+ @property
+ def recorridosz(self):
+ txtout = ""
+ for item in Parada.query.join(Itinerario).filter(Parada.paraderoid==self.id).distinct(Itinerario.lineaid).all():
+ txtout += "{}({}) - ".format(item.lineaTXT, item.secuencia)
+
+ if len(txtout) > 2:
+ return txtout[:-2]
+ else:
+ return txtout
+
+class Ruta(db.Model):
+ __tablename__ = 'rutas'
+
+ id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
+
+ rutaid = db.Column(db.Integer, nullable=False)
+ secuencia = db.Column(db.Integer, nullable=False)
+
+ longitud = db.Column(db.Float, nullable=False)
+ latitud = db.Column(db.Float, nullable=False)
+
+ __table_args__ = (db.UniqueConstraint('rutaid', 'secuencia', name='_rutaid_secuencia_recorrido_uc'), )
+
+
+class Linea(db.Model):
+ __tablename__ = 'lineas'
+
+ id = db.Column(db.Integer, primary_key=True, nullable=False)
+ agenciaid = db.Column(db.String(20), db.ForeignKey('agencias.id'), nullable=False)
+ codigo = db.Column(db.String(50), unique=True)
+ nombre = db.Column(db.Text)
+ color = db.Column(db.String(6))
+
+class Servicio(db.Model):
+ __tablename__ = 'servicios'
+
+ id = db.Column(db.String(20), primary_key=True, nullable=False)
+
+ rutaid = db.Column(db.Integer, nullable=False) # Ruta.rutaid
+ lineaid = db.Column(db.Integer, db.ForeignKey('lineas.id'), nullable=False)
+ direccionid = db.Column(db.Integer, nullable=False)
+ destino = db.Column(db.Text)
+ dotw = db.Column(db.String(1), nullable=False)
+
+ linea = db.relationship('Linea')
+
+ @property
+ def lineatxt(self):
+ self.linea.codigo
+
+ @property
+ def color(self):
+ self.linea.color
+
+
+class Parada(db.Model):
+ __tablename__ = 'paradas'
+
+ id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
+
+ servicioid = db.Column(db.String(20), db.ForeignKey('servicios.id'), nullable=False)
+ paraderoid = db.Column(db.String(20), db.ForeignKey('paraderos.id'), nullable=False)
+ secuencia = db.Column(db.Integer, nullable=False)
+ tipo = db.Column(db.Integer)
+
+ llegada = db.Column(db.Time, nullable=False)
+ salida = db.Column(db.Time, nullable=False)
+ otrodia = db.Column(db.Integer)
+
+ __table_args__ = (db.UniqueConstraint('servicioid', 'secuencia', name='_serviciosid_secuencia_paradas_uc'), )
+
+ servicio = db.relationship('Servicio')
+ paradero = db.relationship('Paradero')
+
+ @property
+ def longitud(self):
+ self.paradero.longitud
+ @property
+ def latitud(self):
+ self.paradero.latitud
+
+ @property
+ def linea(self):
+ self.servicio.linea
+ @property
+ def lineatxt(self):
+ self.servicio.lineatxt
+
+
+# 4cc08782-c-76aabf89-b
+
diff --git a/webinterface/models/modelodatos.py b/webinterface/models/modelodatos.py
new file mode 100644
index 0000000..6b8f431
--- /dev/null
+++ b/webinterface/models/modelodatos.py
@@ -0,0 +1,103 @@
+import os
+
+def load_paraderos():
+ from bs4 import BeautifulSoup
+ from zipfile import ZipFile
+
+# print(os.getcwd())
+
+ with ZipFile('webinterface/models/datos/PARADEROS_FORMALES.kmz', 'r') as kmz:
+ kml = kmz.open(kmz.filelist[0].filename, 'r').read()
+
+ soup = BeautifulSoup(kml, 'xml')
+
+ listado_paraderos = []
+
+ for paradero in soup.find_all("kml:Placemark"):
+ data = {}
+
+ data['latitude'] = int(paradero.find("kml:SimpleData", {"name": "LATITUDE"}).text)/1000000
+ data['longitude'] = int(paradero.find("kml:SimpleData", {"name": "LONGITUDE"}).text)/1000000
+
+ data['codigo'] = paradero.find("kml:SimpleData", {"name": "CODIGO_INT"}).text
+ data['comuna'] = paradero.find("kml:SimpleData", {"name": "COMUNA"}).text
+ data['recorridos'] = paradero.find("kml:SimpleData", {"name": "RECORRIDOS"}).text
+ data['tamano'] = paradero.find("kml:SimpleData", {"name": "SUPERFICIE"}).text
+ data['capacidad'] = paradero.find("kml:SimpleData", {"name": "CAPACIDAD"}).text
+ data['material'] = "{} | {} | {}".format(paradero.find("kml:SimpleData", {"name": "RADIER_MAT"}).text, paradero.find("kml:SimpleData", {"name": "PARED_POS2"}).text, paradero.find("kml:SimpleData", {"name": "TECHUMBRE2"}).text)
+
+
+ listado_paraderos.append(data)
+ return listado_paraderos
+
+
+def load_estaciones():
+ from bs4 import BeautifulSoup
+ from zipfile import ZipFile
+
+ with ZipFile('webinterface/models/datos/ESTACIONES_BIOTREN.kmz', 'r') as kmz:
+ kml = kmz.open(kmz.filelist[0].filename, 'r').read()
+
+ soup = BeautifulSoup(kml, 'xml')
+
+ listado_estaciones = []
+
+ for estacion in soup.find_all("kml:Placemark"):
+
+ lng, lat, _ = estacion.find("kml:coordinates").text.split(",")
+
+ data = {}
+
+ data['latitude'] = float(lat)
+ data['longitude'] = float(lng)
+
+ data['codigo'] = estacion.find("kml:name").text
+
+ listado_estaciones.append(data)
+ return listado_estaciones
+
+
+def listado_recorridos():
+ listado = []
+ for f in next(os.walk("webinterface/models/datos/TRAZADOS/"))[2]:
+ listado.append(f[:-4])
+ return listado
+
+def load_recorrido(recorrido = None):
+ from bs4 import BeautifulSoup
+ from zipfile import ZipFile
+
+ try:
+ with ZipFile('webinterface/models/datos/TRAZADOS/{}.kmz'.format(recorrido), 'r') as kmz:
+ kml = kmz.open(kmz.filelist[0].filename, 'r').read()
+ except:
+ with ZipFile('webinterface/models/datos/TRAZADOS/127 - 31DF RUTA DEL MAR S.A..kmz', 'r') as kmz:
+ kml = kmz.open(kmz.filelist[0].filename, 'r').read()
+
+ soup = BeautifulSoup(kml, 'xml')
+
+ colores = ['#DE4C8A', '#ED760E', '#35682D', '#D6AE01', '#84C3BE', '#293133', '#57A639', '#E63244', '#ED760E', '#2271B3', '#231A24', '#008F39']
+ colorindex = 0
+
+ respuesta_recorridos = []
+
+ for recorrido in soup.find_all("kml:Placemark"):
+
+ puntos = []
+ for punto in recorrido.find("kml:coordinates").text.strip().split(" "):
+ lng, lat, _ = punto.split(",")
+ puntos.append({ 'lat': float(lat), 'lng': float(lng) })
+
+ latitude = 0.5*(puntos[0]['lat'] + puntos[-1]['lat'])
+ longitude = 0.5*(puntos[0]['lng'] + puntos[-1]['lng'])
+
+ data = {}
+ data['latitude'] = latitude
+ data['longitude'] = longitude
+ data['recorrido'] = puntos
+ data['color'] = colores[colorindex]
+
+ colorindex += 1
+
+ respuesta_recorridos.append(data)
+ return respuesta_recorridos
\ No newline at end of file
diff --git a/webinterface/requirements.txt b/webinterface/requirements.txt
new file mode 100644
index 0000000..d3bc765
--- /dev/null
+++ b/webinterface/requirements.txt
@@ -0,0 +1,8 @@
+Flask
+Flask-SQLAlchemy
+SQLAlchemy
+gunicorn
+Werkzeug
+ua-parser
+user-agents
+
diff --git a/webinterface/static/favicon.ico b/webinterface/static/favicon.ico
new file mode 100644
index 0000000..10a6cc9
Binary files /dev/null and b/webinterface/static/favicon.ico differ
diff --git a/webinterface/static/main.css b/webinterface/static/main.css
new file mode 100644
index 0000000..9a80d2d
--- /dev/null
+++ b/webinterface/static/main.css
@@ -0,0 +1,86 @@
+body {
+ background: #fcfcfc;
+ color: #222222;
+ margin-top: 5rem;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #303030;
+}
+
+#map {
+ height: 600px;
+ width: 100%;
+ background-color: grey;
+}
+
+.bg-steel {
+ background-color: #3d3d3d;
+}
+
+.site-header .navbar-nav .nav-link {
+ color: #dce6ec;
+}
+
+.site-header .navbar-nav .nav-link:hover {
+ color: #ffffff;
+}
+
+.site-header .navbar-nav .nav-link.active {
+ font-weight: 500;
+}
+
+.content-section {
+ background: #ffffff;
+ padding: 10px 20px;
+ border: 1px solid #dddddd;
+ border-radius: 3px;
+ margin-bottom: 20px;
+}
+
+.article-title {
+ color: #444444;
+}
+
+a.article-title:hover {
+ color: #428bca;
+ text-decoration: none;
+}
+
+.article-content {
+ white-space: pre-line;
+}
+
+.article-img {
+ height: 65px;
+ width: 65px;
+ margin-right: 16px;
+}
+
+.article-metadata {
+ padding-bottom: 1px;
+ margin-bottom: 4px;
+ border-bottom: 1px solid #e3e3e3
+}
+
+.article-metadata a:hover {
+ color: #333;
+ text-decoration: none;
+}
+
+.article-svg {
+ width: 25px;
+ height: 25px;
+ vertical-align: middle;
+}
+
+.account-img {
+ height: 125px;
+ width: 125px;
+ margin-right: 20px;
+ margin-bottom: 16px;
+}
+
+.account-heading {
+ font-size: 2.5rem;
+}
diff --git a/webinterface/static/public.ico b/webinterface/static/public.ico
new file mode 100644
index 0000000..dddefa7
Binary files /dev/null and b/webinterface/static/public.ico differ
diff --git a/webinterface/static/public.svg b/webinterface/static/public.svg
new file mode 100644
index 0000000..fa55160
--- /dev/null
+++ b/webinterface/static/public.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/webinterface/templates/about.html b/webinterface/templates/about.html
new file mode 100644
index 0000000..963d797
--- /dev/null
+++ b/webinterface/templates/about.html
@@ -0,0 +1,10 @@
+{% extends "layout.html" %}
+{% block content %}
+
Contiene {{paraderos}} paraderos.
+Contiene {{lineas}} recorridos/líneas.
+Contiene {{servicios}} servicios (a la semana).
+Contiene {{detenciones}} detenciones/paradas/estaciones.
+Este código está licenciado bajo MIT para los usuarios de iLab. Para los demás, deben conseguir una licencia especial si quieren utilizar este código con usos comerciales. Para fines educacionales se le puede conceder una licencia GPLv3 si la solicitan a israel.figueroa@ilab.cl.
+El código está pensado para mostrar un contenido web básico utilizando Flask y Python 3. El código incluye un instalador como servicio, que permite que el programa se inicie cada vez que prenda el sistema.
+Este es un sitio web de prueba utilizando Flask.
+Actualmente no tiene ningún contenido ni funcionalidad, de manera que sirva como una plantilla vacía para poder mostrar el contenido deseado, o implementar una funcionalidad sin tener que partir desde cero.
+