text:
__author__ = "waroquiers"

import numpy as np

from pymatgen.analysis.chemenv.connectivity.environment_nodes import EnvironmentNode
from pymatgen.analysis.chemenv.utils.graph_utils import (
    MultiGraphCycle,
    SimpleGraphCycle,
    get_delta,
)
from pymatgen.util.testing import PymatgenTest

class FakeNode:
    def __init__(self, isite):
        self.isite = isite

class FakeNodeWithEqMethod:
    def __init__(self, isite):
        self.isite = isite

    def __eq__(self, other):
        return self.isite == other.isite

    def __hash__(self):
        return 0

class FakeNodeWithEqLtMethods:
    def __init__(self, isite):
        self.isite = isite

    def __eq__(self, other):
        return self.isite == other.isite

    def __lt__(self, other):
        return self.isite < other.isite

    def __str__(self):
        return f"FakeNode_{self.isite:d}"

    def __hash__(self):
        return 0

class FakeNodeWithEqLtMethodsBis(FakeNodeWithEqLtMethods):
    pass

class FakeNodeWithEqMethodWrongSortable:
    def __init__(self, isite):
        self.isite = isite

    def __eq__(self, other):
        return self.isite == other.isite

    def __hash__(self):
        return 0

    def __lt__(self, other):
        return self.isite % 2 < other.isite % 2

