+
    8T-j#                    d   R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIHt ^ RI	H
t ^ RIHt ]P                  R,          R,          t]P                  R,          R,          t]P                  R,          P#                  R	4      t]P                  R
,          R,          t]P(                  P+                  4        U Uu/ uF  w  rV ]! V4      bK  	  upp t
. RuNRvNRwNRxNRyNRzNR{NR|NR}NR~NRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNRNtRR. RORRRR/RR. RORRRR/RR. RORRRR/RR. RORRRR/RR. RORRRR//tRRuttR tR tR tR  tR! tR" t R# t!0 R$kR%kR&kR'kR(kR)kR*kR+kR,kR-kR.kR/kR0kR1kR2kR3kR4kR5kR6kR7kR8kR9kR:kR;kR<kR=kR>kR?kR@kRAkRBkRCkRDkREkRFkRGkRHkRIkRJkRKkRLkRMkRNkt"RO t#RP t$. ROt%. ROt&. ROt'. ROt(RQ t)RR t*RS t+RT t,]t-. ROt.RU t/. ROt0. ROt1. ROt2RV t3. ROt4. ROt5. ROt6. ROt7RW. RORX. RORY. RORZ. ROR[. ROR\. ROR]. RO/t8R^ t9R_ t:R` t;Ra t<Rb t=Rc t>Rd t?Re t@Rf tARg tBRh tCRi tDRj tERk tFRl tGRm tHRn tIRo tJRp tKRq tLRr tMRs tN]ORt8X  d
   ]N! 4        R# R# u upp i )u;  
Cyber Prairie Scoring — Harmonized property evaluation for Paradiso sessions.

Reads enriched_data.json and applies the unified spec from
system/memory/life/cyber-prairie-property-spec.md on top of existing GPT + custom scores.

Usage:
    python3 cyber_prairie_score.py              # Top 10 shortlist
    python3 cyber_prairie_score.py --top 20     # Top 20
    python3 cyber_prairie_score.py --removed    # Show gate removals
    python3 cyber_prairie_score.py --flags      # Tier 2 research summary
    python3 cyber_prairie_score.py --json       # JSON to stdout
N)datetime)Path)CRITERIA)vetted_blockerspricemax_purchase_eurmin_eurmax_total_cost_eurlandmin_m2heritagekeywordsseverity
DISQUALIFYreasonz/Heritage/listed building (2-3x renovation cost)ruinzRuin/not habitablesemi_detachedFLAGz6Semi-detached/attached (limits guest business privacy)	land_onlyzLand only, no building	isolationz)Potentially isolated (>30 min to village)g/$	J@gg3@c                $    V RJ;'       d    V R8  # )zAValues under 1000m2 are almost certainly building area, not land.N   )m2s   &_/Users/jonathan/Documents/Zakelijk/ClaudeOS/03_Lab/paradisomatch/scraper/cyber_prairie_score.pyis_likely_landr      s    T>((bDj(    c                t    \        V 4      '       g   R# V R8  d   ^# V R8  d   ^# V R8  d   ^# V R8  d   ^# ^# )u  Score land for a homestead + market-garden + retreat (1-5). Recalibrated
2026-06-08 (4-pillar rebalance) to reward the USABLE homestead band, not raw
estate size. The old scale (50k+=5) rewarded 5ha+ estates and scored real
candidates (0.4-1.5ha) only 1-2; with land now a co-equal pillar (weight 3.0)
that would have buried the actual homesteads. ~0.8ha+ is ample; the 3,000m²
gate-minimum is merely adequate.Ni@        )r   )land_m2s   &r   score_land_sizer"      s9     '""$q$q$q$qr   c                    V P                  R4      pVe   \        V4      # V P                  R4      ;'       g    RP                  4       P                  4       pR^R^R^/pVP                  V4      # )zCompute environmental risk criterion (1-5) from georisques data.

Uses risk_score from enrich_apis.py if available (already 1-5 scale).
Falls back to risk_profile mapping for properties not yet enriched.
5 = very safe, 1 = high risk.

risk_scorerisk_profile laag	gemiddeldhoog)getroundstriplower)prsprofilemappings   &   r    compute_environmental_risk_scorer2      sl     
|	B	~Ry uu^$**11399;Gq+q&!4G;;wr   c                     V P                  4       p^ Rr2\         F.  w  rEp\        P                  ! WA4      '       g   K$  WR8  g   K,  YVr2K0  	  W#3# )    r&   )r-   
VIBE_RULESresearch)text
text_lower
best_scorebest_regionpatternscorenames   &      r   get_viber?      sG    J *99W))e.@&+ !+ ""r   c                 :   R p\         P                  ! W ,
          4      \         P                  ! W1,
          4      re\         P                  ! V^,          4      ^,          \         P                  ! \         P                  ! V 4      4      \         P                  ! \         P                  ! V4      4      ,          \         P                  ! V^,          4      ^,          ,          ,           pV^,          \         P                  ! \         P
                  ! V4      4      ,          # )i  )mathradianssincosasinsqrt)lat1lon1lat2lon2Rdlatdlonas   &&&&    r   	haversinerO      s    Adk*DLL,E$a!dhht||D'9:TXXdllSWFX=YY\`\d\deijkek\lno\oooAq5499TYYq\***r   c                     V P                  4       p. p\        P                  4        FE  w  r4VR ,           F3  pWQ9   g   K  VP                  RVRVR,          RVR,          RV/4        KC  	  KG  	  V# )r   idr   r   matched)r-   	RED_FLAGSitemsappend)r8   r9   foundflag_idflagkws   &     r   scan_red_flagsrZ      st    JE"*z""BdGZj9I&X	2G H	 # + Lr   c           
       a aa S '       g   R# ^ o^ oV VV3R lpV! R^^#^4       V! R^^#^4       V! R^(^<^4       V! R^(^F^4       V! R^^2^4       S^ 8  d
   SS,          M^ p\        ^\        ^\        V^,          4      4      4      # )u(  Livability (1-5) = ACCESSIBILITY, not proximity.

Reframed 2026-05-28: the old version gave more points the CLOSER an amenity
was, which scored city-centre properties highest — backwards for a rural
homestead. Now it's a saturation model: an amenity reachable within the
'accessible' band scores full points, with NO bonus for being on top of it.
A homestead 15km from a bakery should score the same livability as one 2km
away; being IN the town (everything <2km) is handled separately as an urban
penalty (compute_urban_penalty), not rewarded here.
Nc                    < SV,          oSP                  V 4      pV'       d>   VP                  R R4      pWQ8:  d   SV,          oR# WR8:  d   SVR,          ,          oR# R# R# )km        ?Nr*   )	r>   full_km
partial_kmfull_ptsrN   r]   	amenitiescheckspointss	   &&&&  r   access1compute_livability_from_amenities.<locals>.access   s[    (MM$tS!B}("!(S.( "	 r   bakerysupermarkethospitaltrain_stationtown)maxminr+   )rd   rg   ratiore   rf   s   f  @@r   !compute_livability_from_amenitiesrq      s     FF	) 8RQ
="b!$
:r2q!
?BA&
62r1%zFVOqEq#auqy)*++r   tarbespaubayonnelourdesu
   angoulême	angoulemeu
   périgueux	perigueuxmontpellieru   béziersbezierscarcassonnenarbonne	perpignanrodezalbicastres	montaubancahorsaurillacmendeprivasvalenceu   montélimar
montelimaru   nîmesnimesquimperbrestlorientvanneszsaint-brieuclannionzla rochellesaintes	rochefortniortlimogestulleu   guéretgueretagen
lannemezanc                V  aa Rp. pV P                  R4      ;'       g    / pV P                  R4      pVe   V^8  d    VR,          pVP                  RV R24       MKV^P8  d    VR,          pVP                  R	V R24       M%V^(8  d   VR
,          pVP                  RV R24       \        VR$4      V3# ^ pR% F@  pVP                  V4      pV'       g   K  VP                  RR4      R8:  g   K7  V^,          pKB  	  V^8  d   VR,          pVP                  RV R24       V P                  R4      ;'       g    V P                  R4      ;'       g    ^ pV P                  R4      ;'       g    V P                  R4      ;'       g    ^ p	^ Tu;8  d   R8  d+   M M'V	'       d    VR,          pVP                  RVR R24       V P                  R4      ;'       g    RR,           V P                  R4      ;'       g    R,           R,           V P                  R4      ;'       g    R,           P                  4       o\	        \
        P                  ! R S4      4      o\        VV3R! l\         4       R4      p
V
'       d   VR,          pVP                  R"V
 R#24       \        VR$4      pW3# )&zTier 1 urban detection (deterministic, no LLM). Returns (delta, reasons).

Three coarse signals; superseded by Tier 2 building-density when parcel
coords are available. Penalises city-centre / village-house properties that
are poor homestead fits.
        rd   building_densityNg?ztown/city core (z buildings/250m)r_   zdense built-up area (皙?zedge of town (r]   r^          @333333?zurban core (z amenities <2km)land_size_m2	land_sizebuilding_size_m2building_sizer    皙?zsmall plot (.0fz#m2) + building = village/town housecityr&    locationtitleu   [a-zà-ÿ'\-]+c              3   V   <"   T F  pR V9   d   VS9   g
   VS9   g   K  Vx  K   	  R# 5i)r   Nr   ).0cr8   wordss   & r   	<genexpr>(compute_urban_penalty.<locals>.<genexpr>N  s,      A~!qQ$YAJ A~s   )
)u   commune is a city/préfecture ()g)ri   rj   rk   rl   rm   )	r*   rU   rn   r-   setr6   findallnextURBAN_COMMUNES)r.   deltareasonsrd   densitycloser>   rN   r
   buildingrR   r8   r   s   &          @@r   compute_urban_penaltyr     sl    EGk"((bI
 ee&'GS=SLENN-gY6FGHr\SLENN27);KLMr\SLENN^G94DEF5$(( ENMM$1tS!S(QJE O zeW,<=> 55 ;;AEE+$6;;!Duu'(GGAEE/,BGGaH4$8d3Z/RST
 UU6]  bC'155+<+B+BCcIuuW~##%&+eg 	

