
    Bj
                       S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKJrJr  SSKJrJr  SSKJrJr  SSKJr  SSKJr  SSKJr  \" \R6                  R9                  S	S
5      5      r\R<                  R?                  \R<                  RA                  \!5      5      r"\R<                  RA                  \R6                  R9                  S\R<                  RG                  \"S5      5      5      r$\RJ                  " \$SS9  \R<                  RA                  \R6                  R9                  S\R<                  RG                  \"S5      5      5      r&\R6                  R9                  SS5      r'\R<                  RA                  \R6                  R9                  S\R<                  RG                  \"S5      5      5      r(Sr)SS1r*Sr+\R<                  RG                  \$S5      r,\RJ                  " \,SS9  Sr-\R\                  " 5       r/\R<                  RG                  \$S5      r0\RJ                  " \0SS9  \R<                  RG                  \$S5      r1Sr2\R<                  RG                  \$S5      r3\R\                  " 5       r4SSSSSS S!S"S!S#/ S$QSS%S&.r5S' r6S( r7S) r8S* r9S+S,S-S..r:\R<                  RA                  \R6                  R9                  S/\R<                  RG                  \"S05      5      5      r;\R<                  RA                  \R6                  R9                  S1\R<                  RG                  \"S25      5      5      r<\R<                  RG                  \"S35      \R<                  RG                  \"S45      \R<                  RG                  \"S55      /r=\R<                  RG                  \"S65      \R<                  RG                  \"S75      \R<                  RG                  \"S85      /r>S9r?S:r@\R6                  R9                  S;S<5      rA\B" S=\" \R6                  R9                  S>S?5      5      5      rC\B" S@\" \R6                  R9                  SASB5      5      5      rD\R\                  " 5       rESCSC/ SSD.rFSSE jrGSF rHSG rI\I" 5       rJSH rKSI rL\K" SJ5      rM\N" \MR9                  SKSL5      5      rO\N" \MR9                  SMSN5      5      rPSO\O SP\P SQ3rQSqRSqS\R\                  " 5       rTS9rU\K" SR5      rV\W" \VR9                  SSST5      5      R                  5       rYSU\Y SV3rZS r[\VR9                  SWSXSY/5       V s1 s H  n \W" U 5      R                  5       iM     sn r]\VR9                  SZS[S\/5       V s1 s H  n \W" U 5      R                  5       iM     sn r^\VR9                  S]S^S_/5       V s1 s H  n \W" U 5      iM     sn r_Sq`Sqa\R\                  " 5       rb/ qc\R\                  " 5       rdS` reSa rfSb rgSc rhSSd jriSSe jrjSf rkSg rlSh rmSi rnSj roSk rpSl rqSm rrSn rsSo rtSp ruSq rvSr rwSs rxSt rySu rzSv r{Sw r|Sx r} " Sy Sz\5      r~S{ rS| rS} r " S~ S\5      r " S S\5      rS r\S:X  a  \" 5         ggs  sn f s  sn f s  sn f )u4  
NWALScanner Incident Motion Renderer v030
-----------------------------
Endpoints:
  GET  /proxy/wxdata            — proxies CumulusMX wx data
  GET  /api/outages             — Florence + Sheffield local outage totals
  GET  /api/calls               — returns active calls (scanner + auto-traffic)
  POST /api/calls               — adds a new scanner call
  POST /api/calls/<id>/extend   — extends expiresAt on a call
  DELETE /api/calls/<id>        — removes a call
  GET  /api/traffic             — roadwork events for Lauderdale/Colbert (ticker)
    N)ThreadingHTTPServerSimpleHTTPRequestHandler)urlparseunquote)datetimetimezone)unescape)
