Ë
    }D™j§e  ã                   ó8  — d Z ddlmZmZmZmZmZmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZmZmZ ddlmZmZmZmZmZmZmZmZmZmZ ddlmZ dd	lm Z  dd
l!m"Z"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z)m*Z*m+Z+m,Z,m-Z-  G d„ d«      Z.e/dk(  �rddl0m1Z1  e1jd                  d¬«      Z3e.ji                  e3«      Z5 e6de5jn                  › �«        e6d e8e5jr                  «      › �«        e6d e8e5jt                  «      › �«        e6de5jv                  jx                  › d�«        e6de5jv                  jz                  › d�«        e6de5jv                  j|                  › d�«        e6de5jv                  j~                  › d�«        e6d«        e6e5j�                  d¬«      «       yy) a¿  
Chart Data Factory Module

This module provides factory classes for creating comprehensive chart data models that include
all the pure data from astrological charts, including subjects, aspects, house comparisons,
and other analytical data without the visual rendering components.

This is designed to be the "pure data" counterpart to ChartDrawer, providing structured
access to all chart information for API consumption, data analysis, or other programmatic uses.

Key Features:
    - Comprehensive chart data including subjects and aspects
    - House comparison analysis for dual charts
    - Element and quality distributions
    - Relationship scoring for synastry charts
    - Flexible point and aspect filtering
    - Support for all chart types (Natal, Transit, Synastry, Composite, Return)

Classes:
    ElementDistributionModel: Model for element distribution analysis
    QualityDistributionModel: Model for quality distribution analysis
    SingleChartDataModel: Model for single-subject chart data
    DualChartDataModel: Model for dual-subject chart data
    ChartDataFactory: Factory for creating chart data models

Author: Giacomo Battaglia
Copyright: (C) 2025 Kerykeion Project
License: AGPL-3.0
é    )ÚMappingÚUnionÚOptionalÚListÚLiteralÚcast)ÚAspectsFactory)ÚHouseComparisonFactory)ÚRelationshipScoreFactory)ÚKerykeionExceptionÚ	ChartTypeÚActiveAspect)
ÚAstrologicalSubjectModelÚCompositeSubjectModelÚPlanetReturnModelÚSingleChartAspectsModelÚDualChartAspectsModelÚElementDistributionModelÚQualityDistributionModelÚSingleChartDataModelÚDualChartDataModelÚChartDataModel)Ú$KerykeionSettingsCelestialPointModel)ÚAstrologicalPoint)Úfind_common_active_pointsÚdistribute_percentages_to_100)ÚDEFAULT_ACTIVE_ASPECTS)Ú!DEFAULT_CELESTIAL_POINTS_SETTINGS)Ú ElementQualityDistributionMethodÚcalculate_element_pointsÚcalculate_quality_pointsÚ!calculate_synastry_element_pointsÚ!calculate_synastry_quality_pointsc                   óô  — e Zd ZdZeddeddfddddœdedeee	e
f   d	eeee
f      d
eee      dee   dededee   dedeeeef      defd„«       Zedefdddœdeee	e
f   d
eee      dee   dedeeeef      defd„«       Zededdfdddœded	ed
eee      dee   dedededeeeef      defd„«       Zededfdddœdeded
eee      dee   dededeeeef      defd„«       Zedefdddœde	d
eee      dee   dedeeeef      defd„«       Zededfdddœdede
d
eee      dee   dededeeeef      defd„«       Zedefdddœde
d
eee      dee   dedeeeef      defd„«       Zy)ÚChartDataFactorya£  
    Factory class for creating comprehensive chart data models.

    This factory creates ChartDataModel instances containing all the pure data
    from astrological charts, including subjects, aspects, house comparisons,
    and analytical metrics. It provides the structured data equivalent of
    ChartDrawer's visual output.

    The factory handles all chart types and automatically includes relevant
    analyses based on chart type (e.g., house comparison for dual charts,
    relationship scoring for synastry charts).

    Example:
        >>> # Create natal chart data
        >>> john = AstrologicalSubjectFactory.from_birth_data("John", 1990, 1, 1, 12, 0, "London", "GB")
        >>> natal_data = ChartDataFactory.create_chart_data("Natal", john)
        >>> print(f"Elements: Fire {natal_data.element_distribution.fire_percentage}%")
        >>>
        >>> # Create synastry chart data
        >>> jane = AstrologicalSubjectFactory.from_birth_data("Jane", 1992, 6, 15, 14, 30, "Paris", "FR")
        >>> synastry_data = ChartDataFactory.create_chart_data("Synastry", john, jane)
        >>> print(f"Relationship score: {synastry_data.relationship_score.score_value}")
    NTFÚweighted)Úaxis_orb_limitÚdistribution_methodÚcustom_distribution_weightsÚ