class GraphUtilsTest(PymatgenTest):
    def test_get_delta(self):
        n1 = FakeNode(3)
        n2 = FakeNode(7)
        edge_data = {"start": 3, "end": 7, "delta": [2, 6, 4]}
        self.assertTrue(np.allclose(get_delta(n1, n2, edge_data), [2, 6, 4]))
        edge_data = {"start": 7, "end": 3, "delta": [2, 6, 4]}
        self.assertTrue(np.allclose(get_delta(n1, n2, edge_data), [-2, -6, -4]))
        with self.assertRaisesRegex(
            ValueError,
            "Trying to find a delta between two nodes with an edge that seems not to link these nodes.",
        ):
            edge_data = {"start": 6, "end": 3, "delta": [2, 6, 4]}
            get_delta(n1, n2, edge_data)
        with self.assertRaisesRegex(
            ValueError,
            "Trying to find a delta between two nodes with an edge that seems not to link these nodes.",
        ):
            edge_data = {"start": 7, "end": 2, "delta": [2, 6, 4]}
            get_delta(n1, n2, edge_data)

    def test_simple_graph_cycle(self):
        sg_cycle1 = SimpleGraphCycle([0, 1, 2, 3])

        # Test equality
        sg_cycle2 = SimpleGraphCycle([1, 2, 3, 0])
        self.assertEqual(sg_cycle1, sg_cycle2)
        sg_cycle2 = SimpleGraphCycle([2, 3, 0, 1])
        self.assertEqual(sg_cycle1, sg_cycle2)
        sg_cycle2 = SimpleGraphCycle([3, 0, 1, 2])
        self.assertEqual(sg_cycle1, sg_cycle2)

        # Test reversed cycles
        sg_cycle2 = SimpleGraphCycle([0, 3, 2, 1])
        self.assertEqual(sg_cycle1, sg_cycle2)
        sg_cycle2 = SimpleGraphCycle([3, 2, 1, 0])
        self.assertEqual(sg_cycle1, sg_cycle2)
        sg_cycle2 = SimpleGraphCycle([2, 1, 0, 3])
        self.assertEqual(sg_cycle1, sg_cycle2)
        sg_cycle2 = SimpleGraphCycle([1, 0, 3, 2])
        self.assertEqual(sg_cycle1, sg_cycle2)

        # Test different cycle lengths inequality
        sg_cycle2 = SimpleGraphCycle([0, 1, 2, 3, 4])
        self.assertNotEqual(sg_cycle1, sg_cycle2)

        # Test equality of self-loops
        self.assertEqual(SimpleGraphCycle([0]), SimpleGraphCycle([0]))
        self.assertNotEqual(SimpleGraphCycle([0]), SimpleGraphCycle([4]))

        # Test inequality inversing two nodes
        sg_cycle2 = SimpleGraphCycle([0, 1, 3, 2])
        self.assertNotEqual(sg_cycle1, sg_cycle2)

        # Test inequality with different nodes
        sg_cycle2 = SimpleGraphCycle([4, 1, 2, 3])
        self.assertNotEqual(sg_cycle1, sg_cycle2)

        # Test hashing function
        self.assertEqual(hash(sg_cycle1), 4)
        self.assertEqual(hash(SimpleGraphCycle([0])), 1)
        self.assertEqual(hash(SimpleGraphCycle([0, 1, 3, 6])), 4)
        self.assertEqual(hash(SimpleGraphCycle([0, 1, 2])), 3)

        # Test from_edges function
        #   3-nodes cycle
        edges = [(0, 2), (4, 2), (0, 4)]
        sg_cycle = SimpleGraphCycle.from_edges(edges=edges, edges_are_ordered=False)
        self.assertEqual(sg_cycle, SimpleGraphCycle([4, 0, 2]))

        #   Self-loop cycle
        edges = [(2, 2)]
        sg_cycle = SimpleGraphCycle.from_edges(edges=edges)
        self.assertEqual(sg_cycle, SimpleGraphCycle([2]))

        #   5-nodes cycle
        edges = [(0, 2), (4, 7), (2, 7), (4, 5), (5, 0)]
        sg_cycle = SimpleGraphCycle.from_edges(edges=edges, edges_are_ordered=False)
        self.assertEqual(sg_cycle, SimpleGraphCycle([2, 7, 4, 5, 0]))

        #   two identical 3-nodes cycles
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : Duplicate nodes.",
        ):
            edges = [(0, 2), (4, 2), (0, 4), (0, 2), (4, 2), (0, 4)]
            SimpleGraphCycle.from_edges(edges=edges, edges_are_ordered=False)

        #   two cycles in from_edges
        with self.assertRaisesRegex(ValueError, expected_regex="Could not construct a cycle from edges."):
            edges = [(0, 2), (4, 2), (0, 4), (1, 3), (6, 7), (3, 6), (1, 7)]
            SimpleGraphCycle.from_edges(edges=edges, edges_are_ordered=False)

        with self.assertRaisesRegex(ValueError, expected_regex="Could not construct a cycle from edges."):
            edges = [(0, 2), (4, 6), (2, 7), (4, 5), (5, 0)]
            SimpleGraphCycle.from_edges(edges=edges, edges_are_ordered=False)

        with self.assertRaisesRegex(ValueError, expected_regex="Could not construct a cycle from edges."):
            edges = [(0, 2), (4, 7), (2, 7), (4, 10), (5, 0)]
            SimpleGraphCycle.from_edges(edges=edges, edges_are_ordered=False)

        # Test as_dict from_dict and len method
        sg_cycle = SimpleGraphCycle([0, 1, 2, 3])
        self.assertEqual(sg_cycle, SimpleGraphCycle.from_dict(sg_cycle.as_dict()))
        self.assertEqual(len(sg_cycle), 4)
        sg_cycle = SimpleGraphCycle([4])
        self.assertEqual(sg_cycle, SimpleGraphCycle.from_dict(sg_cycle.as_dict()))
        self.assertEqual(len(sg_cycle), 1)
        sg_cycle = SimpleGraphCycle([4, 2, 6, 7, 9, 3, 15])
        self.assertEqual(sg_cycle, SimpleGraphCycle.from_dict(sg_cycle.as_dict()))
        self.assertEqual(len(sg_cycle), 7)

        # Check validation at instance creation time
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : Duplicate nodes.",
        ):
            SimpleGraphCycle([0, 2, 4, 6, 2])

        # Check the validate method
        # Nodes not sortable
        sgc = SimpleGraphCycle(
            [FakeNodeWithEqMethod(1), FakeNodeWithEqMethod(0), FakeNodeWithEqMethod(2)],
            validate=False,
            ordered=False,
        )
        self.assertFalse(sgc.ordered)
        self.assertEqual(
            sgc.nodes,
            (FakeNodeWithEqMethod(1), FakeNodeWithEqMethod(0), FakeNodeWithEqMethod(2)),
        )
        sgc.validate(check_strict_ordering=False)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : The nodes are not sortable.",
        ):
            sgc.validate(check_strict_ordering=True)

        # Empty cycle not valid
        sgc = SimpleGraphCycle([], validate=False, ordered=False)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : Empty cycle is not valid.",
        ):
            sgc.validate()

        # Simple graph cycle with 2 nodes not valid
        sgc = SimpleGraphCycle([1, 2], validate=False, ordered=False)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : Simple graph cycle with 2 nodes is not valid.",
        ):
            sgc.validate()

        # Simple graph cycle with nodes that cannot be strictly ordered
        sgc = SimpleGraphCycle(
            [
                FakeNodeWithEqMethodWrongSortable(0),
                FakeNodeWithEqMethodWrongSortable(1),
                FakeNodeWithEqMethodWrongSortable(2),
                FakeNodeWithEqMethodWrongSortable(3),
            ],
            validate=False,
            ordered=False,
        )
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : "
            "The list of nodes in the cycle cannot be strictly ordered.",
        ):
            sgc.validate(check_strict_ordering=True)

        # Check the order method
        sgc = SimpleGraphCycle(
            [
                FakeNodeWithEqMethodWrongSortable(0),
                FakeNodeWithEqMethodWrongSortable(1),
                FakeNodeWithEqMethodWrongSortable(2),
                FakeNodeWithEqMethodWrongSortable(3),
            ],
            validate=False,
            ordered=False,
        )
        sgc.order(raise_on_fail=False)
        self.assertFalse(sgc.ordered)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : "
            "The list of nodes in the cycle cannot be strictly ordered.",
        ):
            sgc.order(raise_on_fail=True)

        sgc = SimpleGraphCycle(
            [
                FakeNodeWithEqMethod(8),
                FakeNodeWithEqMethod(0),
                FakeNodeWithEqMethod(3),
                FakeNodeWithEqMethod(6),
            ],
            validate=False,
            ordered=False,
        )
        sgc.order(raise_on_fail=False)
        self.assertFalse(sgc.ordered)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="SimpleGraphCycle is not valid : The nodes are not sortable.",
        ):
            sgc.order(raise_on_fail=True)

        sgc = SimpleGraphCycle(
            [
                FakeNodeWithEqLtMethods(8),
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
            ],
            validate=False,
            ordered=False,
        )
        sgc.order(raise_on_fail=True)
        self.assertTrue(sgc.ordered)
        self.assertEqual(
            sgc.nodes,
            (
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
                FakeNodeWithEqLtMethods(8),
            ),
        )

        sgc = SimpleGraphCycle(
            [
                FakeNodeWithEqLtMethodsBis(8),
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
            ],
            validate=False,
            ordered=False,
        )
        sgc.order(raise_on_fail=False)
        self.assertFalse(sgc.ordered)
        self.assertEqual(
            sgc.nodes,
            (
                FakeNodeWithEqLtMethodsBis(8),
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
            ),
        )
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="Could not order simple graph cycle as the nodes are of different classes.",
        ):
            sgc.order(raise_on_fail=True)

        sgc = SimpleGraphCycle([FakeNodeWithEqLtMethods(85)], validate=False, ordered=False)
        self.assertFalse(sgc.ordered)
        sgc.order()
        self.assertTrue(sgc.ordered)
        self.assertEqual(sgc.nodes, tuple([FakeNodeWithEqLtMethods(85)]))

        sgc = SimpleGraphCycle(
            [
                FakeNodeWithEqLtMethods(8),
                FakeNodeWithEqLtMethods(2),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
                FakeNodeWithEqLtMethods(4),
                FakeNodeWithEqLtMethods(1),
                FakeNodeWithEqLtMethods(64),
                FakeNodeWithEqLtMethods(32),
            ],
            validate=False,
            ordered=False,
        )
        self.assertFalse(sgc.ordered)
        sgc.order()
        self.assertTrue(sgc.ordered)
        self.assertEqual(
            sgc.nodes,
            tuple(
                [
                    FakeNodeWithEqLtMethods(1),
                    FakeNodeWithEqLtMethods(4),
                    FakeNodeWithEqLtMethods(3),
                    FakeNodeWithEqLtMethods(6),
                    FakeNodeWithEqLtMethods(2),
                    FakeNodeWithEqLtMethods(8),
                    FakeNodeWithEqLtMethods(32),
                    FakeNodeWithEqLtMethods(64),
                ]
            ),
        )

        # Test str method
        self.assertEqual(
            str(sgc),
            "Simple cycle with nodes :\n"
            "FakeNode_1\n"
            "FakeNode_4\n"
            "FakeNode_3\n"
            "FakeNode_6\n"
            "FakeNode_2\n"
            "FakeNode_8\n"
            "FakeNode_32\n"
            "FakeNode_64",
        )

    def test_multigraph_cycle(self):
        mg_cycle1 = MultiGraphCycle([2, 4, 3, 5], [1, 0, 2, 0])
        # Check is_valid method
        is_valid, msg = MultiGraphCycle._is_valid(mg_cycle1)
        self.assertTrue(is_valid)
        self.assertEqual(msg, "")
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : "
            "Number of nodes different from number of "
            "edge indices.",
        ):
            MultiGraphCycle([0, 2, 4], [0, 0])  # number of nodes is different from number of edge_indices
        with self.assertRaisesRegex(ValueError, expected_regex="MultiGraphCycle is not valid : Duplicate nodes."):
            MultiGraphCycle([0, 2, 4, 3, 2], [0, 0, 0, 0, 0])  # duplicated nodes
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : "
            "Cycles with two nodes cannot use the same "
            "edge for the cycle.",
        ):
            MultiGraphCycle([3, 5], [1, 1])  # number of nodes is different from number of edge_indices

        # Testing equality

        #   Test different cycle lengths inequality
        mg_cycle2 = MultiGraphCycle([2, 3, 4, 5, 6], [1, 0, 2, 0, 0])
        self.assertFalse(mg_cycle1 == mg_cycle2)

        #   Test equality
        mg_cycle2 = MultiGraphCycle([2, 4, 3, 5], [1, 0, 2, 0])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([4, 3, 5, 2], [0, 2, 0, 1])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([3, 5, 2, 4], [2, 0, 1, 0])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([5, 2, 4, 3], [0, 1, 0, 2])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        #   Test equality (reversed)
        mg_cycle2 = MultiGraphCycle([2, 5, 3, 4], [0, 2, 0, 1])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([5, 3, 4, 2], [2, 0, 1, 0])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([3, 4, 2, 5], [0, 1, 0, 2])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([4, 2, 5, 3], [1, 0, 2, 0])
        self.assertTrue(mg_cycle1 == mg_cycle2)
        #   Test inequality
        mg_cycle2 = MultiGraphCycle([2, 5, 3, 4], [0, 1, 0, 1])
        self.assertFalse(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([2, 5, 3, 4], [1, 0, 2, 0])
        self.assertFalse(mg_cycle1 == mg_cycle2)
        mg_cycle2 = MultiGraphCycle([3, 5, 2, 4], [1, 0, 2, 0])
        self.assertFalse(mg_cycle1 == mg_cycle2)

        #   Test Self-loop case
        self.assertTrue(MultiGraphCycle([2], [1]) == MultiGraphCycle([2], [1]))
        self.assertFalse(MultiGraphCycle([1], [1]) == MultiGraphCycle([2], [1]))
        self.assertFalse(MultiGraphCycle([2], [1]) == MultiGraphCycle([2], [0]))
        self.assertFalse(MultiGraphCycle([2], [1]) == MultiGraphCycle([1], [1]))
        self.assertFalse(MultiGraphCycle([2], [0]) == MultiGraphCycle([2], [1]))

        #   Test special case with two nodes
        self.assertTrue(MultiGraphCycle([2, 4], [1, 3]) == MultiGraphCycle([2, 4], [1, 3]))
        self.assertTrue(MultiGraphCycle([2, 4], [1, 3]) == MultiGraphCycle([2, 4], [3, 1]))
        self.assertTrue(MultiGraphCycle([2, 4], [1, 3]) == MultiGraphCycle([4, 2], [3, 1]))
        self.assertTrue(MultiGraphCycle([2, 4], [1, 3]) == MultiGraphCycle([4, 2], [1, 3]))
        self.assertFalse(MultiGraphCycle([2, 4], [1, 3]) == MultiGraphCycle([4, 2], [1, 2]))
        self.assertFalse(MultiGraphCycle([2, 4], [1, 3]) == MultiGraphCycle([4, 0], [1, 3]))

        # Test hashing function
        self.assertEqual(hash(mg_cycle1), 4)
        self.assertEqual(hash(MultiGraphCycle([0], [0])), 1)
        self.assertEqual(hash(MultiGraphCycle([0, 3], [0, 1])), 2)
        self.assertEqual(hash(MultiGraphCycle([0, 3, 5, 7, 8], [0, 1, 0, 0, 0])), 5)

        # Test as_dict from_dict and len method
        mg_cycle = MultiGraphCycle([0, 1, 2, 3], [1, 2, 0, 3])
        self.assertTrue(mg_cycle == MultiGraphCycle.from_dict(mg_cycle.as_dict()))
        self.assertEqual(len(mg_cycle), 4)
        mg_cycle = MultiGraphCycle([2, 5, 3, 4, 1, 0], [0, 0, 2, 0, 1, 0])
        self.assertTrue(mg_cycle == MultiGraphCycle.from_dict(mg_cycle.as_dict()))
        self.assertEqual(len(mg_cycle), 6)
        mg_cycle = MultiGraphCycle([8], [1])
        self.assertTrue(mg_cycle == MultiGraphCycle.from_dict(mg_cycle.as_dict()))
        self.assertEqual(len(mg_cycle), 1)

        # Check the validate method
        # Number of nodes and edges do not match
        mgc = MultiGraphCycle(
            nodes=[
                FakeNodeWithEqMethod(1),
                FakeNodeWithEqMethod(0),
                FakeNodeWithEqMethod(2),
            ],
            edge_indices=[0, 0],
            validate=False,
            ordered=False,
        )
        self.assertFalse(mgc.ordered)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : "
            "Number of nodes different from "
            "number of edge indices.",
        ):
            mgc.validate(check_strict_ordering=False)

        # Empty cycle not valid
        mgc = MultiGraphCycle([], edge_indices=[], validate=False, ordered=False)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : Empty cycle is not valid.",
        ):
            mgc.validate()

        # Multi graph cycle with duplicate nodes not valid
        mgc = MultiGraphCycle(
            [FakeNodeWithEqMethod(1), FakeNodeWithEqMethod(0), FakeNodeWithEqMethod(1)],
            edge_indices=[0, 1, 0],
            validate=False,
            ordered=False,
        )
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : Duplicate nodes.",
        ):
            mgc.validate()

        # Multi graph cycle with two nodes cannot use the same edge
        mgc = MultiGraphCycle(
            [FakeNodeWithEqMethod(1), FakeNodeWithEqMethod(0)],
            edge_indices=[1, 1],
            validate=False,
            ordered=False,
        )
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : "
            "Cycles with two nodes cannot use the same edge for the cycle.",
        ):
            mgc.validate()

        # Nodes not sortable
        mgc = MultiGraphCycle(
            [FakeNodeWithEqMethod(1), FakeNodeWithEqMethod(0), FakeNodeWithEqMethod(2)],
            edge_indices=[0, 0, 0],
            validate=False,
            ordered=False,
        )
        self.assertFalse(mgc.ordered)
        self.assertEqual(
            mgc.nodes,
            (FakeNodeWithEqMethod(1), FakeNodeWithEqMethod(0), FakeNodeWithEqMethod(2)),
        )
        mgc.validate(check_strict_ordering=False)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : The nodes are not sortable.",
        ):
            mgc.validate(check_strict_ordering=True)

        # Multi graph cycle with nodes that cannot be strictly ordered
        mgc = MultiGraphCycle(
            [
                FakeNodeWithEqMethodWrongSortable(0),
                FakeNodeWithEqMethodWrongSortable(1),
                FakeNodeWithEqMethodWrongSortable(2),
                FakeNodeWithEqMethodWrongSortable(3),
            ],
            edge_indices=[0, 0, 0, 0],
            validate=False,
            ordered=False,
        )
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : "
            "The list of nodes in the cycle cannot be strictly ordered.",
        ):
            mgc.validate(check_strict_ordering=True)

        # Check the order method
        mgc = MultiGraphCycle(
            [
                FakeNodeWithEqMethodWrongSortable(0),
                FakeNodeWithEqMethodWrongSortable(1),
                FakeNodeWithEqMethodWrongSortable(2),
                FakeNodeWithEqMethodWrongSortable(3),
            ],
            edge_indices=[0, 0, 0, 0],
            validate=False,
            ordered=False,
        )
        mgc.order(raise_on_fail=False)
        self.assertFalse(mgc.ordered)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : "
            "The list of nodes in the cycle cannot be strictly ordered.",
        ):
            mgc.order(raise_on_fail=True)

        mgc = MultiGraphCycle(
            [
                FakeNodeWithEqMethod(8),
                FakeNodeWithEqMethod(0),
                FakeNodeWithEqMethod(3),
                FakeNodeWithEqMethod(6),
            ],
            edge_indices=[0, 0, 0, 0],
            validate=False,
            ordered=False,
        )
        mgc.order(raise_on_fail=False)
        self.assertFalse(mgc.ordered)
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="MultiGraphCycle is not valid : The nodes are not sortable.",
        ):
            mgc.order(raise_on_fail=True)

        mgc = MultiGraphCycle(
            [
                FakeNodeWithEqLtMethods(8),
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
            ],
            edge_indices=[2, 5, 3, 7],
            validate=False,
            ordered=False,
        )
        mgc.order(raise_on_fail=True)
        self.assertTrue(mgc.ordered)
        self.assertEqual(
            mgc.nodes,
            (
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
                FakeNodeWithEqLtMethods(8),
            ),
        )
        self.assertEqual(mgc.edge_indices, (5, 3, 7, 2))

        mgc = MultiGraphCycle(
            [
                FakeNodeWithEqLtMethodsBis(8),
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
            ],
            edge_indices=[2, 5, 3, 7],
            validate=False,
            ordered=False,
        )
        mgc.order(raise_on_fail=False)
        self.assertFalse(mgc.ordered)
        self.assertEqual(
            mgc.nodes,
            (
                FakeNodeWithEqLtMethodsBis(8),
                FakeNodeWithEqLtMethods(0),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
            ),
        )
        self.assertEqual(mgc.edge_indices, (2, 5, 3, 7))
        with self.assertRaisesRegex(
            ValueError,
            expected_regex="Could not order simple graph cycle as the nodes are of different classes.",
        ):
            mgc.order(raise_on_fail=True)

        mgc = MultiGraphCycle(
            [FakeNodeWithEqLtMethods(85)],
            edge_indices=[7],
            validate=False,
            ordered=False,
        )
        self.assertFalse(mgc.ordered)
        mgc.order()
        self.assertTrue(mgc.ordered)
        self.assertEqual(mgc.nodes, tuple([FakeNodeWithEqLtMethods(85)]))
        self.assertEqual(mgc.edge_indices, tuple([7]))

        mgc = MultiGraphCycle(
            [
                FakeNodeWithEqLtMethods(8),
                FakeNodeWithEqLtMethods(2),
                FakeNodeWithEqLtMethods(6),
                FakeNodeWithEqLtMethods(3),
                FakeNodeWithEqLtMethods(4),
                FakeNodeWithEqLtMethods(1),
                FakeNodeWithEqLtMethods(64),
                FakeNodeWithEqLtMethods(32),
            ],
            edge_indices=[2, 0, 4, 1, 0, 3, 5, 2],
            validate=False,
            ordered=False,
        )
        self.assertFalse(mgc.ordered)
        mgc.order()
        self.assertTrue(mgc.ordered)
        self.assertEqual(
            mgc.nodes,
            tuple(
                [
                    FakeNodeWithEqLtMethods(1),
                    FakeNodeWithEqLtMethods(4),
                    FakeNodeWithEqLtMethods(3),
                    FakeNodeWithEqLtMethods(6),
                    FakeNodeWithEqLtMethods(2),
                    FakeNodeWithEqLtMethods(8),
                    FakeNodeWithEqLtMethods(32),
                    FakeNodeWithEqLtMethods(64),
                ]
            ),
        )
        self.assertEqual(mgc.edge_indices, tuple([0, 1, 4, 0, 2, 2, 5, 3]))

        # Testing all cases for a length-4 cycle
        nodes_ref = tuple(FakeNodeWithEqLtMethods(inode) for inode in [0, 1, 2, 3])
        edges_ref = (3, 6, 9, 12)
        for inodes, iedges in [
            ((0, 1, 2, 3), (3, 6, 9, 12)),
            ((1, 2, 3, 0), (6, 9, 12, 3)),
            ((2, 3, 0, 1), (9, 12, 3, 6)),
            ((3, 0, 1, 2), (12, 3, 6, 9)),
            ((3, 2, 1, 0), (9, 6, 3, 12)),
            ((2, 1, 0, 3), (6, 3, 12, 9)),
            ((1, 0, 3, 2), (3, 12, 9, 6)),
            ((0, 3, 2, 1), (12, 9, 6, 3)),
        ]:
            mgc = MultiGraphCycle(
                [FakeNodeWithEqLtMethods(inode) for inode in inodes],
                edge_indices=[iedge for iedge in iedges],
            )
            strnodes = ", ".join([str(i) for i in inodes])
            self.assertEqual(
                mgc.nodes,
                nodes_ref,
                msg=f"Nodes not equal for inodes = ({', '.join([str(i) for i in inodes])})",
            )
            self.assertEqual(
                mgc.edge_indices,
                edges_ref,
                msg=f"Edges not equal for inodes = ({strnodes})",
            )

