Skip to content

Commit

Permalink
feature(horoscope): add aspects to response (#7)
Browse files Browse the repository at this point in the history
* Refactor aspect test

* Add orbs when calculating aspects

* Disable rules of arrow-line-body

* Add direction of aspect (bidirecional/unidirectional)

* Add aspects to /horoscope response (using huber orbs)
  • Loading branch information
ryuphi committed Dec 14, 2020
1 parent 3dd5f6a commit 37e8a09
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Expand Up @@ -11,7 +11,8 @@ module.exports = {
camelcase: 0,
"no-bitwise": ["error", { allow: ["|"] }],
"max-len": 0,
quotes: [2, "double", "avoid-escape"]
quotes: [2, "double", "avoid-escape"],
"arrow-body-style": 0
},
settings: {
"import/resolver": {
Expand Down
3 changes: 2 additions & 1 deletion src/api/index.js
Expand Up @@ -10,7 +10,7 @@ router.get("/horoscope", async (req, res) => {
const { latitude, longitude } = req.query;

const planets = astrologer.planets(date);

const aspects = astrologer.aspects(planets);
const houses = astrologer.houses(date, {
latitude: parseFloat(latitude),
longitude: parseFloat(longitude),
Expand All @@ -22,6 +22,7 @@ router.get("/horoscope", async (req, res) => {
...planets,
},
...houses,
aspects
},
});
});
Expand Down
130 changes: 130 additions & 0 deletions src/astrologer/aspects.js
@@ -0,0 +1,130 @@
const { normalizeDegrees } = require("./utils");

const ASPECTS = {
0: "conjunction",
30: "semisextile",
60: "sextile",
90: "quadrature",
120: "trigone",
150: "quincunx",
180: "opposition",
};

// HUBER ORBS... but mars and jupiter modified...
const DEFAULT_ORBS = {
luminary: {
0: 10,
30: 3,
60: 5,
90: 6,
120: 8,
150: 5,
180: 10
},
personal: {
0: 7,
30: 2,
60: 4,
90: 5,
120: 6,
150: 2,
180: 7
},
social: {
0: 6,
30: 1.5,
60: 3,
90: 4,
120: 5,
150: 3,
180: 6
},
transpersonal: {
0: 5,
30: 1,
60: 2,
90: 3,
120: 4,
150: 2,
180: 5
},
other: {
0: 5,
30: 1,
60: 2,
90: 3,
120: 4,
150: 2,
180: 5
}
};

const calculateAspect = (first, second, orbs) => {
return Object.keys({ ...ASPECTS }).filter(
(a) => {
const totalOrbsForAspect = orbs[a];
const from = parseFloat(a) - (totalOrbsForAspect / 2);
const to = parseFloat(a) + (totalOrbsForAspect / 2);

const firstLongitude = normalizeDegrees(first.position.longitude);
const secondLongitude = normalizeDegrees(second.position.longitude);

const diff = Math.abs(firstLongitude - secondLongitude);
return diff >= from && diff <= to;
}
);
};

const aspect = (first, second, orbs) => {
if (orbs === undefined) {
orbs = { ...DEFAULT_ORBS };
}

const aspectsFirst = calculateAspect(first, second, orbs[first.type]);
const aspectsSecond = calculateAspect(first, second, orbs[second.type]);

if (aspectsFirst.length === 0 && aspectsSecond.length === 0) {
return undefined;
}

const direction = aspectsFirst.length === 1 && aspectsSecond.length === 1 ? "bidirectional" : "unidirectional";

return {
name: ASPECTS[aspectsFirst[0]],
direction,
first: {
name: first.name,
exist: aspectsFirst.length === 1
},
second: {
name: second.name,
exist: aspectsSecond.length === 1
},
};
};

const aspects = (planets) => {
return Object.keys(planets).reduce((acc, planetKey) => {
if (acc[planetKey]) {
return acc;
}

acc[planetKey] = [];

Object.values(planets).filter((p) => p.name !== planetKey).forEach((p) => {
if (!acc[p.name]) {
const aspectsFounds = aspect(planets[planetKey], p);
if (aspectsFounds) {
acc[planetKey].push(aspectsFounds);
}
}
});

return acc;
}, {});
};

module.exports = {
aspect,
aspects
};
20 changes: 20 additions & 0 deletions src/astrologer/astros.js
Expand Up @@ -23,6 +23,25 @@ const PLANETS = {
juno: swisseph.SE_JUNO,
};

const planetsByType = {
sun: "luminary",
moon: "luminary",
mercury: "personal",
venus: "personal",
mars: "personal",
jupiter: "social",
saturn: "social",
uranus: "transpersonal",
neptune: "transpersonal",
pluto: "transpersonal",
chiron: "other",
lilith: "other",
ceres: "other",
vesta: "other",
pallas: "other",
juno: "other",
};

const FLAG = swisseph.SEFLG_SPEED | swisseph.SEFLG_SWIEPH;

const getPositionOfAstro = (astro, julianDayUT) => swisseph.swe_calc_ut(julianDayUT, PLANETS[astro], FLAG);
Expand All @@ -44,4 +63,5 @@ const position = (astrologyObject, moment) => {
module.exports = {
PLANETS,
position,
planetsByType
};
8 changes: 6 additions & 2 deletions src/astrologer/index.js
@@ -1,5 +1,6 @@
const { PLANETS, position } = require("./astros");
const { PLANETS, position, planetsByType } = require("./astros");
const { houses } = require("./houses");
const { aspect, aspects } = require("./aspects");

const planets = (date) => {
const astros = Object.keys(PLANETS)
Expand All @@ -9,6 +10,7 @@ const planets = (date) => {
accumulator[name] = {
name,
...planetPosition,
type: planetsByType[name]
};
return accumulator;
},
Expand All @@ -21,5 +23,7 @@ module.exports = {
houses,
position,
PLANETS,
planets
planets,
aspect,
aspects,
};
12 changes: 12 additions & 0 deletions src/astrologer/utils.js
Expand Up @@ -27,8 +27,20 @@ const degreesToDms = (value) => {

const zodiacSign = (degrees) => (Math.floor(degrees / 30) % 12) + 1;

const normalizeDegrees = (degress) => {
if (degress < -180) {
return degress + 360;
}
if (degress > 180) {
return degress - 360;
}

return degress;
};

module.exports = {
utcToJulianUt,
degreesToDms,
zodiacSign,
normalizeDegrees
};
62 changes: 62 additions & 0 deletions test/units/calculate-aspects-between-two-planets.test.js
@@ -0,0 +1,62 @@
const astrologer = require("./../../src/astrologer");

describe("Calculate aspects between two planets", () => {
const planetOne = {
name: "sun",
type: "luminary",
position: {
longitude: 10,
},
};

const planetTwo = {
name: "pluto",
type: "transpersonal",
position: {
longitude: 30,
},
};

it("2 planets may have no aspects", async () => {
planetOne.position.longitude = 10;
planetTwo.position.longitude = 30;
const aspect = astrologer.aspect(planetOne, planetTwo);
expect(aspect).toBe(undefined);
});

it("If two planets longitude difference is equal to 30 then exist conjunction", async () => {
planetOne.position.longitude = 30;
planetTwo.position.longitude = 30;
const aspect = astrologer.aspect(planetOne, planetTwo);
expect(aspect.name).toBe("conjunction");
});

it("If two planets longitude difference is equal to 60 then exist sextile", async () => {
planetOne.position.longitude = 30;
planetTwo.position.longitude = 90;

const aspect = astrologer.aspect(planetOne, planetTwo);
expect(aspect.name).toBe("sextile");
});

it("If two planets longitude difference is equal to 90 then exist quadrature", async () => {
planetOne.position.longitude = 0;
planetTwo.position.longitude = 90;
const aspect = astrologer.aspect(planetOne, planetTwo);
expect(aspect.name).toBe("quadrature");
});

it("If two planets longitude difference is equal to 120 then exist trigone", async () => {
planetOne.position.longitude = 355;
planetTwo.position.longitude = 115;
const aspect = astrologer.aspect(planetOne, planetTwo);
expect(aspect.name).toBe("trigone");
});

it("If two planets longitude difference is equal to 180 then exist opposition", async () => {
planetOne.position.longitude = -270;
planetTwo.position.longitude = -90;
const aspect = astrologer.aspect(planetOne, planetTwo);
expect(aspect.name).toBe("opposition");
});
});

0 comments on commit 37e8a09

Please sign in to comment.