Muchos tienen uno o más de sus proyectos caseros. Estas son pequeñas utilidades, piezas experimentales, muestras de nuevas tecnologías, "asesinos" de Facebook y mucho más. Notablemente con menos frecuencia, tales proyectos se llevan a cabo durante mucho tiempo.
En el artículo compartiré mi experiencia y le contaré cómo durante 5 años trabajé ocasionalmente en el desarrollo de una guía inteligente para San Petersburgo, cómo logré no abandonar este negocio, cómo cambió la actitud hacia el proyecto y qué sucedió al final.

A continuación se describen muchas soluciones técnicas y bicicletas dudosas, pero no se sorprenda: casi todas están justificadas por los objetivos establecidos en ese momento y los recursos disponibles (= generalmente mi conocimiento y tiempo)
Idea
En cualquier gran ciudad turística hay cientos de guías, buenas y no muy buenas, donde se pintan las rutas principales, se indican los puntos principales y un montón de otra información útil.
Pero las rutas allí son constantes y limitadas, y las vistas son generalmente las más importantes, como "qué ver en 3 días".
Por lo tanto, surgió la idea de construir rutas inteligentes. El usuario selecciona los puntos A y B y recibe no la ruta más corta clásica, sino algo cercano, pero que pasa por las atracciones cercanas.
La audiencia de tal guía no es solo turistas, sino también residentes locales que desean diversificar sus rutas típicas a casa / trabajo / tienda (¡y hubo tales críticas en la aplicación!) O simplemente mejor conocer la ciudad.
TL; DR
La conclusión es la aplicación Wander para Android, que ahora solo funciona para San Petersburgo.
Acto 1: prototipo
La idea surgió en la universidad en 2014, ni siquiera estoy seguro de que la idea fuera originalmente mía, en algún curso fue necesario dividirse en grupos, presentar proyectos y completarlos como un documento final. Se estrellaron y generaron la idea del proyecto, y luego comenzó el nombre TravelPath
.
Se suponía que era un servicio web, sabía un poco sobre PHP, así que elegí PHP.
Fue necesario resolver varios problemas:
1. Base de atracciones
Aquí nos reunimos con OpenStreetMap , resultó que este es el proyecto más genial que nos queda perfectamente. OSM es un proyecto de mapa comunitario sin fines de lucro basado en la comunidad. Al igual que Wikipedia, solo sobre mapas.
Descargue el mapa en formato xml de San Petersburgo: hay una lista de recursos donde puede hacer esto.
Recuerdo que en ese momento, los archivos de mapas pesaban más de 1 GB, por lo que se escribe un analizador de transmisión que selecciona objetos de categorías preseleccionadas: monumentos, parques, iglesias, museos.
OSM tiene una amplia documentación sobre etiquetas, atributos y todo lo que necesita aquí , gracias a él no será difícil descubrir cómo obtener los datos que necesita de las tarjetas.
Los datos cartográficos son creados por entusiastas, por lo tanto, no en todas partes y no siempre los objetos tienen las etiquetas necesarias, algunos lugares tienen errores, problemas. Pero para las grandes ciudades, los datos son de bastante alta calidad.
Si desenterré correctamente mi código anterior, usé las siguientes etiquetas para buscar objetos:
building
significa cathedral
, chapel
, church
ha convertido en una categoría de church
amenity
con valores de la fountain
cae en monument
tourism
con artwork
y valores de viewpoint
va al monument
, zoo
y museum
a museum
, y park
theme_park
al park
historic
con boundary_stone
, castle
, memorial
, los valores del monument
van a la categoría de monument
leisure
con un valor en el park
naturalmente, termina en el park
¡Ponemos todos los objetos recibidos en una base de datos con coordenadas y nos alegramos! Se han lanzado más de 1.200 puntos en San Petersburgo.
2. Construyendo una ruta
No estaba destinado a implementar sistemas complejos como parte del curso, y el conocimiento técnico en ese momento era escaso, por lo que decidimos dividir la construcción de la ruta en dos partes: la elección de los objetos en la ruta y la construcción de la ruta en sí. En parte, esto determinó el destino del futuro, porque más tarde no quise cambiar este esquema.
La construcción de una ruta entre los puntos seleccionados fue dada por la API de Google Maps, que construyó rutas de automóviles bastante bien, pero en ese momento no sabía cómo caminar, al menos en Rusia.
La elección de los objetos tuvo que ser implementada por usted mismo. Resultó el siguiente esquema de la aplicación:

La principal desventaja del enfoque es la selección de puntos en la ruta sin tener en cuenta el mapa, solo en función de las coordenadas GPS. Y, en general, esto funciona razonablemente bien, especialmente donde hay una cuadrícula de calles frecuente. Problemas raros son notables a lo largo de ríos con puentes raros, por ejemplo.
A continuación, se nos ocurre un algoritmo para seleccionar puntos en la ruta. Por un lado, es necesario que la ruta no se desvíe mucho hacia un lado, pero por otro lado todavía selecciona algunos puntos en los vecindarios dados.
No es una declaración muy clara del problema, salió el mismo algoritmo, algo similar a A * ( wiki ): se cree que desde cada punto hay transiciones a cada uno. Además, en A *, el precio de ir al vértice n cuando se busca la ruta AB generalmente se expresa de la siguiente manera: f(n) = g(An) + h(nB)
, donde g(x,y)
es la longitud del camino de x a y, y h(x,y)
es una estimación heurística de la distancia de xay. Mi precio es el mismo: f(n) = h(x,n) + h(n,y) * q
, donde q es una constante menor que 1. Al cambiar el valor de q, puede afectar el número de puntos en la ruta.
Implementamos el algoritmo y, por supuesto, todo funciona, ajustamos la interfaz, compramos un dominio, lo subimos al hosting, escribimos informes y otros burocracias y nos regocijamos. Se parecía a esto (y no cambió mucho después):

Total: obtuve un prototipo de una idea genial, me familiaricé con OSM, Google API, trabajé en equipo, obtuve crédito en la universidad y también fue interesante.
Acto 2: primera versión web completa
Realmente me gustó la idea y decidí desarrollarla más, pero ya es una. Y fue claro de inmediato lo que se necesitaba en primer lugar: en ese momento, Google Maps aún no podía construir rutas para caminar, solo se estaban construyendo las de automóviles. Y toda la idea de la aplicación se trata principalmente de caminar, lo que significa que debe poder construir rutas a lo largo de los callejones sombreados de parques, caminos peatonales, puentes y mucho más.
Fue en 2015, y continué trabajando en TravelPath, asumí la corrección de este defecto fatal: comencé a construir caminos por mi cuenta.
No cambié la tecnología, PHP
+ MySQL
. Por supuesto, inmediatamente me di cuenta de que esta no era la mejor pila técnica para tal tarea (¿construir rutas en PHP? ¿En serio?).
Pero estaba limitado en el tiempo y no estaba listo para cambiar a una pila más razonable, y en segundo lugar, hasta ahora el proyecto estaba escrito "sobre la mesa": me gustaría usar una aplicación de este tipo desde un dispositivo móvil, y en esos años solo significaba desarrollo nativo. Es decir, su inaplicabilidad en forma de versión web era obvia, incluso a pesar de algunos intentos de hacer una interfaz adaptativa.
Surgieron las siguientes tareas:
1. Obteniendo un gráfico de ciudad
Aquí el mismo OSM nos salva. Nuevamente, descargue el gráfico en formato xml, analícelo, seleccione solo los tipos de caminos necesarios y admire la cantidad de datos; en ese momento, salieron más de 3 millones de vértices y 500k bordes. La primera idea es que el gráfico puede no estar relacionado.
Los patios, territorios cerrados, cosas incomprensibles no son muy interesantes para construir una ruta, por lo que seleccionamos algún punto, rodeamos todo el gráfico, marcamos los vértices pasados y obtenemos la parte conectada del gráfico.
En total, salieron más de 600k picos y 150k bordes.
Guardado lo recibido en la base de datos y se fue hasta mejores tiempos.
2. Construyendo una ruta
Hay datos, todo queda en manos de los pequeños: crea rutas en ellos. No tuvimos que inventar nada nuevo: recuerde el curso de los algoritmos, lea cuidadosamente los artículos sobre el trabajo con gráficos, tome el algoritmo A *, impleméntelo en PHP y alegrarse frustrado por lo lento que funciona todo.
Hay muchos datos, por lo tanto, al construir el gráfico, no utilizamos el completo, sino que solo leemos parte de él, todo lo que cae dentro del rectángulo obtenido de todos los puntos seleccionados en la ruta.
(marco rojo = ~ dicho gráfico fue leído para construir la ruta)
Lo mismo con los puntos candidatos para la ruta: tenemos en cuenta no todo, sino solo aquellos entre el inicio y el final + un valor pequeño.
Habiendo seleccionado el tamaño de este rectángulo (la constante por la cual lo incrementamos), tratamos de garantizar que leamos el tamaño mínimo de datos requerido.
También existía la idea de dividir la ciudad en cuadrados, construir la ruta primero por cuadrados, y luego leer el gráfico dentro de estos cuadrados y buscar un camino solo a lo largo de él. Y puede calcular previamente las rutas entre todos los cuadrados vecinos. O incluso más: para calcular y guardar el camino entre todas las vistas. Luego, sobre la marcha, solo queda construir los caminos desde el primer objeto hasta el primero, y desde el último objeto hasta la línea de meta.
Pero las manos no alcanzaron la realización de tales bicicletas.
3. Enrutamiento en un tiempo razonable
Inmediatamente se hizo evidente que el cuello de botella es el almacenamiento y el trabajo con datos: el algoritmo de búsqueda en sí no está particularmente acelerado. Y los puntos de referencia en la rodilla confirman que la mayor parte del tiempo se pasa leyendo de la base de datos y manipulaciones similares.
¿Qué se debe hacer en tales casos? No almacene este gráfico. Pero tengo una forma especial, MySQL
y nada más, pero el problema debe resolverse.
- El primero: los datos se normalizaron, lo cual era conveniente al analizar, pero leer decenas de miles de registros e incluso de dos tablas es doloroso. La solución obvia es hacer una de dos tablas (para vértices y aristas), solo para aristas, en las que en cada registro se registran las coordenadas de ambos vértices y su id.
- Contamos por adelantado los vértices más cercanos del gráfico a las vistas, y no lo hacemos sobre la marcha cada vez.
- Se gasta una cantidad significativa de tiempo buscando el punto del gráfico más cercano al usuario dado. Para acelerar esto, dividí todo el gráfico en pequeños sectores, usando la fórmula de coordenadas, puede obtener instantáneamente la identificación del sector y luego seleccionar el vértice solo dentro del sector, y no en todo el gráfico, que es mucho más rápido.
Después de todas las manipulaciones, obtenemos la construcción de cualquier ruta de caminata razonable en San Petersburgo en 2 segundos, lo que suena bien: este es un tiempo de espera aceptable para los usuarios.
El esquema final salió así:

Total: Conocí aún mejor los datos de OSM, en la práctica resolví problemas de gráficos (el caso cuando los algoritmos de gráficos finalmente fueron útiles), escribí mis primeros puntos de referencia.
Acto 3: la primera versión web normal
Aquí vienen los primeros pensamientos sobre el proyecto como un producto que puede ser útil para alguien, y no sobre las manualidades sobre la mesa.
Por lo tanto, debe resolver los dos problemas más importantes:
- Era inmediatamente obvio que construir rutas como lo hice en el último párrafo está mal.
- Una guía en el navegador puede no ser conveniente para nadie: desea caminar por la ciudad, buscando una aplicación conveniente donde pueda leer lo que es especial, etc. En resumen, al menos, necesita una interfaz adaptativa genial y, en el buen sentido, una aplicación móvil.
Pero en esta etapa, decidí tratar solo con el primer punto. Estudiamos Internet sobre este tema y aquí nuevamente OSM ayuda, o mejor dicho, el proyecto que nació gracias a ellos: OSRM .
Basado en datos de mapas de OSM, la máquina de enrutamiento de código abierto puede construir una variedad de rutas en un buen momento. Sí, y un proyecto de código abierto con buena documentación que puede instalar en su servidor y usar.
Como beneficio adicional, también tiene una API bastante conveniente.
Y antaresm ya escribió sobre OSRM en un habr que me ayudó en ese momento. Es cierto que ha fluido mucha agua y el artículo está desactualizado. Pero muchas gracias al autor! La documentación real y bastante buena está aquí .
Después de una instalación exitosa, descartamos, casi sin arrepentimiento, todo nuestro código sobre las rutas y comenzamos a seguir las rutas en la API OSRM, y el diagrama final es el siguiente:

Ni siquiera tocamos la parte del cliente; por su parte, la API de nuestro servicio no cambia.
Total : pensé en el uso real de la aplicación por parte de otros, resultó ser una arquitectura normal y buenas rutas. La versión web todavía está disponible, aunque no ha cambiado desde entonces. https://travelpath.ru/
Acto 4: aplicación de Android
A pesar de la solución a un problema pasado, todavía está claro que el proyecto sigue siendo inútil para todos, excepto para mí. Porque necesita una interfaz normal y, lo más importante, una aplicación móvil, no una versión de navegador. Ahora la tecnología ha avanzado y, tal vez, ya será posible crear una aplicación de navegador de este tipo que funcione bien para clientes móviles, pero no en 2015-2016. Lo que significaba una posibilidad muy limitada de utilizar el proyecto en forma de versión web: sentarse en casa, seleccionar lugares interesantes para visitar con anticipación. Por lo tanto, si estamos hablando de un producto normal, necesita una aplicación móvil con una buena interfaz.
Luego, en 2016, comencé a escribir en Java (pero en el backend) y pensé que en Android también escribían en Java. ¿Por qué no probar el desarrollo de aplicaciones? Debería ser una experiencia interesante.
El segundo problema es que no sé cómo diseñar y no haré una buena interfaz yo mismo. Vine a visitar mi primer lugar de trabajo (un pequeño estudio Le-Dantu) e invité a mi colega burovk a participar en el proyecto. Por extraño que parezca, estuvo de acuerdo, por lo que muchas gracias :)
Los primeros diseños y prototipos.
En primer lugar, estamos tratando de encontrar un nuevo nombre, porque TravelPath no es una abreviatura muy, y también hablando. Y así, a través de los esfuerzos de Cyril aparece "Wander" con un logotipo divertido:
Lo he asociado fuertemente con un hombre bigotudo, pero en general me gusta.
Luego aparecen los primeros diseños de la aplicación futura:

También pensamos, discutimos, aparece la segunda opción, que se convierte en la primera versión de la aplicación:

Desde el lado del desarrollo, conscientemente decidí no usar todo tipo de marcos de moda que hagan magia diferente, porque existen grandes riesgos al usarlos sin comprender el trabajo, y estudiar tanto los conceptos básicos como los que requieren demasiado tiempo. Google, leemos muelles oficiales, artículos educativos y superamos dificultades.
De los problemas y tareas que se recuerdan:
- Para Android, existe
ProGuard
, una utilidad que comprime el código fuente durante el ensamblaje, elimina lo no utilizado, cambia los nombres y más. Es razonable que exista, pero cuando ingresa al desarrollo y lo hace usted mismo, no es obvio que haya cambios de nombre en los campos y esto puede afectar el comportamiento. Y que todo sucede solo en el montaje de productos. Como resultado del lanzamiento, todo es genial, pero por alguna razón no hay estadísticas. Comienza a debitar desde el backend, y el cliente envía algunas tonterías, en lugar de los nombres de campo normales: a, b, c
, etc. Muletas para que la API pueda analizar esto hábilmente, y luego descubres que ProGuard lo intentó y necesitas especificar las clases necesarias como una excepción en su configuración. Nada inusual en general, pero el reloj de depuración se fue volando. - Una tarea interesante fue actualizar los datos de la aplicación. La base de datos principal viene con un archivo
apk
y lo actualizo antes de cada lanzamiento. Pero también debe admitir la actualización a través de la red para que los clientes siempre tengan datos nuevos si hay algún cambio.
En la primera versión, decidí centrarme en el momento de la última actualización. La aplicación almacena el tiempo del objeto más fresco, en cada inicio le pregunta al backend con este tiempo si ha aparecido algo nuevo. Se le envían actualizaciones, el cliente recuerda nuevamente la hora del más nuevo de los objetos recibidos (pero no la hora de la actualización en sí, esto es importante).
Resultó que pensé mal, porque un año después apareció una quinta categoría: edificios. Y al actualizar de la versión anterior a la nueva, surge un problema. Tuve que cambiar un poco y el cliente envía tiempo para cada categoría, no la general. Pero el esquema aún no es perfecto: al agregar nuevos campos a los objetos, surgen problemas que no se pueden resolver de esa manera. Hay ideas sobre cómo hacerlo mejor, pero las manos no llegaron y, en general, la tarea no es muy prioritaria. Moralidad: vale la pena abordar estos temas con cuidado y pensar con un poco de anticipación.
Y también quiero decir lo que todo el mundo ya sabe: Stack Overflow es increíblemente genial y esto es especialmente notable cuando vuelas al desarrollo de algo extraño como yo lo hice: escribe inmediatamente la aplicación, y no sin problemas de cursos, guías, ejemplos de demostración . Y cuando no hay nadie para preguntarle a un amigo. Pero además de él, los chats sobre el desarrollo de Android también ayudaron: allí puede hacer preguntas más abstractas y pedir consejos sobre la mejor manera de hacer algo.
5 de diciembre de 2016 la aplicación llega a Google Play
Solo tenía funciones básicas: trazar una ruta, ver información sobre puntos. ¡Pero incluso eso parecía un éxito! El éxito, por supuesto, solo en sus propios ojos. Se entendió que la aplicación aún está en bruto y necesita ser mejorada.
La primera versión completa y los medios
Por lo tanto, considero que el próximo lanzamiento es una versión completa y el primer lanzamiento.
En primer lugar, revisamos tanto el diseño como el logotipo; ahora se ha convertido así:
Y agregaron funcionalidades importantes para la guía: favoritos, puntos de vista en el mapa, una lista de atracciones con una búsqueda. La aplicación actualizada se veía así:

Otra idea surgió: contactar a Museum Night y hacer un modo separado para el evento en San Petersburgo.
La Noche de los museos es una fiesta internacional anual en la que los museos están abiertos por la noche, a menudo con programas especiales. Un boleto único es válido y muchos intentan moverse por muchos museos a la vez. Al mismo tiempo, no hay un navegador / mapa para dispositivos móviles, solo algunas funcionalidades en el sitio web oficial del evento.
Parece que encaja perfectamente con la idea de Wander y también está en demanda. Me puse en contacto con los organizadores del evento, pero, desafortunadamente, la idea no fue apreciada y se mantuvo en mi mente hasta tiempos mejores.
Al final, resultó genial y finalmente la aplicación se pudo usar por completo. El 2 de junio de 2018, se lanzó un lanzamiento y decidimos intentar mostrárselo al mundo: compramos publicidad en VKontakte e Instagram. Pero lo más importante, escribieron a un par de medios de comunicación. El periódico escribió una nota sobre el lanzamiento de la aplicación, luego de que varias publicaciones de Petersburgo - The Village, Dog y otras - fueran escritas o reimpresas con un abanico. ¡Y finalmente hubo tráfico! Las instalaciones se apresuraron con un pico, gráficos de actividad dentro de la aplicación, también. Por supuesto, no tuvimos que alegrarnos por mucho tiempo, pero obtuvimos los primeros usuarios, comentarios útiles y, en general, fue muy motivador. En el mismo verano, el tráfico de la búsqueda de Google Play fue notable, lo que fue muy agradable, pero más tarde el resultado no pudo reproducirse.
En conjunto, esto dio una motivación bastante fuerte y ayudó a seguir trabajando en la aplicación.
¿Qué hacer a continuación? Noche de museo, malvado Google, rutas circulares
La temporada ha pasado, la actividad en la aplicación ha caído drásticamente y estaba claro que solo las funciones de corte no son muy útiles: nadie las verá, no hay presupuesto para el marketing. Era necesario pensar en algo y luego volvimos a la idea postergada con la Noche de los museos.
Pero, de nuevo, no fue posible acordar una asociación, sin embargo, esta vez decidimos no posponer la idea, sino hacer todo por nuestra cuenta. Resultó una serie de características útiles en un modo de guía separado: museos en el mapa, rutas solo para participantes, información breve, favoritos.
Además de este modo, incluso desde el trabajo atrasado obtuvimos la preservación de la ruta y, lo más importante, la característica de las rutas circulares.
Las rutas circulares siempre fueron más importantes que las rutas AB, pero se ignoraron obstinadamente. Aún así, las personas a menudo caminan alrededor del metro / casa / trabajo / hotel que a propósito de A a B. Finalmente, llegaron a sus manos y se me ocurrió una simple heurística:
Obtenemos todos los puntos dentro del radio dado. El radio es el limitador de la longitud de la ruta. Seleccionamos algún punto primero (condicionalmente aleatorio). Todos los demás están ordenados en orden ascendente del ángulo entre este, el centro y el punto dado. / , .
, .
, , :

, , , , , . — , , .
Kotlin , , Wander. , . , . , java — .
, , , . — The Village. - 1000 , 1400 . , Wander , , , . .
Google . — 2018 , API. — 2018- Places API
. API, - — . .
— Places API
, . , . , — Google Maps, . .
: android Google Play, . burovk , Wander , .
, , , — . , , , — . , — , . , , .
- —
git tag v1.0.5
. - , , , .
- - , .
- — , //etc .
Android . , , , .
— , .
! , . , , , , , .
:
- — ? - ?
- . , — .
- IOS
. , IOS , .
— . Google Play .
Conclusiones
- , — . , . . , .
- — , . backend , , android Kotlin, , , . , .
- — . - , . - . , — .
. IOS ( ) — !
PS
— https://habr.com/post/414433/ . . , ( -!), .