chart_typeÚfirst_subjectÚsecond_subjectÚactive_pointsÚactive_aspectsÚinclude_house_comparisonÚinclude_relationship_scorer'   r(   r)   Úreturnc                óâ  — | dv r|st        d| › d�«      ‚| dk(  rt        |t        «      st        d«      ‚| dk(  rt        |t        «      st        d«      ‚| dk(  rt        |t        «      st        d	«      ‚|s|j                  }
nt        ||j                  «      }
|rt        |
|j                  «      }
| d
v rt        j                  ||
||¬«      }nN|€t        d| › d�«      ‚d}d}| dk(  rd}d}n| dk(  rd}d}n	| dk(  rd}d}t        j                  |||
||||¬«      }d}|rJ|rH| dv rDt        |t        «      r4t        |t        t        f«      rt        |||
¬«      }|j                  «       }d}| dk(  rB|r@|r>t        |t        «      r.t        |t        «      rt        |||¬«      }|j                  «       }g }t        D ]+  }|d   |
v sŒt        |«      }d|d<   |j!                  |«       Œ- |D �cg c]  }t#        d&i |¤Ž‘Œ }}|D �cg c]  }|j$                  j'                  «       ‘Œ }}| dk(  rf|rdt        |t        «      r3t        |t        «      r#t)        ||||||	¬«      }t+        ||||||	¬«      }nAt-        |||||	¬«      }t/        |||||	¬«      }n t-        |||||	¬«      }t/        |||||	¬«      }|d   |d   z   |d   z   |d   z   }|dkD  rt1        |«      ndddddœ}t3        |d   |d   |d   |d   |d   |d   |d   |d   ¬«      }|d   |d    z   |d!   z   }|dkD  rt1        |«      ndddd"œ}t5        |d   |d    |d!   |d   |d    |d!   ¬#«      }| d
v r;t7        t9        t:        d
   | «      |t9        t<        |«      j>                  |||
|¬$«      S |€t        d| › d�«      ‚tA        t9        t:        d   | «      ||t9        tB        |«      j>                  |||||
|¬%«
      S c c}w c c}w )'a<  
        Create comprehensive chart data for the specified chart type.

        Args:
            chart_type: Type of chart to create data for
            first_subject: Primary astrological subject
            second_subject: Secondary subject (required for dual charts)
            active_points: Points to include in calculations (defaults to first_subject.active_points)
            active_aspects: Aspect types and orbs to use
            include_house_comparison: Whether to include house comparison for dual charts
            include_relationship_score: Whether to include relationship scoring for synastry
            axis_orb_limit: Optional orb threshold for chart axes (applies only to single chart aspects)
            distribution_method: Strategy for element/modality weighting ("pure_count" or "weighted")
            custom_distribution_weights: Optional overrides for the distribution weights

        Returns:
            ChartDataModel: Comprehensive chart data model

        Raises:
            KerykeionException: If chart type requirements are not met
        )ÚTransitÚSynastryÚDualReturnChartzSecond subject is required for z charts.Ú	CompositezCFirst subject must be a CompositeSubjectModel for Composite charts.ÚReturnz=Second subject must be a PlanetReturnModel for Return charts.ÚSingleReturnChartzGFirst subject must be a PlanetReturnModel for SingleReturnChart charts.)ÚNatalr6   r8   )r-   r.   r'   NFr4   Tr3   r5   )r-   r.   r'   Úfirst_subject_is_fixedÚsecond_subject_is_fixed)r-   )r'   ÚnameÚ	is_active)ÚmethodÚcustom_weightsÚfireÚwaterÚearthÚairr   )r@   rB   rC   rA   )r@   rB   rC   rA   Úfire_percentageÚearth_percentageÚair_percentageÚwater_percentageÚcardinalÚfixedÚmutable)rH   rI   rJ   )rH   rI   rJ   Úcardinal_percentageÚfixed_percentageÚmutable_percentage)r*   ÚsubjectÚaspectsÚelement_distributionÚquality_distributionr-   r.   )
