Browse Source

Merge branch '10-allergies'

Frédéric G. MARAND 1 month ago
parent
commit
3e1cee366a

+ 27 - 0
allergies/.exercism/config.json

@@ -0,0 +1,27 @@
+{
+  "authors": [
+    "mikeSimonson"
+  ],
+  "contributors": [
+    "arueckauer",
+    "DerTee",
+    "G-Rath",
+    "kunicmarko20",
+    "kytrinyx",
+    "petemcfarlane"
+  ],
+  "files": {
+    "solution": [
+      "Allergies.php"
+    ],
+    "test": [
+      "AllergiesTest.php"
+    ],
+    "example": [
+      ".meta/example.php"
+    ]
+  },
+  "blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.",
+  "source": "Jumpstart Lab Warm-up",
+  "source_url": "https://jumpstartlab.com"
+}

+ 1 - 0
allergies/.exercism/metadata.json

@@ -0,0 +1 @@
+{"track":"php","exercise":"allergies","id":"1c6f0421cf594fd2b0d549654a397184","url":"https://exercism.org/tracks/php/exercises/allergies","handle":"Fairgame","is_requester":true,"auto_approve":false}

+ 89 - 0
allergies/Allergies.php

@@ -0,0 +1,89 @@
+<?php
+
+/*
+ * By adding type hints and enabling strict type checking, code can become
+ * easier to read, self-documenting and reduce the number of potential bugs.
+ * By default, type declarations are non-strict, which means they will attempt
+ * to change the original type to match the type specified by the
+ * type-declaration.
+ *
+ * In other words, if you pass a string to a function requiring a float,
+ * it will attempt to convert the string value to a float.
+ *
+ * To enable strict mode, a single declare directive must be placed at the top
+ * of the file.
+ * This means that the strictness of typing is configured on a per-file basis.
+ * This directive not only affects the type declarations of parameters, but also
+ * a function's return type.
+ *
+ * For more info review the Concept on strict type checking in the PHP track
+ * <link>.
+ *
+ * To disable strict typing, comment out the directive below.
+ */
+
+declare(strict_types=1);
+
+class Allergies {
+
+  /**
+   * @var \Allergen[]
+   */
+  private array $allergies = [];
+
+  public function __construct(int $score) {
+    $score &= Allergen::CATS * 2 - 1;
+    $id = Allergen::EGGS;
+    while ($id <= Allergen::CATS) {
+      if ($id & $score) {
+        $this->allergies[] = new Allergen($id);
+      }
+      $id <<= 1;
+    }
+  }
+
+  public function isAllergicTo(Allergen $allergen): bool {
+    return in_array($allergen, $this->allergies);
+  }
+
+  /**
+   * @return \Allergen[]
+   */
+  public function getList(): array {
+    return $this->allergies;
+  }
+
+}
+
+class Allergen {
+
+  public const EGGS = 1;
+
+  public const PEANUTS = 2;
+
+  public const SHELLFISH = 4;
+
+  public const STRAWBERRIES = 8;
+
+  public const TOMATOES = 16;
+
+  public const CHOCOLATE = 32;
+
+  public const POLLEN = 64;
+
+  public const CATS = 128;
+
+  private int $id;
+
+  public function __construct(int $id) {
+    $this->id = $id;
+  }
+
+  public static function allergenList(): array {
+    return [];
+  }
+
+  public function getScore(): int {
+    return $this->id;
+  }
+}

+ 145 - 0
allergies/AllergiesTest.php

