Para exibir a disponibilidade de bicicletas em tempo real em um aplicativo, associe o número retornado ao seu frescor e às possibilidades de retirada do veículo. Uma observação descreve o que a fonte sabia em um instante; não garante que uma bicicleta ainda estará disponível na chegada.
O contrato de mobilidade ROOTE distingue estações, veículos individuais e seus estados. A interface deve traduzir essas diferenças sem confundir um valor desconhecido, uma estação vazia e uma fonte temporariamente indisponível.
Separar uma estação de um veículo individual
Uma estação pode expor contadores de bicicletas e de vagas de retorno. Um veículo individual possui um estado de disponibilidade e outras informações eventuais. Evite contar uma estação como uma bicicleta ou somar contadores representando o mesmo estoque.
No DTO de mobilidade ROOTE, availability.bikes e availability.docks podem ser desconhecidos. Os campos de propulsão ou bateria devem ser exibidos apenas se existirem e forem interpretados conforme o contrato.
Ler o frescor e os timestamps
| Campo | Interpretação |
|---|---|
| freshness.state | Estado anunciado: fresh, stale, unknown ou static |
| freshness.source_updated_at | Data de atualização da fonte, se conhecida |
| freshness.received_at | Data de recebimento indicada pelo contrato |
| freshness.expires_at | Prazo de validade indicado, se conhecido |
| availability.bikes | Quantidade conhecida ou valor desconhecido |
| pickup.enabled e pickup.state | Informações sobre a retirada de uma bicicleta na estação |
A hora da sua chamada não é automaticamente a da observação. Um resultado recebido às 10h pode conter uma fonte atualizada às 9h45. Não exiba “atualizado agora” com base apenas na hora de recebimento da sua interface.
Prever estados de exibição distintos
| Dado recebido | Exibição a prever |
|---|---|
| Quantidade conhecida e dado fresco | Quantidade observada e indicação temporal |
| Quantidade igual a zero | Nenhuma bicicleta observada, com seu contexto temporal |
| Quantidade null | Disponibilidade desconhecida |
| Estado stale ou prazo vencido | Dado antigo; sugerir uma atualização |
| pickup.enabled=false | Retirada indisponível mesmo se um contador é positivo |
| Erro de busca | Disponibilidade temporariamente indisponível, sem converter para zero |
Não classifique um estado unknown ou static como fresco. Uma informação de estação pode ser estável enquanto o contador evolui rapidamente. Também mantenha os avisos e atribuições exigidos pela resposta.
Um exemplo de normalização antes da renderização
A função a seguir produz um estado de apresentação a partir de uma estação já validada contra o esquema ROOTE. Ela não é um validador completo da resposta. Os rótulos visíveis devem vir das chaves de tradução da sua interface.
function availabilityView(station, now = Date.now()) {
const freshness = station.freshness;
const expiresAt = freshness.expires_at
? Date.parse(freshness.expires_at) : null;
const expired = expiresAt !== null &&
Number.isFinite(expiresAt) && expiresAt <= now;
if (station.pickup.enabled === false ||
station.pickup.state === 'unavailable_now') {
return { state: 'pickup_unavailable', count: null };
}
if (expired || freshness.state === 'stale') {
return { state: 'stale', count: null };
}
const count = station.availability.bikes;
if (freshness.state !== 'fresh' || count === null ||
!Number.isFinite(count) || count < 0) {
return { state: 'unknown', count: null };
}
return {
state: count === 0 ? 'empty' : 'observed', count,
sourceUpdatedAt: freshness.source_updated_at,
receivedAt: freshness.received_at,
pickupState: station.pickup.state
};
}
Mesmo com um estado observed, não transforme pickupState=unknown em retirada confirmada. O contador permanece uma observação. Exiba o contexto da retirada se seu produto ajuda o usuário a escolher uma estação.
Atualizar sem multiplicar chamadas desnecessariamente
Adapte a atualização ao vencimento publicado, às condições do serviço e ao comportamento do usuário. Agrupe pedidos idênticos, evite chamadas em segundo plano em uma página inativa e cancele as de uma busca substituída.
Um tempo local de cache não prova o frescor da fonte. Após um erro, você pode manter a última observação datada se sua interface a apresentar explicitamente como antiga. Não apague essa distinção na primeira retomada bem-sucedida se a fonte continuar stale.
Entender a ligação com GBFS
GBFS descreve os serviços de mobilidade compartilhada e seus estados publicados. Uma integração direta deve interpretar os arquivos, a versão e os timestamps do fluxo. Com uma API normalizada, use o contrato da API; não adicione um campo GBFS supostamente ausente na sua resposta.
Escolher entre GTFS, GTFS Realtime e GBFS
Testar situações que enganam o leitor
Teste um zero real, um valor desconhecido, um prazo vencido, uma retirada desativada e um erro após um resultado válido. Verifique também os fusos horários de exibição. Um contador positivo jamais deve produzir “bicicleta reservada” e uma indisponibilidade nunca deve produzir um zero inventado.
Gerenciar respostas vazias e erros
Aplicar essas regras em um assistente IA
Guia do usuário para encontrar uma bicicleta
Perguntas frequentes
Uma quantidade positiva garante uma bicicleta na minha chegada?
Não. Ela descreve uma observação, que pode mudar entre a consulta e sua chegada.
Pode-se substituir null por zero?
Não. null indica um valor desconhecido; zero é uma quantidade conhecida e tem outro significado.
É preciso atualizar a cada poucos segundos?
Use as indicações de validade, os limites do serviço e as necessidades da sua interface. Uma frequência arbitrária não garante uma fonte mais fresca.