r*   r+   r,   rO   Úhouse_comparisonÚrelationship_scorerP   rQ   r-   r.   © )"r   Ú
isinstancer   r   r-   r   r	   Úsingle_chart_aspectsÚdual_chart_aspectsr   r
   Úget_house_comparisonr   Úget_relationship_scorer   ÚdictÚappendr   r<   Úlowerr"   r#   r    r!   r   r   r   r   r   r   r   rO   r   r   )r*   r+   r,   r-   r.   r/   r0   r'   r(   r)   Úeffective_active_pointsÚaspects_modelr:   r;   rR   Úhouse_comparison_factoryrS   Úrelationship_score_factoryÚavailable_planets_setting_dictsÚbodyÚ	body_dictÚavailable_planets_settingÚcelestial_points_namesÚelement_totalsÚquality_totalsÚtotal_elementsÚelement_percentagesrP   Útotal_qualitiesÚquality_percentagesrQ   s                                  úh/var/www/html/Astrologybackend/backend/venv/lib/python3.12/site-packages/kerykeion/chart_data_factory.pyÚcreate_chart_dataz"ChartDataFactory.create_chart_data[   sk  € ðJ ÐCÑCÉNÜ$Ð'FÀzÀlÐRZÐ%[Ó\Ð\à˜Ò$¬Z¸ÔG\Ô-]Ü$Ð%jÓkÐkà˜Ò!¬*°^ÔEVÔ*WÜ$Ð%dÓeÐeàÐ,Ò,´ZÀÔO`Ô5aÜ$Ð%nÓoÐoñ Ø&3×&AÑ&AÑ#ä&?ÀÈ}×OjÑOjÓ&kÐ#ñ Ü&?Ð@WÐYg×YuÑYuÓ&vÐ#ð ÐDÑDä*×?Ñ?ØØ5Ø-Ø-ô	‰Mð Ð%Ü(Ð+JÈ:È,ÐV^Ð)_Ó`Ð`ð &+Ð"Ø&+Ð#à˜ZÒ'Ø)-Ð&Ø*.Ñ'Ø˜yÒ(Ø)-Ð&Ø*/Ñ'ØÐ0Ò0Ø)-Ð&Ø*/Ð'ä*×=Ñ=ØØØ5Ø-Ø-Ø'=Ø(?ôˆMð  ÐÙÑ6¸:ÐIsÑ;sÜ˜-Ô)AÔBÄzØÔ!9Ô;LÐ MôHô ,BØ! >ÐAXô,Ð(ð $<×#PÑ#PÓ#RÐ ð "ÐØ˜Ò#Ñ(BÁ~Ü˜-Ô)AÔBÄzØÔ 8ôHô .FØ!Ø"Ø#1ô.Ð*ð
 &@×%VÑ%VÓ%XÐ"ð DFÐ'Ü5ò 	BˆDØ�F‰|Ð6Ò6Ü  ›J�	Ø)-�	˜+Ñ&Ø/×6Ñ6°yÕAð		Bð 8öQ
àô 1Ñ8°4Ó8ðQ
Ð!ð Q
ð
 AZÖ!Z¸ $§)¡)§/¡/Õ"3Ð!ZÐÐ!Zà˜Ò#©ô ˜-Ô)AÔBÄzØÔ 8ôHô "CØ-Ø*Ø!Ø"Ø.Ø#>ô"�ô "CØ-Ø*Ø!Ø"Ø.Ø#>ô"‘ô ":Ø-Ø*Ø!Ø.Ø#>ô"�ô ":Ø-Ø*Ø!Ø.Ø#>ô"‘ô 6Ø)Ø&ØØ*Ø:ôˆNô 6Ø)Ø&ØØ*Ø:ôˆNð ˜6Ñ" ^°GÑ%<Ñ<¸~ÈgÑ?VÑVÐYgÐhmÑYnÑnð 	ð
  Ò!ô *¨.Ô9à a°¸AÑ>ð 	ô
  8Ø Ñ'Ø  Ñ)Ø˜uÑ%Ø  Ñ)Ø/°Ñ7Ø0°Ñ9Ø.¨uÑ5Ø0°Ñ9ô	 