,d34E A~ ABFHG8	CD tE>r   c                    V P                  R4      pV P                  R4      pV'       d!   V'       d   V^8  d   \        W,          4      # R# )z8Compute price per m2 of building. Returns value or None.r   r   Nr*   r+   )r.   r   r   s   &  r   compute_price_per_m2r   Y  s:    EE'NEuu'(HhmU%&&r   c                    R P                  \        RV P                  RR4      V P                  RR4      V P                  RR4      V P                  RR4      R P                  V P                  R. 4      ;'       g    . 4      R P                  V P                  R/ 4      ;'       g    / P                  RR4      P                  4       4      .4      4      P	                  4       # )	r   Nr   r&   summarydescriptionanalysiskeyword_signalsextra)joinfilterr*   splitr-   )r.   s   &r   
_text_blobr   w  s     88F4	grAEE)R0	mR !%%
B"7("-334!%%$**//rBHHJK	"  
 	r   c                 .   a  \        V 3R  lV 4       4      # )c              3   8   <"   T F  qS9   g   K  ^x  K  	  R# 5i)   Nr   r   rY   blobs   & r   r   _kw_hits.<locals>.<genexpr>  s     .4R:qq4s   
)sum)r   banks   f&r   _kw_hitsr     s    .4...r   c                D   \        V 4      pV P                  R4      ;'       g    V P                  R4      ;'       g    ^ pV P                  R4      ;'       g    V P                  R4      ;'       g    ^ pV P                  R4      ;'       g    ^ p\        V\        4      pV^8  d   ^MV^8X  d   ^M
V^8  d   ^M^p\        V\        4      pV^8  d
   V^8  d   ^M
V^8  d   ^M^p\        V\
        4      p	V^8  d   ^p
M+V^8X  d   ^p
M!V^8X  d   ^p
MV'       d   ^p
MV	'       d   ^M^p
V	^8  d   V
^8  d
   V
^,          p
\        V\        4      pV^8  d   ^M
V^8  d   ^M^pRV P                  R4      ;'       g    . 9   pVR8  d   ^pM VR	8  d   ^pMVR
8  d   ^pMVR8  d   ^pM^pV'       d   \        V^4      p\        \        V 4      R,           V P                  RR4      ;'       g    R,           4      w  ppV'       d   TM^pRVRVRV
RVRVRVR^RRRR/	# )u   Build a criteria-like dict from listing keywords + attributes — NO LLM.

Used when p['criteria'] is empty (i.e. no prior GPT analysis). Crude vs an
LLM but dependency-free; the in-session precision pass refines the top N.
r   r   r   r   bedroomsPollution des solsrisk_labelsi0u  '  r   r   r   search_regionr&   workshopfood_experienceguest_accommodationdesign_storymarket_gardenr   local_market
livabilityN_proxyT)	r   r*   r   KW_OUTBUILDINGSKW_FOODKW_GUESTKW_CHARACTERro   r?   )r.   r   r   r
   bedsobr   foodr   gguestchr   pollutedmgvibe_r   s   &                 r   derive_proxy_criteriar     s    a=Duu'(GGAEE/,BGGaH55 ;;AEE+$6;;!D55!!D 
$	(B!GqrQw!(c/QqH D'"D AI(c/adaiUVO 	x Aqy!%	AE	AE	qu!a%Av%!)UaZU 
$	%Ba127aL $m(<(B(BCHu}1b	Q	Ar	Ar"QZ z!}s*aeeOR.H.N.NBOPGD!tH 	H?uHd$
 
r   c                   V P                  R4      ;'       g    . pRp. pRV9   g   V P                  R^ 4      ^ 8  d   VR,          pVP                  R4       RV9   g   V P                  R^ 4      ^ 8  d   VR	,          pVP                  R
4       RV9   d   VR,          pVP                  R4       RV9   d   VR,          pVP                  R4       V P                  R4      pV P                  R4      pV'       d%   VR8X  d   VR,          pVP                  R4       W#3# VR8X  d   VR,          pVP                  R4       W#3# )zRule 1 + 5: deterministic penalties for hazards the LLM can't see.
Returns (score_delta, reasons). Applied to the final CP score.r   r   u
   Nucléairenuclear_count      ?znuclear installation (commune)u,   Installations industrielles classées (ICPE)seveso_any_countr   zICPE industrial siteu3   Canalisations de transport de matières dangereusesr_   zhazmat transport pipeliner   r   z(soil pollution flag (verify for farming)has_flood_risk	clay_riskfortuH   flood + strong clay (foundation survey — commune-level, verify parcel)r   z(strong clay shrink-swell (verify parcel))r*   rU   )r.   labelsr   r   floodclays   &     r   hazard_adjustmentr     s2    UU=!''RFEGv!:Q!>785?155I[]^C_bcCc-.<F23v%AB
 EE"#E55Dab > 
AB>r   c                f   V P                  R4      ;'       g    V P                  R4      ;'       g    ^ pRV P                  R4      ;'       g    . 9   pRp. p\        V4      '       db   V'       gZ   VR8  d'   VR,          pVP                  VR,          R	 R
24       M,VR8  d&   VR,          pVP                  VR,          R	 R24       \        \	        V 4      \
        4      pV^8  d   VR,          pVP                  R4       M!V^8X  d   VR,          pVP                  R4       \        V^4      V3# )u  Rule 2 (RETREAT-recalibrated): land is buildings-first — pass/fail at the
floor + a MILD bonus to ~2ha, then FLAT. Past ~2ha extra hectares don't keep
winning (a characterful longère + barns on 1ha beats a cottage on 5ha for a
retreat). Plus a mature-landscape bonus for trees/orchards/groves — these are
decades to grow, instant charm, and self-sufficiency, so they're a real plus.
Returns (bonus, reasons_list).r   r   r   r   r   i N  r   r   .1fzha (ample, capped)333333?ha      ?zmature trees/orchard/grovegQ?zsome mature planting)r*   r   rU   r   r   KW_MATURE_LANDr+   )r.   r
   r   bonusr   hitss   &     r   land_substrate_bonusr     s    55 ;;AEE+$6;;!D#m(<(B(BCHEG dH5=TMENNd5j--?@AU]TMENNd5j-R01 JqM>2Dqy34	-.?G##r   c                  a \        V 4      oRp. p\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      '       d   VR,          pVP                  R4       Mb\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      '       d   VR,          pVP                  R	4       \        ;QJ d#    V3R
 l\
         4       F  '       g   K   RM	  RM! V3R
 l\
         4       4      '       d   VR,          pVP                  R4       \        \        VR4      ^4      V3# )zOPool / swimming pond / natural pool + water features. Returns (bonus, reasons).r   c              3   ,   <"   T F	  qS9   x  K  	  R # 5iNr   r   s   & r   r   (retreat_feature_bonus.<locals>.<genexpr>!       
0":   TFr   z&natural swimming pool/pond (on-thesis)c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   r   $  s     *'B4Z'r  r   zswimming pool (season-extender)c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   r   (  s     
)":r  皙?zwater feature/sourceffffff?)r   anyKW_NATURAL_POOLrU   KW_POOLKW_WATERr+   ro   r.   r   r   r   s   &  @r   retreat_feature_bonusr    s    a=DEG
s
0
0sss
0
000?@	*'**'*	*	*89
s
)
)sss
)
)))-.UD!1%w..r   z3-phase powerzlevel/workable landsouth-facingzwater sourcezindependent guest unitconvertible atticmains drainagec                  a V P                  R4      pVe   \        V4      # \        V 4      o\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      '       d   ^# \        ;QJ d#    V3R l\
         4       F  '       g   K   RM	  RM! V3R l\
         4       4      '       d   ^# ^# )zRenovation condition 1-5 from explicit field or description keywords.
5 = turnkey, 3 = neutral/habitable, 1 = ruin. Returns int.renovation_scorec              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   )derive_condition_score.<locals>.<genexpr>j  s     
-":r  TFc              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   r  l  s     
(":r  )r*   intr   r  KW_RENOVATEDKW_RUIN)r.   r/   r   s   & @r   derive_condition_scorer  c  sv     
!	"B	~2wa=D
s
-
-sss
-
---
s
(
(sss
(
(((r   c           
         \        V 4      p^R^R^R^R^R	/pVP                  VR4      w  r4Y4'       d   RV RV R23# R3# )
u   Condition → score delta. Turnkey rewarded, ruin penalised. The spec's
'renovation reality' (€900-1500/m² + 12-18mo) made concrete. Returns (delta, reason).Nz
condition z/5 (r   )333333?zturnkey/renovated)r   z
light workr   N)333333ӿzheavy renovation / ruin)gܿzruin (full restoration))r  r*   )r.   cstabler   labels   &    r   condition_adjustmentr   q  sh     
 	"B+Q0DQ B24E 99R-LEEZt4wa0DDtDDr   c                f   V P                  R4      p\        V\        \        34      '       d   ^Tu;8:  d   ^8:  d   M M\        V4      # \        P
                  ! R\        V 4      \        P                  4      pV'       d0   \        VP                  ^4      4      p^Tu;8:  d
   ^8:  d    V#  R# R# )u  Bedrooms from field, else extracted from description ('X bedroom/chambre').
Sanity-clamps absurd values (e.g. a parse bug yielding 325) — a value outside
1..15 is treated as unknown rather than trusted, so garbage can't feed the
capacity/revenue deltas or the display.r   z&(\d+)\s*(?:bedroom|chambre|slaapkamer)N)	r*   
isinstancer  floatr6   r7   r   Igroup)r.   bmns   &   r   	_bedroomsr)  |  s}    
 	