class EnvironmentNodesGraphUtilsTest(PymatgenTest):
    def test_cycle(self):
        e1 = EnvironmentNode(central_site="Si", i_central_site=0, ce_symbol="T:4")
        e2 = EnvironmentNode(central_site="Si", i_central_site=3, ce_symbol="T:4")
        e3 = EnvironmentNode(central_site="Si", i_central_site=2, ce_symbol="T:4")
        e4 = EnvironmentNode(central_site="Si", i_central_site=5, ce_symbol="T:4")
        e5 = EnvironmentNode(central_site="Si", i_central_site=1, ce_symbol="T:4")

        # Tests of SimpleGraphCycle with EnvironmentNodes
        c1 = SimpleGraphCycle([e2])
        c2 = SimpleGraphCycle([e2])
        self.assertEqual(c1, c2)

        c1 = SimpleGraphCycle([e1])
        c2 = SimpleGraphCycle([e2])
        self.assertNotEqual(c1, c2)

        c1 = SimpleGraphCycle([e1, e2, e3])
        c2 = SimpleGraphCycle([e2, e1, e3])
        self.assertEqual(c1, c2)
        c2 = SimpleGraphCycle([e2, e3, e1])
        self.assertEqual(c1, c2)

        c1 = SimpleGraphCycle([e3, e2, e4, e1, e5])
        c2 = SimpleGraphCycle([e1, e4, e2, e3, e5])
        self.assertEqual(c1, c2)
        c2 = SimpleGraphCycle([e2, e3, e5, e1, e4])
        self.assertEqual(c1, c2)

        c1 = SimpleGraphCycle([e2, e3, e4, e1, e5])
        c2 = SimpleGraphCycle([e2, e3, e5, e1, e4])
        self.assertNotEqual(c1, c2)

        # Tests of MultiGraphCycle with EnvironmentNodes
        c1 = MultiGraphCycle([e1], [2])
        c2 = MultiGraphCycle([e1], [2])
        self.assertEqual(c1, c2)
        c2 = MultiGraphCycle([e1], [1])
        self.assertNotEqual(c1, c2)
        c2 = MultiGraphCycle([e2], [2])
        self.assertNotEqual(c1, c2)

        c1 = MultiGraphCycle([e1, e2], [0, 1])
        c2 = MultiGraphCycle([e1, e2], [1, 0])
        self.assertEqual(c1, c2)
        c2 = MultiGraphCycle([e2, e1], [1, 0])
        self.assertEqual(c1, c2)
        c2 = MultiGraphCycle([e2, e1], [0, 1])
        self.assertEqual(c1, c2)
        c2 = MultiGraphCycle([e2, e1], [2, 1])
        self.assertNotEqual(c1, c2)

        c1 = MultiGraphCycle([e1, e2, e3], [0, 1, 2])
        c2 = MultiGraphCycle([e2, e1, e3], [0, 2, 1])
        self.assertEqual(c1, c2)
        c2 = MultiGraphCycle([e2, e3, e1], [1, 2, 0])
        self.assertEqual(c1, c2)

