Skip to content

Commit

Permalink
Merge pull request #7 from Kilix/feature/sameEventsChildrenOfOtherOne
Browse files Browse the repository at this point in the history
Handle same events which are children of another one
  • Loading branch information
alefevre19 authored Feb 2, 2018
2 parents c8ce9f5 + 2aff410 commit d39faf7
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 19 deletions.
31 changes: 30 additions & 1 deletion src/utils/__tests__/constructTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe('constructTree', () => {
},
]
const nodes = {
0: {type: 'normal', level: 0, children: [1, 2, 3], depth: 3},
0: {type: 'normal', level: 0, children: [1, 2], depth: 3},
1: {type: 'normal', level: 1, children: [], depth: 3},
2: {type: 'normal', level: 1, children: [3], depth: 3},
3: {type: 'normal', level: 2, children: [], depth: 3},
Expand Down Expand Up @@ -79,6 +79,35 @@ describe('constructTree', () => {
2: {type: 'equal', level: 2, children: [], depth: 3},
})
})
test('with the same events, children of another one', () => {
// Naively, if B == C, and both B and C are children of A, A will pick them as children,
// circumventing the type "equal" process, so we test against that
const events = [
{
id: 0,
allDay: false,
start: new Date(2017, 9, 7, 12, 0, 0),
end: new Date(2017, 9, 7, 14, 30, 0),
},
{
id: 1,
allDay: false,
start: new Date(2017, 9, 7, 13, 0, 0),
end: new Date(2017, 9, 7, 14, 30, 0),
},
{
id: 3,
allDay: false,
start: new Date(2017, 9, 7, 13, 0, 0),
end: new Date(2017, 9, 7, 14, 30, 0),
},
]
expect(constructTree(events)).toEqual({
0: {type: 'normal', level: 0, children: [1], depth: 3},
1: {type: 'equal', level: 1, children: [2], depth: 3},
2: {type: 'equal', level: 2, children: [], depth: 3},
})
})
test('subsequent children, 2 child of 1, 3 child of 2 but not of 1', () => {
const events = [
{
Expand Down
2 changes: 1 addition & 1 deletion src/utils/__tests__/parseData.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('parseData', () => {
},
]
const nodes = {
0: {type: 'normal', level: 0, children: [1, 2, 3], depth: 3},
0: {type: 'normal', level: 0, children: [1, 2], depth: 3},
1: {type: 'normal', level: 1, children: [], depth: 3},
2: {type: 'normal', level: 1, children: [3], depth: 3},
3: {type: 'normal', level: 2, children: [], depth: 3},
Expand Down
36 changes: 19 additions & 17 deletions src/utils/constructTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,52 @@ import isEqual from 'date-fns/fp/isEqual'
import {isSameEvent} from './isSameEvent'
import type {Event, Nodes, Node} from '../types'

// Creates the tree used for the daily "stairs" layout algorithm, i.e. specify which nodes are child
// of which node
// It also assigns for each node it's level (position on each branch) and depth (length of the
// branch)
/*
Creates the tree used for the daily "stairs" layout algorithm, i.e. specify which nodes are child
of which node
It also assigns for each node it's level (position on each branch) and depth (length of the
branch)
*/

// Invariant: the data is always sorted first by start, then by duration
export function constructTree(data: $ReadOnlyArray<Event>): Nodes {
// Tag nodes picked in the tree so that they are only used once
const pickedNodes = {}
let nodes = {}
const nodes = {}

// Finds a node direct children. If more than one event is identical to the node, picks only the
// first one (if a == b == c, it'll be c child of b, and b child of a)
const findChildren = id => {
const findChildren = (id: number, level: number) => {
const createChildrenNodes = n => {
if (typeof nodes[n] === 'undefined') {
nodes[n] = makeNode(level + 1, n)
pickedNodes[n] = true
}
}

const children = []
const currentNode = data[id]
let alreadySameEvent = false
for (let i = 0; i < data.length; i++) {
const targetNode = data[i]
if (
pickedNodes[i] !== true &&
!alreadySameEvent &&
areIntervalsOverlapping(currentNode, targetNode) && // no intersection, no children
(isAfter(currentNode.start)(targetNode.start) ||
(isEqual(currentNode.start)(targetNode.start) &&
currentNode.id !== targetNode.id &&
pickedNodes[i] !== true))
(isEqual(currentNode.start)(targetNode.start) && currentNode.id !== targetNode.id))
) {
if (isSameEvent(currentNode, targetNode)) alreadySameEvent = true

pickedNodes[i] = true
children.push(i)
createChildrenNodes(i)
}
}
return children
}
const makeNode = (level, id): Node => {
const children = findChildren(id)
children.map(n => {
if (typeof nodes[n] === 'undefined') {
nodes[n] = makeNode(level + 1, n)
} else {
if (nodes[n].level < level + 1) nodes[n].level = level + 1
}
})
const children = findChildren(id, level)
const currentNode = data[id]
// Since the events are sorted (and children too) we can only check the next event
const nextNode = children.length > 0 ? data[children[0]] : null
Expand Down

0 comments on commit d39faf7

Please sign in to comment.