@@ -0,0 +1,145 @@
+<?php
+
+/*
+ * By adding type hints and enabling strict type checking, code can become
+ * easier to read, self-documenting and reduce the number of potential bugs.
+ * By default, type declarations are non-strict, which means they will attempt
+ * to change the original type to match the type specified by the
+ * type-declaration.
+ *
+ * In other words, if you pass a string to a function requiring a float,
+ * it will attempt to convert the string value to a float.
+ *
+ * To enable strict mode, a single declare directive must be placed at the top
+ * of the file.
+ * This means that the strictness of typing is configured on a per-file basis.
+ * This directive not only affects the type declarations of parameters, but also
+ * a function's return type.
+ *
+ * For more info review the Concept on strict type checking in the PHP track
+ * <link>.
+ *
+ * To disable strict typing, comment out the directive below.
+ */
+
+declare(strict_types=1);
+
+class AllergiesTest extends PHPUnit\Framework\TestCase
+{
+    public static function setUpBeforeClass(): void
+    {
+        require_once 'Allergies.php';
+    }
+
+    /**
+     * @dataProvider provideListOfAllergen
+     *
+     * @param Allergen $allergen
+     */
+    public function testNoAllergiesMeansNotAllergicToAnything($allergen): void
+    {
+        $allergies = new Allergies(0);
+
+        $this->assertFalse($allergies->isAllergicTo($allergen));
+    }
+
+    /**
+     * @dataProvider provideListOfAllergen
+     *
+     * @param Allergen $allergicTo
+     */
+    public function testAllergiesToOneAllergen($allergicTo): void
+    {
+        $allergies = new Allergies($allergicTo->getScore());
+
+        $this->assertTrue($allergies->isAllergicTo($allergicTo));
+        $otherAllergen = array_filter(Allergen::allergenList(), function ($allergen) use ($allergicTo) {
+            return $allergen != $allergicTo;
+        });
+
+        array_map(function ($allergen) use ($allergies) {
+            $this->assertFalse($allergies->isAllergicTo($allergen));
+        }, $otherAllergen);
+    }
+
+    public static function provideListOfAllergen(): array
+    {
+        require_once 'Allergies.php';
+
+        return [
+            [new Allergen(Allergen::CATS), 'Only allergic to cats'],
+            [new Allergen(Allergen::CHOCOLATE), 'Only allergic to chocolate'],
+            [new Allergen(Allergen::EGGS), 'Only allergic to eggs'],
+            [new Allergen(Allergen::PEANUTS), 'Only allergic to peanuts'],
+            [new Allergen(Allergen::POLLEN), 'Only allergic to pollen'],
+            [new Allergen(Allergen::SHELLFISH), 'Only allergic to shellfish'],
+            [new Allergen(Allergen::STRAWBERRIES), 'Only allergic to strawberries'],
+            [new Allergen(Allergen::TOMATOES), 'Only allergic to tomatoes'],
+        ];
+    }
+
+    public function testAllergicToEggsInAdditionToOtherStuff(): void
+    {
+        $allergies = new Allergies(5);
+
+        $this->assertTrue($allergies->isAllergicTo(new Allergen(Allergen::EGGS)));
+    }
+
+    public function testIsAllergicToLotsOfStuffs(): void
+    {
+        $allergies = new Allergies(248);
+
+        $this->assertEqualsCanonicalizing([
+            new Allergen(Allergen::CATS),
+            new Allergen(Allergen::CHOCOLATE),
+            new Allergen(Allergen::POLLEN),
+            new Allergen(Allergen::STRAWBERRIES),
+            new Allergen(Allergen::TOMATOES),
+        ], $allergies->getList());
+    }
+
+    public function testIsAllergicToEggsAndPeanuts(): void
+    {
+        $allergies = new Allergies(3);
+
+        $this->assertEqualsCanonicalizing([
+            new Allergen(Allergen::EGGS),
+            new Allergen(Allergen::PEANUTS),
+        ], $allergies->getList());
+    }
+
+    public function testIsAllergicToEggsAndShellfish(): void
+    {
+        $allergies = new Allergies(5);
+
+        $this->assertEqualsCanonicalizing([
+            new Allergen(Allergen::EGGS),
+            new Allergen(Allergen::SHELLFISH),
+        ], $allergies->getList());
+    }
+
+    public function testIgnoreNonAllergenScorePart(): void
+    {
+        $allergies = new Allergies(509);
+
+        $this->assertEqualsCanonicalizing([
+            new Allergen(Allergen::CATS),
+            new Allergen(Allergen::CHOCOLATE),
+            new Allergen(Allergen::EGGS),
+            new Allergen(Allergen::POLLEN),
+            new Allergen(Allergen::SHELLFISH),
+            new Allergen(Allergen::STRAWBERRIES),
+            new Allergen(Allergen::TOMATOES),
+        ], $allergies->getList());
+    }
+
+    /**
+     * @dataProvider provideListOfAllergen
+     */
+    public function testIsAllergicToEverything($allergen): void
+    {
+        $allergies = new Allergies(255);
+
+        $this->assertTrue($allergies->isAllergicTo($allergen));
+    }
+}

