From 3e89c654ec7df057002ef04b92eb22f1d781cd76 Mon Sep 17 00:00:00 2001
From: Kacper Donat <kadet1090@gmail.com>
Date: Sun, 9 Sep 2018 13:05:01 +0200
Subject: [PATCH] multiple provider support

---
 config/routes.yaml                            |  7 ++--
 config/services.yaml                          | 14 ++++++--
 package.json                                  |  7 ++--
 resources/components/departures.html          |  4 +++
 resources/components/finder.html              |  2 ++
 resources/styles/_common.scss                 | 16 +++++++++
 resources/styles/main.scss                    |  2 +-
 resources/ts/components/departures.ts         |  1 -
 resources/ts/components/picker.ts             | 24 ++-----------
 resources/ts/urls.ts                          | 12 ++++---
 .../{ => Api/v1}/DeparturesController.php     |  5 +--
 .../{ => Api/v1}/MessagesController.php       |  5 +--
 .../{ => Api/v1}/StopsController.php          |  5 +--
 src/Controller/HomepageController.php         | 17 ---------
 src/Controller/MainController.php             | 27 ++++++++++++++
 src/Provider/Provider.php                     |  3 ++
 .../ZtmGdanskDataUpdateSubscriber.php         | 22 +++++++-----
 src/Provider/ZtmGdanskProvider.php            | 12 ++++++-
 src/Service/EntityConverter.php               |  2 ++
 src/Service/ProviderResolver.php              | 35 ++++++++-----------
 templates/app.html.twig                       | 13 +++++++
 templates/base.html.twig                      | 17 ++++-----
 templates/choose.html.twig                    | 11 ++++++
 webpack.config.js                             |  9 ++++-
 yarn.lock                                     |  8 +++++
 25 files changed, 183 insertions(+), 97 deletions(-)
 rename src/Controller/{ => Api/v1}/DeparturesController.php (91%)
 rename src/Controller/{ => Api/v1}/MessagesController.php (78%)
 rename src/Controller/{ => Api/v1}/StopsController.php (92%)
 delete mode 100644 src/Controller/HomepageController.php
 create mode 100644 src/Controller/MainController.php
 create mode 100644 templates/app.html.twig
 create mode 100644 templates/choose.html.twig

diff --git a/config/routes.yaml b/config/routes.yaml
index c3283aa..b42047c 100644
--- a/config/routes.yaml
+++ b/config/routes.yaml
@@ -1,3 +1,4 @@
-#index:
-#    path: /
-#    controller: App\Controller\DefaultController::index
+api_v1:
+  resource: ../src/Controller/Api/v1
+  type: annotation
+  prefix: /{provider}/api/v1
diff --git a/config/services.yaml b/config/services.yaml
index 279dc5f..57f7d5b 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -4,7 +4,7 @@
 # Put parameters here that don't need to change on each machine where the app is deployed
 # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
 parameters:
-    locale: 'en'
+    locale: 'pl'
 
 services:
     # default configuration for services in *this* file
@@ -15,6 +15,10 @@ services:
                             # fetching services directly from the container via $container->get() won't work.
                             # The best practice is to be explicit about your dependencies anyway.
 
+    _instanceof:
+        App\Provider\Provider:
+            tags: [ app.provider ]
+
     # makes classes in src/ available to be used as services
     # this creates a service per class whose id is the fully-qualified class name
     App\:
@@ -46,8 +50,8 @@ services:
     proxy.config:
         class: 'ProxyManager\Configuration'
         calls:
-        - ['setGeneratorStrategy', ['@proxy.strategy']]
-        - ['setProxiesTargetDir', ['%kernel.cache_dir%/proxy']]
+          - ['setGeneratorStrategy', ['@proxy.strategy']]
+          - ['setProxiesTargetDir', ['%kernel.cache_dir%/proxy']]
 
     ProxyManager\Configuration: '@proxy.config'
 