if __name__ == "__main__":
    import unittest

    unittest.main()


BELOIT — Veterans Day programs will be presented at West Branch Local Schools.
The middle school's assembly begins at 1:45 p.m. Friday in the gymnasium. The middle school band will perform.
Damascus Elementary School students will perform a musical presentation at 9:30 a.m. Friday in the gymnasium.
The high school's program starts at 8 a.m. Monday in the auditorium. Both the band and choir will perform, and students will present readings. A reception for veterans follows.
Each grade level at Knox Elementary School will have a special part in honoring veterans at 9:15 a.m. Monday in the gymnasium. All veterans, parents and community members are welcome to attend.
SALEM — USA Equipment Solutions will sponsor the next Banquet in Salem from 5 to 7 p.m. Monday at the Memorial Building, 785 E. State St. The menu offers fried chicken, mashed potatoes and gravy, green beans, cole slaw, fresh fruit and vegetables and ice cream sundaes. Additional sponsors are needed. For information call Patty Colian at 330-831-2169.
SALEM — Salem Senior Citizens will meet at noon Wednesday at the Memorial Building, 785 E. State St. Thanksgiving dinner will be served to members who purchased tickets in advance only.
SALEM — The Salem Eagles Club is hosting a breakfast from 7 to 11 a.m. Saturday at the club, 1884 N. Ellsworth Ave. An extended menu is now available including haystacks, traditional, pancakes and waffles. All veterans are invited to a free meal when they provide proper military identification.
EAST PALESTINE — East Palestine Area Chamber of Commerce is sponsoring its 10th annual holiday craft show and Chinese auction from 9 a.m. to 4 p.m. Saturday at East Palestine Elementary School, 195 W. Grant St. Admission and parking are free. Food will be available for purchase including pulled pork, sloppy joes, chicken sandwiches, desserts, snacks and beverages.
Vendor spaces are available at $30 for a table and two chairs. Set up begins at 7 a.m. Saturday. Text or call Bonnie Davis at 330-271-1979 or bkddavis74@yahoo.com for a contract.
COLUMBIANA — Crown Theater Productions will hold auditions for "Newsies" from 7 to 9 p.m. Nov. 12 and 13 at Main Street Theater. Call backs will be held on Nov. 15. The cast calls for men and women, and children ages 5 and older. Show dates are Feb. 8, 9, 10, 15, 16 and 17.
SALEM — The annual Charles Burchfield "Trains and Trees" spectacular will be presented again this year.
The Trains show will be held from 1 to 4 p.m. Nov. 17 and 18 at Attorney Frederick E. Naragon's office, 248 E. State St.
The Christmas Trees show will be open from 1 to 4 p.m. Nov. 17 and 18 and also from 1 to 4 p.m. on Saturdays and Sundays through December at the Charles Burchfield Homestead Museum, 867 E. Fourth St. Admission to both shows is $3 for adults and free for children when accompanied by an adult.
LISBON — Nov. 1 marked the first day of the open enrollment period for Ohioans looking to enroll in or change their plan through the Health Insurance Marketplace (Marketplace) for coverage in 2019. Ohioans exploring affordable health insurance options can receive free assistance by making an appointment with a local assister at CAA Health, Behavioral Health and Dental Centers (7880 Lincole Place, Lisbon).
Marketplace plans must include key benefits like mental health care, maternity care, prescription coverage and hospitalization services. Many marketplace shoppers will qualify for a discount based on their income. Last year, more than 8 in 10 shoppers could get a plan for less than $100 per month.
After open enrollment closes on Dec. 15 accessing health insurance in the Marketplace is limited until the next open enrollment period or to those who experience a qualifying life event like job loss, change in household composition, etc. Please note, Medicaid enrollment is available year-round; Ohioans with annual incomes at or below 138 percent of the federal poverty level ($16,753 for an individual) can apply for coverage through Medicaid at any time during the year.
For more information visit caaofcc.org/health.
Make your appointment now for Marketplace Insurance (Obamacare) coverage to start on Jan. 1, 2019.
SEBRING — The Sebring Model Railroad Club is hosting its 2018 annual open house, during the two weekends before Thanksgiving, from 10 a.m. to 5 p.m. Nov. 10, 11, 17 and 18. November is National Model Railroad month and to celebrate, the doors to the clubhouse will be open to the public to see what members have been doing throughout the year. The layout is one of the largest operating model railroads in Northeast Ohio. There will be refreshments available during the open house. Admission is $4 per person. Monies raised help maintain the clubhouse and layout.
COLUMBIANA — An inside Christmas garage sale fundraiser will be held from 9 a.m. to 3 p.m. Nov. 12-16 at Sitler's Florist Greenhouse, 855 E. Park Ave. All proceeds will be directed to the Meals on Wheels programs. For information call 330-482-4353.


text:
Home / Figure Skating News / Serov Returns With a Splash
Serov Returns With a Splash
By Barry Mittan
Photo © Barry Mittan
Israel's Roman Serov returned to the figure skating international scene this season after a two-year absence from major ISU competitions.
Israel's Roman Serov returned to the figure skating international scene this season after a two-year absence from major ISU competitions. Serov, a 27-year-old who was born in Moscow, competed for Russia for many years, finishing in the top six at Russian Nationals between 1999 and 2002. But then he fell in love and married Israeli skater Rachel Lior in August 2002. Since Lior had dual Israeli-U.S. citizenship, Serov elected to skate for Israel, but he had to sit out the last two seasons because of switching countries. "In Russia, there were too many good skaters and I never got to go to Europeans or Worlds or many Grand Prixs," he said. "I definitely want to go to the 2006 Olympics, but after that, we'll see."
Last season, Serov won the Israeli Nationals and Skater Israel and took the bronze at the Golden Spin of Zagreb. He started 2004 by finishing second at the Finlandia Trophy, then scoring a surprising fourth place at the first ISU Grand Prix event, Skate America, in Pittsburgh, Pennsylvania. Serov finished third in the short with the only clean program, completing a triple lutz, triple Axel and triple flip-triple toe loop combination. He landed seven triples in the long program, including a triple Axel-triple toe loop combination to finish fourth overall. "I tried to do my best and not think of a place," he said. "I just wanted to skate like in practice."
Serov is currently working on the quadruple toeloop and loop. "I have landed both of these jumps," he said. "Skating isn't only about jumping anymore though, with the new scoring system. I am not young for figure skating, but I plan to keep on going as long as my body allows me to."
"I already had a clean skate at Finlandia," he continued. "I was familiar with the new system. I like it because before it was jump, jump, jump. Now you have to think about spins and other elements. Now the spins and steps are much more important. I am not a very creative spinner, so I am working hard on some new spins to add into my programs. I think that with some good spins I can easily score a new personal best."
"I began skating when I was five," Serov said. "My mother brought me to the rink because she liked figure skating. She was a runner, not a skater. I wanted to be a hockey player but I became used to skating and now I cannot live without it. By the time I was 12 or 13, I had my first triple toe loop. When I was 19 or 20, I learned the quad toe loop. I have landed the quad loop, but it's too difficult a jump so I don't have it in competition, just the quad toe."
After moving to the United States, Serov began training with Craig Maurizi in Hackensack, New Jersey. "He guides me in the right direction and is a good motivator," said Serov. "He works very hard with me, and expects nothing but the best. I think since I have started working with him, I have improved many aspects of my skating."
Maurizi feels that working with Serov has been much easier than he had earlier anticipated. "When you start working with a skater that has already accomplished so much prior to a particular coaching change, the coach may have certain challenges in getting the skater to try things that are different than what the skater has been used to for years," he said. "Roman is an extremely coachable skater which is rare for someone of his level. We work together as a team very well."
During the summer, he also works with Viktor Kudriatsev in Flims, Switzerland. "I only train for about two hours a day," Serov said, "five or six days a week. Then I coach a couple of lessons a day to pay for it."
Tatiana Druchinina, wife of Olympic pairs champion Artur Dmitriev, choreographed his programs for last season. The short is to a selection of classical music, while the long is to Beethoven's Last Night by the Trans-Siberian Orchestra. "Normally I change the programs every year," he said, "but am keeping the short this season because I did not compete very much last year. I am also using last year's long until my new one is ready. Peter Tchernyshev is choreographing my new one."
"My coach, Craig, has some young students who are working with Peter," said Serov. "We both really admire his work as a choreographer and decided we should do the long program with him." "According to Roman," added Maurizi, "he has mostly skated to one type of music over his career with one style of choreography."
Maurizi continued, "I thought it was very important to change his look for the upcoming European and World Championships. He has been off the scene for almost three years and must come back different and better to regain the ground he has lost by not competing." Maurizi has known Tchernyshev for many years and admires his brilliant choreography. "I feel that Peter gives passion and uniqueness to Serov's new program. This was a perfect match for Roman's new look!"
Serov admitted to being skeptical at first to Tchernyshev's choice of music. "It's the type of music that you hear in a club," he said, "but the energy when you turn on the music though is amazing! Hopefully it will add something good to my skating. Peter and I spent endless hours in the music studio getting just the right cut. It's finally ready for it's debut."
Serov, who enjoys working with Tchernyshev, offered, "We are both young and we get along well and seem to understand each other on the ice. Peter is teaching me new moves for my new long program that for me are hard to execute right now, but I believe it they will work well with the new judging system."
Serov chose music by The Scorpions for his exhibition program. "It's not really ready yet, so I have to make some improvisations when I skate." However, Serov's wife Rachel played Love by Nat King Cole for him, thinking that it might be the perfect exhibition number. "I can really see myself skating to it," said Serov. It is a classic song, and I think it really suits my style of skating. So we might use that."
Away from the rink, he said," I mainly listen to Russian music. I also play tennis a lot. I don't collect anything now but I used to collect coins and stamps. I have a computer but just use it for news and to play games. Mostly I stay at home with my wife and our two dogs. They eat all the toys. When we have people come, we play soccer or basketball and sometimes at the end of the week, I play some hockey. Sometimes we go to movies and Broadway shows."
Roman Serov
← Previous Story Poland's Kauc and Zych Dance Towards 2006 Olympics
Next Story → Weiss Plans Busy Season
Japan's Midori Ito, the 1989 World champion and 1992 Olympic silver medalist, was the first lady to land a triple Axel in international competition at the 1988 NHK Trophy. She is also the first lady to land a triple-triple jump combination in competition (1982 Junior World Figure Skating Championships) and the first lady to land seven triple jumps in a free program (1988 Olympics).
Which ladies are working on triple Axels and who is your favorite? Discuss here!

