Muitos têm um ou mais de seus projetos domésticos. São pequenas utilidades, peças experimentais, amostras de novas tecnologias, “assassinos” do Facebook e muito mais. Notavelmente com menos frequência esses projetos estão envolvidos por um longo tempo.
No artigo, compartilharei minha experiência e contarei como, por cinco anos, trabalhei ocasionalmente no desenvolvimento de um guia inteligente para São Petersburgo, como consegui não abandonar esse negócio, como a atitude em relação ao projeto mudou e o que aconteceu no final.

Muitas soluções técnicas e bicicletas duvidosas são descritas abaixo, mas não se surpreenda - quase todas elas são justificadas pelas metas e recursos disponíveis naquele momento (= geralmente meu conhecimento e tempo)
Idéia
Em qualquer grande cidade turística, existem centenas de guias, bons e não muito bons, onde as principais rotas são pintadas, os principais pontos e várias outras informações úteis.
Mas as rotas são constantes e limitadas, e os pontos turísticos geralmente são apenas os mais importantes, como "o que ver em 3 dias".
Portanto, surgiu a ideia de construir rotas inteligentes. O usuário seleciona os pontos A e B e recebe não a rota mais curta clássica, mas algo próximo a ela, mas passando pelas atrações próximas.
A audiência desse guia não é apenas turistas, mas também residentes locais que desejam diversificar suas rotas típicas para casa / trabalho / loja (e, no final, houve essas avaliações no aplicativo!) Ou simplesmente para conhecer melhor a cidade.
TL; DR
O resultado final é o aplicativo Wander Android, que agora funciona apenas para São Petersburgo.
Ato 1: Protótipo
A ideia voltou à universidade em 2014, nem tenho certeza de que ela era originalmente minha; em algum curso, foi necessário dividir-se em grupos, criar projetos e concluí-los como um trabalho de conclusão de curso. Eles falharam e geraram a ideia do projeto e, em seguida, o nome TravelPath
começou.
Era para ser um serviço da web, eu sabia um pouco sobre PHP, então escolhi o PHP.
Foi necessário resolver vários problemas:
1. Base de Atrações
Aqui nos encontramos com o OpenStreetMap , e esse é o projeto mais legal que nos convém perfeitamente. O OSM é um projeto de mapa da comunidade, sem fins lucrativos, baseado na comunidade. Como a Wikipedia, apenas sobre mapas.
Faça o download do mapa no formato xml de São Petersburgo - há uma lista de recursos onde você pode fazer isso.
Naquele momento, lembro-me de que os arquivos de mapas pesavam mais de 1 GB; portanto, um analisador de fluxo contínuo é escrito para selecionar objetos de categorias pré-selecionadas - monumentos, parques, igrejas, museus.
O OSM possui uma extensa documentação sobre tags, atributos e tudo o que você precisa aqui , graças a isso não será difícil descobrir como obter os dados necessários dos cartões.
Os dados cartográficos são criados por entusiastas, portanto, nem todos os lugares e nem sempre os objetos têm as tags necessárias, alguns lugares têm erros, problemas. Mas para grandes cidades, os dados são de alta qualidade.
Se eu descobri corretamente meu código antigo, usei as seguintes tags para buscar objetos:
building
significado cathedral
, chapel
, church
tornou-se uma categoria de church
amenity
com os valores das fountain
cai no monument
tourism
com valores de artwork
e viewpoint
vai para monument
, zoo
e museum
para museum
e theme_park
para park
historic
com boundary_stone
, castle
, memorial
, valores do monument
vai para a categoria monument
leisure
com um valor no park
naturalmente, acaba no park
Colocamos todos os objetos recebidos em um banco de dados com coordenadas e nos alegramos! Mais de 1.200 pontos foram lançados em São Petersburgo.
2. Construindo uma rota
Não era para implementar sistemas complexos como parte do curso, e como o conhecimento técnico era escasso na época, decidimos dividir a rota em duas partes: a escolha dos objetos na rota e a própria rota. Em parte, isso determinou o destino do futuro, porque mais tarde eu não quis mudar esse esquema.
A construção de uma rota entre os pontos selecionados foi dada pela API do Google Maps, que construiu rotas de carro muito bem, mas na época não sabia andar, pelo menos na Rússia.
A escolha dos objetos teve que ser implementada por você mesmo. O resultado foi o seguinte esquema do aplicativo:

A principal desvantagem da abordagem é a seleção de pontos na rota sem levar em conta o mapa, apenas com base nas coordenadas GPS. E, no geral, isso funciona razoavelmente bem, especialmente onde há uma grade de ruas frequente. Problemas raros são visíveis ao longo de rios com pontes raras, por exemplo.
Em seguida, criamos um algoritmo para selecionar pontos na rota. Por um lado, é necessário que a rota não desvie muito para o lado, mas, por outro lado, ainda seleciona alguns pontos nos bairros em questão.
Não é uma afirmação muito clara do problema, saiu o mesmo algoritmo, algo semelhante ao A * ( wiki ): acredita-se que de cada ponto haja transições para cada um. Além disso, em A *, o preço de ir para o vértice n ao procurar a rota AB é geralmente expresso da seguinte forma: f(n) = g(An) + h(nB)
, onde g(x,y)
é o comprimento do caminho de x para y, h(x,y)
é uma estimativa heurística da distância de x a y. Meu preço é o mesmo - f(n) = h(x,n) + h(n,y) * q
, onde q é uma constante menor que 1. Alterando o valor de q, você pode afetar o número de pontos na rota.
Implementamos o algoritmo e, parabéns, tudo funciona, fixamos a interface, compramos um domínio, carregamos para a hospedagem, escrevemos relatórios e outras burocracias e nos alegramos! Parecia algo assim (e não mudou muito depois):

Total: recebi um protótipo de uma idéia interessante, conheci o OSM, a API do Google, trabalhei em equipe, obtive crédito na universidade e também foi interessante.
Ato 2: primeira versão web completa
Gostei muito da ideia e decidi desenvolvê-la ainda mais, mas já uma. E ficou imediatamente claro o que era necessário antes de tudo: naquela época, o Google Maps ainda não era capaz de construir rotas a pé, apenas as de automóveis. E toda a idéia do aplicativo é principalmente sobre caminhadas, o que significa que você precisa ser capaz de construir rotas ao longo dos becos sombrios de parques, passarelas para pedestres, pontes e muito mais.
Foi em 2015, e continuei a trabalhar no TravelPath, assumi a correção dessa falha fatal - comecei a construir maneiras por conta própria.
Eu não mudei a tecnologia, PHP
+ MySQL
. Obviamente, percebi imediatamente que essa não era a melhor pilha técnica para essa tarefa (construir rotas em PHP? Sério?).
Mas eu tinha um tempo limitado e não estava pronto para mudar para uma pilha mais razoável e, em segundo lugar, até agora o projeto estava escrito "em cima da mesa" - eu gostaria de usar esse aplicativo em um dispositivo móvel e, naqueles anos, significava apenas desenvolvimento nativo. Ou seja, sua inaplicabilidade na forma de uma versão da Web era óbvia, apesar de algumas tentativas de criar uma interface adaptável.
Surgiram as seguintes tarefas:
1. Obtendo um gráfico da cidade
Aqui o mesmo OSM nos salva. Mais uma vez, baixe o gráfico no formato xml, analise-o, selecionando apenas os tipos de estradas necessários e maravilhe-se com a quantidade de dados - naquele momento, mais de 3 milhões de vértices e 500 mil arestas foram lançados. A primeira idéia é que o gráfico pode não estar relacionado.
Quaisquer pátios, territórios fechados, coisas incompreensíveis não são muito interessantes para a construção de uma rota; portanto, selecionamos algum ponto, contornamos todo o gráfico, marcando os vértices passados e obtendo a parte conectada do gráfico.
No total, surgiram mais de 600 mil picos e 150 mil arestas.
Salva os recebidos no banco de dados e sai para tempos melhores.
2. Construindo uma rota
Existem dados, tudo é deixado para os pequenos: crie rotas nele. Não tivemos que inventar nada de novo - lembre-se do curso de algoritmos, leia atentamente os artigos sobre como trabalhar com gráficos, pegue o algoritmo A *, implemente-o em PHP e regozijar-se frustrado com o quão lentamente tudo funciona.
Existem muitos dados, portanto, ao construir o gráfico, usamos não o completo, mas apenas lemos parte dele - tudo o que cai no retângulo obtido de todos os pontos selecionados na rota.
(quadro vermelho = ~ esse gráfico foi lido para construir o caminho)
O mesmo acontece com os pontos candidatos à rota - levamos em conta não tudo, mas apenas aqueles entre o início e o fim + um pequeno valor.
Depois de selecionar o tamanho desse retângulo (a constante pela qual o aumentamos), tentamos garantir que lemos o tamanho mínimo de dados necessário.
Havia também a idéia de dividir a cidade em quadrados, construindo o percurso primeiro por quadrados e, depois, lendo o gráfico dentro desses quadrados e procurando um caminho apenas ao longo dele. E você pode pré-calcular os caminhos entre todos os quadrados vizinhos. Ou ainda mais - para calcular e salvar o caminho entre todos os pontos turísticos. Então, na hora, resta construir apenas os caminhos do objeto inicial ao primeiro e do último objeto à linha de chegada.
Mas as mãos não alcançaram a realização de tais bicicletas.
3. Roteamento em um período de tempo razoável
Imediatamente ficou claro que o gargalo é o armazenamento e o trabalho com dados - o próprio algoritmo de busca não é particularmente acelerado. E benchmarks no joelho confirmam que a maior parte do tempo é gasta lendo o banco de dados e manipulações semelhantes.
O que deve ser feito nesses casos? Não guarde este gráfico. Mas eu tenho uma maneira especial, MySQL
e nada mais, mas o problema precisa ser resolvido.
- O primeiro - os dados foram normalizados, o que era conveniente ao analisar, mas ler dezenas de milhares de registros e até duas tabelas é doloroso. A solução óbvia é criar uma de duas tabelas (para vértices e arestas), apenas para arestas, nas quais em cada registro as coordenadas dos vértices e seu ID.
- Contamos com antecedência os vértices mais próximos do gráfico aos pontos turísticos, e não fazemos isso sempre.
- Uma quantidade significativa de tempo é gasta pesquisando o ponto do gráfico mais próximo do usuário especificado. Para acelerar isso, dividi o gráfico inteiro em pequenos setores. Usando a fórmula de coordenadas, você pode obter instantaneamente o ID do setor e selecionar o vértice apenas dentro do setor, e não no gráfico inteiro, que é muito mais rápido.
Depois de todas as manipulações, conseguimos construir qualquer rota a pé razoável em São Petersburgo em 2 segundos, o que parece bom - esse é um tempo de espera aceitável para os usuários.
O esquema final saiu assim:

Total: familiarizei-me ainda melhor com os dados do OSM; na prática, resolvi problemas de gráficos (o caso em que os algoritmos de gráficos finalmente foram úteis), escrevi meus primeiros benchmarks.
Ato 3: a primeira versão normal da web
Aí vêm os primeiros pensamentos sobre o projeto como um produto que pode ser útil para alguém, e não sobre o artesanato em cima da mesa.
Então, você precisa resolver os dois problemas mais importantes:
- Ficou imediatamente óbvio que a construção de rotas como eu fiz no último parágrafo está errada.
- Um guia no navegador pode não ser conveniente para ninguém - você deseja passear pela cidade, procurando um aplicativo conveniente onde possa ler o que há de especial por aí e assim por diante. Em suma, pelo menos - você precisa de uma interface adaptável legal e, de uma maneira boa, de um aplicativo móvel.
Mas, nesta fase, decidi lidar apenas com o primeiro ponto. Estudamos a Internet sobre esse assunto e aqui novamente o OSM ajuda, ou melhor, o projeto que nasceu graças a eles - OSRM .
Com base nos dados do mapa do OSM, a Open Source Routing Machine pode construir uma variedade de rotas em um bom momento. Sim, e um projeto de código aberto com boa documentação que você pode instalar no servidor e usar.
Como bônus, ele também possui uma API bastante conveniente.
E o antaresmo já escreveu sobre OSRM em um habr que me ajudou na época. É verdade que muita água correu e o artigo está desatualizado. Mas muito obrigado ao autor! A documentação real e muito boa está aqui .
Após uma instalação bem-sucedida, lançamos, quase sem arrependimento, todo o nosso código sobre as rotas e começamos a seguir as rotas na API OSRM, e o diagrama final é o seguinte:

Nem sequer tocamos na parte do cliente; por sua vez, a API do nosso serviço não muda de forma alguma.
Total : pensei no uso real do aplicativo por outros, ele acabou sendo uma arquitetura normal e boas rotas. A versão web ainda está disponível, embora não tenha sido alterada desde então. https://travelpath.ru/
Ato 4: aplicativo para Android
Apesar da solução para um problema passado, ainda está claro que o projeto ainda é inútil para todos, exceto eu. Porque você precisa de uma interface normal e, mais importante, de um aplicativo móvel, não de uma versão do navegador. Agora a tecnologia avançou e, talvez, já seja possível criar um aplicativo de navegador desse tipo para clientes móveis, mas não em 2015-2016. O que significava uma possibilidade muito estreita de usar o projeto na forma de uma versão da Web - para ficar em casa, selecione lugares interessantes para visitar com antecedência. Portanto, se estamos falando de um produto normal, você precisa de um aplicativo móvel com uma boa interface.
Então, em 2016, comecei a escrever em Java (mas o back-end) e pensei que, no Android, eles também escreviam em Java. Por que não tentar o desenvolvimento de aplicativos, deve ser uma experiência interessante.
O segundo problema é que eu não sei projetar e não faço uma boa interface. Eu vim visitar meu primeiro local de trabalho (um pequeno estúdio Le-Dantu) e convidei meu colega Burovk para participar do projeto. Curiosamente, ele concordou, pelo qual muito obrigado :)
Os primeiros layouts e protótipo
Primeiro de tudo, estamos tentando criar um novo nome, porque o TravelPath não é uma abreviação muito e muito faladora. E assim, através dos esforços de Cyril, aparece "Wander" com um logotipo engraçado:
Eu o associei fortemente a um homem de bigode, mas em geral eu gosto.
Aparecem os primeiros layouts do futuro aplicativo:

Também pensamos, discutimos, a segunda opção aparece, que se torna a primeira versão do aplicativo:

Do lado do desenvolvimento, decidi conscientemente não usar todos os tipos de estruturas da moda que fazem mágica diferente - porque há grandes riscos ao usá-las sem entender o trabalho, e estudar tanto o básico quanto eles consome muito tempo. Google, lemos docas oficiais, artigos educacionais e superamos dificuldades.
Dos problemas e tarefas lembrados:
- Para o Android, existe o
ProGuard
- um utilitário que comprime o código fonte durante a montagem, elimina o não utilizado, altera nomes e muito mais. É razoável que exista, mas quando você entra no desenvolvimento e faz você mesmo - não é óbvio que há campos de renomeação e isso pode afetar o comportamento. E que tudo acontece apenas na montagem de prod. Como resultado do lançamento, tudo é legal, mas por algum motivo não há estatísticas. Você começa a debitar no back-end - e o cliente envia algumas bobagens, em vez dos nomes normais dos campos - a, b, c
, etc. Muletas para que a API seja capaz de analisar isso com habilidade e, em seguida, você descobre que o ProGuard tentou e precisa especificar as classes necessárias como uma exceção em sua configuração. Nada incomum em geral, mas o relógio de depuração voou para longe. - Uma tarefa interessante foi atualizar os dados do aplicativo. O banco de dados principal vem com um arquivo
apk
e eu o atualizo antes de cada lançamento. Mas você também precisa oferecer suporte à atualização pela rede, para que os clientes sempre tenham dados atualizados, se houver alguma alteração.
Na primeira versão, decidi me concentrar apenas na hora da última atualização. O aplicativo armazena o horário do objeto mais recente; a cada início, ele pergunta ao back-end com esse horário se algo novo apareceu. As atualizações são enviadas a ele; o cliente se lembra novamente da hora do mais novo dos objetos recebidos (mas não da hora da atualização em si, isso é importante).
Aconteceu que eu pensei mal - porque um ano depois apareceu uma quinta categoria - edifícios. E ao atualizar da versão antiga para a nova, surge um problema. Eu tive que mudar um pouco e o cliente envia um tempo para cada categoria, não a geral. Mas o esquema ainda não é perfeito - ao adicionar novos campos aos objetos, surgem problemas que não podem ser resolvidos dessa maneira. Existem idéias sobre como fazer melhor, mas as mãos não chegaram e, em geral, a tarefa não é muito prioritária. Moralidade - vale a pena abordar cuidadosamente essas questões e pensar um pouco com antecedência.
E também quero dizer o que todo mundo já sabe - o Stack Overflow é incrivelmente legal e isso é especialmente perceptível quando você desenvolve algo estranho do jeito que eu fiz - escreva imediatamente o aplicativo e não com tranqüilidade nos cursos, guias e exemplos de demonstração . E quando não há ninguém para perguntar a um amigo. Mas, além dele, as conversas sobre o desenvolvimento do Android também ajudaram - aí você pode fazer perguntas mais abstratas e pedir dicas sobre a melhor forma de fazer algo.
5 de dezembro de 2016 o aplicativo acessa o Google Play
Ele tinha apenas funções básicas - estabelecer uma rota, visualizar informações sobre pontos. Mas mesmo isso pareceu um sucesso! Sucesso, é claro, apenas aos seus próprios olhos. Havia um entendimento de que o aplicativo ainda é bruto e precisa ser aprimorado.
A primeira versão completa e a mídia
Portanto, considero o próximo lançamento uma versão completa e o primeiro lançamento.
Antes de tudo, revisamos o design e o logotipo - agora ficou assim:
E eles adicionaram funcionalidades importantes para o guia - favoritos, pontos de visualização no próprio mapa, uma lista de atrações com uma pesquisa. O aplicativo atualizado ficou assim:

Outra idéia surgiu - entrar em contato com a Museum Night e criar um modo separado para o evento em São Petersburgo.
A Noite dos Museus é um feriado internacional anual, onde os museus ficam abertos à noite, com programas especiais. Um único bilhete é válido e muitos tentam percorrer muitos museus ao mesmo tempo. Ao mesmo tempo, não há navegador / mapa para celular - apenas algumas funcionalidades no site oficial do evento.
Parece que ele se encaixa perfeitamente com a idéia de Wander e também está em demanda. Entrei em contato com os organizadores do evento, mas, infelizmente, a idéia não foi apreciada e permaneceu em minha mente até tempos melhores.
No final, ficou legal e, finalmente, o aplicativo pôde ser totalmente utilizado. Em 2 de junho de 2018, um lançamento foi lançado e decidimos tentar mostrá-lo ao mundo - compramos publicidade no VKontakte e no Instagram. Mas o mais importante, eles escreveram para alguns meios de comunicação. O jornal escreveu uma nota sobre o lançamento do aplicativo, depois que várias publicações de Petersburgo - The Village, Dog e outros - foram escritas ou reimpressas com um fã. E, finalmente, houve tráfego! As instalações surgiram com um pico, também gráficos de atividades dentro do aplicativo. Obviamente, não tivemos que nos alegrar por muito tempo - mas recebemos os primeiros usuários, um feedback útil e, em geral, foi muito motivador. No mesmo verão, o tráfego da pesquisa do Google Play foi notável, o que foi muito agradável, mas mais tarde o resultado não pôde ser reproduzido.
Ao todo, isso deu uma forte motivação e ajudou a continuar trabalhando no aplicativo.
O que fazer depois? Museum Night, Google mal, rotas circulares
A temporada passou, a atividade no aplicativo caiu drasticamente e ficou claro que apenas serrar recursos não é muito útil - ninguém os verá, não há orçamento para marketing. Era necessário inventar alguma coisa e, em seguida, voltamos à idéia adiada com a Noite dos Museus.
Mas, novamente, não foi possível chegar a um acordo, mas desta vez decidimos não adiar a idéia, mas fazer tudo por conta própria. Ele resultou em vários recursos úteis em um modo de guia separado: museus no mapa, rotas apenas para participantes, informações breves, favoritos.
Além desse modo, mesmo no backlog, conseguimos a preservação da rota e, mais importante, o recurso sobre rotas circulares.
As rotas circulares eram sempre mais importantes que as rotas AB, mas eram teimosamente ignoradas. Ainda assim, as pessoas costumam andar pelo metrô / casa / trabalho / hotel do que propositalmente de A a B. Finalmente, elas alcançaram suas mãos e eu criei uma heurística simples:
Obtemos todos os pontos dentro do raio especificado. Raio é o limitador do comprimento da rota. Selecionamos primeiro algum ponto (aleatoriamente condicional). Todos os outros são ordenados em ordem crescente do ângulo entre ele, o centro e o ponto especificado. / , .
, .
, , :

, , , , , . — , , .
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 .
Conclusões
- , — . , . . , .
- — , . backend , , android Kotlin, , , . , .
- — . - , . - . , — .
. IOS ( ) — !
PS
— https://habr.com/post/414433/ . . , ( -!), .