Ðð )¨Ñ4°~ÀgÑ7NÑNÐQ_Ð`iÑQjÑjˆð  Ò"ô *¨.Ô9à¨!¸Ñ:ð 	ô
  8Ø# JÑ/Ø  Ñ)Ø" 9Ñ-Ø 3°JÑ ?Ø0°Ñ9Ø2°9Ñ=ô 
Ðð ÐDÑDä'Ü¤Ð(QÑ RÐT^Ó_Ø%ÜÔ4°mÓD×LÑLØ%9Ø%9Ø5Ø-ôð ð Ð%Ü(Ð+JÈ:È,ÐV^Ð)_Ó`Ð`Ü%Ü¤Ð(PÑ QÐS]Ó^Ø+Ø-ÜÔ2°MÓB×JÑJØ!1Ø#5Ø%9Ø%9Ø5Ø-ôð ùòcQ
ùò
 "[s   Ç0O'È!O,)r(   r)   rN   c                ó8   — t         j                  | d||||¬«      S )aÏ  
        Convenience method for creating natal chart data.

        Args:
            subject: Astrological subject
            active_points: Points to include in calculations
            active_aspects: Aspect types and orbs to use
            distribution_method: Strategy for element/modality weighting
            custom_distribution_weights: Optional overrides for distribution weights

        Returns:
            ChartDataModel: Natal chart data
        r9   ©r+   r*   r-   r.   r(   r)   ©r%   rm   )rN   r-   r.   r(   r)   s        rl   Úcreate_natal_chart_dataz(ChartDataFactory.create_natal_chart_data\  s.   € ô,  ×1Ñ1Ø!ØØ'Ø)Ø 3Ø(Cð 2ó 
ð 	
ó    c                ó>   — t         j                  | d|||||||¬«	      S )a³  
        Convenience method for creating synastry chart data.

        Args:
            first_subject: First astrological subject
            second_subject: Second astrological subject
            active_points: Points to include in calculations
            active_aspects: Aspect types and orbs to use
            include_house_comparison: Whether to include house comparison
            include_relationship_score: Whether to include relationship scoring
            distribution_method: Strategy for element/modality weighting
            custom_distribution_weights: Optional overrides for distribution weights

        Returns:
            ChartDataModel: Synastry chart data
        r4   )	r+   r*   r,   r-   r.   r/   r0   r(   r)   rp   )r+   r,   r-   r.   r/   r0   r(   r)   s           rl   Úcreate_synastry_chart_dataz+ChartDataFactory.create_synastry_chart_data{  s7   € ô8  ×1Ñ1Ø'Ø!Ø)Ø'Ø)Ø%=Ø'AØ 3Ø(Cð 2ó 

ð 
	
rr   Únatal_subjectÚtransit_subjectc          
      ó<   — t         j                  | d||||||¬«      S )ac  
        Convenience method for creating transit chart data.

        Args:
            natal_subject: Natal astrological subject
            transit_subject: Transit astrological subject
            active_points: Points to include in calculations
            active_aspects: Aspect types and orbs to use
            include_house_comparison: Whether to include house comparison
            distribution_method: Strategy for element/modality weighting
            custom_distribution_weights: Optional overrides for distribution weights

        Returns:
            ChartDataModel: Transit chart data
        r3   ©r+   r*   r,   r-   r.   r/   r(   r)   rp   )ru   rv   r-   r.   r/   r(   r)   s          rl   Úcreate_transit_chart_dataz*ChartDataFactory.create_transit_chart_data£  s4   € ô4  ×1Ñ1Ø'Ø Ø*Ø'Ø)Ø%=Ø 3Ø(Cð 2ó 	
ð 		
rr   Úcomposite_subjectc                ó8   — t         j                  | d||||¬«      S )aë  
        Convenience method for creating composite chart data.

        Args:
            composite_subject: Composite astrological subject
            active_points: Points to include in calculations
            active_aspects: Aspect types and orbs to use
            distribution_method: Strategy for element/modality weighting
            custom_distribution_weights: Optional overrides for distribution weights

        Returns:
            ChartDataModel: Composite chart data
        r6   ro   rp   )rz   r-   r.   r(   r)   s        rl   Úcreate_composite_chart_dataz,ChartDataFactory.create_composite_chart_dataÈ  s.   € ô,  ×1Ñ1Ø+Ø"Ø'Ø)Ø 3Ø(Cð 2ó 
ð 	
rr   Úreturn_subjectc          
      ó<   — t         j                  | d||||||¬«      S )af  
        Convenience method for creating planetary return chart data.

        Args:
            natal_subject: Natal astrological subject
            return_subject: Planetary return subject
            active_points: Points to include in calculations
            active_aspects: Aspect types and orbs to use
            include_house_comparison: Whether to include house comparison
            distribution_method: Strategy for element/modality weighting
            custom_distribution_weights: Optional overrides for distribution weights

        Returns:
            ChartDataModel: Return chart data
        r5   rx   rp   )ru   r}   r-   r.   r/   r(   r)   s          rl   Úcreate_return_chart_dataz)ChartDataFactory.create_return_chart_dataç  s4   € ô4  ×1Ñ1Ø'Ø(Ø)Ø'Ø)Ø%=Ø 3Ø(Cð 2ó 	
ð 		
rr   c                ó8   — t         j                  | d||||¬«      S )a   
        Convenience method for creating single wheel planetary return chart data.

        Args:
            return_subject: Planetary return subject
            active_points: Points to include in calculations
            active_aspects: Aspect types and orbs to use
            distribution_method: Strategy for element/modality weighting
            custom_distribution_weights: Optional overrides for distribution weights

        Returns:
            ChartDataModel: Single wheel return chart data
        r8   ro   rp   )r}   r-   r.   r(   r)   s        rl   Ú%create_single_wheel_return_chart_dataz6ChartDataFactory.create_single_wheel_return_chart_data  s.   € ô,  ×1Ñ1Ø(Ø*Ø'Ø)Ø 3Ø(Cð 2ó 
ð 	
rr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr   r   r   r   r   r   r   r   r   r   ÚboolÚfloatr   r   Ústrr   rm   rq   rt   ry   r|   r   r�   rT   rr   rl   r%   r%   B   si  „ ñð0 ð X\Ø;?Ø-CØ)-Ø+0ð~ð +/Ø@JØEIò~Øð~àÐ5Ð7LÐN_Ð_Ñ`ð~ð ! Ð'?ÐARÐ'RÑ!SÑTð~ð   Ð%6Ñ 7Ñ8ð	~ð
 ˜\Ñ*ð~ð #'ð~ð %)ð~ð ! ™ð~ð >ð~ð &.¨g°c¸5°jÑ.AÑ%Bð~ð 
