Closed weathertopper closed 7 years ago
# I want to build up the tree by LEVEL
# TREE TRUNKS
# TRUNK INDEX 0
# violet's parent 0
# violet 1
# robert 2 -- cora 2
# rosamund 2
# mary 3 -- matthew 3
# edith 3 -- bertie 3
# sybil 3 -- tom 3
# sibbie 4
# george 4
# marigold 4
# TRUNK INDEX 1
# martha 0
# harold 1
# cora 1 STOP
# TRUNK INDEX 2
# isobel 0
# matthew 1 STOP
# TRUNK 3
# tom 0 STOP
# COMBINE THE TRUNKS
# merge to the greater number (subtract the smaller number)
# keep track of merge points
#[tom (TRUNK 0 & 3), matthew (TRUNK 0 & 2), cora (TRUNK 0 & 1)]
# MERGING TOM
# height in trunk 0 == 3
# height in trunk 3 == 0
# MERGE INTO TRUNK 0, ALTER INDICES IN TRUNK 3 BY <OFFSET>
# offset = 3 - 0 = 3
# GO BACK THROUGH TRUNK 3, STARTING AT SUPERPARENT, WITH NEW INDEX OFFSET (3)
# tom index = 0 + 3
# (DONE, THERE WAS NOTHING ELSE IN TRUNK 3)
#
# MERGING MATTHEW
# height in trunk 0 == 3
# height in trunk 2 == 1
# MERGE INTO TRUNK 0, ALTER INDICES IN TRUNK 2 BY <OFFSET>
# offset = 3 - 1 == 2
# GO BACK THROUGH TRUNK 2, STARTING AT SUPERPARENT, WITH NEW INDEX OFFSET (2)
# isobel index = 0 + 2 == 2
# matthew index = 1 + 2 = 3
# (DONE, THERE WAS NOTHING ELSE IN TRUNK 2)
#
#
# MERGING CORA
# height in trunk 0 = 2
# height in trunk 1 = 1
# MERGE INTO TRUNK 0, ALTER INDICES IN TRUNK 1 BY <HEIGHT>
# offset = 2 - 1 = 1
# GO BACK THROUGH TRUNK 1, STARTING AT SUPERPARENT, WITH NEW INDEX OFFSET (1)
# martha index = 0 + 1 = 1
# harond index = 1 + 1 = 2
# cora index = 1 + 1 = 2
#
# NOTICE I ADDED A FAKE RELATIVE ABOVE VIOLET
# CHUCK ALL OBJECTS INTO TRUNK 0. THERE YOU GO
# could order trunk entries during build, but who cares.
def deepSearch (relative, trunks)
found_trunk = -1
found_level = -1
# trunks is array of trunks
trunks.each_with_index do |trunk, trunk_index|
break if (found_trunk > -1) && (found_level > -1)
# trunk is array of levels
trunk.each_with_index do |level, level_index|
break if (found_trunk > -1) && (found_level > -1)
if level.include? relative
found_trunk = trunk_index
found_level = level_index
end
end
end
return {"relative" => relative, "found_trunk" => found_trunk, "found_level" => found_level}
end
# I can compare returned hash to 'null hash'
# (which is {"relative" => relative, "found_trunk" => -1, "found_level" => -1} ) using == ops
What the hell is that? ^^ I don't understand that at all
So I figured it out. I'm sorry to be pasting code here, but I don't have an actual code repo setup yet.
# tree is array of {relative, level} hashes
def buildTree(root, relatives, offspring_branches, spouse_branches)
# 'root' is a predefined relative- assumed to be the first person ever added to the tree
#tree init
tree = [{"relative" => root, "level" => 0}]
tree.each do |knob|
relative = knob["relative"]
level = knob["level"]
#adding spouses
if (relative.sex == 'male') # there has to be a better way to do this
relative.spouse_branches.each do |spouse_branch|
wife = Relative.find(spouse_branch.wife_id)
unless treeIncludes(wife, tree )
tree.insert(tree.length, {"relative" => wife, "level" => level})
end
end
else
relative.spouse_branches.each do |spouse_branch|
husband = Relative.find(spouse_branch.husband_id)
unless treeIncludes(husband, tree )
tree.insert(tree.length, {"relative" => husband, "level" => level})
end
end
end
#adding kids
relative.offspring_branches.each do |kid_branch|
kid = Relative.find(kid_branch.child_id)
unless treeIncludes(kid, tree )
tree.insert(tree.length, {'relative' => kid, "level" => level+1})
end
end
#adding parents
relative.reverse_offspring_branches.each do |parent_branch|
parent = Relative.find(parent_branch.parent_id)
unless treeIncludes(parent, tree )
tree.insert(tree.length, {'relative' => parent, "level" => level-1})
end
end
end
tree.sort_by! { |knob| knob['level'] }
return tree
end
def treeIncludes(relative, tree)
tree.each do |knob|
if knob['relative'] == relative
return true
end
end
return false
end
This is a breadth-first search for the record. Yay algorithms!
^^make the levels start at 0
So this starts at 0, but it's otherwise the same
# tree is array of {relative, level} hashes
def buildTree(root, relatives, offspring_branches, spouse_branches)
# 'root' is a predefined relative- assumed to be the first person ever added to the tree
#tree init
tree = [{"relative" => root, "level" => 0}]
tree.each do |knob|
relative = knob["relative"]
level = knob["level"]
#adding spouses
if (relative.sex == 'male') # there has to be a better way to do this
relative.spouse_branches.each do |spouse_branch|
wife = Relative.find(spouse_branch.wife_id)
unless treeIncludes(wife, tree )
tree.insert(tree.length, {"relative" => wife, "level" => level})
end
end
else
relative.spouse_branches.each do |spouse_branch|
husband = Relative.find(spouse_branch.husband_id)
unless treeIncludes(husband, tree )
tree.insert(tree.length, {"relative" => husband, "level" => level})
end
end
end
#adding kids
relative.offspring_branches.each do |kid_branch|
kid = Relative.find(kid_branch.child_id)
unless treeIncludes(kid, tree )
tree.insert(tree.length, {'relative' => kid, "level" => level+1})
end
end
#adding parents
relative.reverse_offspring_branches.each do |parent_branch|
parent = Relative.find(parent_branch.parent_id)
unless treeIncludes(parent, tree )
tree.insert(tree.length, {'relative' => parent, "level" => level-1})
end
end
end
#sort smallest to largest (highest to lowest) level
tree.sort_by! { |knob| knob['level'] }
#normalize so 'highest' level is 0
smallest_level = tree[0]['level']
difference_to_0 = 0 - smallest_level
tree.each do |knob|
knob['level'] += difference_to_0
end
return tree
end
def treeIncludes(relative, tree)
tree.each do |knob|
if knob['relative'] == relative
return true
end
end
return false
end
So this is the code from the codepen above that turns unordered lists to rough trees
CSS:
* {margin: 0; padding: 0;}
.tree ul {
padding-top: 20px; position: relative;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
transition: all 0.5s;
}
.tree li {
float: left; text-align: center;
list-style-type: none;
position: relative;
padding: 20px 5px 0 5px;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
transition: all 0.5s;
}
/*We will use ::before and ::after to draw the connectors*/
.tree li::before, .tree li::after{
content: '';
position: absolute; top: 0; right: 50%;
border-top: 1px solid #ccc;
width: 50%; height: 45px;
z-index: -1;
}
.tree li::after{
right: auto; left: 50%;
border-left: 1px solid #ccc;
}
/*We need to remove left-right connectors from elements without
any siblings*/
.tree li:only-child::after, .tree li:only-child::before {
display: none;
}
/*Remove space from the top of single children*/
.tree li:only-child{ padding-top: 0;}
/*Remove left connector from first child and
right connector from last child*/
.tree li:first-child::before, .tree li:last-child::after{
border: 0 none;
}
/*Adding back the vertical connector to the last nodes*/
.tree li:last-child::before{
border-right: 1px solid #ccc;
border-radius: 0 5px 0 0;
-webkit-transform: translateX(1px);
-moz-transform: translateX(1px);
transform: translateX(1px);
-webkit-border-radius: 0 5px 0 0;
-moz-border-radius: 0 5px 0 0;
border-radius: 0 5px 0 0;
}
.tree li:first-child::after{
border-radius: 5px 0 0 0;
-webkit-border-radius: 5px 0 0 0;
-moz-border-radius: 5px 0 0 0;
}
/*Time to add downward connectors from parents*/
.tree ul ul::before{
content: '';
position: absolute; top: -12px; left: 50%;
border-left: 1px solid #ccc;
width: 0; height: 32px;
z-index: -1;
}
.tree li a{
border: 1px solid #ccc;
padding: 5px 10px;
text-decoration: none;
color: #666;
font-family: arial, verdana, tahoma;
font-size: 11px;
display: inline-block;
background: white;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
transition: all 0.5s;
}
.tree li a+a {
margin-left: 20px;
position: relative;
}
.tree li a+a::before {
content: '';
position: absolute;
border-top: 1px solid #ccc;
top: 50%; left: -21px;
width: 20px;
}
/*Time for some hover effects*/
/*We will apply the hover effect the the lineage of the element also*/
.tree li a:hover, .tree li a:hover~ul li a {
background: #c8e4f8; color: #000; border: 1px solid #94a0b4;
}
/*Connector styles on hover*/
.tree li a:hover~ul li::after,
.tree li a:hover~ul li::before,
.tree li a:hover~ul::before,
.tree li a:hover~ul ul::before
{
border-color: #94a0b4;
}
HTML:
<div class="tree">
<ul>
<li>
<a href="#">Parent</a>
<ul>
<li>
<a href="#">Child</a>
<ul>
<li>
<a href="#">Grand Child</a>
</li>
</ul>
</li>
<li>
<a href="#">Sub Parent 1</a><a href="#">Sub Parent 2</a>
<ul>
<li><a href="#">Grand Child</a></li>
<li>
<a href="#">Grand Child</a>
<ul>
<li>
<a href="#">Great Grand Child</a>
</li>
<li>
<a href="#">Great Grand Child</a>
</li>
<li>
<a href="#">Great Grand Child</a>
</li>
</ul>
</li>
<li><a href="#">Grand Child</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
The easiest way to view this is plugging this code into a codepen session
My problem is this-- levels are all well and good, but I could simplify drawing by assigning each person ONE parent. If someone has two parents, then his/her 'parent' is the relationship between his/her two parents. Good luck figuring that out.
parallax-scrolling.zip Parallax Scrolling - https://codepen.io/keithclark/pen/JycFw?editors=1100
Generations:
Progressive: 1843-1859 Missionary : 1860-1882 Lost : 1883-1900 G.I. : 1901-1924 Silent: 1925-1945 Baby Boomer: 1946-1964 Generation X: 1965- 1982 Millennial: 1982-1995 Generation Z: 1996- now
cool border animation:
<!DOCTYPE html>
<html>
<head>
<style>
div {
border-style: solid;
width: 100px;
height: 100px;
border-color: transparent;
-webkit-animation-name: example; /* Safari 4.0 - 8.0 */
-webkit-animation-duration: 4s; /* Safari 4.0 - 8.0 */
animation-name: example;
animation-duration: 4s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
/* Safari 4.0 - 8.0 */
@-webkit-keyframes example {
0% {border-color: red;}
25% {border-color: yellow;}
50% {border-color: blue;}
100% {border-color: green;}
}
/* Standard syntax */
@keyframes example {
0% {border-right-color: red;}
25% {border-right-color: red;
border-bottom-color: red;}
50% {
border-right-color: red;
border-bottom-color: red;
border-left-color: red;}
100% {
border-right-color: red;
border-bottom-color: red;
border-left-color: red;
border-top-color: red;}
}
</style>
</head>
<body>
<p><b>Note:</b> This example does not work in Internet Explorer 9 and earlier versions.</p>
<div></div>
</body>
</html>
This has been a dumping ground for a bunch of weird info. Let me update my purpose:
I won't be drawing an actual tree. I will make a portrait wall of all relatives. When a 'tree' button is pressed on the portrait of a relative, all other relative portraits are updated to show how they relate to that selected relative. No drawing. I might (in the FAR AWAY future) try a filtered-tree that won't involve all relatives at once.
Stop being a bum and READ this on parallax scrolling: http://keithclark.co.uk/articles/pure-css-parallax-websites/ Until then, disable it because right now it's obnoxious.
ADD GRAND UNCLES/AUNTS
I have almost no idea how to do this. A simple tree would be one thing, but there are so many edge cases:
I found a css example of a tree once, I might need to find it again.
Maybe I can use d3 (not that I really understand d3).
This'll take some research. I'll add specs on how the tree will function later.