# Path: labella/metrics.py
# def toLayers(nodes):
# def denominator(layers):
# def denominatorWithoutStubs(layers):
# def displacement(nodes):
# def pathLength(nodes):
# def overflowSpace(nodes, minPos=None, maxPos=None):
# def overDensitySpace(nodes, density=None, layerWidth=None, nodeSpacing=0):
# def overlapCount(nodes, buf=0):
# def overlapSpace(nodes):
# def weightedAllocation(nodes):
# def weightedAllocatedSpace(nodes):
# 
# Path: labella/node.py
# class Node(object):
#     def __init__(self, idealPos, width, data=None):
#         self.idealPos = idealPos
#         self.currentPos = idealPos
#         self.width = width
#         self.data = data
#         self.layerIndex = 0
#         self.parent = None
#         self.overlap = None
#         self.overlapCount = 0
#         self.child = None
#         # for rendering
#         self.x = None
#         self.dx = None
#         self.y = None
#         self.dy = None
#         # other
#         self.w = 0
#         self.h = 0
# 
#     def __repr__(self):
#         s = (
#             "Node(idealPos=%r, currentPos=%r, width=%r, "
#             "layerIndex=%r, data=%r)"
#             % (
#                 self.idealPos,
#                 self.currentPos,
#                 self.width,
#                 self.layerIndex,
#                 self.data,
#             )
#         )
#         return s
# 
#     def __str__(self):
#         return repr(self)
# 
#     def distanceFrom(self, node):
#         halfWidth = self.width / 2
#         nodeHalfWidth = node.width / 2
#         maxval = max(
#             self.currentPos - halfWidth, node.currentPos - nodeHalfWidth
#         )
#         minval = min(
#             self.currentPos + halfWidth, node.currentPos + nodeHalfWidth
#         )
#         return maxval - minval
# 
#     def moveToIdealPosition(self):
#         self.currentPos = self.idealPos
# 
#     def displacement(self):
#         return self.idealPos - self.currentPos
# 
#     def overlapWithNode(self, node, buf=None):
#         _buffer = buf if buf else 0
#         return self.distanceFrom(node) - _buffer < 0
# 
#     def overlapWithPoint(self, pos):
#         halfWidth = self.width / 2
#         return (pos >= self.currentPos - halfWidth) and (
#             pos <= self.currentPos + halfWidth
#         )
# 
#     def positionBefore(self, node, buf=None):
#         _buffer = buf if buf else 0
#         return node.currentLeft() - self.width / 2 - _buffer
# 
#     def positionAfter(self, node, buf=None):
#         _buffer = buf if buf else 0
#         return node.currentRight() + self.width / 2 + _buffer
# 
#     def currentRight(self):
#         return self.currentPos + self.width / 2
# 
#     def currentLeft(self):
#         return self.currentPos - self.width / 2
# 
#     def idealRight(self):
#         return self.idealPos + self.width / 2
# 
#     def idealLeft(self):
#         return self.idealPos - self.width / 2
# 
#     def removeStub(self):
#         if self.parent:
#             self.parent.child = None
#             self.parent = None
#         return self
# 
#     def createStub(self, width=None):
#         stub = Node(self.idealPos, width, self.data)
#         stub.currentPos = self.currentPos
#         stub.child = self
#         self.parent = stub
#         return stub
# 
#     def isStub(self):
#         return not (not (self.child))
# 
#     def getPathToRoot(self):
#         path = []
#         current = self
#         while current:
#             path.append(current)
#             current = current.parent
#         return path
# 
#     def getPathFromRoot(self):
#         return list(reversed(self.getPathToRoot()))
# 
#     def getPathToRootLength(self):
#         length = 0
#         current = self
#         while current:
#             targetPos = (
#                 current.parent.currentPos
#                 if current.parent
#                 else current.idealPos
#             )
#             length += abs(current.currentPos - targetPos)
#             current = current.parent
#         return length
# 
#     def getRoot(self):
#         previous = self
#         current = self
#         while current:
#             previous = current
#             current = current.parent
#         return previous
# 
#     def getLayerIndex(self):
#         return self.layerIndex
# 
#     def clone(self):
#         node = Node(self.idealPos, self.width, self.data)
#         node.currentPos = self.currentPos
#         node.layerIndex = self.layerIndex
#         return node


import unittest
from labella import metrics
from labella.node import Node



class MetricsTestCase(unittest.TestCase):

    def test_displacement(self):
        nodes = [
                Node(1, 50),
                Node(2, 50),
                Node(804, 50),
                Node(854, 50)
                ]
        # should return 0 if the input is empty
        self.assertEqual(metrics.displacement([]), 0)
        # should return sum of the displacements
        self.assertEqual(metrics.displacement(nodes), 0)
        nodes[0].currentPos = 10
        nodes[1].currentPos = 10
        self.assertEqual(metrics.displacement([nodes]), 17.0/4.0)

    def test_pathLength(self):
        n1 = Node(1, 50)
        n1.currentPos = 20
        n2 = Node(2, 50)
        n3 = Node(804, 50)
        stub = n3.createStub()
        n3.currentPos = 810