ò~ó ð~ð@ ð <@Ø-Cð
ð
 AKØEIò
ØÐ/Ð1FÐHYÐYÑZð
à Ð%6Ñ 7Ñ8ð
ð ˜\Ñ*ð
ð
 >ð
ð &.¨g°c¸5°jÑ.AÑ%Bð
ð 
ò
ó ð
ð< ð <@Ø-CØ)-Ø+/ð%
ð AKØEIò%
Ø/ð%
à0ð%
ð   Ð%6Ñ 7Ñ8ð%
ð ˜\Ñ*ð	%
ð
 #'ð%
ð %)ð%
ð >ð%
ð &.¨g°c¸5°jÑ.AÑ%Bð%
ð 
ò%
ó ð%
ðN ð <@Ø-CØ)-ð"
ð AKØEIò"
Ø/ð"
à1ð"
ð   Ð%6Ñ 7Ñ8ð"
ð ˜\Ñ*ð	"
ð
 #'ð"
ð >ð"
ð &.¨g°c¸5°jÑ.AÑ%Bð"
ð 
ò"
ó ð"
ðH ð <@Ø-Cð
ð
 AKØEIò
Ø0ð
à Ð%6Ñ 7Ñ8ð
ð ˜\Ñ*ð
ð
 >ð
ð &.¨g°c¸5°jÑ.AÑ%Bð
ð 
ò
ó ð
ð< ð <@Ø-CØ)-ð"
ð AKØEIò"
Ø/ð"
à)ð"
ð   Ð%6Ñ 7Ñ8ð"
ð ˜\Ñ*ð	"
ð
 #'ð"
