Skip to content

Commit

Permalink
updated linter settings
Browse files Browse the repository at this point in the history
  • Loading branch information
bengarvey committed Oct 21, 2024
1 parent 61a254d commit 6a083b0
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 130 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"sourceType": "module"
},
"plugins": ["html"],
"extends": ["airbnb"],
"rules": {
"no-unused-expressions": ["error", { "allowTernary": true }],
"no-use-before-define": ["error", { "functions": false, "classes": true, "variables": true }],
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/eslint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ jobs:
run: npm install

- name: Run ESLint
run: npx eslint js/lineage.js index.html
run: npx eslint js/lineage.js index.html scripts/famgen.js
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
"eslint-plugin-airbnb-base": "^0.0.1-security",
"eslint-plugin-html": "^8.1.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-react-hooks": "^4.6.2"
"eslint-plugin-jsx-a11y": "^6.10.0"
}
}
255 changes: 129 additions & 126 deletions scripts/famgen.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const Chance = require('chance');

const chance = new Chance();

// Constants
const TOTAL_NODES = 10; // This is the number we start with, but we'll end up with more when we add spouses/kids
const MAX_CHILDREN = 5; // Max children per family
const MIN_CHILDREN = 0; // Min children per family
const GENDER_NEUTRAL_NAMES = [
const GENDER_NEUTRAL_NAMES = [
'Alex', 'Jordan', 'Taylor', 'Casey', 'Morgan', 'Riley', 'Avery', 'Quinn', 'Cameron', 'Peyton',
'Rowan', 'Sawyer', 'Charlie', 'Skyler', 'Dakota', 'Emerson', 'Finley', 'Harper', 'Phoenix', 'River',
'Bailey', 'Ellis', 'Hayden', 'Jesse', 'Marlowe', 'Shawn', 'Tatum', 'Addison', 'Ash', 'Blake',
Expand Down Expand Up @@ -50,73 +51,73 @@ const GENDER_NEUTRAL_NAMES = [
'Otto', 'Pace', 'Paxton', 'Rafe', 'Raleigh', 'Ranger', 'Ren', 'Rio', 'Roux', 'Ryker',
'Sequoia', 'Shai', 'Shane', 'Sonny', 'Sorren', 'Stone', 'Taj', 'Tanis', 'Taran', 'Tesla',
'Tobiah', 'Tobin', 'Torren', 'Trace', 'Trey', 'Tully', 'Wade', 'Wayne', 'Weston', 'Xander',
'York', 'Zeppelin', 'Zion', 'Ziv'
'York', 'Zeppelin', 'Zion', 'Ziv',
];
const NON_BINARY_PERCENTAGE = 0.03; // 3%
const SAME_SEX_PERCENTAGE = 0.05; // 5%

let nodes = [];
let links = [];
const nodes = [];
const links = [];
let currentId = 0;

// Keep track of sibling groups to prevent sibling marriages
let siblingGroups = [];
const siblingGroups = [];

// Helper Functions
const getRandomBirthDeathDates = () => {
const birthYear = parseInt(chance.year({ min: 1900, max: 2000 }), 10);
const minDeathYear = birthYear + 20;
const maxDeathYear = Math.min(minDeathYear + 80, 2100);
const birthYear = parseInt(chance.year({ min: 1900, max: 2000 }), 10);
const minDeathYear = birthYear + 20;
const maxDeathYear = Math.min(minDeathYear + 80, 2100);

const deathYear = parseInt(chance.year({ min: minDeathYear, max: maxDeathYear }), 10);
const deathYear = parseInt(chance.year({ min: minDeathYear, max: maxDeathYear }), 10);

const birthMonth = chance.integer({ min: 0, max: 11 });
const birthDay = chance.integer({ min: 1, max: 28 });
const deathMonth = chance.integer({ min: 0, max: 11 });
const deathDay = chance.integer({ min: 1, max: 28 });
const birthMonth = chance.integer({ min: 0, max: 11 });
const birthDay = chance.integer({ min: 1, max: 28 });
const deathMonth = chance.integer({ min: 0, max: 11 });
const deathDay = chance.integer({ min: 1, max: 28 });

const birthDate = new Date(birthYear, birthMonth, birthDay);
const deathDate = new Date(deathYear, deathMonth, deathDay);
const birthDate = new Date(birthYear, birthMonth, birthDay);
const deathDate = new Date(deathYear, deathMonth, deathDay);

if (isNaN(birthDate.getTime()) || isNaN(deathDate.getTime())) {
throw new Error('Invalid date generated');
}
if (Number.isNaN(birthDate.getTime()) || Number.isNaN(deathDate.getTime())) {
throw new Error('Invalid date generated');
}

return { birthDate, deathDate };
return { birthDate, deathDate };
};

const createNode = (gender) => {
const isNonBinary = Math.random() < NON_BINARY_PERCENTAGE;
let name;

if (isNonBinary || gender === 'non-binary') {
name = chance.pickone(GENDER_NEUTRAL_NAMES);
} else {
name = chance.first({ gender: gender.toLowerCase() });
}

const { birthDate, deathDate } = getRandomBirthDeathDates();

const node = {
id: currentId++,
name,
gender: isNonBinary ? 'non-binary' : gender,
lastName: chance.last(),
birthDate: birthDate.toISOString(),
deathDate: deathDate.toISOString()
};

nodes.push(node);
return node;
const isNonBinary = Math.random() < NON_BINARY_PERCENTAGE;
let name;

if (isNonBinary || gender === 'non-binary') {
name = chance.pickone(GENDER_NEUTRAL_NAMES);
} else {
name = chance.first({ gender: gender.toLowerCase() });
}

const { birthDate, deathDate } = getRandomBirthDeathDates();
currentId += 1;
const node = {
id: currentId,
name,
gender: isNonBinary ? 'non-binary' : gender,
lastName: chance.last(),
birthDate: birthDate.toISOString(),
deathDate: deathDate.toISOString(),
};

nodes.push(node);
return node;
};

const createLink = (sourceId, targetId, relation, color) => {
links.push({
source: sourceId,
target: targetId,
relation,
color
});
links.push({
source: sourceId,
target: targetId,
relation,
color,
});
};

const getParentType = (gender) => {
Expand All @@ -126,130 +127,132 @@ const getParentType = (gender) => {
};

const createFamilyTree = (parent1, parent2, generation = 1) => {
const numChildren = chance.integer({ min: MIN_CHILDREN, max: MAX_CHILDREN });
const siblingGroup = [];
const numChildren = chance.integer({ min: MIN_CHILDREN, max: MAX_CHILDREN });
const siblingGroup = [];

for (let i = 0; i < numChildren; i++) {
const childGender = chance.gender();
const child = createNode(childGender);
for (let i = 0; i < numChildren; i += 1) {
const childGender = chance.gender();
const child = createNode(childGender);

// Inherit last name
child.lastName = chance.pickone([parent1.lastName, parent2.lastName]);
// Inherit last name
child.lastName = chance.pickone([parent1.lastName, parent2.lastName]);

// Add child to sibling group
siblingGroup.push(child.id);
// Add child to sibling group
siblingGroup.push(child.id);

// Color parent-child links based on gender of the parent
let parent1Color = parent1.gender === 'Male' ? '#0000FF' : (parent1.gender === 'Female' ? '#FFC0CB' : '#800080');
let parent2Color = parent2.gender === 'Male' ? '#0000FF' : (parent2.gender === 'Female' ? '#FFC0CB' : '#800080');
// Color parent-child links based on gender of the parent
// eslint-disable-next-line no-nested-ternary
const parent1Color = parent1.gender === 'Male' ? '#0000FF' : (parent1.gender === 'Female' ? '#FFC0CB' : '#800080');
// eslint-disable-next-line no-nested-ternary
const parent2Color = parent2.gender === 'Male' ? '#0000FF' : (parent2.gender === 'Female' ? '#FFC0CB' : '#800080');

// Create parent-child links with appropriate colors
createLink(parent1.id, child.id, getParentType(parent1.gender), parent1Color);
createLink(parent2.id, child.id, getParentType(parent2.gender), parent2Color);
// Create parent-child links with appropriate colors
createLink(parent1.id, child.id, getParentType(parent1.gender), parent1Color);
createLink(parent2.id, child.id, getParentType(parent2.gender), parent2Color);

// Recursively generate more families
if (generation < 3) {
let spouseGender = chance.gender();
let isSameSexCouple = Math.random() < SAME_SEX_PERCENTAGE;
// Recursively generate more families
if (generation < 3) {
let spouseGender = chance.gender();
const isSameSexCouple = Math.random() < SAME_SEX_PERCENTAGE;

// For same-sex couple, spouse gender matches the child gender
if (isSameSexCouple) spouseGender = child.gender;
// For same-sex couple, spouse gender matches the child gender
if (isSameSexCouple) spouseGender = child.gender;

const spouse = createNode(spouseGender);
createLink(child.id, spouse.id, 'spouse', '#cc0');
const spouse = createNode(spouseGender);
createLink(child.id, spouse.id, 'spouse', '#cc0');

createFamilyTree(child, spouse, generation + 1);
}
createFamilyTree(child, spouse, generation + 1);
}
}

// Add sibling group to the siblingGroups list
if (siblingGroup.length > 1) {
siblingGroups.push(siblingGroup);
}
// Add sibling group to the siblingGroups list
if (siblingGroup.length > 1) {
siblingGroups.push(siblingGroup);
}
};

// Ensure no siblings marry by checking against sibling groups
const isValidMarriage = (person1Id, person2Id) => {
for (const group of siblingGroups) {
if (group.includes(person1Id) && group.includes(person2Id)) {
return false; // They are siblings
}
}
return true; // Not siblings
};

const linkUnlinkedDescendants = () => {
const unlinked = findUnlinkedDescendants();

chance.shuffle(unlinked);

// Pair up unlinked descendants and create spouse relationships
for (let i = 0; i < unlinked.length - 1; i += 2) {
const descendant1 = unlinked[i];
const descendant2 = unlinked[i + 1];

if (isValidMarriage(descendant1.id, descendant2.id)) {
// Create a spousal link between them
createLink(descendant1.id, descendant2.id, 'spouse', '#cc0');

// Generate children for the newly formed couple
createFamilyTree(descendant1, descendant2);
}
// eslint-disable-next-line no-restricted-syntax
for (const group of siblingGroups) {
if (group.includes(person1Id) && group.includes(person2Id)) {
return false; // They are siblings
}
}
return true; // Not siblings
};

const findUnlinkedDescendants = () => {
const unlinked = [];
const linked = new Set();

// Traverse through all links and mark linked individuals as 'spouses'
links.forEach(link => {
if (link.relation === 'spouse') {
linked.add(link.source);
linked.add(link.target);
}
links.forEach((link) => {
if (link.relation === 'spouse') {
linked.add(link.source);
linked.add(link.target);
}
});

// Find nodes that are not linked as a spouse
nodes.forEach(node => {
if (!linked.has(node.id)) {
unlinked.push(node);
}
nodes.forEach((node) => {
if (!linked.has(node.id)) {
unlinked.push(node);
}
});

return unlinked;
};

const linkUnlinkedDescendants = () => {
const unlinked = findUnlinkedDescendants();

chance.shuffle(unlinked);

// Pair up unlinked descendants and create spouse relationships
for (let i = 0; i < unlinked.length - 1; i += 2) {
const descendant1 = unlinked[i];
const descendant2 = unlinked[i + 1];

if (isValidMarriage(descendant1.id, descendant2.id)) {
// Create a spousal link between them
createLink(descendant1.id, descendant2.id, 'spouse', '#cc0');

// Generate children for the newly formed couple
createFamilyTree(descendant1, descendant2);
}
}
};

// Create initial family
const createInitialFamilies = () => {
const numFamilies = TOTAL_NODES / (MAX_CHILDREN + 2); // Estimate
for (let i = 0; i < numFamilies; i++) {
const parent1Gender = chance.gender();
let parent2Gender = chance.gender();
const numFamilies = TOTAL_NODES / (MAX_CHILDREN + 2); // Estimate
for (let i = 0; i < numFamilies; i += 1) {
const parent1Gender = chance.gender();
let parent2Gender = chance.gender();

// Same-sex couple logic
let isSameSexCouple = Math.random() < SAME_SEX_PERCENTAGE;
if (isSameSexCouple) parent2Gender = parent1Gender;
// Same-sex couple logic
const isSameSexCouple = Math.random() < SAME_SEX_PERCENTAGE;
if (isSameSexCouple) parent2Gender = parent1Gender;

const parent1 = createNode(parent1Gender);
const parent2 = createNode(parent2Gender);
const parent1 = createNode(parent1Gender);
const parent2 = createNode(parent2Gender);

// Link parents as spouses
createLink(parent1.id, parent2.id, 'spouse', '#cc0');
// Link parents as spouses
createLink(parent1.id, parent2.id, 'spouse', '#cc0');

// Create their family
createFamilyTree(parent1, parent2);
}
// Create their family
createFamilyTree(parent1, parent2);
}
};

// Run the generator
createInitialFamilies();
linkUnlinkedDescendants();

const dataset = {
nodes,
links
nodes,
links,
};

// Output the dataset (or write to a file)
Expand Down

0 comments on commit 6a083b0

Please sign in to comment.