ó
    %Ú¢jW   ã                   óÆ   • S r SSKrSSKJr  SSKJr  \R
                  " S5      r\R
                  " S5      rS	r\R                  S
   S    S3r
S rS rS rSS jrS rS rg)aÖ  
DealerKit reader.

Right Drive's DMS (2026-08-19), replacing Clickdealer. Reads the in stock
list for the daily stock count used by the gap / in stock / plenty flag on
the cockpit. bidbrain.readers.clickdealer.model_key is the shared matching
key (first token of make plus first token of model), reused unchanged so a
DealerKit "NISSAN QASHQAI" and a Motorway "Nissan Qashqai Tekna dCi" still
meet on the same key.

Nothing here bids or acts. It reads the screen only.
é    Né   )Úbrowseré   )Úclickdealerz$class="vehicle-title">([^<]+)</span>z/vehicles/(\d+)/overviewz1i.material-icons:has-text("keyboard_arrow_right")Ú	dealerkitÚbase_urlzk/vehicles?instance.life_cycle_status=10&instance.market=%22retail%22&instance.asset_class=%5B%22stock%22%5Dc                 óŠ  • 0 n/ n[        [        R                  U 5      5      n[        R                  U 5       H…  nUR	                  5       R                  SS5      n[        U5      S:  a  M4  US   US   pv[        R                  " Xg5      nU(       d  M\  UR                  US5      S-   X'   UR                  Xg45        M‡     XU4$ )aF  Parse one page of the Vehicles (in stock) list into {model_key: count}
plus the raw (make, model) pairs, and the set of vehicle ids on the page
(used by read_in_stock to know when pagination has run out, the page's
Next control is a plain span with no reliable disabled attribute to read,
so this is the robust signal instead). Returns (counts, pairs, ids).
Every vehicle-title is "MAKE MODEL...", the first word is always the
make (model_key only ever needs each side's first token anyway, so a
compound make like Mercedes-Benz still keys correctly without special
casing it here).Nr   r   r   )ÚsetÚVEHICLE_ID_REÚfindallÚTITLE_REÚstripÚsplitÚlenr   Ú	model_keyÚgetÚappend)	ÚhtmlÚcountsÚpairsÚidsÚtitleÚtoksÚmakeÚmodelÚkeys	            Ú;/Users/stevendouglas/BidBrain/bidbrain/readers/dealerkit.pyÚparse_stockr      sµ   € ð €FØ€EÜ
Œm×#Ñ# DÓ)Ó
*€CÜ×!Ñ! $Ö'ˆØ�{‰{‹}×"Ñ" 4¨Ó+ˆÜˆt‹9�q‹=ÙØ˜1‘g˜t A™wˆeÜ×#Ò# DÓ0ˆÞÙØ—j‘j  aÓ(¨1Ñ,ˆ‰Ø�‰�d�]Ö#ñ (ð ˜#ÐÐó    c           
      ó€  • U=(       d    0 nUR                  S5      =(       d    0 nUR                  S5      n[        U[        5      (       a  UR                  S5      OU=(       d2    UR                  S5      =(       d    UR                  S5      =(       d    SnSR                  [	        U5      R                  5       R                  5       5      nS nS nSSKJn  UR                  S	5      n	[	        U 5      UU" UR                  S
5      =(       d)    UR                  S5      =(       d    UR                  S
5      5      U" UR                  S5      =(       d    UR                  S5      5      [        U	[        5      (       a  UR                  U	5      OU" U	5      U" UR                  S5      5      UR                  S5      S.$ )aD  One in stock car as DealerKit's own stocklist record describes it
(2026-09-10, Steven: "Dealerkit is always the source of truth, the
paid price should never be not known"): the plate, make and model,
DealerKit's purchase cost and retail price, and its stage number.
Anything the record does not carry is None, never guessed.ÚvehicleÚregistrationÚvrmÚ c                 ó€   •  U b  U S:X  a  S $ [        [        [        U 5      5      5      $ ! [        [        4 a     g f = f)Nr$   )ÚintÚroundÚfloatÚ	TypeErrorÚ
ValueError©Úxs    r   Ú_numÚstock_record_row.<locals>._numD   s@   € ð	Ø™9¨¨R«�4ÐI´S¼¼uÀQ»x»Ó5IÐIøÜœ:Ð&ó 	Ùð	ús   ‚
* �* ª=¼=c                 ó  • [        U [        5      (       ab  U R                  S5      =(       dJ    U R                  S5      =(       d2    U R                  S5      =(       d    U R                  S5      =(       d    Sn U c  S$ [        U 5      $ )NÚnameÚlabelÚvaluer   r$   )Ú
isinstanceÚdictr   Ústrr+   s    r   Ú_textÚstock_record_row.<locals>._textI   s^   € ô �aœ×ÑØ—‘�f“×Y §¡ w£×Y°1·5±5¸³>×YÀQÇUÁUÈ7Ã^×YÐWYˆAØ‘YˆrÐ*¤C¨£FÐ*r   r   ©Údealerkit_writeÚpurchase_costr   Úmanufacturerr   Úretail_priceÚlife_cycle_status)Ú
vehicle_idÚregr   r   r:   r<   r=   )
r   r3   r4   Újoinr5   Úupperr   r$   r9   Úpurchase_cost_figure)
r>   ÚdataÚdÚvÚreg_objr?   r-   r6   r9   Úpcs
             r   Ústock_record_rowrH   9   sR  € ð 	�
�€AØ	�‰ˆiÓ×˜B€AØ�e‰e�NÓ#€GÜ!+¨G´T×!:Ñ!:ˆ7�;‰;�uÔÀ×
wÈAÏEÉEÐRWËL×
wÐ\]×\aÑ\aÐbpÓ\q×
wÐuw€CØ
�'‰'”#�c“(—.‘.Ó"×(Ñ(Ó*Ó
+€Còò
+õ #Ø	
�‰ˆÓ	€Bä˜*“oØÙ�a—e‘e˜F“m×M q§u¡u¨^Ó'<×MÀÇÁÀfÃÓNÙ�q—u‘u˜W“~×7¨¯©¨w«Ó8ô FPÐPRÔTX×EYÑEY˜×=Ñ=¸bÔAÑ_cÐdfÓ_gÙ˜QŸU™U >Ó2Ó3ØŸU™UÐ#6Ó7ñ
ð 
r   c           
      óª  • SSK Jn  / nSn[        U5       Hÿ  n UR                  X5      n[	        XV5      nU(       dÆ  [        UR                  S5      [        5      (       a¢  US   nUR                  S5      =(       d    0 R                  S5      =(       d    / n	[        S[        UR                  5       5       SU	(       a4  [        U	S	   [        5      (       a  [        U	S	   R                  5       5      OS
 SUS    35        SnUR                  U5        GM     U$ ! UR                   a    e [         a  n
[        SU SU
 35         Sn
A
GM7  Sn
A
ff = f)a  Read DealerKit's own record for every in stock vehicle id (the same
/api/stocklist read the stage check makes), for the purchase cost of
cars BidBrain never bought. A record that will not read is skipped
with a line, never the whole pass. Returns the rows read.r   r8   Fr:   ÚexpenseÚitemsz&  DealerKit purchase cost shape: keys z, first item r   Únonez
, read as Tz  DealerKit record z not read: N)r$   r9   ÚsortedÚread_recordrH   r3   r   r4   ÚprintÚkeysr   ÚDealerkitSessionExpiredÚ	Exception)Úpager   r9   ÚrowsÚshownÚvidrC   ÚrowrG   rK   Úes              r   Úread_stock_recordsrY   ^   s@  € õ
 #Ø€DØ€EÜ�cŽ{ˆð	=Ø"×.Ñ.¨tÓ9ˆDÜ" 3Ó-ˆCÞœZ¨¯©°Ó(AÄ4×HÑHð ˜/Ñ*�ØŸ&™& Ó+×1¨r×6Ñ6°wÓ?×FÀB�ÜÐ>¼vÀbÇgÁgÃiÓ?PÐ>Qð R$Þ?DÌÐTYÐZ[ÑT\Ô^b×IcÑIc¤F¨5°©8¯=©=«?Ô$;ÐioÐ#pð q!Ø!$ _Ñ!5Ð 6ð8ô 9ð �Ø�K‰K˜×ñ ð$ €Køð	 ×6Ñ6ó 	ØÜó 	=ÜÐ'¨ u¨K¸°sÐ;×<Ó<ûð	=ús   šC:DÄEÄ5EÅEc                 ó$  • [         R                  " U SUS9n UR                  (       a  UR                  S   OUR                  5       nUR	                  [
        SSS9   UR                  SSS	9  UR                  S5        [        U5      u  pVnU(       d  [        S5      eU(       a  XV[        XG5      4UR                  5         $ XV4UR                  5         $ ! [         a    [        S
UR                   S35      ef = f! UR                  5         f = f)zÛOpen DealerKit's in stock list (retail market, stock asset class, the
same filter as Mark's own Vehicles saved view) and return (counts,
pairs) across every page. Fails loudly if the list does not render,
never guesses.r   )Úheadlessr   Údomcontentloadedi`ê  )Ú
wait_untilÚtimeoutz.vehicle-titlei0u  ©r^   zFDealerKit stock list did not render any vehicles (no vehicle-title at zb). The page may have changed or the login may have expired. Run: python3 login.py dealerkit manualiè  zgDealerKit stock list rendered but no vehicle rows were read. The layout may have changed, not guessing.)r   Úopen_reader_contextÚpagesÚnew_pageÚgotoÚ	STOCK_URLÚwait_for_selectorrR   ÚRuntimeErrorÚurlÚwait_for_timeoutÚread_all_pages_with_idsrY   Úclose)Ú
playwrightr[   Úwith_recordsÚctxrS   r   r   r   s           r   Úread_in_stockrn   {   s
  € ô
 ×
%Ò
% j°+ÈÑ
Q€CðØ"ŸyŸyˆs�y‰y˜Š|¨c¯l©l«nˆØ�	‰	”)Ð(:ÀEˆ	ÑJð	Ø×"Ñ"Ð#3¸UÐ"ÑCð 	×Ñ˜dÔ#Ü4°TÓ:Ñˆ�sÞÜð=óð ö ØÔ"4°TÓ"?Ð?ð 	�	‰	�ð ˆ}à�	‰	�øô# ó 	Üð(Ø(,¯© zð 2`ð`óð ð	ûð" 	�	‰	�ús+   ˜AC= ÁC Á.AC= ÃC= Ã$C:Ã:C= Ã=Dc                 ó$   • [        U 5      u  pnX4$ )z?(counts, pairs) across every page, see read_all_pages_with_ids.)ri   )rS   r   r   Ú_idss       r   Úread_all_pagesrq   š   s   € ä1°$Ó7Ñ€F�4Øˆ=Ðr   c                 óÚ  • 0 n/ n[        5       n[        S5       H¹  nU R                  5       n[        U5      u  pgnXƒ-
  n	U	(       d	  U(       a    OˆX8-  nUR	                  5        H  u  p«UR                  U
S5      U-   X'   M     UR                  U5        U R                  [        5      nU(       d    O% UR                  SS9  U R                  S5        M»     XU4$ ! [         a       M  f = f)a‡  Accumulate {model_key: count} and (make, model) pairs across every
page of the in stock list, from an already open, already logged in,
already navigated page (the caller owns the page and its context, the
same shape as Carwow's and Auction4Cars' read_all_pages, so an on demand
refresh pass that already has a headed, logged in page open can reuse
this rather than only ever reading page 1).é2   r   i¸  r_   iÜ  )r
   ÚrangeÚcontentr   rK   r   ÚextendÚquery_selectorÚNEXT_PAGE_SELÚclickrR   rh   )rS   r   r   Úseen_idsÚ_r   Úpage_countsÚ
page_pairsr   Únew_idsÚkÚnÚnxts                r   ri   ri       så   € ð €FØ€EÜ‹u€HÜ�2ŽYˆØ�|‰|‹~ˆÜ'2°4Ó'8Ñ$ˆ Ø‘.ˆÞž8ÙØ‰ˆØ×%Ñ%Ö'‰DˆAØŸ
™
 1 aÓ(¨1Ñ,ˆF‹Iñ (à�‰�ZÔ à×!Ñ!¤-Ó0ˆÞÙð	Ø�I‰I˜dˆIÑ#ð 	×Ñ˜dÖ#ñ% ð& ˜(Ð"Ð"øô ó 	Ûð	ús   Â3CÃ
C*Ã)C*)TF)Ú__doc__Úrer$   r   r   Úcompiler   r   rx   ÚSITESrd   r   rH   rY   rn   rq   ri   © r   r   Ú<module>r‡      sy   ðñó 
Ý Ý à�:Š:Ð=Ó>€Ø—
’
Ð6Ó7€ØC€ð —‘˜kÑ*¨:Ñ6Ð7ð 86ð 6€	ò
ò4"òJô:ò>ó#r   