@@ -86,7 +86,7 @@ export interface ForecastEnrichment {
8686export const LEGACY_FLAG_OPERATORS : readonly string [ ] = [ 'Cruz Roja' ] ;
8787
8888/** Weight of the flag factor in the 0-100 total, and the total itself. */
89- const FLAG_MAX = 20 ;
89+ const FLAG_MAX = 10 ;
9090const SCORE_MAX = 100 ;
9191
9292/**
@@ -99,21 +99,21 @@ export const SUBSCORE_MAX = {
9999 cielo : 25 ,
100100 temperatura : 25 ,
101101 bandera : FLAG_MAX ,
102- viento : 15 ,
102+ viento : 25 ,
103103 oleaje : 10 ,
104104 datos : 5 ,
105105} as const ;
106106
107107/**
108108 * Reachable maximum when the region has no flag service: the flag factor
109- * disappears (-20 ) and `datos` can never award the 2 points that came from
109+ * disappears (-10 ) and `datos` can never award the 2 points that came from
110110 * having a flag reading (-2).
111111 */
112112const SCORE_MAX_WITHOUT_FLAG = SCORE_MAX - FLAG_MAX - 2 ;
113113
114114/**
115115 * Rescales to 0-100 the score of a region with no flag service. Without this
116- * every beach in such a region would lose the same ~22 points, and the bands
116+ * every beach in such a region would lose the same ~12 points, and the bands
117117 * (green ≥60) would read the absence of an operator as bad conditions —
118118 * penalising the whole region for something that has nothing to do with the
119119 * beach.
@@ -254,47 +254,47 @@ export function computeTemperatureScore(tempC: number | null): number {
254254}
255255
256256// ---------------------------------------------------------------------------
257- // Flag score (0-20 )
257+ // Flag score (0-10 )
258258// ---------------------------------------------------------------------------
259259
260260/**
261261 * `unknown` scores the SAME neutral as having no flag service at all, and that
262262 * is the whole point: there is a flag flying, what is missing is our reading of
263263 * it. Docking points for it punished the beach for a failure of ours — and
264264 * punished it HARDER than a beach with no lifeguards, which walks away with the
265- * neutral 10 . Ignorance is not evidence of bad conditions.
265+ * neutral 5 . Ignorance is not evidence of bad conditions.
266266 *
267267 * Safety does not rest on this number: a stale black or red keeps its colour
268268 * (see `GetFeaturedBeaches.getFlagForBeach`) and keeps excluding the beach, so
269269 * what degrades to `unknown` is only ever a green or a yellow.
270270 */
271271const FLAG_SCORE : Record < FlagColor , number > = {
272- green : 20 ,
273- yellow : 10 ,
272+ green : 10 ,
273+ yellow : 5 ,
274274 red : 0 ,
275275 black : 0 ,
276- unknown : 10 ,
276+ unknown : 5 ,
277277} ;
278278
279279/** Neutral when there is nothing to judge: no service, or no reading of it. */
280- const FLAG_NEUTRAL = 10 ;
280+ const FLAG_NEUTRAL = 5 ;
281281
282282export function computeFlagScore ( flag : FlagStatus | null ) : number {
283283 if ( ! flag || ! flag . color ) return FLAG_NEUTRAL ; // no CR coverage → neutral
284284 return FLAG_SCORE [ flag . color ] ?? FLAG_NEUTRAL ;
285285}
286286
287287// ---------------------------------------------------------------------------
288- // Wind score (0-15 )
288+ // Wind score (0-25 )
289289// ---------------------------------------------------------------------------
290290
291291export function computeWindScore ( windSpeedMs : number | null ) : number {
292- if ( windSpeedMs == null ) return 7 ;
293- if ( windSpeedMs <= 3 ) return 15 ;
294- if ( windSpeedMs <= 5 ) return interpolate ( windSpeedMs , 3 , 5 , 15 , 12 ) ;
295- if ( windSpeedMs <= 8 ) return interpolate ( windSpeedMs , 5 , 8 , 12 , 8 ) ;
296- if ( windSpeedMs <= 12 ) return interpolate ( windSpeedMs , 8 , 12 , 8 , 3 ) ;
297- return interpolate ( Math . min ( windSpeedMs , 20 ) , 12 , 20 , 3 , 0 ) ;
292+ if ( windSpeedMs == null ) return 12 ;
293+ if ( windSpeedMs <= 3 ) return 25 ;
294+ if ( windSpeedMs <= 5 ) return interpolate ( windSpeedMs , 3 , 5 , 25 , 20 ) ;
295+ if ( windSpeedMs <= 8 ) return interpolate ( windSpeedMs , 5 , 8 , 20 , 13 ) ;
296+ if ( windSpeedMs <= 12 ) return interpolate ( windSpeedMs , 8 , 12 , 13 , 5 ) ;
297+ return interpolate ( Math . min ( windSpeedMs , 20 ) , 12 , 20 , 5 , 0 ) ;
298298}
299299
300300// ---------------------------------------------------------------------------
@@ -417,7 +417,7 @@ export function computeBeachScore(
417417 cielo : computeSkyScore ( weather ) ,
418418 temperatura : computeTemperatureScore ( weather ?. temperatureC ?? null ) ,
419419 // 0 and out of the sum with no operator in the region: there is no flag to
420- // judge, so a neutral 10/20 would be inventing a middling reading.
420+ // judge, so a neutral 5/10 would be inventing a middling reading.
421421 bandera : hasFlagService ? computeFlagScore ( effectiveFlag ) : 0 ,
422422 viento : computeWindScore ( weather ?. windSpeedMs ?? null ) ,
423423 oleaje : computeWavesScore ( enrichment , weather , isSurf ) ,
@@ -573,7 +573,7 @@ export function buildCautionReason(
573573 const forecastPart = rainPart ? null : rainForecastReasonFragment ( rainForecast ) ;
574574 if ( forecastPart ) parts . push ( forecastPart ) ;
575575
576- if ( subScores . viento <= 3 ) parts . push ( 'viento fuerte' ) ;
576+ if ( subScores . viento <= 5 ) parts . push ( 'viento fuerte' ) ;
577577 if ( subScores . oleaje <= 2 ) parts . push ( 'oleaje fuerte' ) ;
578578 if ( subScores . cielo <= 3 && ! rainPart && ! forecastPart ) parts . push ( 'lluvia o tormenta' ) ;
579579 if ( subScores . temperatura <= 5 ) parts . push ( 'temperatura baja' ) ;
@@ -632,7 +632,7 @@ export function buildDowngradeFactors(
632632 else if ( flag ?. color === 'red' ) parts . push ( 'bandera roja' ) ;
633633 else if ( ! flag ?. color && operador && ! hasFlagStation ) parts . push ( `sin cobertura ${ operador } ` ) ;
634634
635- if ( subScores . viento <= 5 ) parts . push ( 'viento fuerte' ) ;
635+ if ( subScores . viento <= 8 ) parts . push ( 'viento fuerte' ) ;
636636 if ( subScores . oleaje <= 3 ) parts . push ( 'oleaje fuerte' ) ;
637637
638638 if ( outlook ?. direccion === 'empeora' ) {
0 commit comments