@@ -60,3 +64,7 @@ services:
     App\Service\Normalizer\:
         resource: '../src/Service/Normalizer'
         tags: [serializer.normalizer]
+
+    # other servces
+    App\Service\ProviderResolver:
+        arguments: [!tagged app.provider]
diff --git a/package.json b/package.json
index ece12a7..0931b14 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,6 @@
   "author": "Kacper Donat <kadet1090@gmail.com>",
   "license": "MIT",
   "devDependencies": {
-    "webpack": "^4.17.0",
-    "webpack-cli": "^3.1.0",
     "@fortawesome/fontawesome-svg-core": "^1.2.4",
     "@fortawesome/pro-light-svg-icons": "^5.3.1",
     "@fortawesome/pro-regular-svg-icons": "^5.3.1",
@@ -30,7 +28,12 @@
     "vue": "^2.5.17",
     "vue-class-component": "^6.2.0",
     "vue-property-decorator": "^7.0.0",
+    "webpack": "^4.17.0",
+    "webpack-cli": "^3.1.0",
     "xmldom": "^0.1.27",
     "xpath": "^0.0.27"
+  },
+  "dependencies": {
+    "mini-css-extract-plugin": "^0.4.2"
   }
 }
diff --git a/resources/components/departures.html b/resources/components/departures.html
index 12f271b..5daf4a4 100644
--- a/resources/components/departures.html
+++ b/resources/components/departures.html
@@ -24,6 +24,10 @@
                     {{ departure.line.symbol }}
                 </div>
                 <div class="line__display">{{ departure.display }}</div>
+                <div class="line__perks flex-space-left">
+                    <fa :icon="['fas', 'walking']" fixed-width v-if="departure.line.fast"/>
+                    <fa :icon="['fal', 'moon']" fixed-width v-if="departure.line.night"/>
+                </div>
             </div>
 
             <div class="departure__time">
diff --git a/resources/components/finder.html b/resources/components/finder.html
index f9d9bb2..d2173b3 100644
--- a/resources/components/finder.html
+++ b/resources/components/finder.html
@@ -34,9 +34,11 @@
         </div>
     </div>
     <div class="alert alert-warning" v-else-if="filter.length > 2">
+        <fa :icon="['far', 'exclamation-triangle']"></fa>
         Nie znaleziono więcej przystanków, spełniających te kryteria.
     </div>
     <div class="alert alert-info" v-else>
+        <fa :icon="['far', 'search']"></fa>
         Wprowadź zapytanie powyżej, aby wyszukać przystanek.
     </div>
 </div>
\ No newline at end of file
diff --git a/resources/styles/_common.scss b/resources/styles/_common.scss
index 27d2a1d..b9982a8 100644
--- a/resources/styles/_common.scss
+++ b/resources/styles/_common.scss
@@ -13,3 +13,19 @@
 .flex-space-right {
   margin-right: auto;
 }
+
+.alert {
+  border-width: 0;
+  background: transparent;
+
+  @each $color, $value in $theme-colors {
+    &.alert-#{$color} {
+      border-bottom: 2px solid theme-color-level($color, $alert-color-level);
+      transition: background-color ease 200ms;
+
+      &:hover {
+        background-color: rgba(theme-color-level($color, $alert-bg-level), .5);
+      }
+    }
+  }
+}
diff --git a/resources/styles/main.scss b/resources/styles/main.scss
index d3fea81..7359c14 100644
--- a/resources/styles/main.scss
+++ b/resources/styles/main.scss
@@ -1,4 +1,4 @@
-$border-radius: 2px;
+$border-radius: 0;
 $border-radius-lg: $border-radius;
 $border-radius-sm: $border-radius;
 