jA!c5\""qA||1v
		;Z]BDDQA
O<R<H r   c                ~  a \        V 4      pVf   R# \        V 4      o\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      ;'       g'    \        P
                  ! RS\        P                  4      pV^8  d   R# V^8X  d   R# V^8X  d   V'       d   R# R# V'       d   R# R	# )
u  B&B viability by bedroom count. A retreat needs guest rooms; 1 bed can't
host. Soft-gate via penalty (with a farm-complex exception — outbuildings can
convert to letting units). Returns (delta, reason). Killed review #2-class miss
(Saint-Germain 1-bed ranked #1 on charm before this).c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r    capacity_gate.<locals>.<genexpr>  s     <ObTzOr  TF/   (\d+)\s*(?:dépendance|outbuilding|barn|grange)r  )gɿz%only 2 bed (convertible outbuildings))皙ٿzonly 2 bedrooms)r.  z"1 bed but convertible outbuildings)gu!   only 1 bedroom — not B&B-viable)r)  r   r  KW_FARM_COMPLEXr6   r7   r$  )r.   r   convertibler   s   &  @r   capacity_gater1    s    
 Q<D|a=D3<O<333<O<< ` `ii RTXZ\Z^Z^_ qyqyqyBM>lSll;F7wLwwr   c                  a \        V 4      o\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      ;'       gz    \        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      ;'       g0    \	        \
        P                  ! RS\
        P                  4      4      # )zGHas outbuildings / farm-complex form that can convert to letting units.c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   "_is_convertible.<locals>.<genexpr>  s     5_rd
_r  TFc              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   r4    s     8":r  r-  )r   r  r/  r   boolr6   r7   r$  )r.   r   s   &@r   _is_convertibler7    s    a=DC5_5CCC5_55 _ _s88sss888_ _BIIPRVXZX\X\]^`r   c                T   V P                  R4      ;'       g    V P                  R4      ;'       g    ^ p\        V 4      pV'       d   \        V4      '       d
   VR8  d   R# V'       d   \        V4      '       d
   VR8  d   R# V'       d   R# \        V4      '       d
   VR8  d   R	# R
# )u  Research + revealed preference: successful retreats START small and GROW, and
the user's 54-favourite pass (2026-05-30) showed outbuildings/dépendances/gîte-
potential is the single most consistent attribute across hand-picked favourites —
appearing in 7/8 of the top-ranked. Promoted from a modest bonus to near-character
weight so a characterful 2-bed with barns out-ranks a charmless 3-bed with
nowhere to go. Returns (bonus, reason).r   r   r   r   r   )r  z)expandable (outbuildings + land headroom))r   z)expandable (outbuildings + adequate land))g
ףp=
?z&outbuildings to convert (room to grow))r  zland headroom to expandr  )r*   r7  r   )r.   r
   r0  s   &  r   expandability_bonusr9    s     55 ;;AEE+$6;;!D!!$K~d++@@~d++@@==d..r   c                   \        V 4      ;'       g    ^ pV P                  R4      ;'       g    V P                  R4      ;'       g    ^ pV P                  R4      ;'       g    V P                  R4      ;'       g    ^ p\        V 4      pRV P                  R4      ;'       g    . 9   p. pV^8  g	   V'       d   VP                  R4       \	        V4      '       d!   VR8  d   V'       g   VP                  R	4       V'       g   V^8  d   VP                  R
4       \        V4      pV^8  d   RRRP                  V4       R23# V^8X  d   RRRP                  V4       R23# R# )zResearch's #1 success factor: the DIVERSIFIED model (B&B + products +
workshops/events). Reward properties that can carry multiple streams, not just
rooms. Returns (bonus, reason).r   r   r   r   r   r   zB&Br   productszworkshop/eventsg?z3 revenue streams (+r   r   z2 revenue streams (r  )r)  r*   r7  rU   r   lenr   )r.   r   r
   r   r0  r   streamsr(  s   &       r   revenue_viability_bonusr?    s5    Q<1D55 ;;AEE+$6;;!Duu'(GGAEE/,BGGaH!!$K#m(<(B(BCHGqyKudXz"h#o()GA 	Av*388G+<*=Q???Av*388G+<*=Q???r   c                t   Rp. pV P                  R4      p\        V\        \        34      '       g   VR,          pVP	                  R4       V P                  R4      ;'       g    V P                  R4      p\        V\        \        34      '       g   VR,          pVP	                  R4       \        V^4      V3# )	u  Penalize-unknowns (user directive 2026-06-08): a missing KEYSTONE characteristic
must rank BELOW a confirmed one, not score as neutral. Land is the keystone of a
homestead — unknown land is high-risk, so it carries the heaviest unknown-penalty.
This kills the null-bias where a land-less town/village house rides character +
condition up the list (Callac, Vers-Pont-du-Gard). It penalizes, not gates — the
property stays visible, just ranked below verified land. Returns (delta, reasons).r   r   r   z'land size unverified (keystone unknown)r   r   r  zbuilding size unknown)r*   r"  r  r#  rU   r+   )r.   r   r   r
   blds   &    r   critical_data_penaltyrB    s     EG55 DdS%L))@A
%%"
#
=
=quu_'=CcC<((./?G##r   c           	       a \        V 4      P                  4       o\        P                  4        UUu. uFI  w  r\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       g   KG  VNKK  	  pppV'       g   R# \        R\        R\        V4      ,          ^4      4      pVRRP                  V4      ,           3# u uppi )	u  Track 1: reward operational facilitations the listing TEXT discloses (3-phase
power, level/workable land, south aspect, water source, independent guest unit,
convertible attic, mains drainage). +0.04 per distinct category, capped +0.20.
Bounded small on purpose — these are confirmations the property can host the
operation, not headline signals; what needs a floor-plan/visit lives in the
viewing checklist (Track 2), not here. Returns (bonus, reason).c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   %facilitation_bonus.<locals>.<genexpr>  s     >XTWbTzTWr  TFr   g{Gz?zfacilitation: , r  )	r   r-   KW_FACILITATIONrT   r  ro   r+   r=  r   )r.   catkwsr   r   r   s   &    @r   facilitation_bonusrJ    s     a= D / 5 5 7Y 7HC33>XTW>X333>XTW>X;XCC 7DYeD3t9,a01E"TYYt_444	 Zs   &CC;Cc                    V P                  R4      pVf   R	# \        V^,
          R,          ^4      pV P                  R4      ;'       g    RpRV R2V'       d   RV R2MR,           pW$3# )
uJ  Vision-derived character (1-5) → strong ranking signal. Character is the
product a retreat sells, so it sits near the top of the stack: ±0.5 across
the range (comparable to hazard penalties). Only present on photo-assessed
properties (vision rubric); absent = no adjustment (not penalised for missing).
Returns (delta, reason).character_scorer   character_tagsr&   z
character /5 (r   r  r   )r.   r  r   tagr  s   &    r   character_adjustmentrQ    sp     
 	!B	z26T/1%E
%% 
!
'
'RCB#RuA;2>E<r   c           
     Z   V P                  R4      ;'       g    / pV'       g   R# Rp. pVP                  R4      p\        V\        4      '       d   VP                  R4      MRpVf   VR,          q#P                  R4       MIV^8:  d   VR,          q#P                  RV R24       M$V^28  d   VR,          q#P                  RV R	24       VP                  R
4      p\        V\        4      '       d   VP                  R4      MRpVf   VR,          q#P                  R4       MIV^
8:  d   VR,          q#P                  RV R24       M$V^8  d   VR,          q#P                  RV R24       VP                  R4      p\        V\        4      '       d   VP                  R4      MRp	V	f   Vf   VR,          q#P                  R4       M(V	e%   V	^
8:  d   VR,          q#P                  RV	 R24       \	        R\        R\        V^4      4      4      pY#'       d   RP                  V4      3# R3# )uG  Soft signal for amenity proximity. Replaces the hard 'no hospital'/'no
bakery+supermarket' gates that were too brittle against OSM/Overpass
coverage gaps (see comments in check_tier1_gates).

Scoring (cumulative within bounds [-0.25, +0.10]):
  hospital ≤20km: +0.05 | 20-50km: 0 | >50km or unknown: -0.05
  supermarket ≤10km: +0.05 | 10-25km: 0 | >25km or unknown: -0.05
  bakery ≤10km: present-bonus +0.02 if both unknown or none, -0.05

