JSFiddle - React, Tailwind, and code Playground

by peterolson

HTML

<pre id="data">

 1  ?  ? F Agatha
 2  ?  ? M Adam
 3  ?  ? F Betty
 4  1  2 M Bertrand
 5  1  2 F Charlotte
 6  ?  ? M Carl
 7  ?  ? F Daisy
 8  3  4 M David
 9  5  6 F Emma
10  ?  ? M Edward
11  ?  ? F Freya
12  7  8 M Fred
13  9 10 F Grace
14  ?  ? M Gerald
15  ?  ? F Hillary
16 11 12 M Herbert
17 13 14 F Jane
18  ?  ? M James
19 15 16 F Kate
20 17 18 M Larry
21  ? 18 F Mary</pre>

<pre id="input">1 2
8 3
9 13
4 5
9 4
5 8
16 7
1 9
12 5
4 13
16 3
6 17
19 1
2 17
20 4
5 16
8 9
19 20
16 9
12 17
21 20</pre>

JavaScript

var lines = document.getElementById("data").innerHTML.replace(/\n(\W)+/g, "\n").split("\n");
var people = [{
    m: "",
    f: ""
}];
for (var i = 1; i < lines.length; i++) {
    var line = lines[i].replace(/ ( )+/g, " ").split(" ");
    people[+line[0]] = {
        m: line[1] == "?" ? -1 : +line[1],
        f: line[2] == "?" ? -1 : +line[2],
        s: line[3],
        n: line[4]
    };
}

var isSibling = function (a, b) {
    a = people[a];
    b = people[b];
    if ((~a.m && a.m == b.m) && (~a.f && a.f == b.f)) return a.s == "M" ? "brother" : "sister";
}
var isHalfSibling = function (a, b) {
    a = people[a];
    b = people[b];
    if ((~a.m && a.m == b.m) || (~a.f && a.f == b.f)) return a.s == "M" ? "half-brother" : "half-sister";
}
var ordinalify = function (n) {
    var s = ("0" + n).slice(-2),
        t = s[0];
    s = s[1];
    return n + (t == 1 ? "th" : s == 1 ? "st" : s == 2 ? "nd" : s == 3 ? "rd" : "th") + " ";
}
var timesify = function (n) {
    return n == 1 ? "once" : n == 2 ? "twice" : n == 3 ? "thrice" : n + " times";
}
var isAncestor = function (ancestor, child) {
    var children = [child],
        ancestors = [people[child].m, people[child].f],
        i, name;
    for (i = 0; i < people.length; i++) {
        if (~ancestors.indexOf(ancestor)) break;
        children = ancestors.slice();
        ancestors = [];
        for (var c = 0; c < children.length; c++) if (children[c] >= 0) ancestors.push(people[children[c]].m, people[children[c]].f);
    }
    if (i >= people.length) return;
    name = people[ancestor].s == "M" ? "father" : "mother";
    if (i > 0) name = "grand" + name;
    if (i > 1) name = "great-" + name;
    if (i > 2) name = ordinalify(i - 1) + name;
    return name;
}
var isDescendant = function (descendant, ancestor) {
    var relation = isAncestor(ancestor, descendant);
    if (relation) return relation.slice(0, -6) + (people[descendant].s == "M" ? "son" : "daughter");
}
var getSiblings = function (person) {
    var sibs =...