diff --git a/resources/ts/components/departures.ts b/resources/ts/components/departures.ts
index 4d15123..4a0a398 100644
--- a/resources/ts/components/departures.ts
+++ b/resources/ts/components/departures.ts
@@ -23,7 +23,6 @@ export class Departures extends Vue {
     async update() {
         const response = await fetch(urls.prepare(urls.departures, {
             stop: this.stops.map(stop => stop.id),
-            provider: 'gdansk'
         }));
 
         if (response.ok) {
diff --git a/resources/ts/components/picker.ts b/resources/ts/components/picker.ts
index 4f5f6d4..0dc69c6 100644
--- a/resources/ts/components/picker.ts
+++ b/resources/ts/components/picker.ts
@@ -9,26 +9,11 @@ import stop   = require('../../components/stop.html');
 
 import { Prop, Watch } from "vue-property-decorator";
 import { filter, map } from "../utils";
-import { debounce, throttle } from "../decorators";
-import { Departures } from "./departures";
+import { debounce } from "../decorators";
 
 @Component({ template: picker })
 export class PickerComponent extends Vue {
-    protected stops?: Stop[] = [{
-        "id": 2001,
-        "name": "Dworzec Główny",
-        "description": null,
-        "location": [54.35544, 18.64565],
-        "variant": "01",
-        "onDemand": false
-    }, {
-        "id": 2002,
-        "name": "Dworzec Główny",
-        "description": null,
-        "location": [54.35541, 18.64548],
-        "variant": "02",
-        "onDemand": false
-    }];
+    protected stops?: Stop[] = [];
 
     private remove(stop: Stop) {
         this.stops = this.stops.filter(s => s != stop);
@@ -70,10 +55,7 @@ export class FinderComponent extends Vue {
 
         this.state = 'fetching';
 
-        const response = await fetch(urls.prepare(urls.stops.search, {
-            name: this.filter,
-            provider: 'gdansk'
-        }));
+        const response = await fetch(urls.prepare(urls.stops.search, { name: this.filter }));
 
         if (response.ok) {
             this.found = await response.json();
diff --git a/resources/ts/urls.ts b/resources/ts/urls.ts
index c75e86d..0114a69 100644
--- a/resources/ts/urls.ts
+++ b/resources/ts/urls.ts
@@ -45,12 +45,14 @@ export function prepare(url: string, params: UrlParams = { }) {
     return Object.keys(params).length > 0 ? `${url}?${query(params)}` : url;
 }
 
+const base = '/{provider}/api/v1';
+
 export default {
-    departures: '/{provider}/departures',
+    departures: `${base}/departures`,
     stops: {
-        all:    '/{provider}/stops',
-        search: '/{provider}/stops/search',
-        get:    '/{provider}/stop/{id}'
+        all:    `${base}/stops`,
+        search: `${base}/stops/search`,
+        get:    `${base}/stops/{id}`
     },
-    prepare
+    prepare: (url: string, params: UrlParams = { }) => prepare(url, Object.assign({}, { provider: window['app'].provider }, params))
 }
\ No newline at end of file
diff --git a/src/Controller/DeparturesController.php b/src/Controller/Api/v1/DeparturesController.php
similarity index 91%
rename from src/Controller/DeparturesController.php
rename to src/Controller/Api/v1/DeparturesController.php
index a84a68d..8af7783 100644
--- a/src/Controller/DeparturesController.php
+++ b/src/Controller/Api/v1/DeparturesController.php
@@ -1,8 +1,9 @@
 <?php
 
 
-namespace App\Controller;
+namespace App\Controller\Api\v1;
 
+use App\Controller\Controller;
 use App\Model\Departure;
 use App\Provider\DepartureRepository;
 use App\Provider\StopRepository;
@@ -12,7 +13,7 @@ use Symfony\Component\Routing\Annotation\Route;
 /**
  * Class DeparturesController
  *
- * @Route("/{provider}/departures")
+ * @Route("/departures")
  */
 class DeparturesController extends Controller
 {
diff --git a/src/Controller/MessagesController.php b/src/Controller/Api/v1/MessagesController.php
similarity index 78%
rename from src/Controller/MessagesController.php
rename to src/Controller/Api/v1/MessagesController.php
index cd4e0ee..e7b821f 100644
--- a/src/Controller/MessagesController.php
+++ b/src/Controller/Api/v1/MessagesController.php
@@ -1,13 +1,14 @@
 <?php
 
-namespace App\Controller;
+namespace App\Controller\Api\v1;
 
 
+use App\Controller\Controller;
 use App\Provider\MessageRepository;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
 
 /**
- * @Route("/{provider}/messages")
+ * @Route("/messages")
  */
 class MessagesController extends Controller
 {
diff --git a/src/Controller/StopsController.php b/src/Controller/Api/v1/StopsController.php
similarity index 92%
rename from src/Controller/StopsController.php
rename to src/Controller/Api/v1/StopsController.php
index 609e75e..9494f30 100644
--- a/src/Controller/StopsController.php
+++ b/src/Controller/Api/v1/StopsController.php
@@ -1,8 +1,9 @@
 <?php
 
 
-namespace App\Controller;
+namespace App\Controller\Api\v1;
 
+use App\Controller\Controller;
 use App\Provider\StopRepository;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Annotation\Route;
@@ -11,7 +12,7 @@ use Symfony\Component\Routing\Annotation\Route;
  * Class StopsController
  *
  * @package App\Controller
- * @Route("/{provider}/stops")
+ * @Route("/stops")
  */
 class StopsController extends Controller
 {
diff --git a/src/Controller/HomepageController.php b/src/Controller/HomepageController.php
deleted file mode 100644
index f4e53a4..0000000
--- a/src/Controller/HomepageController.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-namespace App\Controller;
-
-
-use Symfony\Component\Routing\Annotation\Route;
-
-class HomepageController extends Controller
-{
-    /**
-     * @Route("/", name="home")
-     */
-    public function homepage()
-    {
-        return $this->render('base.html.twig');
-    }
-}
\ No newline at end of file
diff --git a/src/Controller/MainController.php b/src/Controller/MainController.php
new file mode 100644
index 0000000..89a120a
--- /dev/null
+++ b/src/Controller/MainController.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Controller;
+
+
+use App\Provider\Provider;
+use App\Service\ProviderResolver;
+use Symfony\Component\Routing\Annotation\Route;
+
+class MainController extends Controller
+{
+    /**
+     * @Route("/", name="choose")
+     */
+    public function choose(ProviderResolver $resolver)
+    {
+        return $this->render('choose.html.twig', ['providers' => $resolver->all()]);
+    }
+
+    /**
+     * @Route("/{provider}", name="app")
+     */
+    public function app(Provider $provider)
+    {
+        return $this->render('app.html.twig', ['provider' => $provider]);
+    }
+}
\ No newline at end of file
diff --git a/src/Provider/Provider.php b/src/Provider/Provider.php
index 3fd5a66..386ecc4 100644
--- a/src/Provider/Provider.php
+++ b/src/Provider/Provider.php
@@ -8,4 +8,7 @@ interface Provider
     public function getLineRepository(): LineRepository;
     public function getStopRepository(): StopRepository;
     public function getMessageRepository(): MessageRepository;
+
+    public function getName();
+    public function getIdentifier();
 }
\ No newline at end of file
diff --git a/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php b/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php
index 76f10cb..5d46f6a 100644
--- a/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php
+++ b/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php
@@ -27,6 +27,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
     private $em;
     private $ids;
     private $logger;
+    private $provider;
 
     /**
      * ZtmGdanskDataUpdateSubscriber constructor.
@@ -34,19 +35,24 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
      * @param $provider
      * @param $em
      */
-    public function __construct(EntityManagerInterface $em, IdUtils $ids, LoggerInterface $logger)
-    {
-        $this->em     = $em;
-        $this->ids    = $ids;
-        $this->logger = $logger;
+    public function __construct(
+        EntityManagerInterface $em,
+        IdUtils $ids,
+        LoggerInterface $logger,
+        ZtmGdanskProvider $provider
+    ) {
+        $this->em       = $em;
+        $this->ids      = $ids;
+        $this->logger   = $logger;
+        $this->provider = $provider;
     }
 
     public function update()
     {
         $provider = ProviderEntity::createFromArray([
-            'name'  => 'ZTM Gdańsk',
+            'name'  => $this->provider->getName(),
             'class' => ZtmGdanskProvider::class,
-            'id'    => 'ztm-gdansk',
+            'id'    => $this->provider->getIdentifier(),
         ]);
 
         $this->em->persist($provider);
@@ -94,7 +100,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
                 OperatorEntity::class,
                 $this->ids->generate($provider, $line['agencyId'])
             );
-            $type = [
+            $type     = [
                 2 => LineModel::TYPE_TRAM,
                 5 => LineModel::TYPE_TROLLEYBUS,
             ];
diff --git a/src/Provider/ZtmGdanskProvider.php b/src/Provider/ZtmGdanskProvider.php
index c4ae7db..12e9c8e 100644
--- a/src/Provider/ZtmGdanskProvider.php
+++ b/src/Provider/ZtmGdanskProvider.php
@@ -16,13 +16,23 @@ class ZtmGdanskProvider implements Provider
     private $stops;
     private $messages;
 
+    public function getName()
+    {
+        return 'MZKZG Trójmiasto';
+    }
+
+    public function getIdentifier()
+    {
+        return 'trojmiasto';
+    }
+
     public function __construct(
         EntityManagerInterface $em,
         GenericLineRepository $lines,
         GenericStopRepository $stops,
         ZtmGdanskMessageRepository $messages
     ) {
-        $provider = $em->getReference(ProviderEntity::class, 'ztm-gdansk');
+        $provider = $em->getReference(ProviderEntity::class, $this->getIdentifier());
 
         $lines = $lines->withProvider($provider);
         $stops = $stops->withProvider($provider);
diff --git a/src/Service/EntityConverter.php b/src/Service/EntityConverter.php
index a50d61f..9a2e3e2 100644
--- a/src/Service/EntityConverter.php
+++ b/src/Service/EntityConverter.php
@@ -64,6 +64,8 @@ final class EntityConverter
                     'symbol'   => $entity->getSymbol(),
                     'type'     => $entity->getType(),
                     'operator' => $convert($entity->getOperator()),
+                    'night'    => $entity->isNight(),
+                    'fast'     => $entity->isFast(),
                     'tracks'   => $this->collection($entity->getTracks(), $convert),
                 ]);
                 break;
diff --git a/src/Service/ProviderResolver.php b/src/Service/ProviderResolver.php
index 9aebe2e..d793a14 100644
--- a/src/Service/ProviderResolver.php
+++ b/src/Service/ProviderResolver.php
@@ -3,30 +3,18 @@
 
 namespace App\Service;
 
-
 use App\Exception\NonExistentServiceException;
 use App\Provider\Provider;
-use App\Provider\ZtmGdanskProvider;
+use Kadet\Functional\Transforms as t;
+use Tightenco\Collect\Support\Collection;
 
 class ProviderResolver
 {
-    private const PROVIDER = [
-        'gdansk' => ZtmGdanskProvider::class
-    ];
+    private $providers;
 
-    /**
-     * @var \Symfony\Component\DependencyInjection\ContainerInterface
-     */
-    private $container;
-
-    /**
-     * ProviderResolver constructor.
-     *
-     * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
-     */
-    public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container)
+    public function __construct($providers)
     {
-        $this->container = $container;
+        $this->providers = collect($providers)->keyBy(t\property('identifier'));
     }
 
     /**\
@@ -37,10 +25,17 @@ class ProviderResolver
      */
     public function resolve(string $name): Provider
     {
-        if (!array_key_exists($name, static::PROVIDER)) {
-            throw new NonExistentServiceException();
+        if (!$this->providers->has($name)) {
+            $message = sprintf("Provider '%s' doesn't exist, you can choose from: %s", $name, $this->providers->keys()->implode(', '));
+            throw new NonExistentServiceException($message);
         }
 
-        return $this->container->get(static::PROVIDER[$name]);
+        return $this->providers->get($name);
+    }
+
+    /** @return Provider[] */
+    public function all(): Collection
+    {
+        return clone $this->providers;
     }
 }
\ No newline at end of file
diff --git a/templates/app.html.twig b/templates/app.html.twig
new file mode 100644
index 0000000..fe97015
--- /dev/null
+++ b/templates/app.html.twig
@@ -0,0 +1,13 @@
+{% extends 'base.html.twig' %}
+{% block title "#{parent()} - #{provider.name}" %}
+{% block body %}
+    <stop-picker></stop-picker>
+{% endblock %}
+
+{% block javascripts %}
+    <script>
+        window.app = {
+            provider: {{ provider.identifier|json_encode|raw }}
+        }
+    </script>
+{% endblock %}
diff --git a/templates/base.html.twig b/templates/base.html.twig
index 35aabd2..da1759e 100644
--- a/templates/base.html.twig
+++ b/templates/base.html.twig
@@ -1,16 +1,17 @@
 <!DOCTYPE html>
 <html>
     <head>
-        <meta charset="UTF-8">
-        <title>{% block title %}Welcome!{% endblock %}</title>
-        {% block stylesheets %}{% endblock %}
+        <meta charset="UTF-8"/>
+        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+        <link rel="stylesheet" href="main.css" />
+
+        <title>{% block title %}Czy dojadę?{% endblock %}</title>
     </head>
     <body>
-        {% block body %}
-            <main id="app" class="container">
-                <stop-picker></stop-picker>
-            </main>
-        {% endblock %}
+        <main role="main" class="container" id="app">
+            {% block body %}{% endblock %}
+        </main>
+
         <script src="bundle.js"></script>
         {% block javascripts %}{% endblock %}
     </body>
diff --git a/templates/choose.html.twig b/templates/choose.html.twig
new file mode 100644
index 0000000..a2108e1
--- /dev/null
+++ b/templates/choose.html.twig
@@ -0,0 +1,11 @@
+{% extends 'base.html.twig' %}
+
+{% block body %}
+    <div class="alert alert-primary">
+        <fa :icon="['fal', 'info-circle']"></fa>
+        Wybierz źródło danych
+    </div>
+    {% for provider in providers %}
+        <a href="{{ path('app', { provider: provider.identifier }) }}">{{ provider.name }}</a>
+    {% endfor %}
+{% endblock %}
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index d65d5ca..aaa8d55 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,4 +1,6 @@
 const path = require('path');
+const MiniCssExtractPlugin = require("mini-css-extract-plugin");
+
 const config = {
     entry: {
         main: ['./resources/ts/app.ts'],
@@ -24,7 +26,9 @@ const config = {
             }]
         },{
             test: /\.s[ac]ss$/,
-            use: ["style-loader", "css-loader?sourceMap", "sass-loader?sourceMap"]
+            use: [{
+                loader: MiniCssExtractPlugin.loader,
+            }, "css-loader?sourceMap", "sass-loader?sourceMap"]
         }, {
             test: /\.css$/,
             use: ["style-loader", "css-loader"]
@@ -46,6 +50,9 @@ const config = {
             use: 'raw-loader'
         }]
     },
+    plugins: [
+        new MiniCssExtractPlugin({ filename: '[name].css' })
+    ],
 };
 
 module.exports = (env, argv) => {
diff --git a/yarn.lock b/yarn.lock
index 2b8ea52..995e125 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1967,6 +1967,14 @@ mimic-fn@^1.0.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
 
+mini-css-extract-plugin@^0.4.2:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.2.tgz#b3ecc0d6b1bbe5ff14add42b946a7b200cf78651"
+  dependencies:
+    loader-utils "^1.1.0"
+    schema-utils "^1.0.0"
+    webpack-sources "^1.1.0"
+
 minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"