- /api/synastry: inter-chart aspects with weighted harmony/tension scores, house overlays, written compatibility report - Compatibility tab: biwheel (partner ring in gold), inter-aspect grid, score gauges - Export toolbar: chart .json (re-loadable via Load file), wheel SVG/PNG, print CSS covers synastry - Aspect types explained reference + pair notes for 30+ classic pairs woven into natal aspect texts - Wheel fixes: correct arc sweep direction, text-presentation zodiac glyphs (no more emoji rendering) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
393 lines
35 KiB
Python
393 lines
35 KiB
Python
"""NATEGODD interpretation engine.
|
||
|
||
Hand-written texts for the big three (Sun / Moon / Ascendant in each sign),
|
||
plus a keyword-synthesis engine that generates readable prose for every
|
||
planet-in-sign, planet-in-house and aspect combination — the same trick the
|
||
90s desktop programs used, with a bigger vocabulary.
|
||
"""
|
||
|
||
SIGNS = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
|
||
"Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"]
|
||
|
||
PLANET_MEANING = {
|
||
"Sun": ("your core identity and vital force", "identity"),
|
||
"Moon": ("your emotional nature and instinctive needs", "feelings"),
|
||
"Mercury": ("how you think, learn and communicate", "mind"),
|
||
"Venus": ("how you love, relate and what you find beautiful", "affections"),
|
||
"Mars": ("your drive, desire and how you assert yourself", "will"),
|
||
"Jupiter": ("where you expand, trust and find meaning", "growth"),
|
||
"Saturn": ("where you meet limits, discipline and mastery", "structure"),
|
||
"Uranus": ("where you break rules and demand freedom", "individuality"),
|
||
"Neptune": ("where you dream, idealise and dissolve boundaries", "imagination"),
|
||
"Pluto": ("where you transform, purge and confront power", "depths"),
|
||
"Chiron": ("your deepest wound and your gift for healing others", "wound"),
|
||
"Ceres": ("how you nurture and wish to be nurtured", "care"),
|
||
"Pallas": ("your style of wisdom, strategy and pattern-seeing", "strategy"),
|
||
"Juno": ("what you need from committed partnership", "commitment"),
|
||
"Vesta": ("what you devote yourself to with sacred focus", "devotion"),
|
||
"North Node": ("the direction of growth your life keeps pulling you toward", "destiny"),
|
||
"South Node": ("the well-worn gifts and habits you are meant to grow beyond", "past"),
|
||
"Lilith": ("your untamed, uncompromising instinct", "wildness"),
|
||
"Part of Fortune": ("where circumstance tends to reward you", "fortune"),
|
||
"Ascendant": ("the face you show the world and how life approaches you", "persona"),
|
||
"Midheaven": ("your public role, vocation and reputation", "calling"),
|
||
}
|
||
|
||
SIGN_STYLE = {
|
||
"Aries": ("directly, impulsively and with courage", "a pioneer's urgency — first in, fast, and unafraid of a fight",
|
||
"impatience and starting more than you finish"),
|
||
"Taurus": ("steadily, sensually and with great persistence", "a builder's patience — slow to start, impossible to stop",
|
||
"stubbornness and resistance to any change you didn't choose"),
|
||
"Gemini": ("curiously, quickly and through words", "a storyteller's agility — collecting, connecting and re-telling everything",
|
||
"scatter, restlessness and skating on the surface"),
|
||
"Cancer": ("protectively, intuitively and from memory", "a caretaker's tenacity — sideways approaches and a long, long memory",
|
||
"moodiness and retreating into the shell"),
|
||
"Leo": ("dramatically, warmly and from the heart", "a performer's radiance — generous, loyal and impossible to ignore",
|
||
"pride and a hunger for applause"),
|
||
"Virgo": ("precisely, modestly and in service of improvement", "a craftsman's discrimination — nothing escapes your notice",
|
||
"worry, self-criticism and perfectionism"),
|
||
"Libra": ("gracefully, diplomatically and always in relation to others", "an artist's sense of balance — fairness is a physical need",
|
||
"indecision and keeping the peace at your own expense"),
|
||
"Scorpio": ("intensely, privately and all the way to the bottom", "an investigator's penetration — you find what is hidden",
|
||
"suspicion, control and scorched-earth endings"),
|
||
"Sagittarius": ("expansively, honestly and aimed at the horizon", "an explorer's optimism — meaning matters more than comfort",
|
||
"bluntness, excess and promising more than you deliver"),
|
||
"Capricorn": ("ambitiously, cautiously and for the long game", "a mountain goat's endurance — you climb whatever is in front of you",
|
||
"pessimism, coldness and working when you should rest"),
|
||
"Aquarius": ("independently, inventively and on principle", "a scientist's detachment — humanity in the abstract, freedom in the particular",
|
||
"contrariness and aloofness from your own feelings"),
|
||
"Pisces": ("compassionately, imaginatively and without hard edges", "a mystic's permeability — you feel everything in the room",
|
||
"escapism, vagueness and martyrdom"),
|
||
}
|
||
|
||
HOUSE_MEANING = {
|
||
1: "the house of self — your body, appearance and personal initiative",
|
||
2: "the house of resources — money, possessions, talent and self-worth",
|
||
3: "the house of communication — siblings, short journeys, learning and daily talk",
|
||
4: "the house of home — family, roots, ancestry and your private foundation",
|
||
5: "the house of creativity — romance, children, play and self-expression",
|
||
6: "the house of work and health — daily routine, service, craft and the body's upkeep",
|
||
7: "the house of partnership — marriage, close one-to-one bonds and open enemies",
|
||
8: "the house of shared depths — intimacy, other people's money, crisis and regeneration",
|
||
9: "the house of the far horizon — travel, higher learning, philosophy and publishing",
|
||
10: "the house of career — public standing, authority, ambition and reputation",
|
||
11: "the house of community — friends, groups, causes and hopes for the future",
|
||
12: "the house of the hidden — solitude, dreams, self-undoing and transcendence",
|
||
}
|
||
|
||
# ------------------------- hand-written big three -------------------------
|
||
|
||
SUN_IN_SIGN = {
|
||
"Aries": "You are here to begin things. Aries Sun people run on raw initiative: the idea and the action arrive in the same instant, and waiting is a kind of pain. You are brave, direct and refreshingly free of hidden agendas — what others call recklessness is simply your faith that the door will open if you hit it hard enough. Your growth lies in finishing what you start and discovering that patience is not surrender.",
|
||
"Taurus": "You are here to build things that last. Taurus Sun people have a genius for the physical world — food, music, money, touch, gardens — and a calm that others lean on in a storm. You change slowly and on your own schedule, which is both your greatest strength and the thing that maddens everyone who loves you. Your growth lies in learning that security comes from within, not from what you can hold.",
|
||
"Gemini": "You are here to connect things. Gemini Sun people live through language and curiosity: two of everything, questions before breakfast, and a mind that moves faster than any conversation can. You are the messenger, the translator, the one who makes the room lighter. Your growth lies in depth — staying with one thing, one person, one question long enough to be changed by it.",
|
||
"Cancer": "You are here to care for things. Cancer Sun people feel everything and forget nothing; beneath the shell is the most loyal heart in the zodiac. Home — wherever and whatever that means to you — is not a place but a project, and you protect your people ferociously. Your growth lies in letting yourself be nurtured as fiercely as you nurture, and in leaving the shell even when it might rain.",
|
||
"Leo": "You are here to shine. Leo Sun people carry a warmth that is not performance — it is a genuine wish for everyone in the room to feel more alive. You are generous, dramatic and braver in public than most people are in private. The applause matters more than you admit. Your growth lies in learning that your light does not dim when someone else's is shining.",
|
||
"Virgo": "You are here to perfect things. Virgo Sun people see the flaw, the fix and the better way — instantly and always. Your service is real love in work clothes: you show devotion by improving things for people. The blade you turn on the world you turn hardest on yourself. Your growth lies in accepting that 'good enough' is sometimes the most precise judgement of all.",
|
||
"Libra": "You are here to balance things. Libra Sun people are drawn to beauty, fairness and the space between two people, where you do your finest work. You see every side of every question — a gift in a diplomat, a torment at a menu. Your growth lies in discovering what YOU want when nobody else's preference is available to orbit, and saying it out loud.",
|
||
"Scorpio": "You are here to go beneath things. Scorpio Sun people are the depth psychologists of the zodiac: you sense what is hidden, you keep secrets like a vault, and you love with a totality that frightens lighter souls. You die and are reborn several times in one life. Your growth lies in trusting without testing, and forgiving without forgetting the lesson.",
|
||
"Sagittarius": "You are here to seek the meaning of things. Sagittarius Sun people need a horizon — a journey, a philosophy, a wager, a question big enough to be worth a life. You are honest to a fault (ask anyone who's asked how they look), funny, and allergic to cages. Your growth lies in learning that commitment is not a cage — it is a country you haven't explored yet.",
|
||
"Capricorn": "You are here to master things. Capricorn Sun people are born old and get younger: duty first, the long climb, the dry wit that surprises everyone. You do not want to be given the summit — you want to have earned it. Your growth lies in remembering what the climb was for, and letting the people who love you sit by the fire you built.",
|
||
"Aquarius": "You are here to reinvent things. Aquarius Sun people belong to the future: you see the pattern everyone else is inside of, and you cannot un-see it. Friendship is your religion, principle your compass, and being ordinary the only thing you truly fear. Your growth lies in coming down from the observatory — letting one person, up close, matter as much as humanity in the abstract.",
|
||
"Pisces": "You are here to dissolve the walls between things. Pisces Sun people feel the whole ocean: other people's moods, the mood of the age, music no one else hears yet. You are the zodiac's artist and mystic, compassionate past the point of self-interest. Your growth lies in building a container for the ocean — boundaries, routines, a raft — so the tide carries you instead of sweeping you away.",
|
||
}
|
||
|
||
MOON_IN_SIGN = {
|
||
"Aries": "Emotionally you are a flash fire — quick to anger, quick to laugh, incapable of sulking for long. You need action when you're upset; sitting with a feeling feels like drowning in slow motion. You are safest with people who let you flare without flinching.",
|
||
"Taurus": "Emotionally you are bedrock. You need comfort you can touch: good food, familiar rooms, a body beside you, a predictable rhythm. It takes a great deal to upset you and a great deal more to change your mind afterwards. The Moon is exalted here — feelings, once given, do not waver.",
|
||
"Gemini": "Emotionally you need to talk it out — a feeling isn't real until it's been put into words, preferably with a sympathetic listener and several tangents. Restlessness is how sadness shows up in you. You are safest with people who find your changeability charming rather than alarming.",
|
||
"Cancer": "Emotionally you are at full strength — the Moon rules Cancer, and you feel in tides: high, low, and never negotiable. Memory and mood are fused; an old song can undo you. You need a shell — a home, a person, a ritual — that is unconditionally yours. Your care for others is oceanic.",
|
||
"Leo": "Emotionally you need to be seen. Warm, loyal and dramatic, you give affection like sunlight and wilt in rooms where you're ignored. Wounded pride hurts you more than almost anything real. You are safest with people who applaud first and critique later — or never.",
|
||
"Virgo": "Emotionally you cope by being useful. Anxiety goes into lists, care goes into acts of service, and love is shown by remembering exactly how everyone takes their tea. You need order when you're overwhelmed. Let people love the unedited version of you, too.",
|
||
"Libra": "Emotionally you need harmony the way others need air — conflict in the room registers in your body. You reach instinctively for the balancing word, the fair compromise, the beautiful gesture. Your work is noticing your own feelings before you've adjusted them to suit the company.",
|
||
"Scorpio": "Emotionally you are all-or-nothing in a sealed vault. You feel more intensely than anyone around you and show less of it. Trust is everything and is never fully finished being tested. When you finally open the vault, your loyalty is absolute — and so is your memory of betrayal.",
|
||
"Sagittarius": "Emotionally you need open sky. Heaviness makes you reach for the passport, the joke, the philosophical reframe — anything but the swamp. Your optimism is genuine and medicinal to others. Just notice when the horizon is a direction and when it's an exit.",
|
||
"Capricorn": "Emotionally you are self-contained and self-controlled — feelings are handled, privately, on a schedule. You show love through reliability: being there, paying for it, fixing it. Your work is letting someone see you before the feeling has been fully processed and filed.",
|
||
"Aquarius": "Emotionally you observe yourself from a slight distance — feelings are interesting data, best examined with a friend, ideally about something other than the two of you. You need freedom inside closeness. Your work is staying in the room when the feeling is happening, not after.",
|
||
"Pisces": "Emotionally you are a tidal instrument — you register everyone's weather and sometimes lose track of which feelings are yours. Music, water, sleep and solitude restore you. Your compassion has no floor. Your work is a gentle boundary: you can feel with people without drowning for them.",
|
||
}
|
||
|
||
RISING_IN_SIGN = {
|
||
"Aries": "You come across as direct, energetic and slightly ahead of everyone else — first through the door, first to speak. Life meets you as a series of starts, dares and fresh campaigns. People underestimate your sensitivity because your armour looks so good.",
|
||
"Taurus": "You come across as calm, solid and unhurried — a settling presence people instinctively trust. Life meets you slowly and materially: things build, accumulate, take root. People underestimate how immovable you become once you've decided.",
|
||
"Gemini": "You come across as bright, quick and endlessly conversational — the one who knows a little about everything and someone in every room. Life meets you as a stream of messages, errands and interesting strangers. People underestimate the serious mind behind the banter.",
|
||
"Cancer": "You come across as gentle, receptive and a little guarded — people want to confide in you within minutes. Life meets you through belonging: family, home and the question of who is 'yours'. People underestimate the crab's grip beneath the softness.",
|
||
"Leo": "You come across as warm, confident and impossible to overlook — you have presence before you have said a word. Life meets you as a stage with your name somewhere on the bill. People underestimate how much courage it costs to keep the show running.",
|
||
"Virgo": "You come across as composed, attentive and precise — the person who noticed, and quietly fixed it. Life meets you as work to be done well. People underestimate the dry wit and the depth of care hiding inside the competence.",
|
||
"Libra": "You come across as charming, fair and beautifully put together — people relax around you and can't quite say why. Life meets you through others: partners, audiences, negotiations. People underestimate the steel it takes to keep everything so pleasant.",
|
||
"Scorpio": "You come across as magnetic, contained and faintly unknowable — people feel seen by you and slightly exposed. Life meets you in intensities: all-in bonds, deep endings, real stakes. People underestimate how much you've survived, because you never lead with it.",
|
||
"Sagittarius": "You come across as open, funny and larger than the room — the accent of somewhere else, even at home. Life meets you as a journey with luggage optional. People underestimate the philosopher under the punchlines.",
|
||
"Capricorn": "You come across as capable, reserved and older than your years — authority attaches itself to you unasked. Life meets you as a mountain, and you climb it. People underestimate the loyalty and humour beneath the executive surface.",
|
||
"Aquarius": "You come across as friendly, original and one degree removed — of the group and somehow watching it too. Life meets you as a series of systems to question. People underestimate how much you care, because you care in principles rather than displays.",
|
||
"Pisces": "You come across as soft-edged, kind and a little otherworldly — people project their favourite story onto you. Life meets you as atmosphere: moods, coincidences, callings. People underestimate the tidal strength with which you eventually go where you're going.",
|
||
}
|
||
|
||
# ------------------------- synthesis -------------------------
|
||
|
||
|
||
def planet_in_sign(planet, sign):
|
||
if planet == "Sun":
|
||
return SUN_IN_SIGN[sign]
|
||
if planet == "Moon":
|
||
return MOON_IN_SIGN[sign]
|
||
if planet == "Ascendant":
|
||
return RISING_IN_SIGN[sign]
|
||
if planet not in PLANET_MEANING:
|
||
return ""
|
||
what, _ = PLANET_MEANING[planet]
|
||
style, gift, shadow = SIGN_STYLE[sign]
|
||
return (f"{planet} in {sign} colours {what}: it operates {style}. "
|
||
f"At its best this gives {gift}. "
|
||
f"The shadow side to watch is {shadow}.")
|
||
|
||
|
||
def planet_in_house(planet, house):
|
||
if planet not in PLANET_MEANING or house not in HOUSE_MEANING:
|
||
return ""
|
||
what, _ = PLANET_MEANING[planet]
|
||
return (f"{planet} falls in {HOUSE_MEANING[house]}. "
|
||
f"This is the arena of life where {what} plays out most visibly — "
|
||
f"expect the themes of this house to keep finding you.")
|
||
|
||
|
||
ASPECT_DYNAMICS = {
|
||
"Conjunction": "are fused — they act as one, each permanently coloured by the other",
|
||
"Opposition": "face each other across a divide — life keeps asking you to balance them, often through other people",
|
||
"Trine": "flow together effortlessly — a genuine talent, so natural you may undervalue it",
|
||
"Square": "grind against each other — a lifelong friction that, worked honestly, becomes your engine",
|
||
"Sextile": "cooperate when invited — an opportunity that rewards a little deliberate effort",
|
||
"Quincunx": "speak different languages entirely — they require constant, slightly awkward adjustment",
|
||
"Semisextile": "sit uneasily side by side — a subtle irritant and a subtle resource",
|
||
"Semisquare": "chafe in the background — minor but persistent friction",
|
||
"Sesquiquadrate": "provoke each other at odd moments — friction that surfaces when you least expect it",
|
||
"Quintile": "combine with unusual creativity — a signature talent with a personal twist",
|
||
"Biquintile": "combine with subtle artistry — a refined, almost private gift",
|
||
}
|
||
|
||
|
||
# Deeper notes for the classic planet pairs, keyed by frozenset. Appended to the
|
||
# synthesized aspect text in natal charts; hard aspects lean on the second clause.
|
||
PAIR_NOTES = {
|
||
frozenset(["Sun", "Moon"]): "The Sun–Moon relationship is the axis of the whole chart — how your conscious aims and your instinctive needs get along sets the tone for everything else.",
|
||
frozenset(["Sun", "Mercury"]): "Mind and identity travel together; you think in the first person and take ideas personally.",
|
||
frozenset(["Sun", "Venus"]): "Charm is woven into identity — you need to create, please and be found pleasing.",
|
||
frozenset(["Sun", "Mars"]): "Will and identity are yoked: enormous drive, and a temper that flares exactly when your selfhood is questioned.",
|
||
frozenset(["Sun", "Jupiter"]): "A native optimism and sense of luck — life tends to say yes to you, and excess is the only real danger.",
|
||
frozenset(["Sun", "Saturn"]): "Authority is the lifelong theme — doubting it, earning it, becoming it. Late-blooming and durable.",
|
||
frozenset(["Sun", "Uranus"]): "You are constitutionally unable to be ordinary; expect a life punctuated by sudden reinventions.",
|
||
frozenset(["Sun", "Neptune"]): "The self has soft edges — great for art and empathy, risky for boundaries and self-definition.",
|
||
frozenset(["Sun", "Pluto"]): "An all-or-nothing intensity to the personality; you periodically demolish and rebuild who you are.",
|
||
frozenset(["Moon", "Mercury"]): "Feeling and language are wired together — you can say what you feel, and you feel what is said.",
|
||
frozenset(["Moon", "Venus"]): "Affection comes naturally; you soothe people, and comfort and love are almost the same word.",
|
||
frozenset(["Moon", "Mars"]): "Emotions arrive hot and fast — passionate, brave, quick to flare and quick to defend your own.",
|
||
frozenset(["Moon", "Saturn"]): "Feelings are rationed and guarded — often from an early experience of emotional economy. Tenderness must be deliberately practised.",
|
||
frozenset(["Moon", "Neptune"]): "A psychic sponge — exquisite sensitivity to atmosphere, and a need to check whose feelings you're feeling.",
|
||
frozenset(["Moon", "Pluto"]): "Emotional X-ray vision and volcanic depths; you bond totally or not at all.",
|
||
frozenset(["Moon", "Uranus"]): "Feelings switch suddenly — you need emotional freedom and surprise, and closeness that doesn't cage.",
|
||
frozenset(["Mercury", "Neptune"]): "The imaginal mind — poetry, imagery and intuition strong, literal precision optional.",
|
||
frozenset(["Mercury", "Pluto"]): "The detective's mind — you probe, you keep secrets, and small talk bores you to death.",
|
||
frozenset(["Mercury", "Saturn"]): "The engineer's mind — slow, rigorous, sceptical, and right more often than it is quick.",
|
||
frozenset(["Mercury", "Uranus"]): "The lightning mind — intuitive leaps, brilliant and contrary in equal measure.",
|
||
frozenset(["Venus", "Mars"]): "Desire and affection are fused — magnetism, artistry and appetite; you pursue what you love.",
|
||
frozenset(["Venus", "Saturn"]): "Love is serious business — loyal, slow to trust, and inclined to test affection before believing it.",
|
||
frozenset(["Venus", "Neptune"]): "The romantic idealist — you fall in love with the dream first; art is the safest container for it.",
|
||
frozenset(["Venus", "Pluto"]): "Love as transformation — attractions are fated-feeling, intense and never casual.",
|
||
frozenset(["Venus", "Uranus"]): "Love needs freedom and novelty — sudden attractions, unconventional arrangements.",
|
||
frozenset(["Mars", "Saturn"]): "The disciplined will — drive under control, like a braked engine: frustrating young, formidable later.",
|
||
frozenset(["Mars", "Pluto"]): "Immense force of will — you don't do anything halfway, and you must choose your battles like a surgeon.",
|
||
frozenset(["Mars", "Uranus"]): "Explosive, original energy — sudden action, physical daring, zero tolerance for being told how.",
|
||
frozenset(["Mars", "Neptune"]): "The will works by inspiration, not force — best aimed at creative or compassionate ends, foggy elsewhere.",
|
||
frozenset(["Jupiter", "Saturn"]): "Expansion and contraction in one engine — the master builder's aspect when the two learn to take turns.",
|
||
frozenset(["Saturn", "Pluto"]): "Endurance itself — you can survive and rebuild what would break most people.",
|
||
}
|
||
|
||
# What each aspect TYPE is — geometry, orb, feel. Educational reference.
|
||
ASPECT_EXPLAINER = {
|
||
"Conjunction": ("0° — same place", "Two planets standing together in the zodiac. Their functions fuse into a single, amplified drive — neither operates without the other ever again. Whether that is a blessing depends entirely on the planets involved: Venus–Jupiter conjunct is champagne; Mars–Saturn conjunct is a handbrake and an accelerator in one foot. The most powerful aspect of all."),
|
||
"Opposition": ("180° — opposite signs", "Two planets facing each other across the wheel, like people at either end of a see-saw. You tend to identify with one end and meet the other end in partners — until you notice both are you. Oppositions bring awareness through relationship: tension, yes, but tension you can see, which makes it the most workable of the hard aspects."),
|
||
"Trine": ("120° — same element", "The classic 'easy' aspect: both planets sit in signs of the same element and cooperate effortlessly. Trines are talents so native you barely notice them — which is their one danger: unexamined gifts stay undeveloped. A chart of nothing but trines is pleasant and goes nowhere; trines are the oil, not the engine."),
|
||
"Square": ("90° — same modality", "Two planets at cross-purposes in clashing signs of the same modality. This is friction you cannot ignore — an itch that demands action, which is exactly why squares build the strongest muscles in the chart. Most high achievers run on their squares. Unworked, they repeat as conflict; worked, they become your engine room."),
|
||
"Sextile": ("60° — compatible elements", "A friendly aspect between naturally compatible elements (fire–air, earth–water). Like the trine but politer: it offers an opportunity rather than hands you a gift. Sextiles reward deliberate use — a door that opens easily, but only if you walk over and try the handle."),
|
||
"Quincunx": ("150° — no shared ground", "Also called the inconjunct. The two signs share no element, no modality, no polarity — the planets simply cannot see each other. The result is a chronic, low-grade maladjustment that needs periodic conscious re-balancing, like a door that never quite hangs straight. Common in health and habit matters."),
|
||
"Semisextile": ("30° — next-door signs", "Adjacent signs — related by proximity but nothing else. A subtle irritant or a subtle resource; mostly felt as a faint background friction between two areas of life that ought to get along and don't quite."),
|
||
"Semisquare": ("45° — half a square", "A minor hard aspect: the square's friction at half strength but often more nagging, because it is easier to ignore. Shows up as recurring petty annoyances between the two planets' agendas."),
|
||
"Sesquiquadrate": ("135° — square and a half", "A minor hard aspect with an odd, ambushing quality — the tension surfaces at unexpected moments, often provoked by outside events. Handled consciously, it behaves like a small square."),
|
||
"Quintile": ("72° — a fifth of the circle", "A minor harmonious aspect linked to creative pattern-making. Quintiles mark a signature talent — a distinctly personal way of combining the two planets, often visible in an artist's or craftsman's style."),
|
||
"Biquintile": ("144° — two fifths", "The quintile's subtler sibling: a refined, almost private creative link between two planets. Rarely dramatic, often present in charts of people with a highly individual aesthetic."),
|
||
}
|
||
|
||
SYN_DYNAMICS = {
|
||
"Conjunction": "occupy the same degree — instant recognition; you amplify this part of each other, for better and worse",
|
||
"Opposition": "face each other across the wheel — classic magnetic attraction, with a built-in risk of projection and tug-of-war",
|
||
"Trine": "flow together — this part of each of you is effortlessly welcomed by the other; a genuine ease you'll both take for granted",
|
||
"Square": "collide — friction and chemistry in equal measure; this is where the relationship works or where it grinds",
|
||
"Sextile": "click when engaged — easy allies whenever you actually collaborate here",
|
||
"Quincunx": "keep just missing each other — a chronic small misalignment that needs humour and adjustment",
|
||
"Semisextile": "sit awkwardly adjacent — minor friction, easily ignored",
|
||
"Semisquare": "chafe now and then — a background irritant worth naming before it compounds",
|
||
"Sesquiquadrate": "provoke each other at odd moments — flare-ups that seem to come from nowhere",
|
||
"Quintile": "spark creatively — an unusual, inventive chemistry",
|
||
"Biquintile": "share a subtle creative wavelength",
|
||
}
|
||
|
||
|
||
def aspect_text(a, b, aspect, orb, applying=None):
|
||
da = PLANET_MEANING.get(a, (a.lower(), ""))[0]
|
||
db = PLANET_MEANING.get(b, (b.lower(), ""))[0]
|
||
dyn = ASPECT_DYNAMICS.get(aspect, "interact")
|
||
tight = "This is one of the defining aspects of your chart. " if orb <= 1.5 else ""
|
||
app = ""
|
||
if applying is True:
|
||
app = " (applying — its influence strengthens through life)"
|
||
elif applying is False:
|
||
app = " (separating — an influence you were born already knowing)"
|
||
note = PAIR_NOTES.get(frozenset([a, b]), "")
|
||
if note:
|
||
note = " " + note
|
||
return (f"{a} {aspect.lower()} {b} (orb {orb}°{app}): "
|
||
f"{da.capitalize()} and {db} {dyn}. {tight}{note}").strip()
|
||
|
||
|
||
BALANCE_TEXT = {
|
||
"Fire": "spirit, enthusiasm and the urge to act",
|
||
"Earth": "practicality, patience and the physical world",
|
||
"Air": "ideas, language and social connection",
|
||
"Water": "feeling, intuition and emotional bonds",
|
||
"Cardinal": "initiating — you start things",
|
||
"Fixed": "sustaining — you keep things going",
|
||
"Mutable": "adapting — you adjust and redistribute",
|
||
}
|
||
|
||
|
||
def balance_summary(balances):
|
||
lines = []
|
||
for group_name, group in (("elements", balances["elements"]), ("modalities", balances["modalities"])):
|
||
items = sorted(group.items(), key=lambda kv: -kv[1])
|
||
hi, hi_v = items[0]
|
||
lo, lo_v = items[-1]
|
||
if hi_v >= 2 * max(1, lo_v):
|
||
lines.append(f"Your chart is strongly weighted toward {hi} ({BALANCE_TEXT[hi]}).")
|
||
if lo_v == 0:
|
||
lines.append(f"You have no planets in {lo} — {BALANCE_TEXT[lo]} is the language you must consciously learn, and often the one you seek in partners.")
|
||
elif lo_v <= 1:
|
||
lines.append(f"{lo} is scarce in your chart — {BALANCE_TEXT[lo]} takes deliberate effort.")
|
||
return lines
|
||
|
||
|
||
def synastry_interpretation(syn, name_a, name_b):
|
||
"""Written compatibility report from compute_synastry() output."""
|
||
A = name_a or "Person A"
|
||
B = name_b or "Person B"
|
||
sections = []
|
||
|
||
sc = syn["scores"]
|
||
if sc["blend"] >= 60:
|
||
verdict = "an easy, mutually supportive connection — the harmony clearly outweighs the friction"
|
||
elif sc["blend"] >= 45:
|
||
verdict = "a balanced connection — real ease and real friction, which is the recipe for a relationship that stays interesting"
|
||
elif sc["blend"] >= 30:
|
||
verdict = "a high-voltage connection — more friction than flow, which brings intensity, growth and the need for honest work"
|
||
else:
|
||
verdict = "a demanding connection — the charts challenge each other at almost every turn; transformative if both choose it consciously"
|
||
sections.append({"heading": "Overview", "items": [{
|
||
"title": f"{A} × {B}",
|
||
"body": (f"{sc['contacts']} cross-chart contacts: harmony {sc['harmony']}, tension {sc['tension']} "
|
||
f"({sc['blend']:.0f}% flowing). This reads as {verdict}. "
|
||
"Remember: 'easy' is not the same as 'good' — squares and oppositions are what make two people matter to each other; "
|
||
"trines are what make it feel like home.")}]})
|
||
|
||
items = []
|
||
for x in syn["interaspects"]:
|
||
if x["weight"] < 1.0 and len(items) >= 12:
|
||
continue
|
||
da = PLANET_MEANING.get(x["a"], (x["a"].lower(), ""))[0]
|
||
db = PLANET_MEANING.get(x["b"], (x["b"].lower(), ""))[0]
|
||
dyn = SYN_DYNAMICS.get(x["aspect"], "interact")
|
||
body = (f"{A}'s {x['a']} and {B}'s {x['b']} {dyn} (orb {x['orb']}°). "
|
||
f"{A}'s {da} meets {B}'s {db} here.")
|
||
note = PAIR_NOTES.get(frozenset([x["a"], x["b"]]), "")
|
||
if note and x["weight"] >= 1.5:
|
||
body += " " + note
|
||
items.append({"title": f"{x['a']} {x['glyph']} {x['b']}", "body": body})
|
||
if len(items) >= 24:
|
||
break
|
||
sections.append({"heading": "Key Contacts", "items": items})
|
||
|
||
ov_items = []
|
||
for direction, rows, who, whose in (("a_in_b", syn["overlays"]["a_in_b"], A, B),
|
||
("b_in_a", syn["overlays"]["b_in_a"], B, A)):
|
||
picks = [r for r in rows if r["body"] in ("Sun", "Moon", "Venus", "Mars", "Saturn")]
|
||
for r in picks:
|
||
ov_items.append({"title": f"{who}'s {r['body']} in {whose}'s House {r['house']}",
|
||
"body": (f"{who}'s {PLANET_MEANING[r['body']][0]} lands in {whose}'s "
|
||
f"{HOUSE_MEANING[r['house']]}. {who} activates this whole area of "
|
||
f"{whose}'s life simply by being present.")})
|
||
if ov_items:
|
||
sections.append({"heading": "House Overlays", "items": ov_items})
|
||
return sections
|
||
|
||
|
||
def build_interpretation(chart):
|
||
"""Assemble the full report from a compute_chart() result."""
|
||
by_name = {b["name"]: b for b in chart["bodies"]}
|
||
asc_sign = chart["angles"][0]["position"]["sign"]
|
||
sections = []
|
||
|
||
big3 = []
|
||
if "Sun" in by_name:
|
||
s = by_name["Sun"]["position"]["sign"]
|
||
big3.append({"title": f"Sun in {s}", "body": SUN_IN_SIGN[s]})
|
||
if "Moon" in by_name:
|
||
s = by_name["Moon"]["position"]["sign"]
|
||
big3.append({"title": f"Moon in {s}", "body": MOON_IN_SIGN[s]})
|
||
if not chart.get("time_unknown"):
|
||
big3.append({"title": f"{asc_sign} Rising", "body": RISING_IN_SIGN[asc_sign]})
|
||
sections.append({"heading": "The Big Three", "items": big3})
|
||
|
||
items = []
|
||
for b in chart["bodies"]:
|
||
name = b["name"]
|
||
if name in ("Sun", "Moon", "South Node", "Part of Fortune"):
|
||
continue
|
||
sign = b["position"]["sign"]
|
||
txt = planet_in_sign(name, sign)
|
||
if not txt:
|
||
continue
|
||
extra = ""
|
||
if b["retrograde"]:
|
||
extra += " Retrograde at your birth: this function turns inward — it matures late, privately, and on its own terms."
|
||
if b["dignities"]:
|
||
dg = ", ".join(b["dignities"])
|
||
extra += f" ({dg} — this placement carries special weight.)"
|
||
items.append({"title": f"{name} in {sign}", "body": txt + extra})
|
||
sections.append({"heading": "Planets in Signs", "items": items})
|
||
|
||
if not chart.get("time_unknown"):
|
||
items = []
|
||
for b in chart["bodies"]:
|
||
txt = planet_in_house(b["name"], b["house"])
|
||
if txt:
|
||
items.append({"title": f'{b["name"]} in House {b["house"]}', "body": txt})
|
||
sections.append({"heading": "Planets in Houses", "items": items})
|
||
|
||
items = []
|
||
for a in chart["aspects"]:
|
||
if not a["major"] and a["orb"] > 1.5:
|
||
continue
|
||
items.append({"title": f'{a["a"]} {a["glyph"]} {a["b"]}',
|
||
"body": aspect_text(a["a"], a["b"], a["aspect"], a["orb"], a["applying"])})
|
||
sections.append({"heading": "Aspects", "items": items[:40]})
|
||
|
||
bal = balance_summary(chart["balances"])
|
||
extra_bits = []
|
||
if chart.get("moon_phase"):
|
||
mp = chart["moon_phase"]
|
||
extra_bits.append(f'You were born under a {mp["name"]} ({mp["illumination"]}% illuminated).')
|
||
extra_bits.append("This is a day chart — the Sun was above the horizon; solar themes (identity, visibility, purpose) lead."
|
||
if chart["is_day_chart"] else
|
||
"This is a night chart — the Sun was below the horizon; lunar themes (instinct, memory, belonging) lead.")
|
||
sections.append({"heading": "Chart Signature",
|
||
"items": [{"title": "Balances", "body": " ".join(bal) or "Your chart is unusually evenly balanced across elements and modalities — you can meet life in whatever language it speaks."},
|
||
{"title": "Sect & Moon Phase", "body": " ".join(extra_bits)}]})
|
||
return sections
|