ð >ð"
ð &.¨g°c¸5°jÑ.AÑ%Bð"
ð 
ò"
ó ð"
ðH ð <@Ø-Cð
ð
 AKØEIò
Ø)ð
à Ð%6Ñ 7Ñ8ð
ð ˜\Ñ*ð
ð
 >ð
ð &.¨g°c¸5°jÑ.AÑ%Bð
ð 
ò
ó ñ
rr   r%   Ú__main__)ÚAstrologicalSubjectFactoryzTest Subject)r<   zChart Type: zActive Points: z	Aspects: zFire: ú%zEarth: zAir: zWater: z
---
é   )ÚindentN)Ar…   Útypingr   r   r   r   r   r   Úkerykeion.aspectsr	   Ú3kerykeion.house_comparison.house_comparison_factoryr
   Ú$kerykeion.relationship_score_factoryr   Úkerykeion.schemasr   r   r   Úkerykeion.schemas.kr_modelsr   r   r   r   r   r   r   r   r   r   Ú!kerykeion.schemas.settings_modelsr   Úkerykeion.schemas.kr_literalsr   Úkerykeion.utilitiesr   r   Ú#kerykeion.settings.config_constantsr   Ú!kerykeion.settings.chart_defaultsr   Úkerykeion.charts.charts_utilsr   r    r!   r"   r#   r%   r‚   Ú&kerykeion.astrological_subject_factoryr‹   Úfrom_current_timerN   rq   Ú
natal_dataÚprintr*   Úlenr-   rO   rP   rD   rE   rF   rG   Úmodel_dump_jsonrT   rr   rl   ú<module>r¡      sx  ðñ÷< A× @å ,Ý VÝ Iß IÑ I÷÷ ÷ õ Sõ÷ YÝ FÝ O÷õ ÷g
ñ g
ðT ˆzÓåQð ;Ð(×:Ñ:ÀÔO€GØ!×9Ñ9¸'ÓB€Já	ˆL˜×.Ñ.Ð/Ð
0Ô1Ù	ˆO™C 
× 8Ñ 8Ó9Ð:Ð
;Ô<Ù	ˆI‘c˜*×,Ñ,Ó-Ð.Ð
/Ô0Ù	ˆF�:×2Ñ2×BÑBÐCÀ1Ð
EÔFÙ	ˆG�J×3Ñ3×DÑDÐEÀQÐ
GÔHÙ	ˆE�*×1Ñ1×@Ñ@ÐAÀÐ
CÔDÙ	ˆG�J×3Ñ3×DÑDÐEÀQÐ
GÔHá	ˆ)ÔÙ	ˆ*×
$Ñ
$¨AÐ
$Ó
.Õ/ð# rr   