redpajama_set_name: RedPajamaCommonCrawl


Much of the information on the diplomatic whirl preceding Charles' arrival comes from letters exchanged between Cisneros' representative in Brussels, Diego López de Ayala, and the two men who looked after Cisneros' correspondence: the jurist Jorge Varacaldo and Francisco Ruiz, Bishop of Avila. Ruiz, a native of Toledo, had entered Cisneros' service when he was a young man of eighteen, as has been mentioned. He became his confidant and was a loyal follower, but lacked sophistication and displayed little talent for diplomacy. The letters he sent to Ayala during the frequent illnesses of the Cardinal are written in a crude style and contain many colloquialisms. He was, moreover, unrealistic in his estimate of Cisneros' power and correspondingly insensitive to the power play at the Burgundian court.
The jurist Jorge Varacaldo, by contrast, was entirely realistic. He had been in Cisneros' service since 1509, and in January 1516 was despatched to Brussels for two months as the Cardinal's personal emissary (Cart. Xim. 196). While not disloyal to the Cardinal, he kept a sharp lookout for his own interests. The Cardinal had appointed him Secretary of the Military Orders, but the appointment needed royal assent, and he frequently importuned Ayala to obtain ratification of the document. He finally achieved his object, but his pleasure was short-lived. The King reversed his position, as a letter from Cisneros to Ayala indicates. "You knew how to obtain for Secretary Varacaldo the secretaryship of the Orders of Santiago, Calatrava, and Alcántara in the name of His Highness," he wrote. "… I have now been told that His Highness had not been well informed about this matter and wishes to appoint another person to this office. Since the change is not in his interest and no one but the said secretary should have the post, you must speak about it to His Highness" (Cart. Xim. 120). Nothing could be done, however, and Varacaldo had to relinquish the post.
Publication information: Book title: Jiménez de Cisneros: On the Threshold of Spain's Golden Age. Contributors: Erika Rummel - Author. Publisher: Arizona Center for Medieval and Renaissance Studies. Place of publication: Tempe, AZ. Publication year: 1999. Page number: 95.


Excellent biological research that produces understanding and application can ignore natural selection completely.
Continuing our discussion of whether natural selection has any value in science, we present more cases in the media.
The natural world contains endless examples of intelligent design that can inspire scientists with wonder and inspiration.
Today's trend of gender confusion flies in the face of science. Who is "anti-science" in this hotbed political issue?
The facts of genetics make it clear even to evolutionists: "We are dying" and "More death by selection will not work."
Stem cells were all the rage ten years ago, but news stories these days are less common. What's new?
Evolutionists cannot deny the presence of soft tissue in dinosaur bones, but their explanation burns up in the heat of critical analysis.
Darwinian natural selection sounds convincing until you look at the details of extraordinary designs in nature.
Superflares from the majority of stars would likely sterilize any planet in its "habitable zone."
New and old miracle acts for the origin of life are added continually, to see if people will keep coming with money.
Darwinism cheapens human life. Here's a huge societal debate about the consequences.
The most amazing animals of all may be the tiniest. Consider how much bio-technology has to fit into the head of a fruit fly.
How many people have heard that Darwin's famous branching-tree diagram of universal common ancestry is obsolete? Many scientists haven't heard yet, either.


text:
OJC Women's Basketball Coach, Landon Steele, Moving On
Otero Junior College Athletic Director, Chris Carrillo, has announced that Head Women's Basketball Coach Landon Steele will not be returning to lead the Rattlers in the upcoming 2021-2022 season. Steele has accepted the head coaching position at Dodge City Community College (DCCC). His assistant coach, Audra Lynn, will be moving with him.
"Coach Steele is an amazing coach, mentor and person. He's lead a great program here at OJC. The next coach in will have some big shoes to fill," said Chris Carrillo, OJC athletic director. "He will be missed by the whole campus, but especially his team."
Steele has had an exceptional run during the last two years at Otero. This year, the Women's team won the Region IX tournament and went to the National Championships where they only lost to the eventual champions. Steele was also named North Plains District Coach of the Year.
"We are very excited for Coach Steele and his career. We will always be grateful to him for all his accomplishments with our basketball program and our institution as a whole. Dodge City will be lucky to have a class act like Landon, we are looking forward to following his future successes," said Carrillo.
Head Women's Basketball Coach, Landon Steele, has recently accepted the head coaching position at Dodge City Community College.


text:
Home » Ryder launches software platform to deliver visibility, event management from one source
Ryder launches software platform to deliver visibility, event management from one source
Ryder System Inc. has launched a supply chain software platform it said would provide customers with one point of real-time visibility and event management, even if the customer operates its own transportation management system (TMS) and utilizes multiple shipping modes.
The software, called "NaviShare," provides Ryder with a tool to address increasing shipper demand for supply chain visibility and optimization. It will be rolled out in three phases over the next 18 months, Miami-based Ryder said yesterday. Phase one will provide real-time visibility for truckload customers in Ryder's supply chain and dedicated contract carriage businesses. The software is available for loads originating in the U.S. and Canada. It will be expanded in the third quarter to support loads originating in Mexico, Ryder said.
Phase two will expand the software to Ryder's intermodal, less-than-truckload (LTL), and parcel customers, as well as its vehicle-leasing customers. The third phase will incorporate advanced planning and analytics features to enable freight capacity sharing, as well more effective shipment management through predictive alerts for weather and traffic delays, Ryder said. All three phases should be operational during 2018, according to Gary R. Allen, Ryder's vice president of supply chain excellence.
The software is system-agnostic, meaning it will run in conjunction with a customer's TMS, Allen said. Ryder's five largest "dedicated customers"—businesses that commit to using Ryder drivers and vehicles for a contractually specified level of service—are currently using NaviShare, with the 20 next-largest customers expected to join by the end of the year. The 250 largest truckload carriers in Ryder's Transportation Management program are enrolled, with that number expected to increase to 350 by the end of May, Allen said.
The visibility component of the platform was developed in partnership with Chicago-based shipment-tracking technology firm FourKites, Inc. The platform itself was designed along with a managed-services provider that Allen declined to identify.
NaviShare provides real-time information of load status, tracking status, carriers, shippers, customers, origins, and destinations. A user, which can be a shipper, carrier, driver, or dispatcher, can toggle among multiple features for each load, including stops, maps, updates, and messages. If there is a shipment delay, NaviShare alerts the shipper and recipient, and provides the shipper with a list of re-routing options. The software application also has the capability to track shipments at the SKU/part level, and to monitor the load's condition, Ryder said. In conducting a year's worth of research, Ryder said it found potential users were drawn to the platform's ability to integrate data from 3PLs, carriers, brokers, and private fleets into a centralized visibility and decision tool. The typical Ryder customer is a large business with a complex network supported by disparate systems and carriers, Allen said. For them, the ability to integrate multiple data points into a single point of use will add tremendous value, he predicted.
Technology Business Intelligence/Decision Support
KEYWORDS Ryder
Ryder launches asset-sharing platform to match users with owners of idle equipment
Mojix Launches 'Source', a Platform and App for First to Last-Mile Traceability
Pacejet Shipping Software and Single Source Systems partner to support logistics platform