# Path: labella/metrics.py
# def toLayers(nodes):
# def denominator(layers):
# def denominatorWithoutStubs(layers):
# def displacement(nodes):
# def pathLength(nodes):
# def overflowSpace(nodes, minPos=None, maxPos=None):
# def overDensitySpace(nodes, density=None, layerWidth=None, nodeSpacing=0):
# def overlapCount(nodes, buf=0):
# def overlapSpace(nodes):
# def weightedAllocation(nodes):
# def weightedAllocatedSpace(nodes):
# 
# Path: labella/node.py
# class Node(object):
#     def __init__(self, idealPos, width, data=None):
#         self.idealPos = idealPos
#         self.currentPos = idealPos
#         self.width = width
#         self.data = data
#         self.layerIndex = 0
#         self.parent = None
#         self.overlap = None
#         self.overlapCount = 0
#         self.child = None
#         # for rendering
#         self.x = None
#         self.dx = None
#         self.y = None
#         self.dy = None
#         # other
#         self.w = 0
#         self.h = 0
# 
#     def __repr__(self):
#         s = (
#             "Node(idealPos=%r, currentPos=%r, width=%r, "
#             "layerIndex=%r, data=%r)"
#             % (
#                 self.idealPos,
#                 self.currentPos,
#                 self.width,
#                 self.layerIndex,
#                 self.data,
#             )
#         )
#         return s
# 
#     def __str__(self):
#         return repr(self)
# 
#     def distanceFrom(self, node):
#         halfWidth = self.width / 2
#         nodeHalfWidth = node.width / 2
#         maxval = max(
#             self.currentPos - halfWidth, node.currentPos - nodeHalfWidth
#         )
#         minval = min(
#             self.currentPos + halfWidth, node.currentPos + nodeHalfWidth
#         )
#         return maxval - minval
# 
#     def moveToIdealPosition(self):
#         self.currentPos = self.idealPos
# 
#     def displacement(self):
#         return self.idealPos - self.currentPos
# 
#     def overlapWithNode(self, node, buf=None):
#         _buffer = buf if buf else 0
#         return self.distanceFrom(node) - _buffer < 0
# 
#     def overlapWithPoint(self, pos):
#         halfWidth = self.width / 2
#         return (pos >= self.currentPos - halfWidth) and (
#             pos <= self.currentPos + halfWidth
#         )
# 
#     def positionBefore(self, node, buf=None):
#         _buffer = buf if buf else 0
#         return node.currentLeft() - self.width / 2 - _buffer
# 
#     def positionAfter(self, node, buf=None):
#         _buffer = buf if buf else 0
#         return node.currentRight() + self.width / 2 + _buffer
# 
#     def currentRight(self):
#         return self.currentPos + self.width / 2
# 
#     def currentLeft(self):
#         return self.currentPos - self.width / 2
# 
#     def idealRight(self):
#         return self.idealPos + self.width / 2
# 
#     def idealLeft(self):
#         return self.idealPos - self.width / 2
# 
#     def removeStub(self):
#         if self.parent:
#             self.parent.child = None
#             self.parent = None
#         return self
# 
#     def createStub(self, width=None):
#         stub = Node(self.idealPos, width, self.data)
#         stub.currentPos = self.currentPos
#         stub.child = self
#         self.parent = stub
#         return stub
# 
#     def isStub(self):
#         return not (not (self.child))
# 
#     def getPathToRoot(self):
#         path = []
#         current = self
#         while current:
#             path.append(current)
#             current = current.parent
#         return path
# 
#     def getPathFromRoot(self):
#         return list(reversed(self.getPathToRoot()))
# 
#     def getPathToRootLength(self):
#         length = 0
#         current = self
#         while current:
#             targetPos = (
#                 current.parent.currentPos
#                 if current.parent
#                 else current.idealPos
#             )
#             length += abs(current.currentPos - targetPos)
#             current = current.parent
#         return length
# 
#     def getRoot(self):
#         previous = self
#         current = self
#         while current:
#             previous = current
#             current = current.parent
#         return previous
# 
#     def getLayerIndex(self):
#         return self.layerIndex
# 
#     def clone(self):
#         node = Node(self.idealPos, self.width, self.data)
#         node.currentPos = self.currentPos
#         node.layerIndex = self.layerIndex
#         return node


# Path: tests/test_metrics.py
import unittest
from labella import metrics
from labella.node import Node




class MetricsTestCase(unittest.TestCase):

    def test_displacement(self):
        nodes = [
                Node(1, 50),
                Node(2, 50),
                Node(804, 50),
                Node(854, 50)
                ]
        # should return 0 if the input is empty
        self.assertEqual(metrics.displacement([]), 0)
        # should return sum of the displacements
        self.assertEqual(metrics.displacement(nodes), 0)
        nodes[0].currentPos = 10
        nodes[1].currentPos = 10
        self.assertEqual(metrics.displacement([nodes]), 17.0/4.0)

    def test_pathLength(self):
        n1 = Node(1, 50)
        n1.currentPos = 20
        n2 = Node(2, 50)
        n3 = Node(804, 50)
        stub = n3.createStub()
        n3.currentPos = 810

        n4 = Node(854, 50)