Honest about uncertainty: 'unknown' is penalised mildly because we can't
verify rural access, but never enough to bury a strong property.rd   r   Nrk   r]   皙?zhospital unknownz	hospital zkm (>50)rj   zsupermarket unknownzsupermarket zkm (>25)ri   zno bakery/supermarket datag{Gz?zbakery r  z / r        п)r*   r"  dictrU   rn   ro   r+   r   )
r.   amr   r   hosphosp_kmsupsup_kmbakbak_kms
   &         r   amenity_distance_adjustmentr]    s    
{		!	!rBEG66*D *4 6 6dhhtnDG~~&89	B~~	'"&=>	2~~	'(&CD
&&
C(d33SWWT]F~~~&;<	2~~VHB&?@	"~~VHH&EF
&&
C(d33SWWT]F~&.~~&BC		"~~xr&:;s4ua12E%**W%::d::r   c                   \        V P                  R4      \        \        34      '       d,   \        V P                  R4      \        \        34      '       g   R# \	        \
        \        V R,          V R,          4      pVR8  d
   RRVR R23# VR	8  d
   R
RVR R23# VR8  d
   RRVR R23# VR8  d
   RRVR R23# RRVR R23# )u  Distance from The Hague (NL) → easier/harder visits.

For a Dutch buyer, drive time is the binding constraint on visit frequency,
Gwenda's involvement during build-out, and ferry-runs for furniture. The
scorer already computes dist_km via haversine but never weighted it.

Tiers (one-way drive estimate from haversine × 1.25 road-factor / 80km·h):
  <500km   (~6h): +0.15  — weekend-doable, ferry day-trip possible
  500-700  (~7h): +0.05
  700-900  (~8.5h): 0
  900-1100 (~10h): -0.15
  >1100   (~12h+): -0.30  — overnight needed for any visit, multi-day commitment

Returns (delta, reason). Coords absent = 0 (no signal, no penalty).latlonr     r   u   ≈r   u   km NL — weekend-doablei  rS  u   km NL — easy day-and-halfi  u   km NL — long day driveiL  u%   km NL — overnight needed for visitsu(   km NL — multi-day commitment per visitr  333333ÿr  )r"  r*   r  r#  rO   DH_LATDH_LON)r.   r]   s   & r   distance_from_nl_adjustmentre  7  s     quuU|c5\22155<#u66	661U8QuX	6B	Cxs2c(":;;;	Cxs2c("=>>>	Cxc"S!9:::	DyBs8#HIIIC3xGHHHr   c                    V P                  R4      pVf   R# V^8  d	   RRV R23# VR8  d	   RRV R23# VR	8:  d	   RR
V R23# VR8:  d	   RRV R23# RRV R23# )aZ  Community vitality from commune population (community_vitality.py / INSEE
via geo.api.gouv.fr). Research: deep-rural projects relocate for lack of
footfall (Limousin); a healthy village = services + guest access + alive.
Reward the middle, penalise both extremes (too-remote / too-urban).
Returns (delta, reason). Population absent = 0 (unknown).commune_populationr   zvery remote commune (u    pop — footfall risk)ra  r  zsmall commune (z pop)r   zhealthy village/town (u    pop — alive)ia  zmarket town (zurban commune (r  rT  grb  r`   )r.   pops   & r   community_vitality_adjustmentri  U  s     %%$
%C
{
Sy-cU2IJJJ
SyuE222
e|-cU/BBB
e|mC5...OC5...r   c                r  a Rp. pV P                  R4      pVeL   V^8  d    VR,          pVP                  RV R24       M%V^8  d   VR,          pVP                  RV R24       V P                  R4      pVeL   V^K8  d    VR,          pVP                  R	V R
24       M%V^8  d   VR,          pVP                  RV R24       \        V 4      o\        ;QJ d    V3R lR 4       F  '       g   K   RM	  RM! V3R lR 4       4      '       d   VR,          pVP                  R4       \	        V^4      V3# )zTier-1 deal-breakers from real review feedback: adjacent neighbours
(killed #2) + busy road (killed #4). Graded penalties from parcel-precise
OSM data (urban_density.py). Returns (delta, reasons).r   privacy_buildings_50mr_   zhemmed in (z buildings <50m)r  zclose neighbours (major_road_mz
busy road zm away (noise)r   zmajor road zm awayc              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   $proximity_penalty.<locals>.<genexpr>  s      P !O": !Or  TFz)internet flagged absent (verify Starlink))zno internetzpas d'internetzno fibrezno broadbandzsans internetzno phone linezno mains)r*   rU   r   r  r+   )r.   r   r   privroadr   s   &    @r   proximity_penaltyrq  i  s@    EG 55()D19SLENN[.>?@QYSLENN/v5EFG 55 D"9SLENNZv^<=CZTMENN[f56
 a=D
s P !O Psss P !O P P PBC?G##r   c                6  a \        V 4      oRp. p\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      '       d   VR,          pVP                  R4       \        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      '       g/   V P                  R4      ;'       g    R	P                  4       R9   d   VR
,          pVP                  R4       \        \        VR4      ^4      V3# )zPreference for former-farm-complex (buildings-first ideal) and vineyard
domains (charm + terroir + product). Returns (bonus, reasons).r   c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   !typology_bonus.<locals>.<genexpr>  r  r  TFr   z%former farm complex (buildings-first)c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   rt    s     
,":r  sub_typer&   r   z*vineyard / wine domain (terroir + product)r   )vineyard	vineyeard)	r   r  r/  rU   KW_VINEYARDr*   r-   r+   ro   r  s   &  @r   typology_bonusrz    s     a=DEG
s
0
0sss
0
000>?
s
,
,sss
,
,,,z1B1H1Hb0O0O0QUn0nCDUC!$g--r   c                   ^ pV P                  R4      '       g   V P                  R4      '       d
   V^,          pV P                  R4      '       g   V P                  R4      '       d
   V^,          pV P                  R4      '       d
   V^,          pV P                  R4      f   V P                  R4      '       d
   V^,          pV P                  R4      '       d1   V P                  R/ 4      P                  R	4      '       g
   V^,          pV# )
zGRule 4: how much real data backs the score (1-5). Surfaced, not gating.r   r   r   r   r   r$   georisques_enrichedcriteriar   r`   )r.   haves   & r   compute_data_confidencer    s    Duu  AEE/$:$:DAIDuu^k 2 2DAIDuuW~~tqytuu\&!%%0E*F*FPQ	uuZz2!6!:!:8!D!DdaidKr   c                    V P                  R4      pVe   V# V P                  R4      ;'       g    RP                  4       pR^R^R^/P                  V4      # )zRenovation condition (1=ruin .. 5=move-in). From detail-page read
(renovation_score) or the search-card renovation_estimate, else None
(CRITERIA default of 3 applies).r  renovation_estimater&   minormoderatemajor)r*   r-   )r.   r/   ests   &  r   renovation_scope_scorer    s[     
!	"B	~	55&'--2
4
4
6CQ
Aw266s;;r   c                $	   V P                  R/ 4      pV'       g   \        V 4      p\        V P                  R4      4      pVe   TMVP                  R4      pRVP                  R4      RVP                  R4      RVP                  R4      R	VP                  R	4      RVR
\        V 4      RVP                  R4      RVP                  R4      R\	        V P                  R4      4      R\        V 4      RVP                  R4      /pRpRp. p\        P                  4        FZ  w  rWH,          p
V
f
   V	R,          p
V
e,   WZV	R,          ,          ,          pWiR,          ,          pWV&   KI  VP                  V4       K\  	  V^ 8X  d   ^ ^ WG3# WV,          p\        V 4      w  r\        V 4      w  r\        V 4      w  pp\        V 4      w  pp\        V 4      w  pp\        V 4      w  pp\        V 4      w  pp\!        V 4      w  pp\#        V 4      w  pp\%        V 4      w  pp\'        V 4      w  p p!\)        V 4      w  p"p#\+        V 4      w  p$p%\-        V 4      w  p&p'\/        V 4      w  p(p)\1        V 4      w  p*p+V P                  R4      RJ ;'       d    V P                  R4      RJ p,V,'       d   R8MRp-\3        RW,           V,           V,           V,           V,           V,           V,           V,           V,           V,           V ,           V$,           V&,           V(,           V*,           V-,           V",           4      p.\5        \7        V.R4      ^4      p.\5        V^4      VR&   WR&   \5        V^4      VR&   WR&   \5        V^4      VR&   VVR&   \5        V^4      VR&   VVR&   \5        V^4      VR&   VVR &   \5        V^4      VR!&   VVR"&   \5        V^4      VR#&   VVR$&   \5        V^4      VR%&   VVR&&   \5        V^4      VR'&   VVR(&   \5        V^4      VR)&   VVR*&   \5        V ^4      VR+&   V!VR,&   \5        V"^4      VR-&   V#VR.&   \5        V$^4      VR/&   V%VR0&   \5        V*^4      VR1&   V+VR2&   \9        V 4      VR3&   V,VR4&   VP                  R54      '       d   R6VR7&   \5        V^4      V.WG3# )9zXCompute Cyber Prairie score from a property dict. Returns (raw, final, scores, missing).r}  rd   Nr   r   location_viewr   r   r   environmental_riskr   r   r   r   renovation_scoper   r   defaultweightr$   r   g      @_hazard_delta_hazard_reasons_substrate_bonus_substrate_reasons_feature_bonus_feature_reasons_typology_bonus_typology_reasons_proximity_delta_proximity_reasons_character_delta_character_reason_capacity_delta_capacity_reason_condition_delta_condition_reason_expandability_bonus_expandability_reason_revenue_bonus_revenue_reason_facilitation_bonus_facilitation_reason_critical_data_delta_critical_data_reasons_vitality_delta_vitality_reason_urban_delta_urban_reasons_data_confidence	_unvettedr   T_proxy_criteriagffffffֿ)r*   r   rq   r2   r"   r  r   rT   rU   r   r   r  rz  rq  rQ  r1  r   r9  r?  rJ  rB  ri  re  r]  r   rn   r+   ro   r  )/r.   r}  amenity_livabilityr   scoresweighted_sum
weight_summissingr>   configvalrawhz_delta
hz_reasons	sub_bonussub_reasons
feat_bonusfeat_reasons	typ_bonustyp_reasons
prox_deltaprox_reasons
char_deltachar_reason	cap_delta
cap_reason
cond_deltacond_reason	exp_bonus
exp_reason	rev_bonus
rev_reason	fac_bonus
fac_reason
crit_deltacrit_reasons	vit_delta
vit_reasonnl_delta	nl_reasonam_delta	am_reasonurban_deltaurban_reasonsunvetted
conf_deltafinals/   &                                              r   compute_cp_scorer    s   uuZ$H(+ ;155;MN'9'E#8<<XdKeJ 	HLL,j18<<(9:x||,ABj>qA^4o6_QUU>%:;215^4F LJG (l;#C?&"222L**J4LNN4  ) Q!V$$

#C -Q/H1!4I4Q7J+A.I{03J215J)!,Iz215J/2Iz3A6Iz.q1Iz4Q7J9!<Iz5a8Hi5a8Hi!6q!9K l#t+QQ6H0IT0QH"JS^i/*<yH)*,568BC'(*346?@BJK  )) ,66 9CC DE #eS/1%E#Ha0F? *!&y!!4F#. $Z3F!-F %i 3F"-F!&z1!5F#/F !&z1!5F"-F %i 3F!+F!&z1!5F"-F%*9a%8F!"&0F"#$Y2F *F$))Q$7F !%/F!"%*:q%9F!"'3F#$ %i 3F!+F";2F>,F!8!;F"F;||H$( !a=%00r   c                "  a . pV P                  RR4      P                  4       pVR8X  d5   VP                  RRP                  V P                  R. 4      4       R24       VP                  R4      pVee   V^8:  d^   V P                  R
4      pV P                  R4      pVe   V^28  d   VP                  RVR R24       MVf   Ve   VP                  R4       V P                  R4      pVEeA   V^8:  Ed9   RP                  \	        R	V P                  RR4      V P                  RR4      V P                  R/ 4      ;'       g    / P                  RR4      .4      4      P                  4       o\
        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      ;'       g]    \
        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      ;'       g    RS9   ;'       g    RS9   p	V	'       g   VP                  V R24       V P                  R4      p
V
e   V
R8:  d   VP                  RV
 R24       V^ 8  d   VR8  d   VP                  R V R!24       V P                  R"4      ;'       g    V P                  R#4      p\        V\        \        34      '       d   V^ 8  d   V P                  R$4      RJ ;'       g;    V P                  R%4      RN9   ;'       d    V P                  R&4      ;'       g    ^ ^ 8  pV'       g   \        V4      '       d*   V\        8  d   VP                  R'VR( R)\        R* R+24       V P                  R,4      RJ d   VP                  R-4       V P                  R.4      RJ d   VP                  R/4       V P                  R04      p\        V\        \        34      '       d   V^ 8  d   V\        8  d&   VP                  R1VR( R2\        R3,          R R424       V\        8  d&   VP                  R1VR( R5\        R3,          R R624       V P                  R74      p\        '       dM   \        V\        \        34      '       d1   V\        8  d&   VP                  R8VR( R2\        R3,          R R924       \!        V 4      ^8:  d   VP                  R:4       V P                  R;4      pVe   V^8  d   VP                  R<V R=24       V P                  R>^ 4      ^ 8  d   VP                  R?V R>,           R24       V P                  R@R4      pRAV9   g   RBV9   d   VP                  RC4       RP                  \	        R	V P                  RR4      V P                  RDR4      V P                  RER4      .4      4      P                  4       p. ROOpV F!  pVV9   g   K  VP                  RFV R24        M	  V P                  R@4      ;'       g    RP                  4       pV P                  R
4      ;'       g    V P                  RG4      pV P                  R"4      ;'       g    V P                  R#4      ;'       g    ^ pRHV9   g   RIV9   g   RJV9   d   VP                  RK4       M[\        V\        \        34      '       d@   V^#8  d9   \        V4      '       g(   \#        V 4      '       g   VP                  RLVR RM24       VP%                  \'        V 4      4       V# )PzACheck Tier 1 auto-removal gates. Returns list of triggered gates.user_verdictr&   nozUser reviewed: rejected (rF  
user_flagsr   r   Nr   r   z#Guest capacity = 1 + building only r   r   z"Guest capacity = 1 (cannot do B&B)r   r   r   r   c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   $check_tier1_gates.<locals>.<genexpr>D  s     @":r  TFc              3   ,   <"   T F	  qS9   x  K  	  R # 5ir   r   r   s   & r   r   r  E  s     C?RDj?r     dépendanceoutbuildingu8    bedroom — not B&B-viable, no convertible outbuildingsr$   r   zHigh environmental risk (score z/5)r   zScore z below 1.5 thresholdr   r   land_size_verifiedsourcephoto_countzLand ,.0fz	m2 below ,z,m2 hard floor (market garden non-negotiable)has_electricityzNo electricity (confirmed)has_mains_waterzNo running water (confirmed)r   z
Price EUR z	 exceeds r   zk capz below zk floor (likely ruin/barn)est_total_cost_eurzTotal cost EUR zk cap (purchase+reno)z.Not livable (ruin / heavy renovation required)seismic_zonezSeismic zone z/5 (high earthquake risk)seveso_high_countz#Seveso high-threshold site nearby (urlz/land-for-sale-z	/terrain-zLand-only listing (no building)r   r   zSemi-detached/attached (r   z/apartment/u   appartement à vendrezapartment for saleu'   Apartment — not a homestead candidatezBuilding only u0   m2, no land, no outbuildings — not a homestead)leggett
greenacres)semi-detachedsemi detached	mitoyennemitoyenhalf-vrijstaandterraced	townhouse)r*   r-   rU   r   r   r  r/  r   r"  r  r#  r   LAND_FLOOR_M2
_PRICE_MAX
_PRICE_MIN_PRICE_TOTAL_MAXr  r7  extend_check_new_tier1_gates)r.   r  cp_score	triggeredverdictr   r   r   r   r0  risk_score_valr
   verifiedr   	est_totalseismicr  r8   semi_keywordsrY   url_lbuilding_m2r!   r   s   &&&                    @r   check_tier1_gatesr  '  sX   I eeNB'--/G$4TYYquu\SU?V5W4XXYZ[ JJ,-EUaZ55+,55$HrMB8C.PRST!X%9AB 55DDAIxxtaeeGR&8!%%r:R'(uuWb'9'?'?R&D&D]TV&W&Y Z [[`[`[b 	s@@sss@@@ I I#C?C###C?CCI I'4/I I3@D3H 	 v%]^_ UU<(N!n&;:>:J#NO!|36(+?@A 55 66AEE+$6D$e%%$(EE&'4/ 5 5h#<< 4 4UU=)..Q!3 	
 t,,$2FuT$Kyq8IIuvw 	uu5(56uu5(78EE'NE%#u&&519:z%Yz$s>SSXYZ:z%WZ_S<QQklm EE./	
9sEl C C	TdHdy.>iHXY]H]^aGbbwxy
 a A%IJ( eeN#Gw!|=	1JKLuu !$q(>qAT?U>VVWXY %%r
CC;##5:; 88F4	grAEE)R0!%%
B2G"   	AM:7t1=>  UU5\R&&(E%%*+EEquu_/EKeeN#>>quu['9>>QG!8D!@DX\`D`BC
[3,
/
/K"4D ))/!2D2D>+c)::jkl +A./r   c                   . p\         P                  P                  R/ 4      pVP                  R4      pV P                  R4      pV'       d<   \        V\        \
        34      '       d    WC8  d   VP                  RVR RV R24       VP                  R4      '       dC   V P                  R	4      p\        V\        4      '       d   V^8  d   VP                  V R
24       \         P                  P                  R/ 4      pVP                  R4      '       dK   V P                  R4      p\        V\        \
        34      '       d   V^28  d   VP                  RVR R24       \         P                  P                  R/ 4      P                  R4      '       d<   V P                  R4      RJ g   V P                  R4      RJ d   VP                  R4       \         P                  P                  R/ 4      P                  R4      R8X  d'   V P                  R4      RJ d   VP                  R4       \         P                  P                  R/ 4      P                  R4      R8X  d|   V P                  R4      RJ d   VP                  R4       MTV P                  RR 4      ;'       g    R P                  4       p. R,Op	V	 F   p
W9   g   K  VP                  R!V
 R"24        M	  \         P                  P                  R#/ 4      pVP                  R$4      pVP                  R%4      pV'       dM   V P                  R&4      p\        V\        \
        34      '       d    W8  d   VP                  R'VR R(V R)24       V'       dM   V P                  R*4      p\        V\        \
        34      '       d    W8  d   VP                  R+VR R(V R)24       V# )-u  Tier-1 gates added 2026-05-30 from research audit: privacy, road noise,
internet, septic, heritage exclusion, amenity time-distances.

Each gate checks `data PRESENT AND FAILS` — missing data passes silently
and is captured by the data_confidence delta downstream.
privacymin_neighbour_distance_mnearest_neighbour_mzNearest building r   zm < zm privacy floorno_adjacent_buildingrk  z" buildings within 50m (no privacy)
road_noiseexclude_busy_roadrl  zMajor road within zm (road noise)internet require_fibre_or_starlink_viableinternet_viableFhas_internetzInternet not viable (confirmed)environmentalseptic_compliantrequiredz Septic non-compliant (confirmed)listed_heritageexcludeis_listed_heritageTz)Listed heritage building (DRAC oversight)r   r&   zListed heritage indicated ("z")rd   grocery_max_minuteshospital_max_minutesgrocery_minuteszGrocery zmin > zmin caphospital_minutesz	Hospital )u   classé monument historiquezinscrit aux monumentslisted buildingmonument historique)_CPgatesr*   r"  r  r#  rU   r-   )r.   outpriv_cfgmin_distnbr_m
priv_countroad_cfgrl  r   heritage_kwrY   amen_cfggroc_maxhosp_maxr   hs   &               r   r  r    s    C
 yy}}Y+H||67HEE'(EJusEl338H

