Skip to content

Commit

Permalink
Refactor child connectors
Browse files Browse the repository at this point in the history
  • Loading branch information
SanichKotikov committed Mar 18, 2021
1 parent 8b543c9 commit 8c202de
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 63 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# relatives-tree

A tiny library (~3.02 KB gz) for calculating specific JSON data to family tree nodes and connectors.
A tiny library (~3.01 KB gz) for calculating specific JSON data to family tree nodes and connectors.

🖥 [Here is a demo](https://sanichkotikov.github.io/react-family-tree-example/) app with React rendering.

Expand Down
96 changes: 46 additions & 50 deletions src/connectors/children.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,63 @@
import { getParentsX, withType } from '../utils/family';
import { getUnitX, nodeCount, nodeIds } from '../utils/units';
import { withType } from '../utils/family';
import { inAscOrder, max, min, withId } from '../utils';
import { SIZE } from '../constants';
import { Connector, Family, FamilyType } from '../types';
import { inAscOrder, max, min, withId, withIds } from '../utils';
import { HALF_SIZE, NODES_IN_COUPLE, SIZE } from '../constants';
import { Connector, Family, FamilyType, Unit } from '../types';

// TODO refactor
export const children = (families: Family[]): Connector[] => {
const connectors: Connector[] = [];
export const children = (families: readonly Family[]): readonly Connector[] => (
families
.filter(withType(FamilyType.root, FamilyType.child))
.reduce<Connector[]>((connectors, family) => {
const parent: Unit | undefined = family.parents[0];

families.filter(withType(FamilyType.root, FamilyType.child)).forEach(family => {
let pX = 0;
const mY = family.Y + (family.parents.length ? SIZE : 0);

if (family.parents.length === 1) {
const pUnit = family.parents[0];
pX = getUnitX(family, pUnit) + nodeCount(pUnit); // TODO
const pX = getParentsX(family, parent);
const mY = family.Y + (parent ? SIZE : 0);

// from parent(s) to child
if (pUnit.nodes.every(node => !!node.children.length)) {
const pY = family.Y + 1;
if (parent && parent.nodes.every(node => !!node.children.length)) {
const pY = family.Y + HALF_SIZE;
connectors.push([pX, pY, pX, mY]);
}
}

const parentIds = family.parents.map(nodeIds).flat();
const parentIds = family.parents.map(nodeIds).flat();
const positions: number[] = [];

const cXs: number[] = [];
family.children.forEach(unit => {
const left = getUnitX(family, unit) + HALF_SIZE;

family.children.forEach(cUnit => {
const cX = getUnitX(family, cUnit) + 1;
// from child to parent(s)
unit.nodes.forEach((node, index) => {
if (node.parents.some(withIds(parentIds))) {
const nX = left + (index * SIZE);
positions.push(nX);
connectors.push([nX, mY, nX, mY + HALF_SIZE]);
}
});

// from child to parent(s)
cUnit.nodes.forEach((node, index) => {
if (node.parents.find(rel => parentIds.indexOf(rel.id) !== -1)) {
const nX = cX + (index * 2);
cXs.push(nX);
connectors.push([nX, mY, nX, mY + 1]);
// between child and child's spouse
if (nodeCount(unit) === NODES_IN_COUPLE) {
connectors.push([left, mY + HALF_SIZE, left + SIZE, mY + HALF_SIZE]);
}
});

// between child and child's spouse
if (nodeCount(cUnit) === 2) {
connectors.push([cX, mY + 1, cX + 2, mY + 1]);
}
else if (nodeCount(cUnit) === 1 && cUnit.nodes[0].spouses.length) {
family.children.forEach(nUnit => {
if (nUnit.nodes.findIndex(withId(cUnit.nodes[0].spouses[0].id)) !== -1) {
const xX = [cX, getUnitX(family, nUnit) + 1].sort(inAscOrder);
connectors.push([xX[0], mY + 1, xX[1], mY + 1]);
}
});
}
});
// between child and child's side spouse
else if (nodeCount(unit) === 1 && unit.nodes[0].spouses.length) {
family.children.forEach(nUnit => {
if (nUnit.nodes.some(withId(unit.nodes[0].spouses[0].id))) {
const xX = [left, getUnitX(family, nUnit) + HALF_SIZE].sort(inAscOrder);
connectors.push([xX[0], mY + HALF_SIZE, xX[1], mY + HALF_SIZE]);
}
});
}
});

if (cXs.length > 1) {
// horizontal above children
connectors.push([min(cXs), mY, max(cXs), mY]);
}
else if (cXs.length === 1 && pX !== cXs[0]) {
if (positions.length > 1)
connectors.push([min(positions), mY, max(positions), mY]);

// horizontal between parent(s) and child
connectors.push([Math.min(pX, cXs[0]), mY, Math.max(pX, cXs[0]), mY]);
}
});
else if (positions.length === 1 && pX !== positions[0])
connectors.push([Math.min(pX, positions[0]), mY, Math.max(pX, positions[0]), mY]);

return connectors;
};
return connectors;
}, [])
);
4 changes: 2 additions & 2 deletions src/connectors/middle.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { inAscOrder, withId } from '../utils';
import { getUnitX, nodeCount } from '../utils/units';
import { withType } from '../utils/family';
import { HALF_SIZE, SIZE } from '../constants';
import { HALF_SIZE, NODES_IN_COUPLE, SIZE } from '../constants';
import { Connector, Family, FamilyType, Unit } from '../types';

const calcConnectors = (family: Family, families: readonly Family[]) => (
(connectors: Connector[], unit: Unit) => {
const pX = getUnitX(family, unit) + HALF_SIZE;
const pY = family.Y + HALF_SIZE;

if (nodeCount(unit) === 2) {
if (nodeCount(unit) === NODES_IN_COUPLE) {
connectors.push([pX, pY, pX + SIZE, pY]);
}
// TODO: update and refactor
Expand Down
8 changes: 4 additions & 4 deletions src/connectors/parents.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { prop, withIds } from '../utils';
import { getUnitX, nodeCount } from '../utils/units';
import { withType } from '../utils/family';
import { HALF_SIZE, SIZE } from '../constants';
import { getParentsX, withType } from '../utils/family';
import { HALF_SIZE, NODES_IN_COUPLE, SIZE } from '../constants';
import { Connector, Family, FamilyType, Unit } from '../types';

const getChildIDs = (unit: Unit): readonly string[] => (
Expand All @@ -10,12 +10,12 @@ const getChildIDs = (unit: Unit): readonly string[] => (

const calcConnectors = (family: Family) => (
(connectors: Connector[], unit: Unit) => {
const pX = getUnitX(family, unit) + nodeCount(unit);
const pX = getParentsX(family, unit);
const pY = family.Y + HALF_SIZE;
const mY = family.Y + SIZE;

// between parents
if (nodeCount(unit) === 2) connectors.push([pX - HALF_SIZE, pY, pX + HALF_SIZE, pY]);
if (nodeCount(unit) === NODES_IN_COUPLE) connectors.push([pX - HALF_SIZE, pY, pX + HALF_SIZE, pY]);
// from parent(s) to child
connectors.push([pX, pY, pX, mY]);

Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export const SIZE = 2;
export const HALF_SIZE = SIZE / 2;

export const NODES_IN_COUPLE = 2;
3 changes: 2 additions & 1 deletion src/middle/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { setDefaultUnitShift } from '../utils/setDefaultUnitShift';
import { prop, withRelType } from '../utils';
import { newFamily } from '../utils/family';
import { unitsToNodes } from '../utils/units';
import { NODES_IN_COUPLE } from '../constants';
import { Family, FamilyType, Node, RelType } from '../types';
import { correctOverlaps } from './correctOverlaps';

Expand Down Expand Up @@ -39,7 +40,7 @@ export const createBloodFamilies = (store: Store): readonly Family[] => {
const mainFamily = createFamily(store.root.parents.map(prop('id')), FamilyType.root, true);
const parents = unitsToNodes(mainFamily.parents);

if (parents.length === 2) {
if (parents.length === NODES_IN_COUPLE) {
const { left, right } = getSpouseNodesFunc(store)(parents);

return [
Expand Down
1 change: 1 addition & 0 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { toMap, withId } from './utils';
import { withType } from './utils/family';
import { Family, FamilyType, Node } from './types';

// TODO think about refactoring
class Store {

private nextId: number;
Expand Down
6 changes: 5 additions & 1 deletion src/utils/family.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SIZE } from '../constants';
import { Family, FamilyType, Unit } from '../types';
import { max } from './index';
import { nodeCount, rightSide } from './units';
import { getUnitX, nodeCount, rightSide } from './units';

export const newFamily = (id: number, type: FamilyType, main = false): Family => ({
id,
Expand All @@ -23,3 +23,7 @@ export const heightOf = (family: Family): number => [
export const rightOf = (family: Family): number => family.X + widthOf(family);
export const bottomOf = (family: Family) => family.Y + heightOf(family);
export const unitNodesCount = (units: readonly Unit[]): number => units.reduce((acc, b) => acc + nodeCount(b), 0);

export const getParentsX = (family: Family, unit: Unit | undefined): number => {
return unit ? getUnitX(family, unit) + nodeCount(unit) : 0;
};
5 changes: 3 additions & 2 deletions src/utils/getExtendedNodes.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { getUnitX } from './units';
import { hasHiddenRelatives } from './hasHiddenRelatives';
import { SIZE } from '../constants';
import { ExtNode, Family, FamilyType, Node, Unit } from '../types';

const extendNode = (family: Family) => (
(unit: Unit) => (
unit.nodes.map((node: Node, idx: number) => ({
...node,
top: family.Y + (unit.child && !!family.parents.length ? 2 : 0),
left: getUnitX(family, unit) + (idx * 2),
top: family.Y + (unit.child && !!family.parents.length ? SIZE : 0),
left: getUnitX(family, unit) + (idx * SIZE),
hasSubTree: hasHiddenRelatives(family, node),
}))
)
Expand Down
3 changes: 1 addition & 2 deletions src/utils/getSpouseNodesFunc.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import Store from '../store';
import { NODES_IN_COUPLE } from '../constants';
import { Node, Relation, RelType } from '../types';
import { byGender, relToNode, withRelType } from './index';

const NODES_IN_COUPLE = 2;

type SpousesNodes = {
left: readonly Node[];
middle: readonly Node[];
Expand Down

0 comments on commit 8c202de

Please sign in to comment.