{"id":13442554,"url":"https://github.com/dnaeon/cl-covid19","last_synced_at":"2025-04-13T14:43:07.546Z","repository":{"id":143223679,"uuid":"273314445","full_name":"dnaeon/cl-covid19","owner":"dnaeon","description":"Explore COVID-19 data with Common Lisp, gnuplot, SQL and Grafana","archived":false,"fork":false,"pushed_at":"2022-03-30T15:34:48.000Z","size":8759,"stargazers_count":59,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-27T05:41:37.596Z","etag":null,"topics":["common-lisp","covid-19","covid19","covid19-data","database","gnuplot","grafana","graph","lisp","postgresql","programming","series-data","sql"],"latest_commit_sha":null,"homepage":"","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dnaeon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-06-18T18:42:55.000Z","updated_at":"2024-08-25T22:56:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"535301b4-8929-40f4-9825-b652804040f4","html_url":"https://github.com/dnaeon/cl-covid19","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnaeon%2Fcl-covid19","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnaeon%2Fcl-covid19/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnaeon%2Fcl-covid19/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnaeon%2Fcl-covid19/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dnaeon","download_url":"https://codeload.github.com/dnaeon/cl-covid19/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248731769,"owners_count":21152838,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["common-lisp","covid-19","covid19","covid19-data","database","gnuplot","grafana","graph","lisp","postgresql","programming","series-data","sql"],"created_at":"2024-07-31T03:01:47.190Z","updated_at":"2025-04-13T14:43:07.521Z","avatar_url":"https://github.com/dnaeon.png","language":"Common Lisp","funding_links":[],"categories":["Common Lisp"],"sub_categories":[],"readme":"# Explore COVID-19 data in Common Lisp\n\nThe `cl-covid19` system provides APIs for exploring and reviewing\n[COVID-19](https://en.wikipedia.org/wiki/Coronavirus_disease_2019)\ndata with Common Lisp, SQL, gnuplot and Grafana.\n\nThe system fetches time-series data from the [COVID-19\nAPI](https://covid19api.com), and persists it locally in a\n[SQLite](https://www.sqlite.org) database, so it can be reviewed\noffline.\n\n![COVID-19 Cases in BG with filledcurves](./images/covid19-bg-filledcurves.png)\n\n![COVID-19 Grafana Dashboard](./images/covid19-grafana-1.png)\n\n## Requirements\n\n* [Quicklisp](https://www.quicklisp.org/beta/)\n* [SQLite3](https://sqlite.org) dev libraries\n* [cl-migratum](https://github.com/dnaeon/cl-migratum) for database migrations\n* [gnuplot](http://gnuplot.sourceforge.net) for plotting graphs (optional)\n* [Grafana](https://grafana.com) (optional)\n* [PostgreSQL](https://www.postgresql.org) (optional)\n\n## Installation\n\nClone the `cl-covid19` repo in your [Quicklisp\nlocal-projects](https://www.quicklisp.org/beta/faq.html) directory.\n\n``` shell\ngit clone https://github.com/dnaeon/cl-covid19.git\n```\n\nLoad the system.\n\n``` common-lisp\nCL-USER\u003e (ql:quickload :cl-covid19)\n```\n\n## Usage\n\nThe following section provides examples to get you started.\n\n## Sample database\n\nYou can find an already populated database, that you can use in the\n[databases](./databases/) directory of this repo.\n\n### Create Database\n\nFirst, we need to create a connection to the SQLite database.\n\n``` common-lisp\nCL-USER\u003e (defparameter *db-conn*\n           (covid19:make-db-conn \"covid19.db\"))\n*DB-CONN*\n```\n\nNext, we need to apply the database migrations, so that the database\nschema is properly created. Database schema migrations are handled by\n[cl-migratum](https://github.com/dnaeon/cl-migratum) system.\n\n``` common-lisp\nCL-USER\u003e (covid19:migrate-db *db-conn*)\n```\n\nYou should see similar output when applying the database migrations.\n``` common-lisp\n \u003cINFO\u003e [16:01:37] cl-migratum.core core.lisp (apply-pending) -\n  Found 3 pending migration(s) to be applied\n \u003cINFO\u003e [16:01:37] cl-migratum.core core.lisp (apply-and-register) -\n  Applying migration 20200608135822 - create_countries_table\n \u003cINFO\u003e [16:01:37] cl-migratum.core core.lisp (apply-and-register) -\n  Applying migration 20200611230626 - add_time_series_table\n \u003cINFO\u003e [16:01:37] cl-migratum.core core.lisp (apply-and-register) -\n  Applying migration 20200611234716 - add_time_series_views\n```\n\nThe local SQLite database provides the following tables and views.\n\n| Name                                   | Description                                                                          |\n|----------------------------------------|--------------------------------------------------------------------------------------|\n| `migration`                            | Contains the applied database migrations                                             |\n| `continent`                            | Contains rows about each continent                                                   |\n| `country`                              | Contains the countries fetched from the remote API                                   |\n| `time_series`                          | Time series for each country                                                         |\n| `time_series_global`                   | Aggregated global time series                                                        |\n| `time_series_per_country`              | Time series data per country                                                         |\n| `time_series_per_country_latest`       | Latest time series data per country                                                  |\n| `time_series_per_country_weekly_avg`   | Last 7 days average of new cases per country                                         |\n| `time_series_per_country_biweekly_avg` | Last 14 days average of new cases per country                                        |\n| `time_series_per_country_per_million`  | Cases per million population for each country                                        |\n| `time_series_per_country_incidence`    | [Incidence](https://blog.covidactnow.org/what-is-covid-incidence/) cases per country |\n| `time_series_per_continent`            | Time series data per continent                                                       |\n| `time_series_per_continent_latest`     | Latest time series data per continent                                                |\n| `population`                           | Population for each country on yearly basis                                          |\n| `population_per_country`               | A view which joins `country` and `population`                                        |\n| `population_per_country_latest`        | A view returning the latest population per country                                   |\n\n### Create API Client\n\nIn order to fetch data from the COVID-19 API, we need to create an\nAPI client.\n\n``` common-lisp\nCL-USER\u003e (defparameter *api-client*\n           (covid19:make-api-client))\n*API-CLIENT*\n```\n\n### Updating local database with latest time series data\n\nUsing the API client we've created in the previous step we can now\nfetch the latest time-series data and persist them locally in our\ndatabase. In order to do that simply call the\n`COVID19:UPDATE-ALL-DATA` function.\n\n``` common-lisp\nCL-USER\u003e (covid19:update-all-data *api-client* *db-conn*)\nT\n```\n\nYou should probably do that once in a day, since time-series data\nusually gets updated on daily basis.\n\n### Fetching data from the database\n\nThe following examples show how to fetch various data from the\ndatabase.\n\nBy default each fetch function will return up to\n`COVID19:*DEFAULT-RESULT-LIMIT*` number of items. You can either use\nthe `:limit` keyword parameter of the fetch function you use, or\nrebind the above parameter to a value you want.\n\nAnother common parameter used by the various fetch functions is\n`:offset`, which allows you to skip a given number of items and is\nuseful for retrieving items in pages, when used in combination with\nthe `:limit` keyword parameter.\n\nThe `:order` keyword parameter, used in some fetching functions\ncontrols the order in which items will be returned based on the\n`timestamp` column. By default the results will be in descending order\n(most recent ones). If you need to return items in ascending order\n(oldest to newest ones), you can use the `:asc` value for the `:order`\nkeyword parameter.\n\nHere's how to fetch ten countries using the `COVID19:FETCH-COUNTRIES`\nfunction. You can control the number of results to fetch by using the\n`:limit` keyword parameter.\n\n``` common-lisp\nCL-USER\u003e (covid19:fetch-countries *db-conn* :limit 10)\n((:|id| 1 :|iso_code| \"JE\" :|name| \"Jersey\" :|slug| \"jersey\")\n (:|id| 2 :|iso_code| \"MM\" :|name| \"Myanmar\" :|slug| \"myanmar\")\n (:|id| 3 :|iso_code| \"NA\" :|name| \"Namibia\" :|slug| \"namibia\")\n (:|id| 4 :|iso_code| \"SO\" :|name| \"Somalia\" :|slug| \"somalia\")\n (:|id| 5 :|iso_code| \"AU\" :|name| \"Australia\" :|slug| \"australia\")\n (:|id| 6 :|iso_code| \"GD\" :|name| \"Grenada\" :|slug| \"grenada\")\n (:|id| 7 :|iso_code| \"JP\" :|name| \"Japan\" :|slug| \"japan\")\n (:|id| 8 :|iso_code| \"QA\" :|name| \"Qatar\" :|slug| \"qatar\")\n (:|id| 9 :|iso_code| \"UM\" :|name| \"US Minor Outlying Islands\" :|slug|\n  \"us-minor-outlying-islands\")\n (:|id| 10 :|iso_code| \"AG\" :|name| \"Antigua and Barbuda\" :|slug|\n  \"antigua-and-barbuda\"))\n```\n\nYou can also use the `COVID19:DISPLAY-TABLE` function to display a\ntable of the fetched results from your REPL.\n\n``` common-lisp\nCL-USER\u003e (covid19:display-table\n          (covid19:fetch-countries *db-conn* :limit 10))\n+----+----------+---------------------------+---------------------------+\n| id | iso_code | name                      | slug                      |\n+----+----------+---------------------------+---------------------------+\n|  1 | JE       | Jersey                    | jersey                    |\n|  2 | MM       | Myanmar                   | myanmar                   |\n|  3 | NA       | Namibia                   | namibia                   |\n|  4 | SO       | Somalia                   | somalia                   |\n|  5 | AU       | Australia                 | australia                 |\n|  6 | GD       | Grenada                   | grenada                   |\n|  7 | JP       | Japan                     | japan                     |\n|  8 | QA       | Qatar                     | qatar                     |\n|  9 | UM       | US Minor Outlying Islands | us-minor-outlying-islands |\n| 10 | AG       | Antigua and Barbuda       | antigua-and-barbuda       |\n+----+----------+---------------------------+---------------------------+\nNIL\n```\n\nIn order to get a specific country by either name or ISO code you can use the\n`COVID19:FETCH-COUNTRY` function, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19:fetch-country *db-conn* \"BG\")\n((:|id| 44 :|iso_code| \"BG\" :|name| \"Bulgaria\" :|slug| \"bulgaria\"))\n```\n\nTime series data can be fetched using the `COVID19:FETCH-TIME-SERIES`\nfunction. The results will contain historical records for each\ncountry, ordered by timestamp in descending order.\n\n``` common-lisp\nCL-USER\u003e (covid19:display-table\n          (covid19:fetch-time-series *db-conn* :limit 10))\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+---------------------+---------------------+------------------+\n| timestamp            | confirmed | deaths | recovered | active | new_confirmed | new_deaths | new_recovered | new_active | country_id | country_name        | country_slug        | country_iso_code |\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+---------------------+---------------------+------------------+\n| 2020-06-16T00:00:00Z |       262 |      6 |       179 |     77 |             0 |          0 |             4 |         -4 |          2 | Myanmar             | myanmar             | MM               |\n| 2020-06-16T00:00:00Z |        34 |      0 |        18 |     16 |             2 |          0 |             1 |          1 |          3 | Namibia             | namibia             | NA               |\n| 2020-06-16T00:00:00Z |      2658 |     88 |       649 |   1921 |            16 |          0 |            27 |        -11 |          4 | Somalia             | somalia             | SO               |\n| 2020-06-16T00:00:00Z |      7370 |    102 |      6861 |    407 |            23 |          0 |             5 |         18 |          5 | Australia           | australia           | AU               |\n| 2020-06-16T00:00:00Z |        23 |      0 |        22 |      1 |             0 |          0 |             0 |          0 |          6 | Grenada             | grenada             | GD               |\n| 2020-06-16T00:00:00Z |     17484 |    934 |     15652 |    898 |            45 |          5 |            85 |        -45 |          7 | Japan               | japan               | JP               |\n| 2020-06-16T00:00:00Z |     82077 |     80 |     60461 |  21536 |          1201 |          4 |          1780 |       -583 |          8 | Qatar               | qatar               | QA               |\n| 2020-06-16T00:00:00Z |        26 |      3 |        22 |      1 |             0 |          0 |             2 |         -2 |         10 | Antigua and Barbuda | antigua-and-barbuda | AG               |\n| 2020-06-16T00:00:00Z |       532 |      9 |       236 |    287 |            49 |          0 |             4 |         45 |         11 | Benin               | benin               | BJ               |\n| 2020-06-16T00:00:00Z |      8931 |    212 |      7937 |    782 |            46 |          0 |           109 |        -63 |         12 | Morocco             | morocco             | MA               |\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+---------------------+---------------------+------------------+\nNIL\n```\n\nIf you want to get the time-series data for a given country you can\nuse `COVID19:FETCH-TIME-SERIES-FOR-COUNTRY`. The following command will\nreturn the data for the past 10 days.\n\n``` common-lisp\nCL-USER\u003e (covid19:display-table\n          (covid19:fetch-time-series-for-country *db-conn* \"Bulgaria\" :limit 10))\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+--------------+--------------+------------------+\n| timestamp            | confirmed | deaths | recovered | active | new_confirmed | new_deaths | new_recovered | new_active | country_id | country_name | country_slug | country_iso_code |\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+--------------+--------------+------------------+\n| 2020-06-16T00:00:00Z |      3453 |    181 |      1817 |   1455 |           112 |          5 |            33 |         74 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-15T00:00:00Z |      3341 |    176 |      1784 |   1381 |            51 |          2 |            54 |         -5 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-14T00:00:00Z |      3290 |    174 |      1730 |   1386 |            24 |          2 |             7 |         15 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-13T00:00:00Z |      3266 |    172 |      1723 |   1371 |            75 |          0 |             7 |         68 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-12T00:00:00Z |      3191 |    172 |      1716 |   1303 |           105 |          4 |            28 |         73 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-11T00:00:00Z |      3086 |    168 |      1688 |   1230 |            93 |          1 |            24 |         68 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-10T00:00:00Z |      2993 |    167 |      1664 |   1162 |           104 |          0 |            41 |         63 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-09T00:00:00Z |      2889 |    167 |      1623 |   1099 |            79 |          3 |            36 |         40 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-08T00:00:00Z |      2810 |    164 |      1587 |   1059 |            83 |          4 |            39 |         40 |         44 | Bulgaria     | bulgaria     | BG               |\n| 2020-06-07T00:00:00Z |      2727 |    160 |      1548 |   1019 |            16 |          0 |             3 |         13 |         44 | Bulgaria     | bulgaria     | BG               |\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+--------------+--------------+------------------+\nNIL\n```\n\nLatest (most recent) time-series data per country can be fetched using\nthe `COVID19:FETCH-TIME-SERIES-LATEST` function, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19:display-table\n          (covid19:fetch-time-series-latest *db-conn* :limit 5))\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+--------------+--------------+------------------+\n| timestamp            | confirmed | deaths | recovered | active | new_confirmed | new_deaths | new_recovered | new_active | country_id | country_name | country_slug | country_iso_code |\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+--------------+--------------+------------------+\n| 2020-06-16T00:00:00Z |       262 |      6 |       179 |     77 |             0 |          0 |             4 |         -4 |          2 | Myanmar      | myanmar      | MM               |\n| 2020-06-16T00:00:00Z |        34 |      0 |        18 |     16 |             2 |          0 |             1 |          1 |          3 | Namibia      | namibia      | NA               |\n| 2020-06-16T00:00:00Z |      2658 |     88 |       649 |   1921 |            16 |          0 |            27 |        -11 |          4 | Somalia      | somalia      | SO               |\n| 2020-06-16T00:00:00Z |      7370 |    102 |      6861 |    407 |            23 |          0 |             5 |         18 |          5 | Australia    | australia    | AU               |\n| 2020-06-16T00:00:00Z |        23 |      0 |        22 |      1 |             0 |          0 |             0 |          0 |          6 | Grenada      | grenada      | GD               |\n+----------------------+-----------+--------+-----------+--------+---------------+------------+---------------+------------+------------+--------------+--------------+------------------+\nNIL\n```\n\nIn order to fetch the top countries by given column you can use the\n`COVID19:FETCH-TOP-COUNTRIES-BY` function. The following example will\ndisplay the top 5 countries by `confirmed` cases.\n\n``` common-lisp\nCL-USER\u003e (mapcar (lambda (item)\n                   (getf item :|country_name|))\n                 (covid19:fetch-top-countries-by *db-conn* :column :confirmed :limit 5))\n(\"United States of America\" \"Brazil\" \"Russian Federation\" \"India\"\n \"United Kingdom\")\n```\n\nThe `COVID19:FETCH-TIME-SERIES-GLOBAL` function returns the aggregated\ntime series on a global scale. The following example will display the\nstats for the past 10 days.\n\n``` common-lisp\nCL-USER\u003e (covid19:display-table\n          (covid19:fetch-time-series-global *db-conn* :limit 10))\n+----------------------+-----------+--------+-----------+---------+---------------+---------------+------------+------------+\n| timestamp            | confirmed | deaths | recovered | active  | new_confirmed | new_recovered | new_deaths | new_active |\n+----------------------+-----------+--------+-----------+---------+---------------+---------------+------------+------------+\n| 2020-06-16T00:00:00Z |   8274306 | 451939 |   3954518 | 3867849 |        139803 |         97831 |       6829 |      35143 |\n| 2020-06-15T00:00:00Z |   8134503 | 445110 |   3856687 | 3832706 |        133896 |         87626 |       3843 |      42427 |\n| 2020-06-14T00:00:00Z |   8000607 | 441267 |   3769061 | 3790279 |        134333 |         71408 |       3365 |      59560 |\n| 2020-06-13T00:00:00Z |   7866274 | 437902 |   3697653 | 3730719 |        134598 |         85027 |       4400 |      45171 |\n| 2020-06-12T00:00:00Z |   7731676 | 433502 |   3612626 | 3685548 |        118757 |         72581 |       3990 |      42186 |\n| 2020-06-11T00:00:00Z |   7612919 | 429512 |   3540045 | 3643362 |        154681 |         85889 |       5290 |      63502 |\n| 2020-06-10T00:00:00Z |   7458238 | 424222 |   3454156 | 3579860 |        118483 |         79139 |       4833 |      34511 |\n| 2020-06-09T00:00:00Z |   7339755 | 419389 |   3375017 | 3545349 |        124338 |         82260 |       4974 |      37104 |\n| 2020-06-08T00:00:00Z |   7215417 | 414415 |   3292757 | 3508245 |        109895 |        152488 |       3825 |     -46418 |\n| 2020-06-07T00:00:00Z |   7105522 | 410590 |   3140269 | 3554663 |        118555 |         55087 |       3039 |      60429 |\n+----------------------+-----------+--------+-----------+---------+---------------+---------------+------------+------------+\nNIL\n```\n\nThe `COVID19:FETCH-TIME-SERIES-FOR-CONTINENT` function returns\naggregated time series data for a given continent, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19:display-table\n          (covid19:fetch-time-series-for-continent *db-conn* \"Europe\"))\n+----------------------+-----------+--------+-----------+---------+---------------+---------------+------------+------------+--------------+--------------------+----------------+\n| timestamp            | confirmed | deaths | recovered | active  | new_confirmed | new_recovered | new_deaths | new_active | continent_id | continent_iso_code | continent_name |\n+----------------------+-----------+--------+-----------+---------+---------------+---------------+------------+------------+--------------+--------------------+----------------+\n| 2020-11-18T00:00:00Z |  12791850 | 304380 |   3746938 | 8740532 |        241753 |        120493 |       4784 |     116476 |            6 | EU                 | Europe         |\n| 2020-11-17T00:00:00Z |  12550097 | 299596 |   3626445 | 8624056 |        252012 |        135775 |       5390 |     110847 |            6 | EU                 | Europe         |\n| 2020-11-16T00:00:00Z |  12298085 | 294206 |   3490670 | 8513209 |        212435 |        112199 |       3745 |      96491 |            6 | EU                 | Europe         |\n| 2020-11-15T00:00:00Z |  12085650 | 290461 |   3378471 | 8416718 |        177770 |         62418 |       2530 |     112822 |            6 | EU                 | Europe         |\n| 2020-11-14T00:00:00Z |  11907880 | 287931 |   3316053 | 8303896 |        219967 |         84642 |       3366 |     131959 |            6 | EU                 | Europe         |\n| 2020-11-13T00:00:00Z |  11687913 | 284565 |   3231411 | 8171937 |        264308 |         91708 |       4371 |     168229 |            6 | EU                 | Europe         |\n| 2020-11-12T00:00:00Z |  11423605 | 280194 |   3139703 | 8003708 |        273909 |         72082 |       3985 |     197842 |            6 | EU                 | Europe         |\n| 2020-11-11T00:00:00Z |  11149696 | 276209 |   3067621 | 7805866 |        277106 |         90322 |       4620 |     182164 |            6 | EU                 | Europe         |\n| 2020-11-10T00:00:00Z |  10872590 | 271589 |   2977299 | 7623702 |        228930 |        135396 |       4894 |      88640 |            6 | EU                 | Europe         |\n| 2020-11-09T00:00:00Z |  10643660 | 266695 |   2841903 | 7535062 |        221762 |         66847 |       3174 |     151741 |            6 | EU                 | Europe         |\n+----------------------+-----------+--------+-----------+---------+---------------+---------------+------------+------------+--------------+--------------------+----------------+\nNIL\n```\n\n### Executing database queries\n\nIf you need to execute a custom query or statement against the\ndatabase you can use the `COVID19:DB-EXECUTE` function.\n\nThe following example will fetch a country by given ISO code,\nusing a parameterized query.\n\n``` common-lisp\nCL-USER\u003e (covid19:db-execute *db-conn* \"SELECT * FROM country WHERE iso_code = ?\" \"BG\")\n((:|id| 44 :|iso_code| \"BG\" :|name| \"Bulgaria\" :|slug| \"bulgaria\"))\n```\n\nYou can pass the result of `COVID19:DB-EXECUTE` to `COVID19:DISPLAY-TABLE` to\ndisplay the results in a nice table format.\n\n### Exporting data to CSV\n\nIf you need to export the data in CSV format you can do that by using\nthe `COVID19:WRITE-CSV` function. This example will export all\ntime series data for a given country.\n\n``` common-lisp\nCL-USER\u003e (with-open-file (out \"/tmp/covid19-bg.csv\" :direction :output)\n           (covid19:write-csv (covid19:fetch-time-series-for-country *db-conn* \"BG\") :stream out))\n```\n\n### Plotting graphs\n\nThe following examples assume that you have\n[gnuplot](http://gnuplot.sourceforge.net) installed already.\n\nIn order to plot a graph using the time series data for a given\ncountry you can use the `COVID19:PLOT-TIME-SERIES-FOR-COUNTRY`\nfunction. The `:limit` keyword parameter controls how many rows of\ndata will be fetched from the database.\n\nThis example shows how to plot the data for past 90 days for a given\ncountry.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-time-series-for-country *db-conn*\n                                               \"Bulgaria\"\n                                               :limit 90)\nNIL\n```\n\nThis is how the plot looks like at the time of writing this document.\n\n![COVID-19 Cases in BG with filledcurves](./images/covid19-bg-filledcurves.png)\n\nIf you want to use lines, instead of filled curves, which is what\nabove plot generated you can specify an alternative template to be\nused when plotting the graph, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-time-series-for-country *db-conn*\n                                               \"Bulgaria\"\n                                               :limit 90\n                                               :template covid19:*gnuplot-time-series-with-lines-template*)\nNIL\n```\n\nThe generated graph looks like this.\n\n![COVID-19 Cases in BG with lines](./images/covid19-bg-lines.png)\n\nAnother plot function that can be used is `COVID19:PLOT-TIME-SERIES-GLOBAL`.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-time-series-global *db-conn* :limit 90)\nNIL\n```\n\nThe generated graph on a global scale looks like this.\n\n![COVID-19 Cases Global with filledcurves](./images/covid19-global-filledcurves.png)\n\nThe `COVID19:PLOT-TOP-COUNTRIES-BY` function can be used to plot countries\nby sorting them first on a given column. Here's an example to plot a histogram\nper each country based on the latest data from the `confirmed` column.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-top-countries-by *db-conn* :column :confirmed :limit 100)\nNIL\n```\n\nAn example generated graph looks like this.\n\n![COVID-19 Top Countries By column](./images/covid19-top-by-confirmed.png)\n\nAnother set of useful templates which show the new cases per country\nor on global scale are\n`COVID19:*GNUPLOT-TIME-SERIES-WITH-FILLED-CURVES-NEW-CASES*` and\n`COVID19:*GNUPLOT-TIME-SERIES-WITH-LINES-NEW-CASES*`.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-time-series-for-country *db-conn*\n                                               \"Italy\"\n                                               :limit 100\n                                               :template covid19:*gnuplot-time-series-with-filled-curves-new-cases-template*)\nNIL\n```\n\nThe generated graph looks like this, which plots the new cases on\ndaily basis.\n\n![COVID-19 Cases in IT with lines](./images/covid19-it-new-cases.png)\n\nThe `COVID19:PLOT-TIME-SERIES-FOR-CONTINENT` function is used for\nplotting time-series data for given continent. This example\nplots the time series data for `Europe`.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-time-series-for-continent *db-conn* \"Europe\" :limit 300)\n```\n\nThe generated graph looks like this.\n\n![COVID-19 Cases in Europe with lines](./images/covid19-europe.png)\n\nThe `COVID19:PLOT-TIME-SERIES-GLOBAL-ANIMATION` function creates an\nanimation of the cases using the global time series data.  When\ncreating an animation you need to specify the destination, where the\nanimation will be stored at. The `:limit` keyword parameter in the\nexample below specifies the number of time series records in ascending\norder.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-time-series-global-animation *db-conn*\n                                                    #P\"/tmp/covid19-global.gif\"\n                                                    :limit 200)\nNIL\n```\n\nThe generated animation looks like this.\n\n![COVID-19 Global Cases Animation](./images/covid19-global.gif)\n\nAnother function, which creates animations from time-series data is the\n`COVID19:PLOT-TIME-SERIES-FOR-COUNTRY-ANIMATION`.\n\n``` common-lisp\nCL-USER\u003e (covid19:plot-time-series-for-country-animation *db-conn*\n                                                         \"Italy\"\n                                                         #P\"/tmp/covid19-it.gif\"\n                                                         :limit 200)\nNIL\n```\n\nThe generated animation for a given country looks like this.\n\n![COVID-19 IT Cases Animation](./images/covid19-it.gif)\n\nThe `:delay`, `:height`, `:width` and `:line-width` keyword parameters\ncan be used to further customize the resulting animation.\n\nYou could also render any of the existing `gnuplot(1)` templates\ndefined in the `COVID19.GNUPLOT-TEMPLATE` package and customize them\nfurther, if needed.\n\nIn order to do that you need to pass at least two arguments to the\ntemplate while rendering it - one for the title of the graph, and\nanother one which points to the path containing data points.\n\nThe following example shows how to export the data points for a given country to a\nfile, and then renders a template using that file.\n\n``` common-lisp\nCL-USER\u003e (let ((csv-file #P\"/tmp/covid19-bg.csv\")\n               (data-points (covid19:fetch-time-series-for-country *db-conn* \"Bulgaria\" :limit 90)))\n           (with-open-file (out csv-file :direction :output)\n             (covid19:write-csv data-points :stream out))\n           (covid19:render-gnuplot-template covid19:*gnuplot-time-series-with-filled-curves-template*\n                                            :title \"Bulgaria\"\n                                            :datafile (namestring csv-file)))\n\"#\n# gnuplot(1) template for plotting time series with filledcurves\n#\n\nset title 'Covid19 Cases - Bulgaria'\nset grid\nset xdata time\nset timefmt '%Y-%m-%dT%H:%M:%S+00:00Z'\nset format x '%Y-%m-%d'\nset xtics rotate by 45 right\nset xlabel 'Time'\nset ylabel 'Cases'\nset key outside right center\nset datafile separator ','\nset autoscale fix\nset style fill transparent solid 0.3\nplot '/tmp/covid19-bg.csv' using 1:2:(0) title 'Confirmed' with filledcurves, \\\\\n     '' using 1:3:(0) title 'Deaths' with filledcurves, \\\\\n     '' using 1:4:(0) title 'Recovered' with filledcurves, \\\\\n     '' using 1:5:(0) title 'Active' with filledcurves\n\"\n```\n\n### Debug logging\n\nThe `cl-covid19` system uses `log4cl` for logging purposes.\n\nIf you need to adjust the logging level (e.g. set it to `debug` level), simply\nevaluate the following expression.\n\n``` common-lisp\nCL-USER\u003e (log:config :debug)\n```\n\n## Importing data into PostgreSQL\n\nYou can import the data from the SQLite database into PostgreSQL using\nthe [restore-into-pgsql.sh](./compat/restore-into-pgsql.sh) script.\n\n``` shell\nenv SQLITE_DB=/path/to/covid19.db PGSQL_DB=covid19 ./compat/restore-into-pgsql.sh\n```\n\n## Grafana\n\n[Grafana](https://grafana.com) can be used for plotting the metrics\nfrom the `cl-covid19` database.\n\nAs of now you can find the [world population\ndashboard](./grafana/world-population-dashboard.json) and [COVID-19\ndashboard](./grafana/covid19-dashboard.json) in the\n[grafana](./grafana) directory of this repository.\n\nThe Grafana dashboards use the [PostgreSQL\ndatasource](https://grafana.com/docs/grafana/latest/datasources/postgres/),\nso first make sure that you import the data from the SQLite database\ninto a PostgreSQL database. You can do that easily by using the\n[restore-into-pgsql.sh](./compat/restore-into-pgsql.sh) script.\n\nNext, import the dashboards into your Grafana instance.\n\nHere are a few screenshots of the World Population and COVID-19\ndashboards in Grafana.\n\n![Grafana Population Per Country](./images/population-per-country.png)\n![Grafana COVID-19 Dashboard-1](./images/covid19-grafana-1.png)\n![Grafana COVID-19 Dashboard-2](./images/covid19-grafana-2.png)\n\n## API Client Usage\n\nThis section provides some examples on how to use the API client for\ninterfacing with the [COVID-19 API](https://covid19api.com).\n\nThe `COVID19.API` package exports functionality for creating an API\nclient and fetching data from the remote API endpoint, most of these\nsymbols are re-exported by the `COVID19` package.\n\nFirst, create an API client.\n\n``` common-lisp\nCL-USER\u003e (defparameter *api-client*\n           (covid19:make-api-client))\n*API-CLIENT*\n```\n\nIf you experience timeout issues, you can also change the timeout\nsettings of the HTTP client, e.g.\n\n``` common-lisp\n(setf dexador:*default-connect-timeout* 300)\n(setf dexador:*default-read-timeout* 300)\n```\n\nYou can get the list of countries by using the `COVID19:GET-COUNTRIES-DATA` function, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19.api:get-countries-data *api-client*)\n```\n\nA summarized statistics for COVID-19 can be retrieved by using the `COVID19:GET-SUMMARY-DATA`\nfunction, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19.api:get-summary-data *api-client*)\n```\n\nThe COVID-19 API provides an endpoint for exporting all data as a ZIP\narchive.  You can get a ZIP archive of all time series data by using\nthe `COVID19:GET-TIME-SERIES-ARCHIVE` function, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19:get-time-series-archive *api-client* #P\"/tmp/all-data.zip\")\n```\n\nYou can also display the list of available API endpoints by using the\n`COVID19:DISPLAY-API-ROUTES` function, e.g.\n\n``` common-lisp\nCL-USER\u003e (covid19:display-api-routes *api-client*)\n```\n\nAn example output looks like this.\n\n``` text\n.-------------------------------------------------------------------------------------------------------------------------------------------------------------------------.\n|                                                                           API Routes @ v0.0.8                                                                           |\n+--------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+\n| PATH                                             | NAME                                                                                                                 |\n+--------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+\n| /webhook                                         | Add a webhook to be notified when new data becomes available                                                         |\n| /summary                                         | Summary of new and total cases per country                                                                           |\n| /live/country/:country/status/:status            | Get a time series Of Cases Per Country Per Province By Case Type                                                     |\n| /live/country/:country/status/:status/date/:date | Get a Time Series Of Cases Per Country Per Province By Case Type After A Date                                        |\n| /live/country/:country                           | Get Live List Of Cases Per Country Per Province By Case Type                                                         |\n| /export                                          | Get All Data as a zip file                                                                                           |\n| /total/country/:country                          | Get List Of Cases Per Country By Case Type                                                                           |\n| /total/country/:country/status/:status           | Get List Of Cases Per Country By Case Type                                                                           |\n| /country/:country/status/:status                 | Get List Of Cases Per Country Per Province By Case Type                                                              |\n| /country/:country/status/:status/live            | Daily list of cases per Country per Province by Case Type, updated with latest live count                            |\n| /total/dayone/country/:country/status/:status    | Get List Of Cases Per Country By Case Type From The First Recorded Case                                              |\n| /dayone/country/:country/status/:status          | Get List Of Cases Per Country Per Province By Case Type From The First Recorded Case                                 |\n| /dayone/country/:country/status/:status/live     | Get List Of Cases Per Country Per Province By Case Type From The First Recorded Case, updated with latest live count |\n| /country/:country                                | Get List Of Cases Per Country Per Province By Case Type                                                              |\n| /total/dayone/country/:country                   | Get List Of Cases Per Country By Case Type From The First Recorded Case                                              |\n| /dayone/country/:country                         | Get List Of Cases Per Country Per Province By Case Type From The First Recorded Case                                 |\n| /countries                                       | Get List Of Countries                                                                                                |\n| /all                                             | Get All Data                                                                                                         |\n+--------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+\n```\n\n## Various ~/.sqliterc config settings\n\nWhen using the command-line interface of SQLite, you might find these\nconfig settings useful, which you can just drop in your `~/.sqliterc`\nfile.\n\n``` text\n.headers on\n.mode column\n.timer on\n```\n\n## Contributing\n\n`cl-covid19` is hosted on\n[Github](https://github.com/dnaeon/cl-covid19). Please contribute by\nreporting issues, suggesting features or by sending patches using pull\nrequests.\n\n## Authors\n\n* [Marin Atanasov Nikolov](mailto:dnaeon@gmail.com)\n\n## License\n\nThis project is Open Source and licensed under the [BSD\nLicense](http://opensource.org/licenses/BSD-2-Clause).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnaeon%2Fcl-covid19","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdnaeon%2Fcl-covid19","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnaeon%2Fcl-covid19/lists"}