&uSkhZOP||*++UU23
j#&&:?JJ*%GHI yy}}\2.H||'((uu^,lS%L11lR6GJJ+L+=^LM
 yy}}Z$(()KLL55"#u,n0E0NJJ89 yy}}_b)--.@AZO55#$-JJ9: yy}}_b)--.?@IM55%&$.JJBC EE-,2299;DEK!:JJ!=bTDE " yy}}["-H||12H||23HEE#$a#u&&1<JJ!Cxj@AEE$%a#u&&1<JJ1S'zABJr   c                   . pV P                  R4      f   VP                  R4       V P                  R4      f   VP                  R4       V P                  R4      e   V P                  R4      f   VP                  R4       VP                  R4      ^8X  d+   \        R,          R	,          R
8X  d   VP                  R4       V P                  R4      ;'       g    . pV P                  R4      '       g   RV9  d   VP                  R4       V P                  R4      '       g   RV9  d   VP                  R4       VP                  R4       V P                  R4      f   VP                  R4       V# )z8Return Tier 2 research flags for shortlisted properties.r   verify_pricer   verify_land_sizer_  r`  verify_coordinatesr  r  unavailableverify_renovationr   r  verify_electricityr  verify_waterverify_internetr$   verify_environmental_risk)r*   rU   r   )r.   r  flagssignalss   &&  r   get_tier2_flagsr6    s%   EuuW~^$uu^$'(uuU|quuU|3)*zz$%*x8J/KH/UYf/f()ee%&,,"G55"##(9(H)*55"##(9(H^$	LL"#uu\"01Lr   c                   F$   \         P                  ! R R7      p V P                  R\        ^
RR7       V P                  RRRR7       V P                  R	RR
R7       V P                  RRRR7       V P                  RRRR7       V P	                  4       p\        VP                  4      pVP                  4       '       g6   \        RV R2\        P                  R7       \        P                  ! ^4       \        VRR7      ;_uu_ 4       p\        P                  ! V4      pRRR4       \        X\         4      '       d   \#        VP%                  4       4      MTp\&        P(                  ! 4       P+                  R4      p. p. p/ p	V EFM  p
V
P-                  R4      R8X  d   K  \/        V
4      w  rKrRP1                  \3        RV
P-                  RR4      V
P-                  RR4      V
P-                  RR4      V
P-                  RR4      .4      4      p\5        V4      w  ppV
P-                  R 4      ;'       g    V
P-                  R!4      pV
P-                  R"4      ;'       g    V
P-                  R#4      pRpV'       dc   V'       d[    \7        V4      \7        V4      pp^)Tu;8  d   ^48  d5   M M1RTu;8  d   ^
8  d#   M M\9        \;        \<        \>        VV4      4      pRP1                  \3        RV
P-                  R$R4      V
P-                  RR4      V
P-                  RR4      .4      4      p\E        V4      pV
P-                  RR4      pR%V9   d   R&pMR'V9   d   R(pMR)pV
P-                  R*4      V
P-                  R+4      VV
P-                  R,4      V
P-                  R-4      .p\G        R. V 4       4      pV
P-                  R// 4      p/ pR Fy  pVP-                  V4      pV'       dO   VP-                  R54      '       d'   VP-                  R5R4      R6,           R7VR8,           R92MVR8,           R82VV&   Kj  V'       g   Kt  R:VV&   K{  	  \I        V
4      p / R;VbR<VbR=VbR>VbR?VbR@VbRAVbRBVbRCVbRDVbR/VbREV bRVbRV
P-                  RR4      bRV
P-                  R4      ;'       g    RRF,          bR*V
P-                  R*4      bRGV
P-                  R+4      bRHV
P-                  R-4      R,\K        V
4      RIV
P-                  RI4      ;'       g    RRJV
P-                  RJ4      ;'       g    . RKV
P-                  RK4      ;'       g    / RLV
P-                  RMR4      RNV
P-                  RN4      ROV
P-                  RO4      RPV
P-                  RP4      RQV
P-                  RQ4      RRV
P-                  RR4      RSV
P-                  RS^ 4      RTV
P-                  RT^ 4      RV
P-                  R4      ;'       g    RRU,          /Cp!V Uu. uF  q3RV,          RW8X  g   K  VNK  	  p"p\M        WV4      p#V"'       d(   T#PO                  V" Uu. uF  q3RX,          NK  	  up4       V#'       d   V#V!RY&   VPQ                  V!4       EK  \S        WRZR[7      p$V$'       * V!R\&   V$V!R]&   \U        W4      V!R^&   V!R^,           F  p%V	P-                  V%^ 4      ^,           V	V%&   K!  	  VPQ                  V!4       EKP  	  VPW                  R_ R`7       VP                  '       dn   RaVRb\Y        V4      Rc\Y        V4      \Y        V4      ,           Rd\Y        V4      Re\Y        V4      RfVRgV/p&\        \        PZ                  ! V&^RZ\\        Rh7      4       R# VP^                  Ri,          p'\        V'RjRR7      ;_uu_ 4       p\        P`                  ! RaVRfVReV/V^RZ\\        Rh7       RRR4       \Y        V4      \Y        V4      ,           p(\G        Rk V 4       4      p)\        4        \        R4       \        Rl4       \        RmV Rn24       \        R4       \        RoV( Rp\Y        V4       Rq\Y        V4       RrV) 24       \        Rs4       \        4        ^Rt^Ru^Rv^Rw^Rx^ Ry/p*\c        VRVPd                   4       EF  w  p+p,V,R=,          p-\        V,R*,          \        \6        34      '       d   V,R*,          ^ 8  d   RzV,R*,          R{ 2MR|p.V,RG,          '       d   V,RG,          R},          R~ R2MR|p/V,R,,          '       d   \]        V,R,,          4      MR|p0V,RA,          '       d(   V,RA,           R\9        V,RA,          ^P,          ^4       R2MR|p1V,R@,          '       d&   V*P-                  V,R?,          Ry4       RV,R@,           2MRyp2\f        R,          RC,          R8X  d   RM\]        V-P-                  RR|4      4      p3\        RmR 24       V,RD,          ^8  d   RV,RD,           R2MRp4\        RV+^,            RV,R;,          R RV,RC,           RV2 RmV4 2
Pi                  4       4       \        RmV,R,          ;'       g    V,R,          R,           24       V,P-                  RE4      '       d   RV,RE,          R R2MRp5\        RmV. RV/ RV0 RV1 RV,RL,           RmV5 2Pi                  4       4       \        RV-P-                  RR|4       RV-P-                  RR|4       RV-P-                  RR|4       RV-P-                  RR|4       RV-P-                  RR|4       RV-P-                  RR|4       RV-P-                  RR|4       RV-P-                  RR|4       RV-P-                  RR|4       RV3 RV-P-                  RR|4       24       V,P-                  R// 4      p6V6'       dd   . p7R F>  pV6P-                  VR|4      p8R0RR1RR2RR3RR4R/V,          p9V7PQ                  V9 RV8 24       K@  	  \        RmRP1                  V74       24       . p:V,P-                  RO4      '       d   V:PQ                  RV,RO,           R24       V,P-                  RP4      '       d   V:PQ                  RV,RP,           R24       V,P-                  RQ4      '       d   V:PQ                  R4       V,P-                  RR4      p;V;'       d   V;R8w  d   V:PQ                  RV; 24       V,P-                  RS^ 4      ^ 8  d   V:PQ                  RV,RS,           24       V,P-                  RT^ 4      ^ 8  d   V:PQ                  RV,RT,           24       V:'       d   \        RRP1                  V:4       24       V,P-                  RB. 4       Uu. uF  q3RV,          R8X  g   K  VNK  	  p<pV<'       d%   \        RRP1                  R V< 4       4       24       V,P-                  R^4      '       dO   V,R^,           Uu. uF  q3R8w  g   K  VR8w  g   K  VNK  	  p=pV='       d   \        RRP1                  V=4       24       \        RmV,R,           24       \        4        EK  	  VPj                  '       d   V'       d   \        4        \        R4       \        R\Y        V4       R24       \        R4       VR,           Fl  p,RP1                  V,P-                  RY. 4      4      p>V,R,          ;'       g    V,R,          R,          p?\        RmV?R RV> 24       \        RV,R,           24       Kn  	  \Y        V4      ^8  d    \        R\Y        V4      ^,
           R24       VPl                  '       dm   V	'       de   \        4        \        R4       \        R4       \        R4       \o        V	Pq                  4       R R`7       F  w  p%p@\        RmV%R RmV@ R24       K  	  \        RmR 24       \        R\Y        V4       R24       \        RmR 24       / pAV F  p,V,R@,          ;'       g    RpBV,R?,          pCVBXA9  d   R^ RXCR^ R^ /XAXB&   XAXB,          R;;,          ^,          uu&   \s        VAVB,          R,          V,R;,          4      VAVB,          R&   \        V,R*,          \        \6        34      '       g   K  V,R*,          ^ 8  g   K  XAXB,          R;;,          ^,          uu&   K  	  ^Rt^Ru^Rv^Rw^Rx^ Ry/p*\o        XAPq                  4       R R`7       Fg  w  pBpDVDR,          '       d   RXDR,           R2MRpE\        RmV*P-                  XDR,          Ry4      R RmXBR RmVDR,          R RVDR,          R~ RmVE 2
4       Ki  	  / pFV F-  p,XFP-                  V,RC,          ^ 4      ^,           VFV,RC,          &   K/  	  \        RRP1                  R \o        XFPq                  4       R R`7       4       4       24       \        RV' 24       \        4        R#   + '       g   i     EL; i  \@        \B        3 d     ELi ; iu upi u upi   + '       g   i     E
LY; iu upi u upi )z)Cyber Prairie Harmonized Property Scoring)r   z--topzNumber of top results to show)typer  helpz	--removed
store_truezShow Tier 1 gate removals)actionr9  z--flagsz!Show Tier 2 research flag summaryz--jsonzOutput JSON to stdoutz--inputzproperties.jsonzfInput file (SOT = properties.json; enriched_data.json kept for legacy compatibility but not canonical))r  r9  zError: z
 not found)filezutf-8)encodingNz%Y-%m-%d %H:%MstatusRemovedr   r   r&   r   r   r  r_  latituder`  	longituder   frenchestateagentsLeggett	idealista	Idealista
Properstarr   r   r   r   c              3   0   "   T F  qf   K  ^x  K  	  R # 5ir   r   )r   vs   & r   r   main.<locals>.<genexpr>h  s     H;a;s   
rd   ri   rk   rl   rj   airportr>   :N   NrO  r]   zkm)noner  cp_rawr  r  
vibe_scorevibe_regiondist_km	red_flagsr  data_completenessprice_per_m2:NP   Nr!   r  	thumbnail
photo_urlsverdictsriskr%   r$   r  radon_levelr   r   r  r   :N   Nr   r   r   gate_reasonsF)gatedvettedr   tier2_flagsc                 <    V R ,          ) V R,          ) V R,          ) 3# )r  rN  rR  r   xs   &r   <lambda>main.<locals>.<lambda>  s!    Qz]NQ|_4DqI\G]F]#^r   )key	generatedtotal_evaluatedactiveshortlistedr\  	shortlistgated_removals)indentensure_asciir  zcyber_prairie_shortlist.jsonwc              3   T   "   T F  qP                  R 4      R8X  g   K  ^x  K   	  R# 5i)r>  r?  Nr`   )r   r.   s   & r   r   rI    s     N:axI1M:s   (
(z  CYBER PRAIRIE SHORTLISTz  z)  |  Spec: cyber-prairie-property-spec.mdz  Evaluated: z  |  Shortlisted: z  |  Gated: z  |  Removed: zT  Threshold: >= 3.0/5  |  Risk: georisques.gouv.fr (seismic/flood/radon/Seveso/clay)z*****z****z***z***-zEUR r  ?r   r   z hazkm (~zh)r  r.  z[?]zData: rN  z  #z  CP Score: z.2fz/5  |  z  |  Vibe: :N2   Nu   €r  u   /m²z  |  z
 beds  |  z  |  Risk: z  Wkshp:r   z  Loc:r  z  Food:r   z  Guest:r   z  Live:r   z
  EnvRisk:r  z	  Design:r   z  Gdn:r   z  Land:r   z  Reno:z  Mkt:r   BakerHospTrainSuperAir:z | zSeis:zRadon:z/3FLOODfaiblezClay:z	SEVESO-H:zNUCLEAR:z	  Risks: r   z  !! rF  c              3   2   "   T F  qR ,          x  K  	  R# 5i)r   Nr   )r   fs   & r   r   rI    s     #DAhKKs   r2  r/  z  Research: z  TIER 1 GATE REMOVALS (z properties):N   N:N(   N35sz    z
  ... and z morez  TIER 2 RESEARCH FLAGS SUMMARYc                     V ^,          ) # r   r   r`  s   &r   rb  rc  &  s
    1r   25sz propertiesz  REGION OVERVIEW (all z shortlisted)Othercountr   	top_score	has_pricec                 F    V ^,          R,          ) V ^,          R,          ) 3# )r   r   r  r   r`  s   &r   rb  rc  :  s    ad6l]QqTRY]N<[r   (z with price)z(no prices)5s20s2dz properties  Best: z
  Sources: c              3   4   "   T F  w  rV R V 2x  K  	  R# 5i)z: Nr   )r   sr   s   &  r   r   rI  B  s     #i<hDAqcA3K<hs   c                     V ^,          ) # r  r   r`  s   &r   rb  rc  B  s    cdefcgbgr   z

  Saved: )ri   rk   rl   rj   rJ  rm   zP================================================================================u   ───────────────────────────────────────────────────────────────────────────)ri   rk   rl   rj   rJ  ):argparseArgumentParseradd_argumentr  