+ 52 - 0
allergies/HELP.md

@@ -0,0 +1,52 @@
+# Help
+
+## Running the tests
+
+## Running the tests
+
+1. Go to the root of your PHP exercise directory, which is `<EXERCISM_WORKSPACE>/php`.
+   To find the Exercism workspace run
+
+       ➜ exercism debug | grep Workspace
+
+1. Get [PHPUnit] if you don't have it already.
+
+       ➜ wget -O phpunit https://phar.phpunit.de/phpunit-9.phar
+       ➜ chmod +x phpunit
+       ➜ ./phpunit --version
+
+2. Execute the tests:
+
+       ➜ ./phpunit file_to_test.php
+
+   For example, to run the tests for the Hello World exercise, you would run:
+
+       ➜ ./phpunit HelloWorldTest.php
+
+[PHPUnit]: https://phpunit.de
+
+## Submitting your solution
+
+You can submit your solution using the `exercism submit Allergies.php` command.
+This command will upload your solution to the Exercism website and print the solution page's URL.
+
+It's possible to submit an incomplete solution which allows you to:
+
+- See how others have completed the exercise
+- Request help from a mentor
+
+## Need to get help?
+
+If you'd like help solving the exercise, check the following pages:
+
+- The [PHP track's documentation](https://exercism.org/docs/tracks/php)
+- The [PHP track's programming category on the forum](https://forum.exercism.org/c/programming/php)
+- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
+- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
+
+Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
+
+To get help if you're having trouble, you can use one of the following resources:
+
+ - [/r/php](https://www.reddit.com/r/php) is the PHP subreddit.
+ - [StackOverflow](https://stackoverflow.com/questions/tagged/php) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.

+ 54 - 0
allergies/README.md

@@ -0,0 +1,54 @@
+# Allergies
+
+Welcome to Allergies on Exercism's PHP Track.
+If you need help running the tests or submitting your code, check out `HELP.md`.
+
+## Instructions
+
+Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.
+
+An allergy test produces a single numeric score which contains the
+information about all the allergies the person has (that they were
+tested for).
+
+The list of items (and their value) that were tested are:
+
+* eggs (1)
+* peanuts (2)
+* shellfish (4)
+* strawberries (8)
+* tomatoes (16)
+* chocolate (32)
+* pollen (64)
+* cats (128)
+
+So if Tom is allergic to peanuts and chocolate, he gets a score of 34.
+
+Now, given just that score of 34, your program should be able to say:
+
+- Whether Tom is allergic to any one of those allergens listed above.
+- All the allergens Tom is allergic to.
+
+Note: a given score may include allergens **not** listed above (i.e.
+allergens that score 256, 512, 1024, etc.).  Your program should
+ignore those components of the score.  For example, if the allergy
+score is 257, your program should only report the eggs (1) allergy.
+
+## Source
+
+### Created by
+
+- @mikeSimonson
+
+### Contributed to by
+
+- @arueckauer
+- @DerTee
+- @G-Rath
+- @kunicmarko20
+- @kytrinyx
+- @petemcfarlane
+
+### Based on
+
+Jumpstart Lab Warm-up - https://jumpstartlab.com