This is actually my preferred EITS album because of the rawer feel the album has to it, while still being a great improvement from the first album. I also feel it has a bit more variation from The Earth... Drums are certainly more forward in the mix here, and can be noticed throughout much of the record.
Their are many dynamics in play here, and while remaining relatively simple and subtle, their is a distinct quality and feeling as a result of the dynamics (which weren't really present on the first album). The tracks tend to build from a soft, genial nature towards more chaos at the ends when the concept is fully realized (a trademark of the genre). So, if you don't like a track, give it time to develop before hitting the "skip" button. As such, it makes it increasingly difficult to merely "sample" a section of the work as it is all essential to the atmosphere of the music.
The latter part of the album is more "aggressive" if you will in demeanor, overlapping itself into post-metal terminology. This is certainly an album more suited for younger fans or for more "rock" fans as it lacks many of the trademarks associated with the prog/symphonic prog genre. If you give it time, however, it can be a very engaging experience.


In addition to carrying nationally known labels, PERFORMANCE Foodservice has developed its own proprietary brand food and food-related products created to meet customers' specific needs. The Roma specialty is Italian and Italian-American food products. Since the beginning, "quality service, quality products" has been their motto. Their experienced sales force is well trained and focused on providing all the products and services that meet the unique needs of their customers.
PERFORMANCE Foodservice/Roma has assembled a team of in-house specialists to add expert advice for every operation's special needs. The category management team provides supply chain solutions for all product needs. They track the markets and buy the freshest products at the best possible price. Category Managers are dedicated to each product category. Chemical and disposable specialists provide the solutions and products needed to run the operational side of the business. When needed Performance Foodservice provides professional chef services to consult on menu ideas and today's trends. Customers can also tap into professional training services such as: Food Cost Analysis, Server Training, Menu Profitability Analysis, and Restaurant Marketing & Promotions.


Petko, Paul and Sarah enjoying some stimulating conversation!
Interested in learning a foreign language? Travelling to a German-speaking destination (there are more than you think)? Or just want to jog your grey cells a bit? Try our informal German conversation sessions - no matter whether you are complete beginner or are quite fluent. This is NOT a formal language course and you won't have to do homework. Most weeks we'll have two tutors available: both Kerstin and Petko are happy to prepare sessions that cover topics of your choice and progress will be at a speed that is comfortable for everyone.
If you are interested or have questions, please contact Kerstin Mason via email kerstin@jkmason.net or text to 07943 866330.
These sessions usually take place at St. Oswald's Church Hall at Cargill Avenue in Maybole. Contact Kerstin to join the mailing list for this group and to receive updates on locations for upcoming meetings (just in case we need to use an alternative venue).
Our German conversation sessions now run on Friday afternoons at 2.00pm.


Smithtown Personal Training & Nutrition in Smithtown, reviews near to real people. It revised its plans of expansion in East London furthermore in December 2014. Free CNA Training In Illinois - Nursing Career Tips Here is a list of WIA approved training programs in Illinois. MATH, CALCULUS ACCOUNTING STATISTICS CLASSES (chicago) map hide this posting restore restore this posting. DEPARTMENT OF HEALTH PROFESSIONS. Chicago, IL High Schools offering cna certification line CNA programs. Au cna book online pairs, nannies, childminders, nursery/pre-school. Get reviews, hours, directions, coupons also further due to Smithtown Personal Training rn bsn ba & Nutrition found in 55 E Main St, virginia physician license lookup Smithtown, NY. The current cost of 24 hour nursing care, full meals. 2 jobs amid Butler County Community College to view along among apply because now with Inside Higher Ed Careers. Dekalb Technical College Nursing Assistant Course. 79 Butler Community College Jobs available by Indeed. What does a Ophthalmic Medical Assistant do in a workday? Colorado Caregiver Training nursing licensed practical lgbt also Certified Nursing Aide School.


text:
Die Amateurliga Schleswig-Holstein wurde zur Saison 1963/64 das 17. Mal ausgetragen und bildete bis zur Saison 1973/74 den Unterbau der zweitklassigen Regionalliga Nord. Die beiden erstplatzierten Mannschaften durften an der Aufstiegsrunde zur zweitklassigen Regionalliga Nord teilnehmen, die Mannschaften auf den drei letzten Plätzen mussten in die 2. Amateurliga absteigen.

Vereine

Im Vergleich zur Saison 1962/63 veränderte sich die Zusammensetzung der Liga folgendermaßen: Der SV Friedrichsort war erstmals in die Regionalliga Nord aufgestiegen, während keine Mannschaft aus Schleswig-Holstein aus der Oberliga Nord abgestiegen war. Die beiden Absteiger Holstein Kiel Amateure (nach acht Jahren) und VfR Neumünster Amateure (nach sechs Jahren) hatten die Amateurliga verlassen und wurden durch die drei Aufsteiger SC Comet Kiel (Rückkehr nach sechs Jahren), FC Holstein Segeberg (Rückkehr nach acht Jahren) und VfB Kiel (Rückkehr nach einem Jahr) ersetzt.

Saisonverlauf

Die Meisterschaft und damit die Teilnahme an der Aufstiegsrunde sicherte sich der VfL Oldesloe. Als Zweitplatzierter durfte der FC Kilia Kiel ebenfalls teilnehmen. Beide verpassten den Aufstieg in die Regionalliga Nord.

Tabelle

|}

Aufstiegsrunde zur Amateurliga Schleswig-Holstein 1964/65

An der Aufstiegsrunde nahmen die Meister und Zweitplatzierten der sechs Staffeln der 2. Amateurliga teil. Sie spielten in drei Staffeln. Der Sieger jeder Staffel stieg in die Amateurliga auf. Bei Punktgleichheit wurde ein Entscheidungsspiel angesetzt.

Staffel A

|}

Staffel B

|}

Staffel C

|}

Quellen
 Bericht zur Saison 1963/64
 Amateurliga Schleswig-Holstein 1963/64 im deutschen Fußball-Archiv

Fußballsaison 1963/64
1963

redpajama_set_name: RedPajamaWikipedia