HTMLParser)get_local_outages
NWALS_PORT9000NWALS_RUNTIME_DIRruntimeT)exist_okNWALS_CALLS_FILEz
calls.jsonNWALS_PEET_URLz*http://127.0.0.1:5000/api/data/currentdataNWALS_LOCATION_PROFILEzlocation_profile.jsonz/https://api.algotraffic.com/v4.0/TrafficEvents/
lauderdalecolbert,  rendered_incidentsi0  sponsorszsponsors.jsoni   zbroadcast_takeover.jsonF   
         )zTornado WarningzSevere Thunderstorm WarningzFlash Flood Warning )armedmanual_takeoverenabledlightning_enabledwarnings_enablednearby_radius_milesimmediate_radius_milesnearby_min_strikeslookback_minutesreturn_delay_minuteswarning_typeslast_auto_trigger_atlast_reasonc                  V   0 n  [        [        SSS9 n[        R                  " U5      n[	        U[
        5      (       a  Un S S S 5        [        [        5      nUR                  U 5        U$ ! , (       d  f       N0= f! [         a     N?[         a  n[        SU 3SS9   S nANZS nAff = f)Nrutf-8encodingz[TAKEOVER] State read failed: Tflush)openTAKEOVER_FILEjsonload
isinstancedictFileNotFoundError	Exceptionprint_TAKEOVER_DEFAULTSupdate)datafhloadedexcouts        //mnt/data/v093work/serve_v097_incident_video.py_takeover_loadrC   C   s    DB-w72YYr]F&$'' 8 !
"CJJtJ 87   B.se4DABs:   A< .A+A< +
A95A< 9A< <
B(	B(B##B(c                 r   [        [        5      nUR                  [        U [         5      (       a  U O0 5        [        S-   n[
           [        USSS9 n[        R                  " XSS9  S S S 5        [        R                  " U[        5        S S S 5        U$ ! , (       d  f       N3= f! , (       d  f       U$ = fNz.tmpwr-   r.      indent)r7   r;   r<   r6   r3   _TAKEOVER_LOCKr2   r4   dumposreplace)r=   mergedtmpr>   s       rB   _takeover_saverP   R   s    $%F
MM*T400$b9
&
 C	#sW-IIf+ .


3& 
 M .- 
 Ms$   B'B)#B'
B$	 B''
B6c                    SS K nUR                  U 5      UR                  U5      peUR                  X -
  5      nUR                  X1-
  5      nUR                  US-  5      S-  UR                  U5      UR                  U5      -  UR                  US-  5      S-  -  -   n	SUR	                  UR                  U	5      UR                  [        SSU	-
  5      5      5      -  $ )Nr   rG   gɅ@           )mathradianssincosatan2sqrtmax)
lat1lon1lat2lon2rT   p1p2dphidlambdaas
             rB   _takeover_milesrd   \   s    \\$d!3<<	"Dll49%Ga!dhhrl488B<78KQ8NNNA4::diilDIIc#acl4KLLL    c                     [        5       n [        R                  " 5       n/ nS nSn[        5       n[        UR	                  SUR	                  S5      S;  5      5      n[        SS5      n[        UR	                  S[        5      5      n[        UR	                  S[        5      5      n	[        S	[        [        U R	                  S
S5      5      S	-  5      5      n
[        U R	                  SS5      5      n[        U R	                  SS5      5      nUR	                  S5      =(       d    /  H  n [        UR	                  SUR	                  SUR	                  SS5      5      5      5      nUS:  a  US-  nU(       a  X-
  U
:  a  M[  [        X[        US   5      [        US   5      5      nUb  X:  a  UnX::  a  US-  nM  M     / n [        5       nU R	                  S5      =(       d    /  Vs1 s H  n[        U5      R                  5       iM     nnUR	                  S5      =(       d    /  He  n[        UR	                  S5      =(       d    0 R	                  S5      =(       d    S5      nUR                  5       U;   d  MT  UR!                  U5        Mg     S n[        U R	                  S!5      5      (       a  [        U R	                  S"5      5      (       a  U R	                  S#5      (       a   U(       a  SnUR!                  S$US   -   5        U R	                  S%5      (       aa  U(       aZ  Ub  X<::  a  SnUR!                  S&US' S(35        O9U[        U R	                  S)S*5      5      :  a  SnUR!                  U S+US, S-35        U(       a#  XS.'   S/R%                  U5      U S0'   ['        U 5        [        S[        U R	                  S1S25      5      S	-  5      n[        U R	                  S.S5      =(       a!    U[        U R	                  S.S5      5      -
  U:  5      n[        U R	                  S!5      =(       a    U R	                  S"5      =(       ak    U R	                  S%5      =(       aS    U(       + =(       aE    U R	                  S.S5      =(       a,    S[        U R	                  S0S5      5      R                  5       ;   5      n[        U R	                  S!5      5      =(       a5    [        U R	                  S"5      5      =(       a    U=(       d    U=(       d    Un[        U R	                  S35      5      =(       d    UnU R	                  S35      (       a  S4nOGU(       a  S/R%                  U5      nO.U(       a  S5nO$U(       a  U R	                  S05      =(       d    S6nOS7nS8nU(       d  Ub  X<::  a  S9nO	U(       a  S:nSUUUXb  [)        US5      OS UUUR	                  S;UR	                  SS<5      5      UUR	                  S=5      [*        R,                  " [.        R0                  5      R3                  5       R5                  S>S?5      S@.$ ! [         a     GM!  f = fs  snf ! [         a  n[#        SU 3SS9   S nAGNS nAff = f)ANr   feed_healthyprovider>   Nnone	lightning	referencelatitude	longitude<   r&   r   r#   r   r$   strikestimestamp_mst	timestampg   mB     @@latlonrS   r(   features
propertieseventr   z$[TAKEOVER] Alert evaluation failed: Tr0   Fr   r    r"   zLocal r!   z
Lightning z.1fz mi from homer%   r   z strikes within gz mir)   u    · r*   r'   r   r   Manual weather takeoveru0   Lightning data unavailable · safety hold activezWeather takeover holdzNormal playlistquiethighactiveprovider_labelri   error+00:00Z)okr}   reasonactivitystatenearest_lightning_milesnearby_strikeswarning_eventslightning_providerlightning_healthylightning_errorserver_time)rC   timeload_lightning_packageboolget_profile_dictfloat_forecast_lat_forecast_lonrZ   intrd   r9   load_local_alertsstrlowerappendr:   joinrP   roundr   nowr   utc	isoformatrM   )r   r   reasonsnearestcount_nearbylightning_pkgr   lightning_refref_latref_lon
lookback_snear_rimmediate_rstriketsmilesr   alertsvwantedfrx   r@   auto_triggerhold_snormal_holdfeed_fail_hold	auto_holdr}   r   r   s                                  rB   broadcast_takeover_statusr   d   s   E
))+CGGL*,M]..~}?P?PQ[?\dr?rst!+{;MM%%j-@AGM%%k=ABGRU599-?#CDRGHIJ5992267F		":2>?K $$Y/525	vzz.&**S&**[Z[B\2]^_BDy","*,h#GeF5M6JERXY^R_L`aE%/U7 1 6 NH"$).?)C)Ir)IK)I1A)IKJ'-2-Aquu\*0b55g>D"EE{{}&%%e, . LEIIgD9)=$>$>99'((^LNN8nQ&77899()).?"w'=!GC=FGUYY/CA%F!GG!,/?qzMN&)$%#[[1muquyy!7:;B>?Fuyy!7:vs5SijkIlCm?mpv?vwK		' 	Duyy3 	D		BU8V 	D!!	D&+ii0Fq&I	D3uyyr:;AACCN
 599W%&y4		)0D+Ey<Kx[fKxjxI		+,-:Fyy"##(	{{7#	A	yy'B+B H'-'2HTZ8	xfHGZ53C`d&.+//0@-BSBST^_eBfg.(,,W5||HLL1;;=EEhsS k  		 L
  H4SE:$GGHsJ   ,AX;9X;&Y +#YA,Y >Y ;
Y
	Y
Y 
Y4Y//Y4.png.jpg.webp)	image/png
image/jpeg
image/webpNWALS_SPARK_DATA_FILEzspark_lightning.jsonNWALS_SPARK_STATUS_FILEzspark_lightning_status.jsonzglm_lightning.jsonzgoes_glm_lightning.jsonzgoes_lightning.jsonzglm_lightning_status.jsonzgoes_glm_lightning_status.jsonzgoes_lightning_status.jsoni  x   NWALS_HAZCAMS_LIGHTNING_URLz/https://realtime.hazcams.com/api/lightning.json   !NWALS_HAZCAMS_LIGHTNING_REFRESH_S10rG   !NWALS_HAZCAMS_LIGHTNING_TIMEOUT_S6rR   )last_attemptlast_successro   r   c           	      z   [         R                   " 5       n[           U (       dB  U[        [        R	                  SS5      5      -
  [
        :  a  [        [        5      sS S S 5        $ U[        S'   S S S 5         [        R                  R                  [        S[        ;   a  SOS-   S-   [        [        US-  5      5      -   SSS	.S
9n[        R                  R                  U[        S9 n[        R                   " UR#                  5       R%                  S5      5      nS S S 5        ['        W[(        5      (       a  UO(['        U[        5      (       a  UR	                  S/ 5      O/ n/ nU H)  n[+        US5      nU(       d  M  UR-                  U5        M+     UR/                  S SS9  [        U[0        -
  S-  5      n	U V
s/ s H&  n
[        U
R	                  SS5      5      U	:  d  M$  U
PM(     nn
[           [        R3                  XS S.5        [        [        5      sS S S 5        $ ! , (       d  f       GN= f! , (       d  f       GN"= fs  sn
f ! , (       d  f       g = f! [4         aP  n[           [        U5      [        S'   [        [        5      sS S S 5        s S nA$ ! , (       d  f        S nAg = fS nAff = f)Nr   r   ?&z_=  application/jsonzNWALScanner/0.89 lightningAccept
User-Agentheaderstimeoutr-   ro   hazcams_realtimec                     U S   $ Nrq    items    rB   <lambda>,_refresh_hazcams_lightning.<locals>.<lambda>   s    cre   Tkeyreverserp   )r   ro   r   r   )r   _HAZCAMS_LIGHTNING_LOCKr   _HAZCAMS_LIGHTNING_CACHEr   HAZCAMS_LIGHTNING_REFRESH_Sr7   urllibrequestRequestHAZCAMS_LIGHTNING_URLr   r   urlopenHAZCAMS_LIGHTNING_TIMEOUT_Sr4   loadsreaddecoder6   list_normalize_striker   sortLIGHTNING_MAX_AGE_Sr<   r9   )forcer   reqresponserawrecords
normalizedrecordr   	cutoff_msr   r@   s               rB   _refresh_hazcams_lightningr      s-   
))+C	 u%=%A%A.RS%TUUXss01 
!	  47 0 
!2nn$$!C3H,HScRUYY\_`cdgjndn`o\pp1A]^ % 
 ^^##C1L#MQY**X]]_33G<=C N#C..#zZ]_cOdOdSWWY5Kjl
F&v/ABFv!!&)  	2DA22d:;	'1cztS.RS9T5UYb5bdz
c$$++ #T-  01	 %$) 
!	  NM d$$
  2$03C$W-01 %$$$$2s   A H&&	H&8A1I  )4H8A I  ?I   #I
'I
-I  5'I	I  &
H58
II  
II  I   
J:*J50!J 	J5J: 
J2	*J52J55J:c                      [        U R                  S5      5      =(       a+    [        R                  " 5       [        U S   5      -
  [        :*  $ ! [
         a     gf = f)Nr   F)r   r   r   r   LIGHTNING_PROVIDER_STALE_Sr9   )caches    rB   _hazcams_is_healthyr     sM    EIIn-.{499;u^G\A]3]a{3{{ s   AA 
AAc                      [        [        SSS9 n [        R                  " U 5      n[	        U[
        5      (       a  UO0 sS S S 5        $ ! , (       d  f       g = f! [         a  n[        SU 3SS9  0 s S nA$ S nAff = f)Nr,   r-   r.   z*[PROFILE] Using built-in Shoals defaults: Tr0   )r2   LOCATION_PROFILE_FILEr4   r5   r6   r7   r9   r:   )handlevaluer@   s      rB   _load_location_profiler   
  sj    'w?6IIf%E&ud335 @??  :3%@M	s:   A /A
 	A 

AA A 
A>%A93A>9A>c                      [         nU  H,  n[        U[        5      (       a  UR                  U0 5      O0 nM.     [        U[        5      (       a  U$ 0 $ N)LOCATION_PROFILEr6   r7   r   keysr   r   s      rB   r   r     F    E&0&=&=		#r"2 ud++533re   c                      [         nU  H,  n[        U[        5      (       a  UR                  U/ 5      O/ nM.     [        U[        5      (       a  U$ / $ r  )r  r6   r7   r   r   r  s      rB   _profile_listr    r  re   weatherrl   g_fA@rm   g,eXUz:https://api.weather.com/v3/wx/forecast/daily/5day?geocode=z%2CzK&format=json&units=e&language=en-US&apiKey=e1f10a1e78da46f5b10a1e78da96f525r   	stateCodeALz+https://api.weather.gov/alerts/active?area=z(&status=actual&message_type=alert,update	areaNames
LauderdaleColbertugcCodesALC077ALC033	sameCodes001077001033c                      [        U SSS9 n[        R                  " U5      sS S S 5        $ ! , (       d  f       g = f! [         a    Us $ f = f)Nr,   r-   r.   )r2   r4   r5   r9   )pathdefaultr   s      rB   load_json_filer  E  s?    $g.!99Q< /.. s#   > -	> 
;> > AAc                     U S;   a  g  [         R                  " [        U 5      R                  SS5      5      R	                  [
        R                  5      R                  5       $ ! [         a     g f = f)N)Nr   r   r   )	r   fromisoformatr   rM   
astimezoner   r   rr   r9   r   s    rB   _parse_utc_timestampr  M  sa    
%%c%j&8&8h&GHSST\T`T`akkmm s   AA# #
A0/A0c                  T    [        [        / 5      n [        U [        5      (       a  U $ / $ r  )r  SPONSOR_FILEr6   r   r  s    rB   load_sponsorsr  U  s%    <,Eud++533re   c                     [         S-   n[        USSS9 n[        R                  " XSS9  S S S 5        [        R
                  " U[         5        g ! , (       d  f       N*= frE   )r  r2   r4   rK   rL   rM   )itemsrO   r   s      rB   save_sponsorsr"  Y  sD    

C	c3	)V		%* 
*JJsL! 
*	)s   A
Ac                     Uc  [         R                   " 5       OUn[        U R                  S5      5      n[        U R                  S5      5      nU R                  SS5      (       d  gUb  X:  a  gUb  X:  a  gg)	NstartAtendAtr    Tdisabledupcomingexpiredr}   )r   r  r   )r   now_sstart_send_ss       rB   _sponsor_statusr,  _  sj     =DIIKeE"488I#67G '!23E88It$$uU^re   c                     [        U 5      nUR                  SS 5        [        X5      US'   [        R                  R                  [        U R                  S5      =(       d    S5      5      nU(       a  SU-   OS US'   U$ )NdiskPathstatusfilenamer   /sponsor_assets/url)r7   popr,  rL   r  basenamer   r   )r   r)  viewr0  s       rB   sponsor_public_viewr6  k  sf    :DHHZ$T1DNwwDHHZ$8$>B ?@H3;$x/DKKre   c                      [         R                   " 5       n [        5        Vs/ s H  n[        X5      S:X  d  M  [        X5      PM!     nnUR	                  S S9  U$ s  snf )Nr}   c                 |    [        U R                  S5      5      =(       d    SU R                  S5      =(       d    S4$ )Nr$  r   	createdAtr   )r  r   r   s    rB   r   !active_sponsors.<locals>.<lambda>v  s0    !5dhhy6I!J!OaQUQYQYZeQfQljl mre   )r   )r   r  r,  r6  r   )r)  r   r!  s      rB   active_sponsorsr;  s  sT    IIKE:G/v/$_]aMimuMu- -/Ev	JJmJnL ws
   AAc                     U  H6  n[         R                  R                  U5      (       d  M)  [        X!5      U4s  $    US 4$ r  )rL   r  existsr  )pathsr  	candidates      rB   _first_existing_jsonr@  z  s;    	77>>)$$!)5y@@  D=re   c                    U c  g [        U 5      nUS:  a  US-  n[        U5      $ ! [         a     Of = f [        [        R                  " [        U 5      R                  SS5      5      R                  5       5      $ ! [         a     gf = f)zENormalize seconds, milliseconds, or an ISO timestamp to Unix seconds.Nl    J)rs   r   r   )r   r   r9   r   r  r   rM   rr   )r   numbers     rB   _timestamp_secondsrC    s    }u%%fF6{ 8))#e**<*<S(*KLVVXYY s    ' 
44AA> >
B
Bc                    [        U [        [        45      (       a   [        U 5      S:  a  U S   U S   U S   pCnS nO[        U [        5      (       a  U R                  SU R                  S5      5      nU R                  SU R                  S5      5      nU R                  S	U R                  S
U R                  S5      5      5      nU R                  S5      nOg  [        U5      n[        U5      n[        U5      nUc  g [        [        R                  " 5       5      nXg[        -
  :  d  XgS-   :  a  g U(       d  US SUS SU 3n[        U5      UUUUUS-  [        SXv-
  5      US.$ ! [         a     g f = f)Nr   r   rS   rG   rt   laru   lorr   rq   rp   idr   z.5f:r   )rG  rt   ru   rq   rr   rp   age_secondsrh   )r6   r   tuplelenr7   r   r   r9   rC  r   r   r   r   rZ   )r   rh   rt   ru   raw_ts	strike_idr   r)  s           rB   r   r     sm   &4-((S[A-=!!9fQi&		FD	!	!jj

4 01jj

4 01JJsFJJ~67
 JJt$	CjCj 
F	#B	z		E	'''2+;3iqS	2$/	 )nT	1ej)	 	  s   E& &
E32E3c                 t   [        U [        5      (       a`  U R                  S5      n[        U[        5      (       d  U R                  S5      nU R                  S5      n[        U[        5      (       d  / nO[        U [        5      (       a  U n/ nO/ n/ n/ n[	        5       nU HE  n[        Xa5      nU(       a	  US   U;   a  M   UR                  US   5        UR                  U5        MG     [	        5       nU H+  n[        Xa5      nU(       d  M  UR                  US   5        M-     UR                  S SS9  XH4$ )Nro   r=   new_strikesrG  c                     U S   $ r   r   r   s    rB   r   -_normalize_provider_payload.<locals>.<lambda>  s    T#Yre   Tr   )	r6   r7   r   r   setr   addr   r   )	payloadrh   r   new_recordsr   seenr   r   new_idss	            rB   _normalize_provider_payloadrX    s   '4  ++i('4((kk&)Gkk-0+t,,K	GT	"	"J5D"64-&!  eG"646KKt% 
 OO.O=re   c                 ,   [        U [        5      (       d  gU R                  S5      SL a/  U R                  S5      n US L =(       d    [        U5      [        :*  $ [        U R                  SS5      5      R                  5       S:H  $ ! [
         a     gf = f)NFhealthyTcapture_age_secondsr/  r   )r6   r7   r   r   r   r9   r   r   )r/  ages     rB   _spark_is_healthyr]    s    fd##zz)$jj./	$;J%*0J"JJ vzz(B'(..0I==  		s   B 
BBc           	      |   U(       d  g[        U [        5      (       d  gU R                  S5      SL a  g[        U R                  SU R                  SS5      5      5      R	                  5       nUS;   a  gU R                  SU R                  S	5      5      n Ub  [        U5      [        :  a  gg! [         a     gf = f)
NFTrZ  r   r/  r   >   r   stalefailedoffliner[  rI  )r6   r7   r   r   r   r   r   r9   )r/  ro   r   r\  s       rB   _glm_is_healthyrb    s    fd##zz)%

7FJJx$<=>DDFE77
***FJJ},E
FC?uSz,FF   s   B. .
B;:B;c                     [        [        R                  " 5       5      n [        5       n[        U5      (       aI  [	        UR                  S5      =(       d    / 5      nSSSU S[        U5      SU/ SUR                  S5      S	.$ [        [        0 5      n[        [        0 5      n[        US
5      u  pV[        U5      (       an  U Vs/ s H  owS   U;   d  M  UPM     nn[        U[        5      (       a  [        U5      O0 n	U	R                  S
SSSU [        U5      [        U5      UUSS.
5        U	$ [        [         / 5      u  p[        ["        0 5      u  p[        U
S5      u  p[%        X5      (       a@  SSSSU S[        U5      SU/ SU(       a!  [&        R(                  R+                  U5      S.$ SS.$ SSSU SSS/ / SSUR                  S5      S.$ s  snf )zPReturn Hazcams realtime lightning when healthy, then legacy Spark/GLM fallbacks.ro   r   zHazcams Realtime Lightningprimary   r   Tr   )rh   r~   provider_modegenerated_athistory_minutesstrike_countnew_strike_countro   rO  rg   last_success_epochweatherbug_sparkrG  zWeatherBug Sparkfallbackz*Hazcams realtime feed unavailable or stale)
rh   r~   rf  fallback_reasonrg  ri  rj  ro   rO  rg   goes_glmzGOES GLMz&Hazcams and Spark unavailable or staleN)rh   r~   rf  rn  rg  rh  ri  rj  ro   rO  rg   source_fileri   zLightning Data Unavailablera  FzBHazcams realtime, Spark, and GLM lightning sources are unavailabler   )rh   r~   rf  rg  rh  ri  rj  ro   rO  rg   r   hazcams_error)r   r   r   r   r   r   rK  r  SPARK_LIGHTNING_FILESPARK_LIGHTNING_STATUS_FILErX  r]  r6   r7   r<   r@  GLM_LIGHTNING_FILE_CANDIDATESGLM_LIGHTNING_STATUS_CANDIDATESrb  rL   r  r4  )r)  hazcamsro   spark_payloadspark_statusspark_strikesspark_new_idsr   rO  packageglm_payloadglm_path
glm_status_glm_strikess                  rB   r   r     s   		E(*G7##w{{9-34*:&!!L ! ")++n"=
 	
 ##7<M!"=rBL#>}N`#a M&&,9[M&D\]=ZvM[)3M4)H)H$}%b*>P'<h!3}3E #K 0]&
 	 01NPRSK()H"MMJ0jINKz//"jS]GY^!3{3CYZ"2t9A277++H5
 	

 HL
 	
 .J"EbqRPRU W- / \s   GGc                  ~   [        5       n [        [        0 5      n[        [        0 5      u  p#U R                  S5      U R                  S5      U R                  S5      U R                  S5      S;  a  SOS[        U R                  SU R                  S5      S;  5      5      U R                  S5      U R                  S	5      U R                  S
S5      U R                  SS5      U R                  S5      U R                  S5      UUU(       a  [        R                  R                  U5      OS U R                  S5      S.$ )Nrh   r~   rf  >   Nri   onlinera  rg   r   rq  ri  r   rj  nearest_strikeradius_counts)rh   r~   rf  r   rZ  r   rq  ri  rj  r  r  sparkglmglm_status_filer   )
r   r  rs  r@  ru  r   r   rL   r  r4  )r{  rx  r~  glm_status_paths       rB   load_lightning_statusr  :  s   $&G!"=rBL"6'
#J KK
+!++&67 _5 {{:&n< NGKK
4KSa4abcW% _5NA6#KK(:A>!++&67 _5  GG_-W%/ re   c                  6  ^ [         R                  R                  [        5      (       d  / $  [	        [        S5       n [
        R                  " U 5      nS S S 5        [        R                  " 5       mU4S jnW Vs/ s H  o2" U5      (       d  M  UPM     nn[        U5      [        U5      :  a0  [	        [        S5       n [
        R                  " X@SS9  S S S 5        U$ U$ ! , (       d  f       N= fs  snf ! , (       d  f       U$ = f! [         a    / s $ f = f)Nr,   c                    > U R                  S5      nU(       d  g [        R                  " UR                  SS5      5      nUR	                  5       T:  $ ! [
         a     gf = f)N	expiresAtFr   r   )r   r   r  rM   rr   r9   )c
expires_atexpr   s      rB   	is_activeload_calls.<locals>.is_actived  s\    {+J,,Z-?-?X-NO}},, s   8A 
A"!A"rF   rG   rH   )rL   r  r=  
CALLS_FILEr2   r4   r5   r   rK  rK   r9   )r   callsr  r  r}   r   s        @rB   
load_callsr  ]  s    77>>*%%	*c"aIIaLE #iik	 #3Uil!U3v;U#j#&!		&A. 'v! #" 4&& 	s^   D	 C!'D	 ;C2C2*D	 ?C7	D	 D	 !
C/+D	 7
DD	 D	 	DDc                     [        [        S5       n[        R                  " XSS9  S S S 5        g ! , (       d  f       g = f)NrF   rG   rH   )r2   r  r4   rK   )r  r   s     rB   
save_callsr  u  s(    	j#	!		%1% 
		s   0
>c                     U=(       d    SR                  5       nSU;   d  SU;   a  gSU;   a  gSU;   d  SU;   a  g	U S
:X  a  gg)z8Map AlgoTraffic severity/title to a broadcast call type.r   crash	collisionWRECKfirezVEHICLE FIREdebrishazardzROAD HAZARDClosedROAD CLOSEDzTRAFFIC INCIDENT)r   )severitytitletitle_lowers      rB   algo_severity_to_typer  y  sQ    ;B%%'K+!;;(k"98re   c                 <   U R                  S5      nU(       a   [        R                  " UR                  SS5      5      n[        R                  " [
        R                  5      nX#-
  R                  5       nUS:  a9  [        R                  " [        R                  " 5       S-   [
        R                  S9nUR                  S5      $ [        R                  " [        R                  " 5       S-   [
        R                  S9R                  S5      $ ! [         a     NTf = f)	u;   Return ISO expiresAt — use event end or 2 hours from now.endr   r   iQ i  )tz%Y-%m-%dT%H:%M:%SZi   )r   r   r  rM   r   r   r   total_secondsfromtimestampr   strftimer9   )rx   r  r  now_dtdeltas        rB   algo_expires_isor    s    
))E
C
		((S()CDC\\(,,/F\002Eu},,TYY[4-?HLLQ<< 455 !!$))+"4FOOPdee  		s   B+D 
DDc                 j  ^^ [        U [        5      (       d  gU R                  S5      =(       d    0 mSR                  U4S jS 5       5      R	                  5       m[        U4S j[         5       5      (       a  gTR                  S5      =(       d    0 nUR                  S	5      =(       d    /  Vs1 s H  n[        U5      R                  5       iM     nnUR                  S
5      =(       d    /  Vs1 s H  n[        U5      iM     nn[        U[        -  =(       d	    U[        -  5      $ s  snf s  snf )NFrw    c              3   j   >#    U  H(  n[        TR                  U5      =(       d    S 5      v   M*     g7f)r   N)r   r   ).0r   propss     rB   	<genexpr>"_alert_is_local.<locals>.<genexpr>  s(     R9Q#C		#,"--9Qs   03)areaDescheadlinec              3   ,   >#    U  H	  oT;   v   M     g 7fr  r   )r  countytexts     rB   r  r    s     
;(:fT>(:s   TgeocodeUGCSAME)r6   r7   r   r   r   anyNWS_LOCAL_COUNTIESr   upperr   NWS_LOCAL_UGCNWS_LOCAL_SAME)featurer  r   ugcsamer  r  s        @@rB   _alert_is_localr    s    gt$$KK%+E88R9QRRXXZD

;(:
;;;ii	"(bG,3KK,>,D",D
F,D%3u:,DC
F%,[[%8%>B%>@%>5CJ%>D@m#<tn'<== G@s   1#D+2D0c            
         [         R                   " 5       n [           [        n[        nS S S 5        Wb  U W-
  [        :  a  U$ [
        R                  R                  [        SSS.S9n [
        R                  R                  USS9 n[        R                  " UR                  5       R                  S5      5      nS S S 5        WR                  S5      =(       d    /  Vs/ s H  n[        U5      (       d  M  UPM     nnS	U[         R"                  " [$        R&                  5      R)                  5       [+        [,        R                  S
SS/5      5      [        SS.n[           Uq[         R                   " 5       qS S S 5        U$ ! , (       d  f       GNa= f! , (       d  f       N= fs  snf ! , (       d  f       U$ = f! [.         a  n	[1        SU	 3SS9  [           [        n
S S S 5        O! , (       d  f       O= fW
b%  [3        U
5      nSUS'   [5        U	5      US'   Us S n	A	$ S	/ [         R"                  " [$        R&                  5      R)                  5       S[5        U	5      SS.s S n	A	$ S n	A	ff = f)Nzapplication/geo+jsonz5NWALScannerWeatherV3/1.0 (operations@nwalscanner.com)r   r      r   r-   rv   FeatureCollectionr  r  r  zapi.weather.gov)typerv   rg  county_filtercache_secondssourcez[ALERTS] NWS fetch failed: Tr0   r_  r   )r  rv   rg  r_  r   r  )r   _nws_alert_lock_nws_alert_cache_nws_alert_cache_timeNWS_ALERT_CACHE_Sr   r   r   NWS_ALERTS_URLr   r4   r   r   r   r   r  r   r   r   r   r   r   _alerts_profiler9   r:   r7   r   )r   cachedcached_timer   r   rT  r  rv   resultr@   r_  
stale_copys               rB   r   r     s   
))+C	!+ 
 cK/2CCnn$$,Q
 % G#
^^##GR#8Hjj!7!7!@AG 9 %,KK
$;$Ar$A
$Aw' $A 	 

 ( $LL6@@B!/"5"5kLR[C\"]^.'
 %$(IIK!  ? 
 98
 _  
+C51>$E __eJ"&Jw"%c(Jw'$LL6@@BX'
 	

s   F)F= 4F;$F= F&7F&=A$F= !F+9	F= 
F
F#F= +
F:5F= :F= =
I/I*G*!	I**
G8	4)I*I/#AI*$I/*I/c                       [         R                  R                  [        SS0S9n [         R                  R	                  U SS9 n[
        R                  " UR                  5       R                  5       5      nS S S 5        / n/ nW H  nUR                  S5      (       d  M  UR                  S5      =(       d    0 nUR                  S5      =(       d    S	R                  5       nU[        ;  a  Mi  UR                  S
S	5      nUS:X  a  UR                  U5        M  US;   d  M  UR                  U5        M     / n	U GH0  nUR                  S5      =(       d    0 nUR                  S5      =(       d    UR                  S5      =(       d    S	n
UR                  S5      =(       d    S	nUR                  S5      =(       d    UR                  S5      =(       d    S	nUR                  SS	5      nU	R                  UR                  S5      UR                  SS	5      U
UUR                  SS	5      UR                  S5      =(       d    UR                  SS	5      UUUR                  SS	5      S.	5        GM3     [           U	qS S S 5        [        5       nU Vs1 s H+  oR                  S5      (       d  M  UR                  S5      iM-     nn[!        5       nU GHF  n[#        UR                  S5      5      nUR%                  U5        UR                  S5      =(       d    0 nUR                  SS	5      nUR                  S5      =(       d    Un
UR                  S5      =(       d    S	nUR                  S5      =(       d    S	nU(       d  U(       a  U SU 3R'                  S5      OS	nUR                  S5      =(       d    UR                  S5      =(       d    SnUR                  S5      =(       d    S	nUR                  SS	5      nSSSSS .nUR                  UU5      nUU;  a  0 SS!U-   _SU_S"S#_S
[)        UU5      _SS$U 3_SU
_S%U_S&U_SU_S'U_SU_S(S	_S)S*_S+S,_S-[*        R*                  " 5       _S.[-        U5      _S/[*        R.                  " S0[*        R0                  " 5       5      _nUR3                  S1U5        UR%                  U5        [5        S2U S3U S435        GM  U H3  nUR                  S5      U:X  d  M  [-        U5      US.'   UUS''   XS'     GMD     GMI     U Vs/ s H2  nUR                  S5      (       a  UR                  S5      U;   d  M0  UPM4     nn[7        U5        [*        R:                  " [<        5        GM  ! , (       d  f       GN= f! , (       d  f       GN!= fs  snf s  snf ! [8         a  n[5        S5U 35         S nANhS nAff = f)6Nr   r   r   r   r   r}   startLocationr  r   r  Incident)RoadworkFacilitycitydisplayRouteDesignatordescriptionr  r  rG  shortSubTitlesubTitlepermLink)	rG  r  r  roadr  subtitler  r  r  algoIddisplayCrossStreetz at z atzTraffic Incidentr  zMAJOR DELAYzMODERATE DELAYzMINOR DELAY)r  
MajorDelayModerateDelay
MinorDelayalgo_r  algotrafficz
[TRAFFIC] locationaddressr/  unitscautionzPLEASE USE CAUTION IN THIS AREAholdSeconds   r   r  receivedr  r   z[ALGO] New incident: z in z Countyz[ALGO] Poll error: )r   r   r   ALGO_URLr   r4   r   r   r   r   r   ALGO_COUNTIESr   _cache_lock_roadwork_cacher  rR  r   rS  stripr  r   r  r  gmtimeinsertr:   r  r9   sleepALGO_POLL_S)r   r,   eventslocal_incidentslocal_roadworkevlocr  ev_typeroadwork_itemsr  r  descsevr  r  existing_algo_idsactive_algo_idsalgo_idcrossr  r  r  sev_map	sev_labelcalles                              rB   poll_algotrafficr    sw   
m	-..((HFX;Y(ZC''R'8AAFFHOO$56 9 !O Nvvh''ff_-3''(+1r88:.&&,j(#**2. 88"))"-   N$vvo.4"wwvA#''(*;Arww78>Bvvm,EwE2vvj"-%% "t #" 5 $ $ "w 3 " 7 Q266*b;Q ##' "z2 6
' 
 %" "0  LE */!).A%%/h  ! "eO%rvvd|,##G,66/28b778R0776?4f77#;<B77#78>BAEdV4w/55e<UW66'?[bff_.E[I[66-06B66*b1%2,<-Y#KK(;	"33w'8 w !} '<Xu'M	
  E7'; t #w "w !v !y &t  r "'H &r tyy{  $'7';!" #t}}5I4;;='Y#D& LLD)%))'21%VHGLM #55?g5-=b-AAkN-6AhK/3m,! #U &f ! auuX!%%/_*L 5   u
 	

;a  98N !n  	-'s+,,	-s{   AV/ 3V8B&V/ "EV/ 6V9V/ V%,V%H3V/ 8&V/ /V*V*V/ 
VV/ 
V"V/ /
W9WWc                     [         R                  " SS[        U =(       d    S5      5      R                  S5      R	                  5       n U S S =(       d    S$ )Nz[^a-zA-Z0-9]+-incident2   )resubr   r  r   r  s    rB   
_safe_slugr  Q  sD    FF#S#e.Az*BCII#NTTVE":##re   c                     Sn SnS n SSK Jn  Sn  U" 5        nUR                  R                  SS9nUR	                  5         S S S 5        Sn[        R                  " S5      n[        U =(       a    U=(       a    U5      SSS	S
[        U U[        U5      U[        US.$ ! , (       d  f       Na= f! [
         a  n[        U5      n S nAN|S nAff = f! [
         a  n[        U5      n S nANS nAff = f)NFr   sync_playwrightT)headlessffmpegv022v030zincident_graphic.htmlzincident_graphic_v030.html)r   platform_versionincident_motion_versiongraphicgraphic_sourceportplaywright_installedchromium_installedffmpeg_foundffmpeg_pathoutput_directoryr   )playwright.sync_apir  chromiumlaunchcloser9   r   shutilwhichr   PORTINCIDENT_VIDEO_DIR)playwright_okchromium_okplaywright_errorr  pbrowserr@   r#  s           rB   incident_render_statusr2  V  s    MK$7	( "a**++T+: # K ,,x(K=@[@[A"#)*6 -)[)".!  #"  	("3x	( $s8$sQ   C B. *B
B. 
B+'B. .
C8CC CC 
C/C**C/c                 	   [         R                  " S5      nU(       d  [        S5      e SSKJn  SSKJn  U R                  SS	5      U R                  S
S5      U R                  SS5      U R                  SS5      U R                  SS5      U R                  SS	5      U R                  SS	5      U R                  SS	5      SSSSS.nS[         S3U" U5      -   n[        R                  " 5       R                  S5      nS[        U R                  S
5      5       SU S3n[        R                  R!                  ["        U5      n	[$        R'                  SS9(       d  [        S 5      e [(        R*                  " S!S"9 n
SnU" 5        n UR,                  R/                  S#S$/S%9nUR1                  S'S(S).U
S'S(S).S*S+9n[2        R4                  " 5       nUR7                  5       n[9        S,S#S-9  [9        S.U 3S#S-9  [9        S/U	 3S#S-9  UR;                  US0S1S29  UR=                  S3S1S49  UR?                  S55        UR=                  S6S7S49  [A        S8[2        R4                  " 5       U-
  5      nURC                  S95        S:[        U R                  S
5      5       SU S;3n[        R                  R!                  ["        U5      nURE                  USS<9  [9        S=U 3S#S-9  URC                  [F        5        URH                  nURK                  5         URK                  5         UR                  5       nURK                  5         SSS5        U(       a$  [        R                  RM                  U5      (       d  [        S>5      eUS?S@SASBSCWSD SEUSFSGSHSISJSKSLSMSNSOSPSQSRSSSTU	/n[N        RP                  " US#S#SUSV9nURR                  S:w  a$  [        SWURT                  SXS =(       d    SY-   5      e SSS5        [        R                  RM                  U	5      (       a#  [        R                  RW                  U	5      SZ:  a  [        S[5      eU[$        RY                  5         $ ! [
         a  n[        S5      UeSnAff = f! [
         a  n[        S&5      UeSnAff = f! , (       d  f       GNZ= f! , (       d  f       N= f! [$        RY                  5         f = f)\zLRecord the animated incident scene and encode a deterministic 12-second MP4.r  z@FFmpeg was not found in PATH. Run ffmpeg -version in PowerShell.r   r  zNPlaywright is not installed for this Python. Run: py -m pip install playwrightN)	urlencoder  r   r  zActive Incidentr  zLocation unavailabler  z
NW Alabamar/  Activer  r  reported1r  )r  r  r  r  r/  r  r  r6  motionlooprenderbuildzhttp://127.0.0.1:z/incident_graphic.html?z%Y%m%d_%H%M%S	incident_r  z.mp4F)blockingzQAnother incident video is already rendering. Wait for it to finish and try again.incident_render_)prefixTz--disable-dev-shm-usage)r  argszFPlaywright Chromium is missing. Run: py -m playwright install chromium     )widthheightrS   )viewportrecord_video_dirrecord_video_sizedevice_scale_factorz@
>>> INCIDENT MOTION V025 FREEDOM V LIGHTBAR RENDERER ACTIVE <<<r0   z>>> EXACT GRAPHIC URL: z>>> OUTPUT MP4: domcontentloaded0u  )
wait_untilr   z window.__INCIDENT_READY === truer   zwindow.startIncidentMotion()z"window.__INCIDENT_STARTED === truei  rR   i  render_proof_r   )r  	full_pagez>>> PROOF SCREENSHOT: z%Chromium did not produce a video filez-yz-hide_bannerz	-loglevelr   z-ssz.3fz-iz-tz12.0z-anz-vfz#fps=30,scale=1280:720:flags=lanczosz-c:vlibx264z-presetmediumz-crf19z-pix_fmtyuv420pz	-movflagsz
+faststart   )capture_outputr  r   zFFmpeg failed: iPzunknown error'  z.Rendered MP4 was missing or unexpectedly small)-r)  r*  RuntimeErrorr%  r  r9   urllib.parser4  r   r+  r   r   r  r  rL   r  r   r,  _INCIDENT_RENDER_LOCKacquiretempfileTemporaryDirectoryr&  r'  new_contextr   	monotonicnew_pager:   gotowait_for_functionevaluaterZ   wait_for_timeout
screenshotINCIDENT_VIDEO_DURATION_MSvideor(  r=  
subprocessrun
returncodestderrgetsizerelease)rT  r  r  r@   r4  paramspage_urlstampr0  output_pathrO   	webm_pathr0  r1  contextcapture_opened_atpagestable_motion_offsetproof_filename
proof_pathrd  commandprocs                          rB   render_incident_videorx  x  s   \\(#F]^^v7 'FB'W&78KK
,BCFL1++h1{{="5;;y"-KK
B/F #4&(?@9VCTTHLLN##O4E:gkk'&:;<AeWDIH'',,18<K !((%(8nooE(((0BCsI "azjj//!%78 0 G "--'+s;%(04&D()	 .  %)NN$4!'')Yaef/z:$G(6dC		(/A5	Q&&'ISX&Y<=&&'KUY&Z
 (+30@CT0T'U$ %%c*#0GKK<P1Q0RRSTYSZZ^!_WW\\*<nM
Z5A.zl;4H%%&@A



!JJL	Y #\ BGGNN9$=$="#JKK nk7.s3dIfe<	9hI{LG >>'$TSVWD!#"#4EF8K8^#_`` ${ D@ ww~~k**bggook.JV.SOPP%%'A  vklruuvH ! z&'opvyyz #" DCH 	%%'sz   Q %R/ 9
RRQ. FR9B&R AR/ 
Q+Q&&Q+.
R	8RR		R
R	R
R,(R/ /Sc                   :   ^  \ rS rSrU 4S jrS rS rS rSrU =r	$ )_CrimeRadarIncidentParseri  c                    > [         TU ]  SS9  SU l        / U l        S U l        / / / S.U l        / U l        SU l        SU l        SU l	        / U l
        g )NT)convert_charrefsF)h1h2r   r   )super__init__capture_scriptscript_chunkscapture_tagtext_chunksall_textaside_depthin_ai_summary_asidecapture_ai_summary_h2ai_summary_chunks)self	__class__s    rB   r  "_CrimeRadarIncidentParser.__init__  sc    $/#"$B;
 #( %*"!#re   c                    [        U5      nUS:X  a  SU;   a  SU l        US:X  ap  U R                  (       a  U =R                  S-  sl        OI[	        UR                  SS5      5      R                  5       R                  5       S:X  a  SU l        SU l        US	:X  a  U R                  (       a  SU l        XR                  ;   a  U R                  c  Xl
        g g g )
Nscriptzdata-audio-card-payloadTasiderS   z
aria-labelr   zai generated summaryr~  )r7   r  r  r  r   r   r  r   r  r  r  )r  tagattrss      rB   handle_starttag)_CrimeRadarIncidentParser.handle_starttag  s    U(?8EA"&D'>''  A% UYY|R01779??AE[[+/(#$ $;433)-D&"""t'7'7'?" (@"re   c                 >   US:X  a  U R                   (       a  SU l         US:X  a  U R                  (       a  SU l        US:X  aD  U R                  (       a3  U =R                  S-  sl        U R                  S::  a  SU l        SU l        XR                  :X  a  S U l        g g )Nr  Fr~  r  rS   r   )r  r  r  r  r  )r  r  s     rB   handle_endtag'_CrimeRadarIncidentParser.handle_endtag
  s    (?t22"'D$;455).D&'>d66!1$+0(#$ """#D #re   c                    U R                   (       a  U R                  R                  U5        SR                  [	        U=(       d    S5      R                  5       5      nU(       a  U R                  R                  U5        U R                  (       a  U R                  R                  U5        U R                  U R                  ;   a)  U R                  U R                     R                  U5        g g g )Nr  r   )r  r  r   r   r   splitr  r  r  r  r  )r  r=   cleans      rB   handle_data%_CrimeRadarIncidentParser.handle_data  s    %%d+TZR..01MM  '))&&--e44#3#33  !1!1299%@ 4	 re   )	r  r  r  r  r  r  r  r  r  )
__name__
__module____qualname____firstlineno__r  r  r  r  __static_attributes____classcell__r  s   @rB   rz  rz    s    $ #$$	A 	Are   rz  c                    U R                   R                  S5      R                  S5      =(       d    S/S   n[        R                  " SSU[        R
                  S9nSR                  S UR                  S5       5       5      $ )	N/r   r   z-al$flagsr  c              3   R   #    U  H  o(       d  M  UR                  5       v   M     g 7fr  )
capitalize)r  words     rB   r  ,_crimeradar_city_from_url.<locals>.<genexpr>&  s     J/$T%DOO%%/s   
''r  )r  r  r  r  r  Ir   )parsedfirstslugs      rB   _crimeradar_city_from_urlr  #  sb    [[s#))#.62$:E66'2uBDD1D88J$**S/JJJre   c                     [        U =(       d    S5      R                  5       n [        R                  " SU [        R                  S9nU(       a  UR                  S5      R                  5       $ S$ )Nr   z\bat\s+(.+)$r  rS   )r   r  r  searchr  group)r  matchs     rB   _crimeradar_location_from_titler  )  sM    ""$EIIouBDD9E%*5;;q>!22re   c                    [        [        U =(       d    S5      R                  5       5      nUR                  =(       d    SR	                  5       R                  S5      n1 SknUR                  S;  d  X#;  a  [        S5      eUR                  R                  S5       Vs/ s H  oD(       d  M  UPM     nn[        U5      S:  a  US   OSn[        R                  " S	U[        R                  S
9(       d  [        S5      e[        R                  R!                  U SSS.S9n[        R                  R#                  USS9 nUR%                  5       n	[        U	5      R                  =(       d    SR	                  5       R                  S5      n
X;  a  [        S5      eUR'                  S5      R)                  SSS9nS S S 5        [+        5       nUR-                  W5        0 nSR/                  UR0                  5      R                  5       nU(       a    [2        R4                  " [7        U5      5      nSR/                  UR:                  S   5      R                  5       nSR/                  UR<                  5      R                  5       n[        R>                  " SSU[        R                  S
9R                  5       n[A        U5      n[C        U5      nSR/                  URD                  5      nSnUR:                  RG                  S5      =(       d    / nU(       a  US   nU(       d<  [        RH                  " SU[        R                  S
9nU(       a  URK                  S5      nSnS HJ  n[        RH                  " S[        RL                  " U5      -   S-   U[        R                  S
9(       d  MH  Un  O   U(       d  U(       d  [        S5      eS W	UUUUUUURG                  S!5      =(       d    SURG                  S"5      URG                  S#5      =(       d    SURG                  S$5      =(       d    SURG                  S%5      =(       d    / S&.$ s  snf ! , (       d  f       GN= f! [8         a    0 n GN>f = f)'Nr   .>   crimeradar.ususcrimeradar.comwww.crimeradar.uswww.uscrimeradar.com>   httphttpszPaste a CrimeRadar incident URLr  rG   rS   z%^(?:c-)?\d+_\d+_[A-Za-z0-9]+(?:-.+)?$r  z5Use a CrimeRadar incident-detail URL, not a city pagez+Mozilla/5.0 (NWAL Scanner Incident Command)ztext/html,application/xhtml+xml)r   r   r   r   r   z,CrimeRadar redirected to an unsupported hosti    r-   rM   )errorsr  r}  z\s*Share This Information\s*$r   r   z5\b\d{1,2}/\d{1,2}/\d{4}\s+\d{1,2}:\d{2}\s*(?:AM|PM)\b)TrafficFireMedicalPoliceWeatherz\bz3CrimeRadar incident data was not found on that page
crimeradaraudioaudio_durationaudio_duration_string
transcripttranscript_segments)r  
source_urlr  summaryr  r  categorydisplayed_timer  r  r  r  r  )'r   r   r  hostnamer   rstripscheme
ValueErrorr  r  rK  r  r  r  r   r   r   r   geturlr   r   rz  feedr   r  r4   r   r	   r9   r  r  r  r  r  r  r   r  r  escape)r2  r  hostallowedpart
path_partsincident_slugr   r   	final_url
final_hosthtmlparserrT  raw_payloadr  r  r  r  visiblerr   timestamp_candidatesmr  r?  s                            rB   fetch_crimeradar_incidentr  /  s   c#)n**,-FOO!r((*11#6D`G}}--1D:;;
 $*;;#4#4S#9B#94T$#9JB%(_%9JqMrM88<mSUSWSWXPQQnn$$G7
 % G 
				4OO%	y)228b??AHHM
$KLL}}_-44WY4O 
5 '(F
KKG''&../557K	jj+!67G HHV''-.446Ehhv//0668G ff5r7"$$OUUWG$V,D.u5Hhhv'G I!--11&9?R(+	IINPW_a_c_cd!''!*iHD	99URYYy11E97"$$OO H E
 NOO #W%+!++&67!(-D!E!Kkk,/52&{{+@AGR q C 
5	4  	G	s+   
Q-Q>A;QQ 
QQ-,Q-c                   L   ^  \ rS rSrS rU 4S jrS rS rS rS r	S r
S	rU =r$ )
Handleri  c                 f    U R                  S5        U R                  5         U R                  5         g )N   )send_response_corsend_headersr  s    rB   
do_OPTIONSHandler.do_OPTIONS  s%    3

re   c                   > [        U R                  5      nUR                  R                  S5      nUS:X  a   [        [        S5       nUR                  5       nS S S 5        U R                  S5        U R                  SS5        U R                  SS5        U R                  S	[        [        W5      5      5        U R                  5         U R                  5         U R                  R                  U5        g US:X  a  U R                  S[!        5       5        g US:X  a  U R                  S[#        5       5        g US:X  a  [$        R$                  " 5       n['        5        Vs/ s H  n[)        Xv5      PM     nnUR+                  S SS9  U R                  SS[,        R.                  " [0        R2                  5      R5                  5       R7                  SS5      US.5        g US:X  a_  U R                  SS[,        R.                  " [0        R2                  5      R5                  5       R7                  SS5      [9        5       S.5        g UR;                  S5      (       Ga~  [<        R                  R?                  U5      n	[<        R                  RA                  [B        U	5      n
[<        R                  RE                  U
5      (       d  U R                  SSS05        g [<        R                  RG                  U	5      S   RI                  5       nSSSSS.RK                  US5      n [        U
S5       nUR                  5       nS S S 5        U R                  S5        U R                  SU5        U R                  S	[        [        W5      5      5        U R                  SS 5        U R                  5         U R                  5         U R                  R                  U5        g UR;                  S!5      (       GaM  [<        R                  R?                  U5      n	[<        R                  RA                  [L        U	5      n
[<        R                  RE                  U
5      (       d  U R                  SSS"05        g  [        U
S5       nUR                  5       nS S S 5        U R                  S5        U R                  SS#5        U R                  S	[        [        W5      5      5        U R                  S$S%U	 S&35        U R                  SS5        U R                  5         U R                  5         U R                  R                  U5        g US':X  a   [N        RP                  RS                  [T        S(S)9 nUR                  5       nS S S 5        U R                  S5        U R                  SS*5        U R                  5         U R                  5         U R                  R                  W5        g US-:X  a   U R                  S[W        5       5        g US2:X  a  U R                  S[[        5       5        g US3:X  Gad  [$        R$                  " 5       n[\           [^        n[`        nS S S 5        Wb   UW-
  [b        :  a  U R                  SU5        g  [N        RP                  Re                  [f        S*S4S5.S69n[N        RP                  RS                  US7S)9 nUR                  5       n[h        Rj                  " URm                  S85      5      nS S S 5        WRK                  S95      =(       d    S /S:   =(       d    0 n[o        URK                  S;5      [p        5      (       d  [s        S<5      e[\           Uq/[$        R$                  " 5       q0S S S 5        U R                  SU5        g US?:X  a  U R                  S[u        5       5        g US@:X  a  U R                  S[w        5       5        g USA:X  a  [y        5       n[h        Rz                  " U5      R}                  5       nU R                  S5        U R                  SS*5        U R                  SS5        U R                  5         U R                  5         U R                  R                  U5        g USB:X  a  [~           [q        [        5      nS S S 5        [h        Rz                  " W5      R}                  5       nU R                  S5        U R                  SS*5        U R                  SS5        U R                  5         U R                  5         U R                  R                  U5        g [        TU G]	  5         g ! , (       d  f       GN= f! [         a!  nU R                  S
SSU 305         S nAg S nAff = fs  snf ! , (       d  f       GNL= f! [         a'  nU R                  S
S[        U5      05         S nAg S nAff = f! , (       d  f       GND= f! [         a'  nU R                  S
S[        U5      05         S nAg S nAff = f! , (       d  f       GN= f! [         aO    U R                  S+5        U R                  5         U R                  5         U R                  R                  S,5         g f = f! [         a6  n[Y        S.U 3SS/9  U R                  S+S0[        U5      / S1.5         S nAg S nAff = f! , (       d  f       GNu= f! , (       d  f       GN= f! , (       d  f       GNx= f! [         ao  n[Y        S=U 3SS/9  [\           [^        nS S S 5        O! , (       d  f       O= fWb  U R                  SU5         S nAg U R                  S+SS>U 305         S nAg S nAff = f! , (       d  f       GN= f)CNr  z/location_profile.jsonrbr  Content-Typezapplication/json; charset=utf-8zCache-Controlzno-storeContent-Length  r   zLocation profile unavailable: /api/takeover/api/render/status/api/sponsorsc                 6    U R                  S5      =(       d    S$ )Nr9  r   )r   r   s    rB   r    Handler.do_GET.<locals>.<lambda>  s    (=(C(Cre   Tr   r   r   )r   	serverNowslidesz/api/sponsors/activer1    zSponsor image not foundrS   r   r   r   )r   r   z.jpegr   zapplication/octet-streamzno-cache/rendered_incidents/zVideo not foundz	video/mp4zContent-Dispositionzattachment; filename=""z/proxy/wxdatar   r   r   i     {}z/api/outagesz[OUTAGES] Aggregator error: r0   F)successr   countiesz/api/alerts/api/forecastzNWALScannerWeatherV3/1.0r   r   r   r-   daypartr   daypartNamez1Weather.com response did not contain daypart dataz%[FORECAST] Weather.com fetch failed: z"Weather.com forecast unavailable: z/api/lightningz/api/lightning/status
/api/calls/api/traffic)Cr   r  r  r2   r   r   r  send_headerr   rK  r  r  wfilewriter9   _json_responser   r2  r   r  r6  r   r   r   r   r   r   rM   r;  
startswithrL   r4  r   SPONSOR_DIRisfilesplitextr   r   r,  r   r   r   CUMULUS_URLr   r:   r   _v3_forecast_lock_v3_forecast_cache_v3_forecast_cache_timeV3_FORECAST_CACHE_Sr   V3_WEATHERCOM_FORECAST_URLr4   r   r   r6   r   r  r   r  r  dumpsencoder  r  r  do_GET)r  r  r  r>   r=   r@   r)  r   r!  r0  	file_pathextcontent_typer,   r   r  r  r   r   r   r  r_  r  bodyr  s                           rB   r  Handler.do_GET  s	   $))$##C(++\/6"779D 7""3'  1RS  *=  !13s4y>B

  "

  & ?"%>%@A''%;%=>?"IIKEBO/R/$(5/ERJJCTJR%\\(,,7AACKKHVYZ& 
 ))%\\(,,7AACKKHVYZ)+& 
 ??-..ww''-H[(;I77>>),,##C'3L)MN''""8,Q/557C$/P\gstxxy|  Y  ZL>)T*b779D +""3'  >  !13s4y>B  *=

  "

  & ??122ww''-H%7BI77>>),,##C'3D)EF>)T*b779D +""3'  =  !13s4y>B  !6:PQYPZZ[8\]  *=

  "

  & ?"(^^++K+Cq668D D""3'  1CD

  "

  & >!##C):)<= = %6%89?" ))+C"+5 # !cK&7:M&M##C0! ..00."4&@ 1  ^^++GR+@H"--/C::cjj&9:D A !HHY/9D61=C!'++m"<dCC$%XYY&)-&.2iik+ ' ##C.  ##%;%=>**%:%<=<LEJJu%,,.Ds#^-?@_j9JJLJJT">!O, ::d#**,Ds#^-?@_j9JJLJJT"G 76  \##C'5STWSX3Y)Z[[\ S4 +*  >##C'3s8)<==> +*  >##C'3s8)<==> DC  (""3'

  "

  '(  4SE:$G##C$ X "*  
 " #"  A@ '&
  =cUC4P&.E '&& $''U33 	 '' $Fse"LM  H s\  e 	d<Be  e<f +f<Bf -g 9g
B2g "h &h7A&h %i; j><Ak4 ?6k5A$k4 k"1k4 ?m0<
ee 
e9e44e9
ff 
gf??g
gg 
h
#hh

hh Ai87i8;
j;,j66j;>
k
kk4 "
k1,k4 4
m->m(l!	m(!
l/	+m(m((m-0
m?c                    [        U R                  5      nUR                  R                  S5      nUR                  S5      R	                  S5      nUS:X  GaD  [        U R                  R                  SS5      5      n U(       a8  [        R                  " U R                  R                  U5      =(       d    S5      O0 n[        5       n[        UR                  S5      =(       d    S5      R                  5       nUS:X  a  S	US
'   OpUS:X  a  SUS
'   SUS'   SUS'   OZUS:X  a  S	US'   SUS'   OIUS:X  a  SUS'   SUS'   SUS'   O3US:X  a  1 SknU H  n	X;   d  M
  XY   Xi'   M     OU(       a  [        S5      e[!        U5        U R#                  S[%        5       5        g US:X  a  [        U R                  R                  SS5      5      nU R                  R                  U5      n [        R                  " U=(       d    S5      n[)        UR                  S5      5      nU R#                  SS	US.5        g US:X  Gaj  [        U R                  R                  SS5      5      nUS::  d  U[,        S-  :  a  U R#                  S SS!S.5        g U R                  R                  U5      n [        R                  " U=(       d    S5      n[        UR                  S"5      =(       d    S5      R                  5       n[.        R                  U5      nU(       d  [        S#5      e[        UR                  S$5      =(       d    S5      nS%U;   aG  UR                  5       R                  5       R1                  S&5      (       a  UR	                  S%S'5      S'   nSS KnUR5                  US	S(9nU(       a  [7        U5      [,        :  a  [        S)5      eUR                  S*5      =(       dB    [8        R:                  " [<        R>                  5      RA                  5       RC                  S+S,5      nUR                  S-5      =(       d    S n[E        U5      n[E        U5      nUc  [        S.5      eU(       a  Uc  [        S/5      eUb  UU::  a  [        S05      e[        [F        RH                  " 5       5      nUU-   n[J        R                  RM                  [N        U5      n[Q        US15       nURS                  U5        S S S 5        [        UR                  S25      =(       d    S35      n[U        S4[W        S5U5      5      nU[        UR                  S65      =(       d    UR                  S75      =(       d    S85      S S9 [        UR                  S75      =(       d    S5      S S: UU[8        R:                  " [<        R>                  5      RA                  5       RC                  S+S,5      [8        RX                  " U[<        R>                  5      RA                  5       RC                  S+S,5      UbC  [8        RX                  " U[<        R>                  5      RA                  5       RC                  S+S,5      OS US	S;.
n[[        5       nUR]                  U5        [_        U5        U R#                  SS	[a        U5      S<.5        g US=:X  a  [        U R                  R                  SS5      5      nU R                  R                  U5      n [        R                  " U=(       d    S5      n[c        U5      nU R#                  SS	US>U-   S?S@SA[J        R                  Re                  [J        R                  RM                  [f        U5      5      SB.5        g [7        U5      SE:X  Ga  US   SF:X  a  US'   SG:X  a  USH   SI:X  a  US   n[        U R                  R                  SS5      5      nU R                  R                  U5      n [        R                  " U5      n[i        5       nSn U H@  n!U!R                  SL5      U:X  d  M  UR                  SMU!R                  SM5      5      U!SM'   S	n   O   U (       a   [k        U5        U R#                  SSNS	05        g U R#                  SOSJSP05        g USQ:X  Ga	  [        U R                  R                  SS5      5      nU R                  R                  U5      n [        R                  " U5      n"SLU";  a!  [        [F        RH                  " 5       5      U"SL'   SRU";  a  [l        Rl                  " 5       U"SR'   [l        Rn                  " SS[l        Rp                  " 5       5      U"ST'   [i        5       nURs                  SU"5        [k        U5        U R#                  SS	U"SL   SU.5        g U R#                  SOSJSV05        g ! [&         a(  n
U R#                  SS[        U
5      S.5         S n
A
g S n
A
ff = f! [&         a5  n
[+        SU
 3S	S9  U R#                  SS[        U
5      S.5         S n
A
g S n
A
ff = f! , (       d  f       GN@= f! [&         a(  n
U R#                  SS[        U
5      S.5         S n
A
g S n
A
ff = f! [&         a5  n
[+        SCU
 3S	S9  U R#                  SDS[        U
5      S.5         S n
A
g S n
A
ff = f! [&         a    U R#                  SSJSK05         g f = f! [&         a    U R#                  SSJSK05         g f = f)WNr  r  r  r   r  actionr   armTr   disarmFr   r)   takeoverrz   r*   returnconfig>	   r    r(   r&   r"   r!   r%   r#   r'   r$   zUnknown takeover actionr  i  r   r   z/api/crimeradar/importr2  )r   r  z[CRIMERADAR] Import failed: r0   r  rG   i  z$Sponsor upload is empty or too largemimeTypezUse a PNG, JPG, or WEBP imagebase64,zdata:rS   )validatez&Sponsor image must be 12 MB or smallerr$  r   r   r%  zInvalid start date/timezInvalid expiration date/timez'Expiration must be after the start timewb
durationMsrT  i  rJ  r  originalNamezSponsor Slider   rR  )
rG  r  r'  r0  r!  r9  r$  r%  r&  r    )r   slide/api/render/incident-videor  r  rA  rB  )r   r0  r2  duration_secondsrC  rD  bytesz[VIDEO] Render failed: r     apir  r   extendr   zInvalid JSONrG  r  r   r  zCall not foundr  r   r  r  )r   rG  	Not found):r   r  r  r  r  r   r   r   r4   r   rfiler   rC   r   r   r  rP   r  r   r9   r  r:   SPONSOR_MAX_BYTESSPONSOR_ALLOWED_MIMEr  r"  	b64decoderK  r   r   r   r   r   rM   r  uuiduuid4rL   r   r  r2   r  rZ   minr  r  r   r"  r6  rx  ri  r,  r  r  r   r  r  r  )#r  r  r  partslengthrT  r   r  r  r   r@   r   r  	mime_type	extensionencodedr"  image_bytesstart_atend_atr*  r+  
sponsor_idr0  r  r>   duration_msr   r!  call_idr  r  updatedr  r
  s#                                      rB   do_POSTHandler.do_POSTS  sk	   $))$##C(C&&s+ ?"))*:A>?FKJP$**TZZ__V%<%EFVX&(W[[28b9??AU?%)E'Nx'%*E'N/4E+,45E01z)/3E+,+DE-(x'/4E+,45E01+-E-(x' OG&>)0EJ  ' $%>??u%##C)B)DE ++))*:A>?F**//&)CK**S\E24W[[5GH##C()KL ?"))*:A>?F{f(9A(=>##C@f)gh**//&)C/K**S\E2J 7 =2>DDF	044Y?	 $%DEEgkk(39r:'>gmmo&;&;&=&H&H&Q&Q%mmC3A6G$..w.F"c+&69J&J$%MNN";;y1rX\\(,,5O5Y5Y5[5c5cdlnq5r W-5.x8,V4?$%>??em$%CDD$')9$%NOO .
%	1GGLLh?	)T*bHH[) +!'++l";"DuE!$E;(?@$ W!5!g^9T!gXghimjmn$'N(C(Ir$J4C$P ( )!)hll!;!E!E!G!O!OPXZ]!^'55gx||LVVX``aiknoot  pAX33E8<<HRRT\\]egjk  GK"-# &T"e$##C?RSW?X)YZ //))*:A>?F**//&)CK**S\E209##C (1H<(*!!WW__RWW\\:Lh-WX*   u:?uQx50U1X5HUSTXYaMaAhG$,,**+;Q?@Fjjoof-Czz# LEG55;')%)XXk155;M%NAkN"G	 
 5!##C$6  ##C'3C)DE<))*:A>?FZZ__V,Czz# 4 .T
4!YY[T
#}}-A4;;=QDLELLD!uDT
%CDC';!78O  K##CC)IJJK  K4SE:$G##CC)IJJKJ +*(  K##CC)IJJK&  K/u5TB##CC)IJJK  ##C'>)BC,  ##C'>)BCs   >Cf+ Af+ #Ag  #H4h4 h")F9h4 *Bi) "j+ k +
g5gg 
h*+hh"
h1,h4 4
i&>i!!i&)
j(3+j##j(+kkk0/k0c                    [        U R                  5      nUR                  R                  S5      R                  S5      n[	        U5      S:X  Ga  US   S:X  Ga  US   S:X  Ga  US   n[        5       nS n/ nU H0  nUR                  S5      U:X  a  Uc  UnM  UR                  U5        M2     Uc  U R                  S	S
SS.5        g [        U5        [        R                  R                  [        UR                  S5      =(       d    S5      5      nU(       a9   [        R                  " [        R                  R                  [        U5      5        U R                  SSUS.5        g [	        U5      S:X  a  US   S:X  ax  US   S:X  ao  US   n
['        5       n[	        U5      nU Vs/ s H  oR                  S5      U
:w  d  M  UPM     nn[)        U5        U R                  SSU[	        U5      -
  S.5        g U R                  S	SS05        g ! [          a     N["         a  n	[%        SU SU	 3SS9   S n	A	NS n	A	ff = fs  snf )Nr  r   r   r-  rS   r   rG   rG  r  FzSponsor slide not foundr   r0  r   z[SPONSOR] Could not remove z: Tr0   r  )r   removedr  r   r/  )r   r  r  r  rK  r  r   r   r  r"  rL   r4  r   remover   r  r8   r9   r:   r  r  )r  r  r7  r?  r!  rF  keptr   r0  r@   rA  r  beforer  s                 rB   	do_DELETEHandler.do_DELETE  s   $))$""3'--c2u:?uQx50U1X5KqJ!OEGD88D>Z/GO"GKK%	 
 ##C@Y)Z[$ww''GKK
,C,Ir(JKHWIIbggll;AB
 DZ%HIu:?uQx50U1X5HAhG lE%jF"'B%Q55;'+Aq%EBuDVc%j=P%QRC';!78 )   W7zC5IQUVW Cs*   8H &H>H>
H;	H;!H66H;c                 p    U R                  SS5        U R                  SS5        U R                  SS5        g )NzAccess-Control-Allow-Origin*zAccess-Control-Allow-MethodszGET, POST, DELETE, OPTIONSzAccess-Control-Allow-Headersr  )r  r  s    rB   r  Handler._cors&  s6    6=79UV7Hre   c                    [         R                  " U5      R                  5       nU R                  U5        U R	                  SS5        U R                  5         U R                  5         U R                  R                  U5        g )Nr  r   )	r4   r  r  r  r  r  r  r  r  )r  codeobjr  s       rB   r  Handler._json_response+  s^    zz#%%'4 );<



re   c                     U(       a;  [        U5      S:  a+  S[        US   5      ;   a  [        SUS    SUS    35        g g g g )NrG   z/api/r   z	[SERVER] u    → rS   )rK  r   r:   )r  fmtr@  s      rB   log_messageHandler.log_message3  sD    CINw#d1g,'>Id1gYeDG956 (?N4re   r   )r  r  r  r  r  r  rC  rJ  r  r  rU  r  r  r  s   @rB   r  r    s1    
IVl9\#9JI
7 7re   r  c                       \ rS rSrSrSrSrg)NWALThreadingHTTPServeri9  Tr   N)r  r  r  r  allow_reuse_addressdaemon_threadsr  r   re   rB   rX  rX  9  s    Nre   rX  c                  T   [         R                  " [         R                  R                  [         R                  R	                  [
        5      5      5        [        R                  " [        SS9n U R                  5         [        S[         S3SS9  [        SSS9  [        SSS9  [        SSS9  [        S	[         S
3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        S[         S3SS9  [        SSS9  [        S [         S3SS9  [        SSS9   [        S![        4[        5      n[        S)[         3SS9  UR!                  5         g ! [         aJ  n[        S"SS9  [        S#[         S$U 3SS9  [        S%[         S&3SS9  [        S'SS9  [        S(SS9  e S nAff = f)*NT)targetdaemonu6     [ALGO] AlgoTraffic poller started — polling every sr0   r   z  NWALScanner Broadcast Serverz+  -----------------------------------------z#  Broadcast map : http://localhost:z/stormtracker_outagewatch.htmlz#  Call entry    : http://localhost:z/nwals_combined_admin.htmlz#  Sponsors      : http://localhost:z/sponsor_manager.htmlz#  Calls API     : http://localhost:r  z#  Traffic API   : http://localhost:r  z#  Forecast API  : http://localhost:r  z#  Alerts API    : http://localhost:z"/api/alerts  [20-second NWS cache]z#  Outages API   : http://localhost:z$/api/outages  [Florence + Sheffield]z#  Lightning API : http://localhost:z8/api/lightning  [Hazcams primary / Spark + GLM fallback]z#  Video status  : http://localhost:r  z(  Incident video: POST http://localhost:r)  u}     ─────────────────────────────────────────z"  Tailscale: http://100.77.235.11:z0.0.0.0z  SERVER FAILED TO STARTz  Port z is already in use or blocked: z*  Fix: close the other process using port z$, or set NWALS_PORT to another port.z       set NWALS_PORT=9010z       python serve.pyz  SERVER LISTENING ON 0.0.0.0:)rL   chdirr  dirnameabspath__file__	threadingThreadr  startr:   r  r+  rX  r  OSErrorserve_forever)rq   serverr  s      rB   
run_serverri  >  s7   HHRWW__RWW__X678 	 0>AGGI	B;-q
QY]^	"D	
*$7	
7tD	/v5S
T\`a	/v5O
PX\]	/v5J
KSWX	/vZ
@M	/v\
B$O	/v]
C4P	/v5W
X`de	/v5Y
Zbfg	/v5m
nvz{	/v5G
HPTU	4TF:T
U]ab	  J  SW  X	.tf4N
OW[\	"D()T):GD 
*4&
1>
  (5v<QC@M:4&@demqr*$7&d3s   G 
H'AH""H'__main__)Fr  )__doc__r4   rL   r   r4  rc  urllib.requestr   rY  re  r)  r  http.serverr   r   rV  r   r   r   r   r  r	   html.parserr
   outage_sourcesr   r   environr   r+  r  r`  ra  rb  BASE_DIRr   RUNTIME_DIRmakedirsr  r  r   r  r  r  r,  rc  LockrW  r  r  r1  r3   rJ   r;   rC   rP   rd   r   r2  rr  rs  rt  ru  r   r   r   rZ   r   r   r   r   r   r   r   r  r   r  _weather_profiler   r   r   r  r  r  r  r  r  r   r  NWS_ALERT_STATEr  r  r   r  r  r  r  r  r  r  r  r  r  r  r"  r,  r6  r;  r@  rC  r   rX  r]  rb  r   r  r  r  r  r  r  r   r  r  r2  rx  rz  r  r  r  r  rX  ri  r  )r   s   0rB   <module>rw     sY   Y X X X X E * '  " ,"**..v6777??277??845ggoobjjnn-@"'',,xYbBcde K$ 'ggoobjjnn-?hXdAefg
jjnn-/[\

7OQSQXQXQ]Q]^fh  RA  )B  C ?y)WW\\+/CD   ." !(  ggll;
3 K$ 'ww||K9$ 
 [*CD! ^  MSj   wwrzz~~6Mrww||\df|O}'~  ggoobjjnn=VXZX_X_XdXdem  pM  YN  /O  P 
 GGLL/0GGLL45GGLL01!  GGLL67GGLL;<GGLL78#     
 

!5  "!S8[]a)b%cd !!S8[]`)a%bc #..* d 2@ *+ 44 !+ &**:w?@&**;ABc-//    NN$    )o))+t<=CCE>>OOwx .=.A.A+P\^gOh.ij.ic!flln.ij )8)<)<Z(T\I])^_)^AQ)^_"1"5"5kHhCW"XY"XQ#a&"XY  .." .."
4"
")XD	>*7r F0&f"
>3
nr l$
Dh(^9A
 9AxK3Pdt7& t7p1 
%N zL ]) k_Ys   3 Y-, Y2%Y7