diff --git a/src/Collections/Comparable.php b/src/Collections/Comparable.php new file mode 100644 --- /dev/null +++ b/src/Collections/Comparable.php @@ -0,0 +1,9 @@ +list = []; + } + + /// + /// Helper methods + /// + + public function add ($item, float $weight = 1.0) : void { + $this->list[] = new WeightedValue($item, $weight); + } + + public function clear () : void { + $this->list = []; + } + + public function getHeaviest () { + $value = null; + + foreach ($this->list as $candidate) { + if ($value === null || $candidate->compareTo($value) > 0) { + $value = $candidate; + } + } + + return $value; + } + + public function toSortedArray () : array { + $weights = []; + $values = []; + + foreach ($this->list as $item) { + $weights[] = $item->getWeight(); + $values[] = $item->getValue(); + } + + array_multisort($weights, SORT_DESC, $values, SORT_ASC); + + return $values; + } + + /// + /// IteratorAggregate implementation + /// + + public function getIterator () : Iterator { + return new ArrayIterator($this->list); + } + + /// + /// Countable implementation + /// + + public function count () : int { + return count($this->list); + } + +} diff --git a/src/Collections/WeightedValue.php b/src/Collections/WeightedValue.php new file mode 100644 --- /dev/null +++ b/src/Collections/WeightedValue.php @@ -0,0 +1,75 @@ +value = $value; + $this->weight = $weight; + } + + /// + /// Getters and setters + /// + + public function getWeight () : float { + return $this->weight; + } + + public function setWeight (float $weight) : self { + $this->weight = $weight; + + return $this; + } + + public function getValue () { + return $this->value; + } + + public function setValue ($value) : self { + $this->value = $value; + + return $this; + } + + /// + /// Helper methods + /// + + public function compareTo (object $other) : int { + if (!$other instanceof WeightedValue) { + throw new TypeError; + } + + return $this->getWeight() <=> $other->getWeight(); + } + +} diff --git a/tests/Collections/WeightedListTest.php b/tests/Collections/WeightedListTest.php new file mode 100644 --- /dev/null +++ b/tests/Collections/WeightedListTest.php @@ -0,0 +1,79 @@ +list = new WeightedList; + $this->list->add("LOW", 0.1); + $this->list->add("HIGH", 4); + $this->list->add("AVERAGE"); + } + + /// + /// Tests + /// + + public function testAdd () : void { + $count = count($this->list); + + $this->list->add("ANOTHER"); + + $this->assertEquals($count + 1, count($this->list)); + } + + public function testClear () : void { + $this->list->clear(); + $this->assertEquals(0, count($this->list)); + } + + public function testGetHeaviest () : void { + $this->assertEquals(4, $this->list->getHeaviest()->getWeight()); + } + + public function testToSortedArray () : void { + $array = $this->list->toSortedArray(); + + $this->assertEquals(3, count($array)); + $this->assertEquals(["HIGH", "AVERAGE", "LOW"], $array); + } + + public function testToSortedArrayWithDuplicateValues () : void { + $this->list->add("AVERAGE"); + $array = $this->list->toSortedArray(); + + $this->assertEquals(4, count($array)); + $this->assertEquals(["HIGH", "AVERAGE", "AVERAGE", "LOW"], $array); + } + + public function testGetIterator () : void { + $count = 0; + + foreach ($this->list as $item) { + $this->assertInstanceOf(WeightedValue::class, $item); + $count++; + } + + $this->assertEquals(3, $count); + } + + public function testCount() : void { + $this->assertEquals(3, $this->list->count()); + } + +} diff --git a/tests/Collections/WeightedValueTest.php b/tests/Collections/WeightedValueTest.php new file mode 100644 --- /dev/null +++ b/tests/Collections/WeightedValueTest.php @@ -0,0 +1,79 @@ +lowValue = new WeightedValue("LOW", 0.1); + $this->highValue = new WeightedValue("HIGH"); + } + + /// + /// Tests + /// + + public function testGetWeight () : void { + $this->assertSame(0.1, $this->lowValue->getWeight()); + $this->assertSame( + WeightedValue::DEFAULT_WEIGHT, + $this->highValue->getWeight() + ); + } + + public function testSetWeight () : void { + $this->lowValue->setWeight(0.2); + $this->assertSame(0.2, $this->lowValue->getWeight()); + } + + public function testGetValue () : void { + $this->assertEquals("LOW", $this->lowValue->getValue()); + $this->assertEquals("HIGH", $this->highValue->getValue()); + } + + public function testSetValue () : void { + $this->lowValue->setValue("FOO"); + $this->assertEquals("FOO", $this->lowValue->getValue()); + } + + public function testCompareTo () : void { + $this->assertEquals( + 0, + $this->lowValue->compareTo($this->lowValue) + ); + + $this->assertEquals( + -1, + $this->lowValue->compareTo($this->highValue) + ); + + $this->assertEquals( + 1, + $this->highValue->compareTo($this->lowValue) + ); + } + + public function testCompareToWithApplesAndPears () : void { + $this->expectException("TypeError"); + $this->highValue->compareTo(new \stdClass); + } + +}