Ë
    ßœÐjñ2  ã            	       ó   — d Z ddlZddlZddlZddlZej
                  j                  ej
                  j                  ej
                  j                  ej
                  j                  e«      «      «      «      Z	ej
                  j                  dej
                  j                  e	d«      «       ddlZd„ Zd„ Zd„ Zdd„Zd„ Zed	k(  r‡ eej
                  j                  ej&                  d
   «       eej&                  «      dkD  rej&                  d   nd«      Z e ej.                  ed
¬«      «        ej0                  ed   rdnd
«       yy)aÏ  Contract check of an Astra vehicle GLB (cars, buses, motorbikes, bicycles) before it becomes a card.
usage: python3 tools/vehicles/check_vehicle.py <job_dir> [<glb>]   -> prints JSON {ok, errors, warnings, facts}; exit 1 on errors.
Checks: required node names, wheels on the right side/end (+X = left, +Z = front), wheel origins at hub height, tyres on
y = 0, Paint material with a factor (recolour contract), Glass/Lamps materials, size against job.json, budget.é    NÚlibc                 óÂ   ‡ ‡‡— i Šˆ ˆˆfd„Šg d¢g d¢g d¢g d¢g}‰ j                  di g«      ‰ j                  dd«         j                  d	g «      D ]  } ‰||«       Œ ‰S )
z4{name: (world position, node index)} for every node.c                 ó4  •— ‰d   |    }t        j                  |t        j                  |«      «      }t        d«      D �cg c]  }t	        ||   d   d«      ‘Œ c}| f‰|j                  dd| › �«      <   |j                  dg «      D ]  } ‰||«       Œ y c c}w )NÚnodesé   ÚnameÚnodeÚchildren)ÚglbÚ_mulÚ_matÚrangeÚroundÚget)	ÚiÚparentÚnÚmÚrÚcÚdocÚoutÚwalks	         €€€úK/home/claude-agent/forge-build/forge-assets/tools/vehicles/check_vehicle.pyr   zworld_nodes.<locals>.walk   s�   ø€ Ø�‰L˜‰OˆÜ�H‰H�VœSŸX™X a›[Ó)ˆÜFKÈAÃhÖ*OÀ¬5°°1±°a±¸!Õ+<Ò*OÐQRÐ)SˆˆA�E‰E�&˜D  ˜*Ó%Ñ&Ø—‘�z 2Ó&ò 	ˆAÙ��A�Jñ	ùò +Ps   Á B)é   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   ÚscenesÚscener   r   ©r   )r   ÚidentÚsr   r   s   `  @@r   Úworld_nodesr!      sd   ú€ à
€Cöò š<ª²|ÐD€EØ�W‰W�X ˜tÓ$ S§W¡W¨W°aÓ%8Ñ9×=Ñ=¸gÀrÓJò ˆÙˆQ��ðà€Jó    c                 óÞ   — t        «       t        | d   |   j                  dg «      «      }}|r?|j                  «       }|j	                  |«       || d   |   j                  dg «      z  }|rŒ?|S )Nr   r
   )ÚsetÚlistr   ÚpopÚadd)r   r   r   ÚstackÚks        r   Ú_descr*      sg   € Ü“œ˜S ™\¨!™_×0Ñ0°¸RÓ@ÓAˆ€CÙ
Ø�I‰I‹Kˆ˜Ÿ™ œ U¨c°'©l¸1©o×.AÑ.AÀ*ÈbÓ.QÑ%Q Uò à€Jr"   c                 óf   — t        j                  d| «      D �cg c]  }t        |«      ‘Œ c}S c c}w )Nz(\d+(?:\.\d+)?) m\b)ÚreÚfindallÚfloat)ÚtextÚxs     r   Únumsr1   !   s&   € Ü Ÿj™jÐ)?ÀÓFÖG˜ŒE�!�HÒGÐGùÒGs   ™.c                 ó  ‡‡1‡2‡3‡4‡5— t        j                  t        | › d�«      «      }|xs | › d|d   › d�}t        j                  |«      d   Š1t        j
                  |«      }t        ‰1«      Š4t        ‰4«      }|j                  d«      }|dv }g g }}|dv }	g d	¢g d
¢g d¢ddgg d¢dœj                  |g d¢«      }
|j                  d«      dk(  r#g d¢}
ddh|k  sh d£|k  s|j                  d«       |
D ]  }||vsŒ|j                  d|› �«       Œ |dk(  rddh|k  sddh|k  s|j                  d«       d}‰4j                  «       D �]  \  }\  }}‰1d    |   }t        j                  ||«      r|j                  d!«      €Œ:‰1d"   |d!      d#   D �cg c]  }d$|d%   v sŒ‰1d&   |d%   d$      ‘Œ }}t        d'«      D �‡cg c]  Št        ˆfd(„|D «       «      ‘Œ c}Š3t        d'«      D �‡cg c]  Št        ˆfd)„|D «       «      ‘Œ c}Š2d*t        d+„ t!        ‰2‰3«      D «       «      z  d,z   Š5t#        ˆ2ˆ3ˆ5fd-„t        d'«      D «       «      r�Œ|j                  |› d.�«       �Œ d/|d0   v rd1|vr|j                  d2«       |d3k(  r3d4|v r/d|v r+‰4d   d5   t%        ‰1‰4d4   d5   «      vr|j                  d6«       |rKd7|v rGd8|v rC‰4d8   d5   }‰1d    |   j                  d9g «      }‰4d7   d5   |vr|d   d:k7  r|j                  d;«       ‰4j                  «       D ���ci c]"  \  }\  }}t        j                  d<|«      sŒ ||“Œ$ }}}}‰4j                  «       D ���ci c]"  \  }\  }}t        j                  d=|«      sŒ ||“Œ$ }}}}|j                  «       D ][  \  }}|d>   d?k(  r"|d   dk  r|j                  |› d@|d   › dA�«       |d>   dBk(  sŒ9|d   dk\  sŒB|j                  |› dC|d   › dA�«       Œ] |d3k(  r+t'        |«      d>k  r|j                  t'        |«      › dD�«       |j                  «       D �]3  \  }}t'        |«      dEkD  r|dF   ndG}|j)                  dH«      d5   }|j+                  dI«      r"|dJ   dk  r|j                  |› dK|dJ   › dA�«       |j+                  dB«      r"|dJ   dk\  r|j                  |› dL|dJ   › dA�«       |sM|dMv r"|d   dk  r|j                  |› d@|d   › dA�«       |dNv rN|d   dk\  rF|j                  |› dC|d   › dA�«       n+t-        |d   «      d*kD  r|j                  |› dO|d   › dA�«       |d5   dPk  s�Œ|j                  |› dQ|d5   › dA�«       �Œ6 |r`|	r^|j/                  «       D �cg c]  }|dJ   ‘Œ	 }}t        |«      t        |«      z   dJz  }t-        |«      dRkD  r|j                  dS|dT›dA�«       |dU   }t-        |dV   d5   «      dWkD  r|j                  dX|dV   d5   dT›dY�«       ‰1j                  dZg «      D �ci c]  }|j                  d[dG«      |“Œ }}|j                  d\«      } | s|j                  d]«       nA| j                  d^i «      }!|!j                  d_g d`¢«      }"|"d d' g da¢k(  r|j                  db«       |j                  dc«      xs dd|j                  d dG«      v }#|devr|#sdf|vr|j                  dg«       dh|vr|dik7  r|j                  dj«       t'        |«      |dk   d5z   kD  r#|j                  t'        |«      › dl|dk   › dA�«       t1        |dm   «      }$|dn   dJ   }%|dn   d   }&|dn   d5   }'|$rÄt-        |%|$d   z
  «      |$d   z  dRkD  r#|dk(  r|n|j                  do|%dp›dq|$d   › dr�«       t        j2                  ds|dm   «      }(|(rlt-        |'t5        |(j7                  d5«      «      z
  «      t5        |(j7                  d5«      «      z  dtkD  r(|j                  du|'dp›dq|(j7                  d5«      › dr�«       t9        t        j:                  dv|dw   «      dF   «      dxz  })|dw   |)dyz  kD  r|j                  |dw   › dz|dw   › �«       |d{   D �*cg c]4  }*t        |*j                  d|d«      |*j                  d}d«      «      d~kD  sŒ3|*‘Œ6 }+}*|+r|j                  t'        |+«      › d�«       g },t<        j>                  jA                  | › d€�«      r5	 t        j                  t        | › d€�«      «      j                  d�«      xs g },t'        |,«      dƒk  r|j                  t'        |,«      › d„�«       d }.|j                  d…«      r/tE        | |‰1‰4|«      }.|.d†   d>k  r|j                  d‡|.d†   › dˆ�«       tG        tI        |&d'«      tI        |'d'«      tI        |%d'«      g|dw   tK        |«      t'        |d{   «      tI        |d‰   d5«      tI        |dŠ   d‹z  dJ«      |t'        |,«      tK        ˆ1ˆ4fdŒ„|D «       «      ¬�«	      }/tG        |d   | |||/¬Ž«      }0|.r|.|0d…<   |0S c c}w c c}w c c}w c c}}}w c c}}}w c c}w c c}w c c}*w # tB        $ r}-|j                  d‚|-› �«       Y d }-~-�Œ_d }-~-ww xY w)�Nz	/job.jsonú/Úslugz.glbr   Úfamily)ÚmotosÚbikes)ÚcarsÚbusesÚwheeled)	ÚFrameÚForkÚWheel_FÚWheel_RÚ
Seat_RiderÚHand_LÚHand_RÚFoot_LÚFoot_R)r;   r<   r=   r>   r?   r@   rA   rB   rC   ÚCrankÚPedal_LÚPedal_R)ÚHullÚTurretÚGunÚTrack_LÚTrack_RÚMuzzleÚFuselageÚ
Seat_Pilot)rM   Ú	Gear_NoseÚGear_LÚGear_RrN   )r6   r7   ÚtanksÚrotorÚjets)ÚBodyÚWheel_FLÚWheel_FRÚWheel_RLÚWheel_RRÚSteeringWheelÚSeat_DriverÚlayoutÚ
turretless)rG   rJ   rK   rI   rL   >   ÚGun_LÚGun_RÚMuzzle_LÚMuzzle_Rz4no Gun + Muzzle (or Gun_L/Gun_R + Muzzle_L/Muzzle_R)zmissing node rS   Ú	MainRotorÚ	TailRotorÚRotor_FrontÚ
Rotor_Rearz6no MainRotor + TailRotor (or Rotor_Front + Rotor_Rear)zx(MainRotor|TailRotor|Rotor_Front|Rotor_Rear|Rotodome|Turret|Gun|Gun_[LR]|Gun_Hull|Barrel|MG|MG_\d+|Wheel_\w+|Fork|Crank)r   ÚmeshÚmeshesÚ
primitivesÚPOSITIONÚ
attributesÚ	accessorsr   c              3   ó.   •K  — | ]  }|d    ‰   –— Œ y­w)ÚminN© ©Ú.0Úar)   s     €r   ú	<genexpr>zcheck.<locals>.<genexpr>G   s   øè ø€ Ò+ !�!�E‘(˜1•+Ñ+ùó   ƒc              3   ó.   •K  — | ]  }|d    ‰   –— Œ y­w)ÚmaxNrn   ro   s     €r   rr   zcheck.<locals>.<genexpr>G   s   øè ø€ ÒIcÐZ[È!ÈEÉ(ÐSTÍ+ÑIcùrs   çš™™™™™©?c              3   ó,   K  — | ]  \  }}||z
  –— Œ y ­w©Nrn   )rp   ÚhÚls      r   rr   zcheck.<locals>.<genexpr>H   s   è ø€ Ò7¡4 1 a˜˜Q�Ñ7ùs   ‚g{®Gáz”?c              3   óV   •K  — | ]   }‰|   ‰z
  d cxk  xr ‰|   ‰z   k  nc –— Œ" y­w)r   Nrn   )rp   r)   ÚhiÚloÚpads     €€€r   rr   zcheck.<locals>.<genexpr>I   s.   øè ø€ ÒE°q�2�a‘5˜3‘; !Ö2 r¨!¡u¨s¡{×2Ð2ÑEùs   ƒ&)z] origin is outside its own geometry (pivot not on the part: it will orbit instead of turning)ÚawacsÚidÚRotodomezmissing node RotodomerR   rH   r   zDGun is not under Turret (turret traverse would leave the gun behind)r=   r<   r
   z
cargo-bikezBWheel_F is not a child of Fork (steering will not carry the wheel)zWheel_(F|R|FL|FR|RL|RR|RL2|RR2)zWheel_[LR]\d+é   ÚLz not on +X (left) side (x=ú)ÚRz not on -X (right) side (x=z/ track wheels as nodes (Wheel_L1.., Wheel_R1..)é   éÿÿÿÿÚ Ú_ÚFé   z not at the front (z=z not at the rear (z=)ÚFLÚRLÚRL2)ÚFRÚRRÚRR2z off the centre line (x=gš™™™™™¹?z origin not at the hub (y=ç{®Gáz´?z1origin not midway between axles (axle midpoint z=z.3fÚboundsrm   g¸…ëQ¸ž?zlowest point y=z (tyres should touch 0)Ú	materialsr   ÚPaintz+no material named Paint (recolour contract)ÚpbrMetallicRoughnessÚbaseColorFactor)r   r   r   r   )r   r   r   zDPaint baseColorFactor is white: default colour baked in the texture?Úopen_cockpitzOPEN-COCKPIT)r6   r7   rR   ÚGlasszno material named GlassÚLampsr7   zno material named LampsÚmatsz materials (budget ÚsizeÚsize_xyzzlength z.2fz m vs asked z mz(\d+(?:\.\d+)?) m highg¸…ëQ¸¾?zheight z(\d+)kÚtrisiè  gÍÌÌÌÌÌô?z tris over budget ÚtexturesÚwry   i   z( textures above 1024 px (pack caps them)z/nodes.jsonÚpaintsznodes.json unreadable: é   z paints in nodes.json (asked 6)ÚdamageÚpartszonly z4 Part_ nodes (bolt-on items must be their own nodes)Úgpu_mb_decodedÚbytesç    €„.Ac              3   ó^   •K  — | ]$  }‰d    ‰|   d      j                  d«      �Œ!|–— Œ& y­w)r   r   rf   Nr   ©rp   r   r   r   s     €€r   rr   zcheck.<locals>.<genexpr>Ž   s3   øè ø€ Òb a°C¸±LÀÀqÁÈ!ÁÑ4M×4QÑ4QÐRXÓ4YÑ4a¤Ñbùs   ƒ"-¦-)	rœ   rž   r”   rŸ   Úgpu_mbÚmbÚwheelsr¡   Úempties)r4   ÚokÚerrorsÚwarningsÚfacts)&ÚjsonÚloadÚopenr   ÚreadÚmeasurer!   r$   r   ÚappendÚitemsr,   Ú	fullmatchr   rm   ru   ÚzipÚallr*   ÚlenÚsplitÚ
startswithÚabsÚvaluesr1   Úsearchr.   ÚgroupÚintr-   ÚosÚpathÚexistsÚ	ExceptionÚcheck_damageÚdictr   Úsorted)6ÚjdÚfÚjr   ÚnamesÚfamÚtwoÚerrÚwarnÚfourÚneedr   ÚMOVINGÚnmr‰   r   ÚndÚprÚaccr)   Úfork_iÚkidsÚpr¬   ÚtwÚsideÚtagÚzsÚmidÚbÚmtr›   ÚpaintÚpbrÚfacr˜   Úszrƒ   ÚWÚHÚhmÚtmaxÚtÚbigr¡   ÚeÚdmgr±   r   r   r|   r}   r   r~   s6                      `                             @@@@@r   Úcheckrð   %   s(  ý€ Ü�	‰	”$˜"˜˜YÐ'Ó(Ó)€AØ	Ò$�ˆt�1�Q�v‘Y�K˜tÐ$€AÜ
�(‰(�1‹+�a‰.€CÜ�‰�A‹€AÜ˜Ó€EÜ�‹J€EØ
�%‰%�‹/€CØ
Ð#Ð
#€CØ�Bˆ€CØÐ.Ð.€DÚrò RÚNØ  ,Ð/ÚOñ	÷
 ‰c�#ÒoÓpð 	ð 	‡u�uˆXƒ˜,Ò&Ú-ˆØ˜Ð! UÒ*Ò.XÐ\aÒ.aØ�J‰JÐMÔNØò ;ˆØ�EŠ>˜3Ÿ:™:¨°a°SÐ&9Õ:ð;à
ˆg‚~ ¨[Ð9¸UÒBÀ}ÐVbÐFcÐglÒFlØ�
‰
ÐKÔLð I€FØ—k‘k“mó }‰
ˆ‰FˆQ�Ø�‰\˜!‰_ˆÜ�|‰|˜F BÔ'¨2¯6©6°&«>Ð+AØØHKÈHÉÐVXÐY_ÑV`ÑHaÐbnÑHoö  SÀ"Ðs}ð  BDð  EQñ  BRò  tRˆs�;Ñ  <Ñ 0°Ñ <Ó=ð  Sˆð  SÜ5:¸1³X×>°ŒcÓ+ sÔ+Õ+Ò>ˆÔmrÐstÓmu×EvÐhiÄcÓIcÐ_bÔIcÕFcÒEvÀØ”SÑ7¬3¨r°2«;Ô7Ó7Ñ7¸$Ñ>ˆÜÕE¼EÀ!»HÔEÖEØ�J‰J˜"˜ÐzÐ{Ö|ð}ð �!�D‘'Ñ˜j°Ñ5Ø�
‰
Ð*Ô+Ø
ˆg‚~˜( eÑ+°¸±À5ÈÁ<ÐPQÁ?ÔZ_Ð`cÐejÐksÑetÐuvÑewÓZxÑCxØ�
‰
ÐYÔZÙ
ˆy˜EÑ! f°¡oØ�v‘˜qÑ!ˆØ�7‰|˜FÑ#×'Ñ'¨
°BÓ7ˆØ�Ñ˜AÑ dÑ*¨q°©y¸LÒ/HØ�K‰KÐ\Ô]Ø$)§K¡K£M×iÐi‘y�q™&˜1˜a´R·\±\ÐBdÐfgÕ5hˆa�‰dÐi€FÒiØ %§¡£×	SÐ	S‘9�1‘f�q˜!´·±Ð>NÐPQÕ1Rˆ!ˆQ‰$Ð	S€BÒ	SØ—‘“
ò [‰ˆˆ1ØˆQ‰4�3Š;˜1˜Q™4 1š9 c§j¡j°A°3Ð6PÐQRÐSTÑQUÐPVÐVWÐ1XÔ&YØˆQ‰4�3‹;˜1˜Q™4 1›9 c§j¡j°A°3Ð6QÐRSÐTUÑRVÐQWÐWXÐ1YÕ&Zð[ð ˆg‚~œ#˜b›' Aš+ t§{¡{´c¸"³g°YÐ>mÐ3nÔ'oØ—‘“ó 	K‰ˆˆ1Ü˜A› š
ˆq�Šu¨ˆØ�g‰g�c‹l˜1‰oˆØ�>‰>˜#Ô 1 Q¡4¨1¢9¨c¯j©j¸A¸3Ð>SÐTUÐVWÑTXÐSYÐYZÐ9[Ô.\Ø�>‰>˜#Ô 1 Q¡4¨1¢9¨c¯j©j¸A¸3Ð>RÐSTÐUVÑSWÐRXÐXYÐ9ZÔ.[ÙØÐ)Ñ)¨a°©d°aªi¸¿¹ÀqÀcÐIcÐdeÐfgÑdhÐciÐijÐDkÔ9lØÐ)Ñ)¨a°©d°aªi¸¿¹ÀqÀcÐIdÐefÐghÑeiÐdjÐjkÐDlÕ9mÜ��1‘‹Y˜Ò˜tŸ{™{¨a¨SÐ0HÈÈ1ÉÈÈaÐ+PÔQØˆQ‰4�#Œ:�s—z‘z Q CÐ'AÀ!ÀAÁ$ÀÀqÐ"IÖJð	Kñ ‘$Ø"ŸM™M›OÖ,�qˆa�‹dÐ,ˆÐ,Ü�2‹wœ˜R›Ñ  AÑ%ˆÜˆs‹8�dŠ?˜DŸK™KÐ*[Ð\_Ð`cÐ[dÐdeÐ(fÔgØ	ˆ(‰€AÜ
ˆ1ˆU‰8�A‰;Ó˜$Ò §¡¨o¸aÀ¹hÀq¹kÈ#Ð=NÐNeÐ,fÔ gØ-0¯W©W°[À"Ó-EÖF rˆB�F‰F�6˜2Ó Ñ"ÐF€DÐFØ�H‰H�WÓ€EÙØ�
‰
Ð@ÕAà�i‰iÐ.°Ó3ˆØ�g‰gÐ'ªÓ6ˆØˆr�ˆ7’iÒ §¡Ð-sÔ!tØ—5‘5˜Ó(ÒP¨N¸a¿e¹eÀGÈRÓ>PÐ,P€LØ
Ð-Ñ-±lÀwÐVZÑGZÐ\_×\fÑ\fð  hAô  ]BØ�dÑ˜s gš~¨t¯{©{Ð;TÔ/UÜ
ˆ4ƒy�1�V‘9˜q‘=Ò  $§+¡+´°T³°Ð;NÈqÐQWÉyÈkÐYZÐ.[Ô"\Ü	ˆa�‰i‹€BØ	ˆ*‰�aÑ€A˜a 
™m¨AÑ.˜!°A°j±MÀ!Ñ4D°Ù	Üˆq�2�a‘5‰y‹>˜B˜q™EÑ! DÒ(Ø˜G’^‰T¨×4Ñ4°w¸qÀ¸gÀ\ÐRTÐUVÑRWÐQXÐXZÐ5[Ô\Ü�Y‰YÐ0°!°F±)Ó<ˆÙ”#�aœ% §¡¨£Ó,Ñ,Ó-´°b·h±h¸q³kÓ0BÑBÀTÒIÈ4Ï;É;ÐY`ÐabÐcfÐ`gÐgsÐtv×t|Ñt|Ð}~Ótð  tAð  ACð  XDô  LEÜŒr�z‰z˜) Q v¡YÓ/°Ñ3Ó4°tÑ;€DØˆ�y�4˜#‘:Ò˜tŸ{™{¨a°©i¨[Ð8JÈ1ÈVÉ9È+Ð+VÔWØ˜
‘mÖ
P�¤s¨1¯5©5°°a«=¸!¿%¹%ÀÀQ»-Ó'HÈ4Ó'OŠ1Ð
P€CÐ
PÙ
ˆD�K‰Kœ3˜s›8˜*Ð$LÐMÔNØ€FÜ	‡w�w‡~�~˜˜˜KÐ(Ô)ð	7Ü—Y‘Yœt r d¨+Ð$6Ó7Ó8×<Ñ<¸XÓFÒLÈ"ˆFô ˆ6ƒ{�Q‚˜Ÿ™¤s¨6£{ mÐ3RÐ$SÔTØ
€CØ‡u�uˆX„Ü˜2˜q # u¨aÓ0ˆØˆw‰<˜!Ò˜SŸZ™Z¨%°°G±¨~Ð=qÐ(rÔsÜ”u˜Q “{¤E¨!¨Q£K´°q¸!³Ð=ÀAÀfÁIÔY_Ð`dÓYeÔpsÐtuð  wAñ  uBó  qCÜ˜aÐ 0Ñ1°1Ó5¼%ÀÀ'Á
ÈSÑ@PÐRSÓ:TÐ]cÔloÐpvÓlwÜÔb¨5ÔbÓbôd€Eô �A�f‘I c '°#ÀÈEÔ
R€CÙ
˜CˆC�‰MØ€JùòW SùÚ>ùÒEvùô jùÜ	Sùò  -ùò
 Gùò* Qøô ò 	7Ø�K‰KÐ1°!°Ð5×6Ò6ûð	7ús`   Æh,Æh,Æ?h1Ç+h6Ì!h;Ì:h;Í!iÍ9iÕ=i	Øiá)4iâiã(4i é	j é!i;é;j c                 ó¤	  ‡‡‡‡— g g }}|j                  d«      dk(  }t        ˆˆfd„‰D «       «      }d|j                  dd«      v }	t        |«      |	rdndk  r$|j                  t        |«      › d	|	rdnd› d
�«       dD ]  }
|
‰vsŒ|j                  d|
› �«       Œ d‰vr|s|j                  d«       | › d|d   › d�}dg|rdgng z   }t        j
                  j                  |«      st        dt        |«      ddg||¬«      S t        j                  |«      d   Št        ‰«      Št        j                  |«      }‰j                  di g«      ‰j                  dd«         j                  dg «      D �cg c]  }‰d   |   j                  d«      ‘Œ }}g d¢|rg ndgz   }|D ]5  }
|
‰vr|j                  d|
› �«       Œ|
|vsŒ!|j                  d|
› d�«       Œ7 dMd „}d!‰v rd!nd"}d#|fg|rg nd$d%gz   }|D ]O  \  }}|‰v sŒ|‰v sŒ |‰|   d   ‰|   d   «      rŒ&|j                  d|› d&‰|   d   › d'|› d(‰|   d   › d)�	«       ŒQ d*D ]7  }
|
‰v sŒ |‰|
   d   g d+¢«      rŒ|j                  d|
› d,‰|
   d   › d
�«       Œ9 t        ˆˆfd-„‰D «       «      }|D �cg c]  }d.|d/d0 z   ‰vsŒ|‘Œ }}|r"|j                  t        |«      › d1|d0d/ › �«       |D �cg c],  }d.|d/d0 z   ‰v sŒ |‰|   d   ‰d.|d/d0 z      d   d2«      rŒ+|‘Œ. }}|r"|j                  t        |«      › d3|d0d/ › �«       t        |«      d4k  r|j                  t        |«      › d5�«       t        d6„ ‰D «       «      }d7D �
cg c]  }
|
‰vr|
‘Œ
 }}
|r#|j                  dd8j                  |«      › �«       |d9   d:kD  r|j                  d;|d9   › d<�«       d=‰j                  d>g «      D �ch c]  }|j                  d«      ’Œ c}vr|j                  d?«       |s|r|s|j                  d@«       dA‰v rdB‰v r|j                  dC«       d#‰v r|j                  dD«       dE‰v r|sd‰v r|j                  dF«       t        | t        |«      t        |«      t        |«      ||||d9   t        |dG   dHz  dI«      t        |dJ   dK«      ¬L«
      S c c}w c c}w c c}w c c}
w c c}w )Na4  tank-damage/v1: Part_ nodes in the healthy file + <slug>-damage.glb (Hull_Damage, Turret_Damage, Wreck_Hull,
    Wreck_Turret). Returns {ok, parts, twins, errors, warnings, states}: a tank with a broken damage file still gets its
    card (healthy contract), the card lists only the states that really exist.r\   r]   c              3   ó‚   •K  — | ]6  }|j                  d «      sŒ‰d   ‰|   d      j                  d«      €Œ3|–— Œ8 y­w)ÚPart_r   r   rf   N©r¾   r   r©   s     €€r   rr   zcheck_damage.<locals>.<genexpr>š   s@   øè ø€ Òs˜ q§|¡|°GÕ'<ÀÀWÁÈeÐTUÉhÐWXÉkÑAZ×A^ÑA^Ð_eÓAfÑAr”1Ñsùó   ƒ?š?¸?z
Small tankr   rˆ   é
   é   z Part_ nodes (asked r„   )Ú	Fx_EngineÚFx_AmmoÚHatch_Commanderzmissing ÚBarrelzno Barrel node (recoil)r3   r4   z-damage.glbÚhealthyÚstrippedFr   zno damage file)r®   r¤   Útwinsr¯   r°   Ústatesr   r   r   )ÚHull_DamageÚTurret_DamageÚ
Wreck_HullÚWreck_Turretzdamage file: missing zdamage file: z is not a top-level nodec                 ó@   ‡— t        ˆfd„t        | |«      D «       «      S )Nc              3   óF   •K  — | ]  \  }}t        ||z
  «      ‰k  –— Œ y ­wrx   )r¿   )rp   r0   ÚyÚtols      €r   rr   z-check_damage.<locals>.near.<locals>.<genexpr>ª   s"   øè ø€ Ò(Q¹t¸qÀ!¬¨Q°©U«°sÕ):Ñ(Qùs   ƒ!)r»   rº   )rq   râ   r  s     `r   Únearzcheck_damage.<locals>.nearª   s   ø€ ¤SÓ(QÄsÈ1ÈaÃyÔ(QÓ%QÐQr"   rI   r^   Ú
Gun_Broken)r  rH   )r  rH   z at z but z is at z (they must share the pivot))r   r  )r   r   r   z not at the origin (c              3   ó‚   •K  — | ]6  }|j                  d «      sŒ‰d   ‰|   d      j                  d«      €Œ3|–— Œ8 y­w)ÚDmg_r   r   rf   Nrô   )rp   r   ÚddÚdns     €€r   rr   zcheck_damage.<locals>.<genexpr>²   s>   øè ø€ Òk˜ A§L¡L°Õ$8¸RÀ¹[ÈÈAÉÈqÉÑ=R×=VÑ=VÐW]Ó=^Ñ=j”1Ñkùrõ   ró   r¢   Nz- Dmg_ twins without a Part of the same name: r’   z& Dmg_ twins not at their Part origin: r‚   z Dmg_ twins (asked 11)c              3   óD   K  — | ]  }|j                  d «      sŒ|–— Œ y­w)ÚScar_N)r¾   )rp   r   s     r   rr   zcheck_damage.<locals>.<genexpr>¸   s   è ø€ Ò:˜ A§L¡L°Õ$9”1Ñ:ùs   ‚ ™ )ÚScar_Hull_FrontÚScar_Hull_LÚScar_Hull_RÚScar_Hull_RearÚScar_Turret_FrontÚScar_Turret_LÚScar_Turret_RÚScar_Turret_RearÚTrack_L_BrokenÚTrack_R_Brokenr	  z, rž   g    ÀtAzdamage file z tris (budget 110k)ÚBurntr”   z$damage file: no material named BurntÚhitr  r  Úimmobilisedzgun-outr  Úwreckr¦   r§   r‹   r¥   r   )
r®   r¤   rþ   Úscarsr¯   r°   rÿ   rž   r«   rª   )rv   )r   rÊ   r¼   r·   rÄ   rÅ   rÆ   rÉ   r   rµ   r!   r¶   Újoinr   )rË   rÍ   r   r   r   rî   r    r]   r¤   Úsmallr   rÌ   rÿ   Údmr   ÚtopÚwant_topr  Úbase_gunÚpairsrq   râ   rþ   rì   ÚloneÚoffr  Úmissrã   r  r  s     ``                         @@r   rÈ   rÈ   ”   sM  û€ ð ˆr€q€AØ—‘�x“ LÑ0€JÜÔs˜eÔsÓs€EØ˜AŸE™E '¨2Ó.Ð.€EÜ
ˆ5ƒz™5‘R bÒ)¨1¯8©8´s¸5³z°lÐBVÑ]bÑWYÐhjÐVkÐklÐ4mÔ+nØ8ò 4ˆØ�EŠ>˜1Ÿ8™8 h¨q¨c NÕ3ð4à�uÑ¡Z°·±Ð:SÔ1TØˆ$ˆa��&‘	ˆ{˜+Ð&€AØˆ[©E˜Z™L°rÑ:€FÜ�7‰7�>‰>˜!ÔÜ�u¤C¨£J°aÐAQÐ@RÐ]^ÐgmÔnÐnÜ	�‰�!‹�Q‰€Bœk¨"›o˜´C·K±KÀ³N¨rØ/1¯v©v°hÀÀÓ/EÀbÇfÁfÈWÐVWÓFXÑ/Y×/]Ñ/]Ð^eÐgiÓ/jÖ
k¨!ˆ2ˆg‰;�q‰>×Ñ˜fÕ%Ð
k€CÐ
kÚ=ÁzÁÐXfÐWgÑh€HØò QˆØ�B‰;˜Ÿ™Ð#8¸¸Ð!<Õ=Ø�cŠ\˜1Ÿ8™8 m°A°3Ð6NÐ$OÕPðQó RØ ™‰u¨G€HØ˜HÐ%Ð&±
©"ÐA\Ð^xÐ@yÑz€EØò p‰ˆˆ1Ø�Š7�q˜E’z©$¨r°!©u°Q©x¸¸q¹À!¹Õ*EØ�H‰H�} Q C t¨B¨q©E°!©H¨:°U¸1¸#¸WÀUÈ1ÁXÈaÁ[ÀMÐQmÐnÕoðpð +ò sˆØ�Š7™4  1¡ a¡ª)Õ4°a·h±hÀÈqÈcÐQeÐfhÐijÑfkÐlmÑfnÐeoÐopÐ?qÕ6rðsäÔk˜bÔkÓk€EØÖ=�! ¨!¨A¨B¨%¡°uÒ <ŠAÐ=€DÐ=ÙˆQ�X‰Xœ˜T›˜Ð#PÐQUÐVXÐWXÐQYÐPZÐ[Ô\ØÖ
p�˜w¨¨1¨2¨™°%Ò7ÁÀRÈÁUÈ1ÁXÈuÐU\Ð_`ÐabÐacÐ_dÑUdÑOeÐfgÑOhÐjnÕ@oŠ1Ð
p€CÐ
pÙ
ˆA�H‰Hœ˜C›�zÐ!GÈÈBÈQÈÀyÐQÔRÜ
ˆ5ƒz�A‚~�q—x‘x¤3 u£: ,Ð.DÐ EÔFÜÑ:˜bÔ:Ó:€Eðoö �!ØrsÐ{}Ñr}ò ð €Dð áˆQ�X‰XÐ-¨d¯i©i¸«oÐ->Ð?Ô@Ø	ˆ&�z�LÒ  !§(¡(¨\¸"¸V¹*¸ÐEXÐ+YÔ"ZØ°·±°{ÀBÓ0GÖH¨"�r—v‘v˜f•~ÒHÑHÈ!Ï(É(ÐSyÔJzÙ‘™t f§m¡m°EÔ&:Ø˜2ÑÐ"2°bÑ"8¸&¿-¹-ÈÔ:VØ�rÑ˜6Ÿ=™=¨Ô3Ø�rÑ™z¨^¸rÑ-AÀFÇMÁMÐRYÔDZÜ�q�5¤ E£
´#°e³*ÄCÈÃJÐWXÐcdÐmsØ˜‘Z¤E¨"¨W©+¸Ñ*;¸QÓ$?ÌÈbÐQaÑNbÐdeÓHfôhð hùò; lùò >ùâ
pùòùò Is0   Å3R9ÊR>Ê,R>ËSË*SÌSÍ2SÏSÚ__main__r   r‹   )Úindentr®   rx   )Ú__doc__r²   rÄ   r,   ÚsysrÅ   ÚdirnameÚabspathÚ__file__ÚROOTÚinsertr  r   r!   r*   r1   rð   rÈ   Ú__name__Úargvr¼   r   ÚprintÚdumpsÚexitrn   r"   r   ú<module>r7     s  ðñr÷ × Ø	‡w�w‡��r—w‘w—‘ r§w¡w§¡°r·w±w·±ÀxÓ7PÓ'QÓRÓS€Ø ‡�‡���2—7‘7—<‘<  eÓ,Ô -Û 
òòòHólò^/hðd ˆzÒÙˆb�g‰g�o‰o˜cŸh™h q™kÓ*¹3¸s¿x¹x»=È1Ò;L¨C¯H©H°QªKÐRVÓW€AÙ	ˆ*ˆ$�*‰*�Q˜qÔ
!Ô"Ø€C‡H�H�!�D’'‰Q˜qÕ!ð r"   