parse_argsr   inputexistsprintsysstderrexitopenjsonloadr"  rU  listvaluesr   nowstrftimer*   r  r   r   r?   r#  r+   rO   rc  rd  
ValueError	TypeErrorrZ   r   r   r)  r  r  rU   r   r6  sortr=  dumpsstrparentdump	enumeratetopr   rstripremovedr4  sortedrT   rn   )Gparserargs	data_pathr|  r  
propertiesr  rh  r\  flagged_countsr.   r  r  r  search_textrN  rO  r_  r`  rP  lat_flon_f	flag_textrQ  r  r  data_fieldsrR  rd   amenity_summaryrd  infoprice_m2entrydisqualified_flagsr  blockersrX   outputoutput_pathactive_countremoved_count
vibe_starsier  	price_strland_strbeds_strdist_strvibe_strreno_strdata_qpm2_strrV  am_partsr  	short_key
risk_partsr   
warn_flagst2r   locr  region_datargvtrd
price_notesourcessG                                                                          r   mainr  '  s*   $$1\]F
c2<[\
L?Z[
	,=`a
<ST
	+<  Dl  mDTZZ I	{*-CJJ?	i'	*	*aiil 
+'1#t'<'<cjjl##J
,,.
!
!"2
3CKEN55?i'&6q&9#F hhvdEE*b!155"#5EE)R !%%r"2-
    #+;"7
K eeEl//aeeJ/eeEl00aeeK03$Sz5:u??rEB#IffeU$KLG
 HHVDEE*b!155"#5quuY7K+
  	 #9-	 eeE23&FC F!F uuW~quu^'<c155CTVWV[V[\nVopH;HH EE+r*	\C==%DZ^ZbZbciZjZj$((62*>s*C)DBtDzlRU'Vswx|s}r~  A  qB$'-$ ] (* 
 
c 
 f 
 w	 

 * 
 ; 
 w 
  
 f 
  !2 
  
 H 
 3 
 j"- 
 aeeGn**C0 
  QUU7^! 
" quu^,# 
$ 155!34	!{+11r!%%-33j)//RAEE."-!%%-AEE.1155/aee$45{+':A!>QUU?A6i(..B5? 
F *3TA
m|6SaaT!!U3LL/AB/A!H++/ABC$)E.!LL 'qu=H"*lE(O'/E#$#21#=E- m,,'5'9'9$'BQ'Ft$ -u%[ ` ^_ yyys:c+&U33{+SZe
 	djjsKL ""%CCK	k3	1	1Q		;[+wNAE3	@ 
2
 {#c%j0LN:NNM	G	(O	
%&	Bse<
=>	(O	M,'9#k:J9K<X[\aXbWccqr  rA  B  C	`b	GWaE1dAsAsKJ+itxx011hK0:1W:U|0T0TYZ[bYcfgYgd1W:d+,mp	56y\\a	l5(-S1s)*:3q}%CJKI,,a	l^5q|B)B(C2F\_STUbScScjnnQ|_c:;1Q}=M<NOil$%78BmS5Y\]^]b]bcuwz]{Y|8*o89:M8NQR8R6!/014XZAaC5Qz]3$7wq{m;W_V``bcibjkrrtu1Z=33AgJsO45656UU>5J5JC.)!,D1PR9+U8*E(:hZ{[\]c[dZeeghogpqxxz{z#./vaeeOC6P5Q/45XaeeDYZ]>^=_l3/0
155AUVY;Z:[!%%s34quu_S12'!%%C:P9QznS(A'BD 	E UU;#HXffS#&%w
FOU\*GYGGJL	9+Qse 45	 Y
 Buzz(+,-. 
55  a&7%8;<55q'7&8;<55!""g&uu[!DH$dVn-55$a(1,	!,?*@)ABC55!$q(?);(<=>Iejj4567!"{B!7S!7AZ=F;Raa!7
SE$))#D#DDEFG55}-e-6G1G!AQdLd!!-BeTYYr]O451U8*o{ 2@ |||h(ULABhsAiinb 9:GJ-221W:c?CBs3iuWI./D5
#$	 
 u:?Js5zB/u56 zzznh/0h!."6"6"8oNKD%BtCj5'56 O 
Bxj/	#C$4#5]
CD	Bxj/K}((|_[ &62{A{TUVKOB A% '*;r?;+G:'WB$aj3,//AgJNOK(A-(  WaE1dAsAsKJ**,2[\B:<[//qK)6}
:>>"V*c226bC2g;rBRRefhitfuvyezz|  ~H  }I  J  	K ]
 G&{{1X;:Q>( 	M$))#iF7==?Xg<h#iij
kl	K}
%&	G_ 
+	*	*> 	* J U CF 
2	1	1L T
 fs{   AG 'AG#(AG#:AG#0AG;AG;/AH 
&AHAH1AHAHAHAHGAG 	G#AG8G7AG8HAH	__main__)u   \bhérault\b|\bherault\b   u   Hérault)u   \bdrôme\b|\bdrome\br  u   Drôme)u   \bcévennes\b|\bcevennes\br  u	   Cévennes)z\bpic saint.loup\br  zPic Saint-Loup)z\bcharente\b   Charente)z\bdordogne\br  Dordogne)z\btarn.et.garonne\br  zTarn-et-Garonne)u   \bardèche\b|\bardeche\br  u   Ardèche)z\bgers\br  Gers)z\bgard\b   Gard)u   \bcorrèze\b|\bcorreze\br  u   Corrèze)z\blanguedoc\br  	Languedoc)z\blimousin\br  Limousin)z
\bcreuse\br  Creuse)z\blot\b(?!.et.garonne)r  Lot)z
\bvienne\br  Vienne)u    \bdeux.sèvres\b|\bdeux.sevres\br  u   Deux-Sèvres)z	\bnormand   Normandy)z
\bmanche\br  Manche)z\borne\br  Orne)z\bmayenne\br  Mayenne)z\baquitaine\b|\bgironde\br  	Aquitaine)z\bmidir  u   Midi-Pyrénées)z	\bindre\br  Indre)u3   \bpyrénées.atlantiques\b|\bpyrenees.atlantiques\br  u   Pyrénées-Atlantiques)u$   \bcôtes.d.armor\b|\bcotes.d.armor\br   u   Côtes-d'Armor)z\bmorbihan\br   Morbihan)u   \bfinistère\b|\bfinistere\br   u
   Finistère)z\bbrittany\b|\bbretagne\br   Brittany)z\bille.et.vilaine\br   zIlle-et-Vilaine)z\bliguria\b|\bligurir  Liguria)z\btoscane?\b|\btuscany\br  Tuscany)z\bumbria\b|\bumbrir  Umbria)z\bmarche\b|\bmacerata\br  z	Le Marche)z"\bpuglia\b|\bapulia\b|\bmanduria\br  Puglia)z\babruzzo\br  Abruzzo)z\bpiemonte?\b|\bpiedmont\br  Piedmont)z\bcalabria\br  Calabria)z\bsicilr  Sicily)z\bsardegna\b|\bsardinia\br  Sardinia)z\bcampania\br  Campania)z