text:
Harry Potter and the Incredibly Conservative Aristocratic Children's Club
by Maria Bustillos November 23, 2010
The richly imaginative details of J.K. Rowling's fictive world, it must be admitted, are pleasurable. The hot-rod brooms, the flowing robes and flying cars, the goth Heaven of the sullen Slytherins, the snake language and the magic wands enclosing phoenix feathers or unicorn hairs, the metamorphic potions, the leaping or fizzing sweets! All these have been fully and lovingly realized in the Warner Brothers movie adaptations of the Harry Potter books, including the most recent, which is a fine-looking but completely incoherent mess with a morally bankrupt and politically repugnant story at its core.
No expense has been spared, naturally; Warner Brothers has seen $5.7 billion out of these movies in theatrical revenue, so far. The visual imagination of director David Yates (he has helmed Harry Potter 5 through 8) is kind of pedestrian but there are some lovely set pieces, notably an animated vignette that is just so beautiful and interesting. The movie was bound to be entertaining, a spectacle, provided you don't look too closely at what's being said.
The multitude of sins committed in Rowling's imaginative but horrible story can be roughly divided into three classes: ethical or pedagogical, literary and political.
Some years ago I was driving a carful of kids to some practice or party, and from the crowded back seat I heard one breathlessly ask the others, "When you were little," (they were maybe twelve at the time), "did you think you were going to get a letter from Hogwarts?"
Giggles arose in the car, some lofty and some sounding a little embarrassed; a couple of the kids admitted that they had in fact fantasized about receiving such an invitation. (When you are chosen to attend Hogwarts, the public school for wizards attended by Harry Potter, an owl shows up with a letter informing you that you are one of the lucky ones.) This concept of "chosenness" has always put me off the Potter books because it seems so harmful for kids, even though I am a lifelong SF/fantasy fan (a genre where this crops up frequently, to be sure).
In the world of Harry Potter, rules are for the little people. The "wisest" adult, headmaster Albus Dumbledore, showers magical gifts and indulgences on his favorites and lets them break every rule because they are so special, better than all others. How come they are so much better? Well, the general awesomeness and favoriteness of Harry Potter and his friends is mostly arbitrary, the result of the chosenness itself, rather than of effort or application. Harry Potter is just naturally fantastic at flying around on a broom and conjuring illuminated stags up out of his soul and things, Hermione Granger is just naturally the most brilliant student Hogwarts has ever seen, and so on. Ron Weasley, the impoverished aristocrat, is a Sancho Panza-like figure whose rough common sense is meant to keep Harry on the straight and narrow; his noble blood is his "chosen" quality, and marks him, too, as an unimpeachable Establishment figure.
Which brings us to the disconnect between reality and appearances regarding the nonconformity that Rowling so hamfistedly praises at every turn. Harry Potter and his friends, far from being renegades, are in fact slavishly obedient to the all-powerful, omniscient, do-no-wrong Dumbledore. And why not, when he provides them in advance with every rare and fabulous magical gewgaw and hint they will ever need in order to extricate themselves from whatever peril they may find themselves in.
Rowling's adherence to the old English principle of blood-nobility — that weird but deeply held superstition that has caused countless English protagonists to discover that unbeknownst to them, they were peers of the realm all along — is in stark contrast to the biggest conflict depicted in the Potter stories, the blood purity conflict. The bad guys, Voldemort and crew, are race purists, anti-Muggle (meaning anti-human), which is to say that they are against any magical Muggles or intermingling of Muggle blood ("Mudblood") and wizard blood. Yet Rowling's heroes are all noblemen, with the exception of one: Harry Potter learns in the old-fashioned surprise way that his father was a fabulously rich wizard, and his godfather is a rich aristocrat, too; Ron Weasley is a nobleman of the purest blood, though poor. The sole pure-Muggle wizard of any consequence at all in these books is Hermione, the author's personal projection of herself (there are two other minor pure-Muggle wizards, boys, both of whom are bumped off). So this story can be read pretty effectively as an explanation of why J.K. Rowling should be allowed to hang around with the nobility (she is smart, is why).
Maybe, incidentally, the reason no other woman as smart as Hermione appears in the books is that J.K. Rowling, like the Turk, can bear no sister near the throne. Her volcanic ego burns down everything in its path. Where the Twilight books are works produced from and for a state of sexual yearning and frustration, Rowling's "wizarding world" is a fantasy place created for the benefit of Hermione Granger, for her infinite sagacity, foresightedness and teacher's-pet-hood to be rewarded at every turn.
In any case it is a horrible thing to be teaching children, that you have to be "chosen"; that the highest places in this world are gained by celestial fiat, rather than by working out how to get there yourself and then busting tail until you succeed. If the "special" and "chosen" and "gifted" automatically receive all the honors there are, then what would be the point of working hard to achieve anything? So it is really terrible to hear these twelve-year-old kids so smitten with the idea that fulfillment would literally fly to them out of the sky, via owl.
Rowling is a self-avowed liberal who gave a million pounds to the Labour Party in 2008, but her values are Tory through and through. In her books it is the hoary old white guys who run everything; women are popped in here and there for liberal flavor. The tokenism is unbelievable.
Rowling named her first child after Jessica Mitford, the lefty Mitford sister (as opposed to the Nazi-sympathizing ones). Rowling often says she read Mitford's Hons and Rebels at age fourteen, and that it affected her profoundly; this book in fact provides a perfect illustration of Rowling's political disconnect, because Jessica Mitford was the daughter of the second Baron Redesdale, a "terrific Hon," as the Mitfords would have said. She was a super-blue-blood with rebelliously liberal views. It's exactly this privileged, elitist compassion-from-on-high that Rowling admires and has consistently depicted in the Potter books. But the liberal values, the openmindedness, the diversity, are all fake.
I am no fan of Ann Althouse, but I had to admit to a shudder of recognition when I read her criticism of liberals last week:
What is liberal about this attitude toward other people? You wallow in self-love, and what is it you love yourself for? For wanting to shower benefits on people… that you have nothing but contempt for.
This may not be such a very good description of liberals in general but it is an excellent description of J.K. Rowling. In the "touching" climactic scene in Harry Potter and the Deathly Hallows, the house-elf Dobby has been "liberated" by, and now sacrifices himself to save, Harry Potter & co. The house-elves as depicted in the movies are horrifyingly pathetic, small, cringing, grateful; the sad, brave little creature Dobby literally expires with the name of Harry Potter on his lips. It's like freedom is the gift of the chosen ones to bestow, and those thus benefited can die of gratitude and be "properly buried," which really, there is this long burial scene complete with Harry Potter and shovel. It's a perfect illustration of the "liberal condescension" that conservatives are always yodeling about, and it made my hair stand on end.
So don't think about that! Think instead of the strapping young buck Rupert Grint, a fine young actor who manages to rise above the tawdry, maudlin script, or even more, of Helena Bonham-Carter as the queen of the goths, Bellatrix Lestrange, whose gorgeous performance had me totally rooting for the bad guys, as usual. She's always got a magic wand or a knife at someone's throat, that girl. Alan Rickman as Severus Snape, too, is as seductive as ever. Just to hear his voice for me is easily worth the price of a movie ticket; really he could read the phone book aloud, for all I care.
The most conservative element of Harry Potter's world is that it is a materialist paradise, full of costly and rare magical artifacts, invisibility cloaks and piles of "wizard gold" at Gringott's Bank. Things, that you can make toys out of, things that you can worship and desire and buy. There's nothing in this story of alleged iconoclasts and rebels that would present the slightest challenge to the establishment. That's why the story dovetails so easily into a series of Hollywood blockbusters.
The Rowling story of the Single Welfare Mom Who Made Good is not exactly accurate, either; her background is solidly middle class, her dad was a Rolls-Royce engineer, she read French and classics at Exeter, and the father of her first child (whom she divorced, rather than the other way around) was a Portuguese TV personality.
So this good liberal's face is absolutely the face of the corpocracy. The number of lawsuits brought all over the world by Rowling and Warner Brothers against practically anybody who would dare to slap the Potter moniker on so much as a work of fanfic would curl your hair. Well, finally she allowed this one guy to write a fanfic novel, after having threatened to sue, perhaps because she knew she wouldn't have won. If it were up to J.K. Rowling, I think Jean Rhys would have been thrown in jail for daring to write Wide Sargasso Sea. Which is fanfic, too, come to that.
In the best-known and most terrible of these lawsuits, the proud liberal Rowling saw fit to sue a fan who'd devoted years of his life to making an online encyclopedia about her books. I don't believe I'll ever cry again over the plight of an alleged copyright violator but you never know, I guess. Steve Vander Ark wept openly himself when he testified at the trial, and even though Rowling personally sued him, he later wrote on the blog part of the Harry Potter Lexicon — just like a house-elf! — that he was "still Jo's man, through and through." It just breaks your heart, the integrity and gentleness of this man, the love he bears these wretched books, the way he was so wrongly disgraced. A shorter version of Vander Ark's book finally did see the light of day, in 2009.
On the literary side, suffice it to say that Rowling is ferociously dull and long-winded, that there is no suspense, that she kills people off (nobody Chosen, though) simply in order to show how serious things have become; magical artifacts are produced, used once for the specific purpose for which they were invented and then never seen again; the bad guys, whose actual aims are hopelessly opaque, have got the immemorial bad-guy cluelessness regarding the element of surprise, they let one opportunity after another to bump off our heroes slip past them, etc. Christopher Hitchens's 2007 review in the New York Times is generous, but pretty searing, too. ("The repeated tactic of deus ex machina (without a deus) has a deplorable effect on both the plot and the dialogue. The need for Rowling to play catch-up with her many convolutions infects her characters as well.")
Anybody should write whatever he or she pleases, of course, and there's no doubt that Rowling did something right in creating her fictional world of Quidditch and faux-Latin magical incantations, if only because so many people love it so dearly. But if you have a young Harry Potter fan in your orbit, you might steer him or her toward Philip Pullman, whose Dark Materials trilogy is genuine in every way that Harry Potter is false; a fully realized work of fantasy to rival Tolkien in its wisdom, inventiveness and questioning. Because Pullman's novels really do threaten the establishment view of religion and institutionalized coercion, because they are really subversive in the manner in which Harry Potter pretends to be, the Hollywood establishment chickened out completely and made a perfect hash of the first Pullman movie. Tom Stoppard, who'd adapted the original screenplay, was dumped by director Chris Weitz (of American Pie fame), who preferred to write his own. Hollywood is, unfortunately, an absolute tool of the corpocracy, and will never be equal to any story that presents a legitimate threat to conventionality or to materialist values.
Maria Bustillos is the author of Dorkismo: The Macho of the Dork and Act Like a Gentleman, Think Like a Woman.
at-the-movies


