Formula de Pontuacao
O pipeline de scoring vive em src/lib/rider-score/. O kernel puro e scoreFromSignals() em compute-trip-score.ts e tem testes unitarios. A pontuacao rolante vive em update-rolling-score.ts.
Pontuacao por viagem
Cada viagem concluida recebe uma pontuacao de 0 a 100, recortada em ambas extremidades, escrita em ride_safety_signals com weights_snapshot para reprodutibilidade.
Formula padrao
score = clamp(
20 * speed_compliance_pct
+ 15 * parking_compliance
+ 15 * (1 - geofence_violation_decay)
+ 10 * (1 - hard_brake_rate)
+ 10 * (1 - throttle_aggression_rate)
+ 10 * clean_end_bool
+ 10 * helmet_verified_bool
+ 10 * (1 - sidewalk_event_rate) // peso 0 ate CV
- 5 * open_violation_count
- 2 * open_intervention_count,
0, 100
)
Entradas
| Sinal | Fonte | O que mede |
|---|---|---|
| Conformidade de velocidade | ride_locations.speed vs limite da zona | % das amostras GPS ate o limite da zona |
| Conformidade de estacionamento | ride_zone_events no fim da viagem | Binario: terminou em zona aprovada? |
| Violacoes de geofence | ride_zone_events no meio da viagem | Contagem, decaida por recencia |
| Frenagem brusca | Deltas de desaceleracao do GPS | Contagem de eventos acima do limite |
| Agressao no acelerador | ride_locations.throttle_position | % da viagem acima de 85% |
| Fim limpo | rides.end_method | Verdadeiro se terminou limpo |
| Capacete verificado | rider_helmet_selfies.passed_at | Verdadeiro se selfie nao-expirada existe |
| Eventos de calcada | Pipeline de CV (projeto 4) | Peso 0 ate CV |
| Violacoes abertas | violations.ride_id | -5 pontos cada |
| Intervencoes abertas | rider_interventions | -2 pontos cada |
Regra de inicio frio
Em viagens 1-3, o ciclista esta no nivel Iniciante. A pontuacao e registrada mas nao impulsiona intervencoes e nao contribui ainda para a pontuacao rolante.
Exclusao de viagens curtas
Viagens com menos de 60s ou 200m sao excluidas da pontuacao rolante.
Normalizacao por comprimento
Scoring por viagem e baseado em taxas. Uma viagem longa nao e penalizada por ser longa.
Pontuacao rolante
A pontuacao rolante e uma media movel ponderada exponencialmente das pontuacoes por viagem nos ultimos 90 dias.
rolling_score = clamp(
sum(trip_score_i * weight_i) / sum(weight_i),
0, 100
)
onde weight_i = exp(-ln(2) * age_days_i / halflife_days)
- Janela: 90 dias, configuravel.
- Meia-vida: 30 dias, configuravel.
- Inicio frio: menos de 3 viagens pontuadas = nivel Iniciante.
Armazenada em rider_scores.rolling_score.
Atribuicao de nivel
| Nivel padrao | Pontuacao rolante |
|---|---|
| Platina | 90+ |
| Ouro | 80 a 89 |
| Prata | 70 a 79 |
| Bronze | 50 a 69 |
| Em Risco | abaixo de 50 |
| Iniciante | menos de 3 viagens pontuadas |
Transicoes de nivel disparam concessoes de recompensa e re-avaliacoes da escada.
Reprodutibilidade
Cada linha de pontuacao por viagem carrega um blob JSON weights_snapshot com os pesos, limites e sinais exatos usados.
O que roda onde
| Codigo | Proposito |
|---|---|
src/lib/rider-score/compute-trip-score.ts | Puxa sinais, calcula pontuacao por viagem |
src/lib/rider-score/update-rolling-score.ts | EWMA, escolhe nivel |
src/lib/rider-score/post-ride.ts | Coordenador, soft-fail |
src/lib/rider-score/intervention-engine.ts | Avalia a escada |
src/lib/rider-score/reward-engine.ts | Emite recompensas via pipeline de reembolso |
O que nao acontece
- Nao pontuamos o operador ou a frota.
- Nao penalizamos viagens cortadas por bateria morta.
- Nao reutilizamos pontuacao entre subcontas na v1.
Proximo
Veja Pesos e Configuracoes para ajustar a formula. Veja Solucao de Problemas se uma pontuacao nao corresponde a expectativa.