\bmolise\br  Molise)z\balentejo\br  Alentejo)z3\bcentro\b.*portugal|\bcastelo branco\b|\balcains\br  zCentral Portugal)u   \bminho\b|\btrás.os.montes\br  zNorthern Portugal)z\balgarve\br  Algarve)z\basturias\br  Asturias)z\bgalicia\b|\bgalicir  Galicia)z\bnavarra\br  Navarra)u   \baragón\b|\baragon\br  u   Aragón)z\bcastilla\b|\bcastile\br  Castilla)z\bextremadura\br  Extremadura)z
\bistria\br  Istria)z\bdalmatia\br  Dalmatia)z\bcork\b|\bkerry\br  z
SW Ireland)z\bgalway\b|\bclare\br  z	W Ireland)z\bcrete\b|\bkreta\br  Crete)z\bpeloponner  Peloponnese)r  u   classéz
inscrit aur  u   bâtiment classéu   patrimoine protégézhistorisch monumentDRAC)	ruinezruin bouwvalzto demolishu   à démolirznot habitablezniet bewoonbaarinhabitableonbewoonbaar)
r  r  r  r  r  halfvrijstaandr  r  zmaison de villagezvillage house)u   terrain à bâtirzbuilding plot	bouwgrondzland for salezterrain constructiblezplot of land)zvery remoteu   très isolézzeer afgelegenzextremely isolatedzno neighbors withinzaucun voisin)barnbarnsgranger  outbuildings
dependancer  u   dépendancesatelierr   hangargite   gîtechaiu   écuriestablestables	bijgebouwschuur)stonepierre	characteru
   caractèrehistoric