Before I get started, I want readers to understand that this is not a story of defeat, but instead it is a mostly a story of victory after overcoming enormous odds. I started to do this story anonymously but realized that I would only be perpetuating the shame often felt by trauma survivors and their families. I am not "anonymous" and my name is LaVerne Daisy Miller, daughter of Rose Miller and granddaughter of Daisy Henderson.
I also want to discourage readers from stereotyping African American families because the story that I tell is but is a situation experienced by many women, regardless of their race, ethnicity, and sometimes class. It is about the relationship between poverty and a child welfare system that continually traumatized and retraumatized many families like my own but did not break it. I have always felt different and I am.
I recently started including my full middle name "Daisy" instead simply using the letter "D" (more about this personal act of both love and defiance later). The reasons behind this change are complicated and have really been informed by the work that I do at PRA that focuses on different kinds of trauma and the physical, physiological, and emotional impact that inter-generational general trauma has upon so-called "survivors" and their families. The intersection between my work and my personal life initially caused a great deal of pain for me, but as the pain has slowly subsided, I have learned a lot about my grandmother, my mother, my aunts, and my cousins. I will start from the beginning. A lot of the information has been handed down verbally and I will share what I can remember from my perspective.
My maternal grandmother migrated from an affluent town in the D.C. area to Harlem, New York just before the Depression. She eloped with my grandfather when her family disapproved of him and cut off all ties with her family. In a short span of 12 years, she had 7 daughters. After the death of her husband, she increasingly depended on public benefits to take care of her family.
As the Great Depression set in and it became harder for my mother to take care of her family; my mother and her sisters were placed in either congregate care or foster care. They lived in different settings and with different families in different parts of New York City. They did not see each other often as children and young adults. Due to a congenital hip problem, my mother had major surgery to shorten one of her legs (a much more involved and gruesome procedure than it is now), and spent several years in the hospital.
One of the first things that the well-meaning nurses did after her surgery was to cut my mother's hair. The braid that went down her back was deemed too difficult to manage on a ward with so many ill children, so it had to go. I doubt that the nurses ever realized that cutting my mother's hair without her permission was yet another traumatic experience for a young girl. Removed by the state from her mother, hospitalized for several years, her pride and joy severed, and no family members or medical staff to comfort her or to understand how she was traumatized her.
After her discharge from the hospital, my mother spent most of life (before she married my father) in foster care like many of her sisters. It is because of what I have learned through my work at PRA that I have encouraged my mother to talk about her experiences in foster care. Like many of her sisters, she was alternately ignored, physically abused, and frequently sexually abused by the males in her foster families. My mother kept these secrets to insulate her children from the stigma surrounding foster children. But I think that the most compelling reason why she did not talk about these experiences and the impact it had on her and by extension, my siblings and me, was that she did not believe that she had any rights that anyone was bound to respect.
I realized that I also had to create a safe space for my mother to talk to me. We built up trust with each other bit by bit, and slowly she shared things with me confident that they would not scar or hurt me for life. I also think that my mother's concerns over my frequent bouts of often debilitating depression helped her open up to me over time. She sensed that that these discussions were a necessary part of my own healing process.
The first thing that I learned was that the maternal relatives that I had always considered "blood relatives" were members of my mother's foster family. As an adolescent, certain things did not add up for me; for instance, we were treated differently from other children who were a part of this large extended family.
While my mother talked to me about her experiences in foster care, why she was so protective of me and my two sisters, and how she was really scared for us, she never talked about my maternal grandmother. No one had ever asked her about what happened to her, her sisters, or her mother.
I only met my maternal grandmother once and never made any connection between my middle name and my mother's need to honor her mother. Finally, I learned that her name was Daisy and that my middle name was to honor her; she was not forgotten.
My parents enjoyed a long marriage before my father's untimely death in 1997, but his unconditional love for her and empathy for her helped her heal. The respect and love that she received from my paternal grandmother also helped her develop a sense of worth and the understanding that my grandmother's love and support would help my siblings and me overcome many challenges.
Most of all, my mother taught me about the power of forgiveness. She never speaks bitterly about her experiences and has consciously chosen to live a life of love. I will miss her when I can no longer hear her voice or benefit from her advice. I will miss ending our calls with "I love you" – words she never heard from her mother or her foster parents.
My siblings and I all suffer from depression and struggle deeply with negative feelings of self-worth. But we have chosen to live lives of compassion and kindness rather than lives of anger and resentment.
Now back to my decision to replace my middle initial "D" with the real person that it stands for, my maternal grandmother Daisy. It is important that I hear her name and that others hear it as well. Her life was a difficult one but she is a part of me. Sometimes I just find myself shouting her name so that unlike so many forgotten women of her generation, she is acknowledged. I honor her life whenever I can.
Part of my concern about doing this blog was that it would open a Pandora's Box about my personal life. But I think that the value of sharing my story far outweighs the potential cost. My family has been profoundly impacted by both my mother's and grandmother's experiences. But we are no longer in denial about the impact of trauma on our lives and the lives of our children. We work hard to not be defined by trauma.
Of my siblings, H is a teacher, D works with the developmentally challenged, B graduated from college in July, and me, Daisy, I am a lawyer. Trauma-informed care and therapy continue to help us heal. Peer support is also an important part of our recovery process as individuals and as a family. We are all at different stages in our recovery processes because we are four very different people. We have many more good days than we have bad days. We are also working together to ensure that what remains of my mother's life is filled with love, joy, and gratitude.


text:
HP Photosmart Wireless All-in-One B109
HP Photosmart Wireless All-in-One B109 Review
By Simon Williams November 15, 2009 12:00 am GMT
Trusted Score
After testing HP's new flagship Photosmart Premium C309 a couple of weeks back, it's interesting to look at the mid-range model. Costing less than half the price, the Photosmart Wireless B109 still has some of the key features of its more expensive sibling, such as wireless connection, touch-button controls and the same print engine, and even gives it a run for its money on print speed.
All dressed out in high-gloss black plastic, a bit last year and an absolute magnet for fingerprints, the B109 is still a smart, well-designed device. The Contact Image Sensor (CIS) scanner sits low on the machine, increasing its height only slightly and to the left of the scanner cover is a convenient little control panel.
With a small, 37mm LCD display in the middle, it has three touch-buttons down either side, with fixed functions labelled Return, Cancel and OK down the left and soft function keys down the right, with labels coming from menus on the display.
HP makes no attempt to integrate the paper tray into the body of the machine, instead designing it to fold up against the front panel. Fold down and swing out the extra support and you have a feed tray for either plain or photo paper. Paper feeds out to finish up on top of the feed stack.
Below the control panel on the left are two memory card slots, for SD, MemoryStick and xD cards, but there's no PictBridge or USB socket, which is a shame. At the back is a USB connection, but no Ethernet. The only network connection is a wireless one.
Wireless installation involves connecting the machine temporarily via USB and HP thoughtfully provides a cable for this function, but other machines, including the Photosmart Premium C309, can manage to make the link without the need for a cable.
Drivers are provided for Windows and OS X and can be downloaded for various incarnations of Linux. Other software includes the HP Solutions Centre and a copy of Windows Live Gallery, which we imagine Microsoft is keen to get into the market.
The four separate ink cartridges, with designs very similar to those used in Canon PIXMA machines, snap into the semi-permanent head and after you've printed an alignment page and re-scanned it, you're ready to go.
All inkjet printers have to undergo housekeeping, to maintain the nozzles in their print heads and keep the print quality high. This usually involves squirting small amounts of ink onto an absorbent pad inside the printer every so often. There's been a trend in recent printers and all-in-ones to increase the time taken for this housekeeping, which happens periodically before the start of a print job. The Photosmart Wireless B109 takes this to extremes, though.
At the start of printing our five-page text print test, the machine chuntered away for 30 seconds before starting to print. This is a long time, as long as we've seen from any inkjet, but when printing our best quality photo print the machine 'prepared' for a full minute before feeding paper and starting to print.
This is unacceptable, particularly as print speeds are quoted excluding any preparation time and so give an unrealistic impression of the time you'll have to wait for a print. This preparation doesn't occur on every job, but it did twice during our comparatively short test sequence.
The best times we could get from the machine were 36 seconds for the five-page text print, which is a speed of 8.33ppm and this increased to 10.17ppm for the 20-page job. Our five-page text and colour graphics test gave 5.17ppm. These speeds are all a little faster than from the C309, which is slightly odd for the cheaper machine.
The prints themselves are good, with strong, well-formed black text characters and little sign of any feathering. Colour graphics are also good, with clean, solid colour fills, good bright colours and excellent registration of black text over colour. A colour photocopy also reproduced well and was hard to tell from the original.
The photo test at best quality produced the kind of results we expect from HP inkjets, with good, natural colours, smooth transitions in areas of sky and a high level of detail, even caught in shadowed areas of the image. The machine is also capable of reproducing bright shades, when an image demands. These were altogether better results than from the Photosmart Premium.
This printer uses the same cartridges as its more expensive sibling, giving very similar costs. Using the high yield, XL cartridges, we calculate an ISO black page to be 3.25p and a colour one 7.91p. Both these costs are very reasonable, particularly for a machine costing under £90.
In nearly all respects, this is an excellent budget all-in-one, offering high quality print, at good prices and with the added convenience of wireless connection and touch controls. HP really does need to look at the length of time the machine spends housekeeping, though. There's little point in engineering fast print speeds, if it takes up to a minute before the printer starts its work.
Score in detail
Print Speed 6
Value 9
Print Quality 8
By Simon Williams
Simon Williams contributed printer reviews to Trusted Reviews between 2004 and 2017. …
Why trust our journalism?
Founded in 2004, Trusted Reviews exists to give our readers thorough, unbiased and independent advice on what to buy.
Today, we have millions of users a month from around the world, and assess more than 1,000 products a year.
Editorial independence means being able to give an unbiased verdict about a product or company, with the avoidance of conflicts of interest. To ensure this is possible, every member of the editorial staff follows a clear code of conduct.
We also expect our journalists to follow clear ethical standards in their work. Our staff members must strive for honesty and accuracy in everything they do. We follow the IPSO Editors' code of practice to underpin these standards.


text:
Q: Node JS Find all devices connected to the local network Hi guys Im trying to find a package or a code to find all connected devices on local network, I want to determine a list of all printers, and other devices on my network.
I found these two packages:
https://www.npmjs.com/package/local-devices
But it requires net-tools to be installed on my pc, to have arp command available
And the other one is
https://github.com/jas-/node-libnmap
But these other one requires Nmap to be installed, is there any solution in pure node ?

A: If you want to run on any platform, you need an universal third party application, though arp is available in most OS (Windows/Linux/Mac). If you want to run only on Windows you can use net view using exec.
const { exec } = require('child_process');
exec('net view', (error, stdout, stderr) => {
  var servers = stdout.match(/(\\\\\S+)/g);
  console.log("Servers available:");
  for (var server of servers) {
    console.log(server);
  }
});

redpajama_set_name: RedPajamaStackExchange