historique   longèrelongere	farmhousefermecharentaiseu   maison de maîtremanoiru   châteauchateauperiod18th19thancien	authenticbeampoutre	fireplaceu	   cheminée)
kitchencuisinediningu   salle à manger	dinatoirepizzaz
bread ovenu   four à painzsummer kitchenu   cuisine d'été)poolpisciner  r  r   u   chambre d'hôtezb&bzbed and breakfastseparateindependentannexe)zmature treezmature gardencentennizcentury-oldz	old treeszancient treeorchardvergerz
fruit treezolive grove	oliveraievinesrw  vignewalnutnoyerchestnutu
   châtaignioaku   chêneparklandu   parc arborézarbres centenaireszspecimen treewoodedu   boiséwoodland)	znatural swimmingznatural poolzpiscine naturellezbaignade naturellezswimming pondu   étang de baignadezbio poolzeco poolbiotope)zswimming poolr4  zheated poolzplunge poolr3  )pondu   étanglakelacstreamruisseauspringr  riveru   rivièrewellpuits)zcorps de fermezformer farmzfarm complexzancienne fermezold farmfermettehameauhamletz mas bastidedomainer  r   zagricultural complexzmultiple buildingszseveral outbuildings	courtyardu   cour ferméezgroup of buildingsu   ensemble de bâtiments)rw  vignoblezwine estatezdomaine viticolewineryzwine domainz chaicognacr<  r=  viticole)u   à restaurerza restaurerz
to restorezto renovatezto be renovatedu   à rénoverz	a renoverr   r  zgros oeuvreu   gros œuvreshellzrenovation requiredzneeds renovationzfor renovationu   rénovation complèteu   entièrement à rénoverrestaurationu   habitable après travaux)	renovatedu   rénovérenoverestoredu	   restaurézmove-inturnkeyu   clé en mainzcle en mainu   refait à neufzrefait a neufztastefully restoredzbeautifully renovatedzfully renovatedzrecently renovatedu   habitable immédiatement)u	   triphaséu
   tri-phasétriphasez3-phasezthree-phasezthree phasezforce motricezcorrente trifase)zterrain platzterrain plain-piedzlevel groundz	flat landz
level landzgently slopingzterreno pianeggiantezplat et)
zexposition sudz	plein sudu   orienté sudzoriente sudr  zsouth facingzsouthern exposurezesposizione sudz	sud-ouestz
south-west)forageboreholecaptage
irrigation)u   entrée indépendantezentree independantezindependent entrancezseparate entranceu   gîte indépendantzgite independantu   accès indépendantu   logement indépendantu   appartement indépendantzself-containedzindependent apartmentzguest house)u   combles aménageableszcombles amenageablesu   grenier aménageableu   combles à aménagerr  zattic to convert
sottotettozattic conversion)u   tout à l'égoutztout a l'egoutr  zmains sewerzassainissement collectifu   tout-à-l'égout)P__doc__r  r  rA   r6   r  r   pathlibr   criteria_loaderr   r  vettingr   r  r  r  r*   r  _LAND_FLOORweighted_criteriarT   rU  r5   rS   rc  rd  r   r"   r2   r?   rO   rZ   rq   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r  r	  r
  r  r/  ry  r  r  rG  r  r   r)  r1  r7  r9  r?  rB  rJ  rQ  r]  re  ri  rq  rz  r  r  r  r  r  r6  r  __name__)r>   cfgs   00r   <module>rm     sb      	 
   , # YYw 23
YYw	*
99W%))*>? ii)
 .1-B-B-H-H-JK-J	D$s)O-JKG
 1G +G 4G 1G %G %G 3G 1G G  !G" 1#G$ '%G& %'G( !)G* *+G, !-G. =/G2 "3G4 !5G6 7G8 #9G: 3;G< &=G> ?G@ ZAGD CEGF %GGH 7IGJ 2KGL 3MGP ,QGR 0SGT )UGV 1WGX 9YGZ #[G\ 3]G^ %_G` aGb 2cGd %eGf !gGj %kGl TmGn ?oGp #qGt %uGv ,wGx #yGz .{G| 1}G~ +GB !CGD %EGF -GGH .IGJ )KGL 'MG
X  aLC	  XL&	  ; 	FJ  >F*	  <F=	5 	D &
)
  &#+	%,V )+79DFR *,57DFP   ! #, .9 ;C EO 	 	 !	 #0	 2>	 @H	 JQ	
 
 
 "
 $,
 .<
 >G   * ,3 5> @G     ".<~"[<OF	/8vD C$J6 M2/2C
OSn  ; _ h C Y  <  H#,E x,`(8$(5(;VI</($$N.<o1d[|FR2]@	 zF 0 Ls   <J,