Context

Notes about analyses of COVID-19 data. Inspired by an article on Towards Data Science. This document is an R markdown notebook available from my personal viral2020 GitHub repository.

Worldwide cases and mortalities

Using information made available from the European Centre for Disease Prevention and Control and updated on a daily basis. There are likely other sources that are updated more regularly (e.g. the many sources used by worldometers), but this is a decent starting point.

Worldwide, there were 6,005,018 confirmed cases and 348,480 deaths as this document was generated using the data obtained from the ECDC (HTML document generated 2020-06-02 08:18:47 AST). A total of 208 countries had COVID-19 reported cases, 169 countries had more than 100 reported cases, and 71 countries had more than 100 reported deaths.

Number of new deaths vs. cumulative deaths

Plot the number of new deaths or cases as a function of the cumulative number of deaths or cases and use a log scale on both axes. We do this for the number of deaths in the 10 countries with the most fatalities to date.

Loading required package: ggrepel

Let’s now do the same for another subset of countries.

Progression since 100 confirmed cases

Present the number of cumulative cases starting on the date when 100 or more cases were recorded in each country, and use a logarithmic scale for the y axis.

And do the same for the number of cumulative cases per one million people.

Country-level summaries

How are different countries doing? I am testing a function that takes a country as an argument and fits both an exponential growth and a logistic growth model to the number of cumulative cases.

LS0tDQp0aXRsZTogIk5vdGVib29rIG9mIENPVklELTE5IGFuYWx5c2VzIg0KYXV0aG9yOiAiRGFuaWVsIFJpY2FyZCAoZGFuaWVsLnJpY2FyZEBnbWFpbC5jb20pIg0KZGF0ZTogJ2ByIHBhc3RlMCgiTGFzdCBtb2RpZmllZCB0aW1lc3RhcDogIiwgZm9ybWF0KFN5cy50aW1lKCksICIlWS0lbS0lZCAlSDolTTolUyAlWiIpKWAnDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIENvbnRleHQNCk5vdGVzIGFib3V0IGFuYWx5c2VzIG9mIENPVklELTE5IGRhdGEuIEluc3BpcmVkIGJ5IFthbiBhcnRpY2xlIG9uIFRvd2FyZHMgRGF0YSBTY2llbmNlXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdmlzdWFsaXplLXRoZS1wYW5kZW1pYy13aXRoLXItY292aWQtMTktYzM0NDNkZTNiNGU0KS4gVGhpcyBkb2N1bWVudCBpcyBhbiBSIG1hcmtkb3duIG5vdGVib29rIGF2YWlsYWJsZSBmcm9tIG15IHBlcnNvbmFsIFt2aXJhbDIwMjAgR2l0SHViIHJlcG9zaXRvcnldKGh0dHBzOi8vZ2l0aHViLmNvbS9yaWNhcmRkL3ZpcmFsMjAyMC8pLg0KDQojIFdvcmxkd2lkZSBjYXNlcyBhbmQgbW9ydGFsaXRpZXMNClVzaW5nIGluZm9ybWF0aW9uIG1hZGUgYXZhaWxhYmxlIGZyb20gdGhlIFtFdXJvcGVhbiBDZW50cmUgZm9yIERpc2Vhc2UgUHJldmVudGlvbiBhbmQgQ29udHJvbF0oaHR0cHM6Ly93d3cuZWNkYy5ldXJvcGEuZXUvZW4vcHVibGljYXRpb25zLWRhdGEvZG93bmxvYWQtdG9kYXlzLWRhdGEtZ2VvZ3JhcGhpYy1kaXN0cmlidXRpb24tY292aWQtMTktY2FzZXMtd29ybGR3aWRlKSBhbmQgdXBkYXRlZCBvbiBhIGRhaWx5IGJhc2lzLiBUaGVyZSBhcmUgbGlrZWx5IG90aGVyIHNvdXJjZXMgdGhhdCBhcmUgdXBkYXRlZCBtb3JlIHJlZ3VsYXJseSAoZS5nLiB0aGUgbWFueSBzb3VyY2VzIHVzZWQgYnkgW3dvcmxkb21ldGVyc10oaHR0cHM6Ly93d3cud29ybGRvbWV0ZXJzLmluZm8vY29yb25hdmlydXMvKSksIGJ1dCB0aGlzIGlzIGEgZGVjZW50IHN0YXJ0aW5nIHBvaW50Lg0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCiMjIHRoaXMgaXMgY29waWVkIGFuZCBwYXN0ZWQgZnJvbSB0aGUgRUNEQyB3ZWJzaXRlDQoNCiN0aGVzZSBsaWJyYXJpZXMgbmVlZCB0byBiZSBsb2FkZWQNCmxpYnJhcnkodXRpbHMpDQpsaWJyYXJ5KGh0dHIpDQoNCiNkb3dubG9hZCB0aGUgZGF0YXNldCBmcm9tIHRoZSBFQ0RDIHdlYnNpdGUgdG8gYSBsb2NhbCB0ZW1wb3JhcnkgZmlsZQ0KR0VUKCJodHRwczovL29wZW5kYXRhLmVjZGMuZXVyb3BhLmV1L2NvdmlkMTkvY2FzZWRpc3RyaWJ1dGlvbi9jc3YiLCBhdXRoZW50aWNhdGUoIjoiLCAiOiIsIHR5cGU9Im50bG0iKSwgd3JpdGVfZGlzayh0ZiA8LSB0ZW1wZmlsZShmaWxlZXh0ID0gIi5jc3YiKSkpDQoNCiNyZWFkIHRoZSBEYXRhc2V0IHNoZWV0IGludG8g4oCcUuKAnS4gVGhlIGRhdGFzZXQgd2lsbCBiZSBjYWxsZWQgImRhdGEiLg0KZGF0YSA8LSByZWFkLmNzdih0Ziwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KbmFtZXMoZGF0YSlbMV0gPC0gImRhdGVSZXAiDQojIyBEUg0KZGF0YSRkYXRlUmVwIDwtIGFzLkRhdGUoZGF0YSRkYXRlUmVwLCBmb3JtYXQ9IiVkLyVtLyVZIikgIyMgRFIsIGluY29taW5nIGRhdGEgaXMgZm9ybWF0dGVkIGRheS9tb250aC95ZWFyIGFuZCB3YXMgbm90IHJlY29nbmlzZWQgY29ycmVjdGx5IGFzIGEgZGF0ZQ0KIyMgY29tcHV0ZSB0aGUgY3VtdWxhdGl2ZSBudW1iZXIgb2YgY2FzZXMgYnkgY291bnRyeQ0KIyMgY29tcHV0ZSB0aGUgY3VtdWxhdGl2ZSBudW1iZXIgb2YgZmF0YWxpdGllcyBieSBjb3VudHJ5DQpsaWJyYXJ5KGRwbHlyKQ0KZGYgPC0gZGF0YVtvcmRlcihkYXRhJGNvdW50cmllc0FuZFRlcnJpdG9yaWVzLCBkYXRhJGRhdGVSZXApLF0gJT4lIGdyb3VwX2J5KGNvdW50cmllc0FuZFRlcnJpdG9yaWVzKSAlPiUgbXV0YXRlKGN1bXN1bS5jYXNlcyA9IGN1bXN1bShjYXNlcykpICU+JSBtdXRhdGUoY3Vtc3VtLmRlYXRocyA9IGN1bXN1bShkZWF0aHMpKQ0KZGYkZGVhdGgucmF0ZS5wZXJjZW50IDwtIDEwMCooZGYkY3Vtc3VtLmRlYXRocyAvIGRmJGN1bXN1bS5jYXNlcykNCmRmJGNhc2VzLnBlci5lMDYgPC0gKGRmJGN1bXN1bS5jYXNlcyAvIGRmJHBvcERhdGEyMDE4KSoxRTA2DQpkZiRkZWF0aHMucGVyLmUwNiA8LSAoZGYkY3Vtc3VtLmRlYXRocyAvIGRmJHBvcERhdGEyMDE4KSoxRTA2DQojIyBtYWtlIHN1cmUgdGhhdCBhbGwgY291bnRyaWVzIGhhdmUgYSAzLWxldHRlciBjb2RlIHNvIHRoYXQgdGhleSBjYW4gYmUgbWVyZ2VkIHdpdGggdGhlIG90aGVyIGRhdGEgZnJhbWUgbGlua2luZyBlYWNoIGNvdW50cnkgdG8gYSBjb250aW5lbnQNCiN0YWJsZShkZiRjb3VudHJ5dGVycml0b3J5Q29kZSwgZXhjbHVkZT1GQUxTRSkNCiN0LmRmIDwtIGRmW2RmJGNvdW50cnl0ZXJyaXRvcnlDb2RlPT0iIixdDQojdGFibGUodC5kZiRjb3VudHJpZXNBbmRUZXJyaXRvcmllcykNCg0KZGZbZGYkY291bnRyaWVzQW5kVGVycml0b3JpZXM9PSJCb25haXJlLCBTYWludCBFdXN0YXRpdXMgYW5kIFNhYmEiLCJjb3VudHJ5dGVycml0b3J5Q29kZSJdIDwtICJCRVMiDQpkZltkZiRjb3VudHJpZXNBbmRUZXJyaXRvcmllcz09IkZhbGtsYW5kX0lzbGFuZHNfKE1hbHZpbmFzKSIsImNvdW50cnl0ZXJyaXRvcnlDb2RlIl0gPC0gIkZMSyINCg0KDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQojIyBodHRwczovL2RhdGFodWIuaW8vSm9oblNub3dMYWJzL2NvdW50cnktYW5kLWNvbnRpbmVudC1jb2Rlcy1saXN0DQpjb250aW5lbnQuZGYgPC0gcmVhZC5jc3YoImNvdW50cnktYW5kLWNvbnRpbmVudC1jb2Rlcy1saXN0LWNzdl9jc3YudHh0IikNCiNoZWFkKGNvbnRpbmVudC5kZikNCiNkZlt3aGljaChkZiRjb3VudHJ5dGVycml0b3J5Q29kZT09IiIpLF0NCiN0YWJsZShjb250aW5lbnQuZGYkQ291bnRyeV9OYW1lKQ0KI2NvbnRpbmVudC5kZlt3aGljaChjb250aW5lbnQuZGYkQ291bnRyeV9OYW1lPT0iQW5ndWlsbGEiKSxdDQpkZi5jb250aW5lbnQgPC0gbWVyZ2UoZGYsIGNvbnRpbmVudC5kZiwgYnkueD0iY291bnRyeXRlcnJpdG9yeUNvZGUiLCBieS55PSJUaHJlZV9MZXR0ZXJfQ291bnRyeV9Db2RlIikNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMjIGEgdGFibGUgc2hvd2luZyB0b2RheSdzIG51bWJlciBvZiBjYXNlcyBpbiBkZWNyZWFzaW5nIG9yZGVyDQpmb3Iua2FibGUgPC0gdW5ncm91cChkZikgJT4lIGZpbHRlcihkYXRlUmVwID09IGZvcm1hdChTeXMudGltZSgpLCIlWS0lbS0lZCIpKSAlPiUNCiBhcnJhbmdlKGRlc2MoY3Vtc3VtLmNhc2VzKSkNCmBgYA0KDQpXb3JsZHdpZGUsIHRoZXJlIHdlcmUgYHIgZm9ybWF0KHN1bShmb3Iua2FibGUkY3Vtc3VtLmNhc2VzKSxiaWcubWFyaz0iLCIpYCBjb25maXJtZWQgY2FzZXMgYW5kIGByIGZvcm1hdChzdW0oZm9yLmthYmxlJGN1bXN1bS5kZWF0aHMpLGJpZy5tYXJrPSIsIilgIGRlYXRocyBhcyB0aGlzIGRvY3VtZW50IHdhcyBnZW5lcmF0ZWQgdXNpbmcgdGhlIGRhdGEgb2J0YWluZWQgZnJvbSB0aGUgRUNEQyAoSFRNTCBkb2N1bWVudCBnZW5lcmF0ZWQgYHIgZm9ybWF0KFN5cy50aW1lKCksICIlWS0lbS0lZCAlSDolTTolUyAlWiIpYCkuIEEgdG90YWwgb2YgYHIgbnJvdyhmb3Iua2FibGUpYCBjb3VudHJpZXMgaGFkIENPVklELTE5IHJlcG9ydGVkIGNhc2VzLCBgciBucm93KGZvci5rYWJsZVtmb3Iua2FibGUkY3Vtc3VtLmNhc2VzPjEwMCxdKWAgY291bnRyaWVzIGhhZCBtb3JlIHRoYW4gMTAwIHJlcG9ydGVkIGNhc2VzLCAgYW5kIGByIG5yb3coZm9yLmthYmxlW2Zvci5rYWJsZSRjdW1zdW0uZGVhdGhzPjEwMCxdKWAgY291bnRyaWVzIGhhZCBtb3JlIHRoYW4gMTAwIHJlcG9ydGVkIGRlYXRocy4NCg0KIyMgTnVtYmVyIG9mIG5ldyBkZWF0aHMgdnMuIGN1bXVsYXRpdmUgZGVhdGhzDQoNClBsb3QgdGhlIG51bWJlciBvZiBuZXcgZGVhdGhzIG9yIGNhc2VzIGFzIGEgZnVuY3Rpb24gb2YgdGhlIGN1bXVsYXRpdmUgbnVtYmVyIG9mIGRlYXRocyBvciBjYXNlcyBhbmQgdXNlIGEgbG9nIHNjYWxlIG9uIGJvdGggYXhlcy4gV2UgZG8gdGhpcyBmb3IgdGhlIG51bWJlciBvZiBkZWF0aHMgaW4gdGhlIDEwIGNvdW50cmllcyB3aXRoIHRoZSBtb3N0IGZhdGFsaXRpZXMgdG8gZGF0ZS4NCg0KYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTgsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KI29idGFpbiB0b3AgMjAgYW5kIDEwIGNvdW50cnkgZm9yIGZhdGFsaXRpZXMNCnRvcDIwLmRlYXRocyA8LSB1bmdyb3VwKGRmKSAlPiUgZmlsdGVyKGRhdGVSZXAgPT0gZm9ybWF0KFN5cy50aW1lKCksIiVZLSVtLSVkIikpICU+JQ0KIHRvcF9uKG49MjAsIHd0PWN1bXN1bS5kZWF0aHMpICU+JQ0KIGFycmFuZ2UoZGVzYyhjdW1zdW0uZGVhdGhzKSkNCg0KdG9wMTAuZGVhdGhzIDwtIHVuZ3JvdXAoZGYpICU+JSBmaWx0ZXIoZGF0ZVJlcCA9PSBmb3JtYXQoU3lzLnRpbWUoKSwiJVktJW0tJWQiKSkgJT4lDQogdG9wX24obj0xMCwgd3Q9Y3Vtc3VtLmRlYXRocykgJT4lDQogYXJyYW5nZShkZXNjKGN1bXN1bS5kZWF0aHMpKQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQpyZXF1aXJlKGdncmVwZWwpDQoNCmcgPC0gDQogIGdncGxvdChmaWx0ZXIoZGYsIGNvdW50cmllc0FuZFRlcnJpdG9yaWVzICVpbiUgdG9wMTAuZGVhdGhzJGNvdW50cmllc0FuZFRlcnJpdG9yaWVzLCBkZWF0aHM+MCwgY3Vtc3VtLmRlYXRocz49MTApLCBhZXMoY3Vtc3VtLmRlYXRocywgZGVhdGhzKSkgKw0KICBnZW9tX2xpbmUoYWVzKGdyb3VwPWNvdW50cmllc0FuZFRlcnJpdG9yaWVzLCBjb2xvcj1jb3VudHJpZXNBbmRUZXJyaXRvcmllcykpICsNCiAgc2NhbGVfeF9sb2cxMCgpICsNCiAgc2NhbGVfeV9sb2cxMCgpICsNCiAgeGxhYigiQ3VtdWxhdGl2ZSBudW1iZXIgb2YgZGVhdGhzIikgKw0KICB5bGFiKCJEYWlseSBudW1iZXIgb2YgZGVhdGhzIikgKw0KICBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsPWNvdW50cmllc0FuZFRlcnJpdG9yaWVzLCBjb2xvcj1jb3VudHJpZXNBbmRUZXJyaXRvcmllcyksDQogZnVuY3Rpb24oZCkgZFtkJGRhdGVSZXAgPT0gZm9ybWF0KFN5cy50aW1lKCksIiVZLSVtLSVkIiksXSkgKw0KdGhlbWVfbWluaW1hbChiYXNlX3NpemU9MTQpICsNCiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIA0KIysNCiMgIGdlb21fcG9pbnQoZGF0YT1maWx0ZXIoZGYsIGNvdW50cmllc0FuZFRlcnJpdG9yaWVzID09ICJJdGFseSIsIGRhdGVSZXA9Zm9ybWF0KFN5cy50aW1lKCksIiVZLSVtLSVkIikpKQ0KZw0KYGBgDQoNCkxldCdzIG5vdyBkbyB0aGUgc2FtZSBmb3IgYW5vdGhlciBzdWJzZXQgb2YgY291bnRyaWVzLg0KDQpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OCwgZWNobz1GQUxTRX0NCmxpYnJhcnkoZHBseXIpDQpteS5jb3VudHJpZXMgPC0gYygiVVMiLCJBVCIsIlNFIiwiQ1oiLCJJVCIsIkVTIiwiREUiLCJGUiIsIkNBIiwiQVUiLCJLUiIsIk5aIiwiREsiLCJCUiIsIkVDIiwiQ0wiKQ0KDQpnIDwtIA0KICBnZ3Bsb3QoZmlsdGVyKGRmLCBnZW9JZCAlaW4lIG15LmNvdW50cmllcywgZGVhdGhzPjAsIGN1bXN1bS5kZWF0aHM+PTEwKSwgYWVzKGN1bXN1bS5kZWF0aHMsIGRlYXRocykpICsNCiAgZ2VvbV9saW5lKGFlcyhncm91cD1jb3VudHJpZXNBbmRUZXJyaXRvcmllcywgY29sb3I9Y291bnRyaWVzQW5kVGVycml0b3JpZXMpKSArDQogIHNjYWxlX3hfbG9nMTAoKSArDQogIHNjYWxlX3lfbG9nMTAoKSArDQogIHhsYWIoIkN1bXVsYXRpdmUgbnVtYmVyIG9mIGRlYXRocyIpICsNCiAgeWxhYigiRGFpbHkgbnVtYmVyIG9mIGRlYXRocyIpICsNCiAgZ2VvbV90ZXh0X3JlcGVsKGFlcyhsYWJlbD1jb3VudHJpZXNBbmRUZXJyaXRvcmllcywgY29sb3I9Y291bnRyaWVzQW5kVGVycml0b3JpZXMpLA0KIGZ1bmN0aW9uKGQpIGRbZCRkYXRlUmVwID09IGZvcm1hdChTeXMudGltZSgpLCIlWS0lbS0lZCIpLF0pICsNCnRoZW1lX21pbmltYWwoYmFzZV9zaXplPTE0KSArDQogdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSANCmcNCmBgYA0KDQoNCiMjIFByb2dyZXNzaW9uIHNpbmNlIDEwMCBjb25maXJtZWQgY2FzZXMgDQpQcmVzZW50IHRoZSBudW1iZXIgb2YgY3VtdWxhdGl2ZSBjYXNlcyBzdGFydGluZyBvbiB0aGUgZGF0ZSB3aGVuIDEwMCBvciBtb3JlIGNhc2VzIHdlcmUgcmVjb3JkZWQgaW4gZWFjaCBjb3VudHJ5LCBhbmQgdXNlIGEgbG9nYXJpdGhtaWMgc2NhbGUgZm9yIHRoZSB5IGF4aXMuIA0KDQpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OCwgZWNobz1GQUxTRX0NCmZpcnN0LmRheS4xMDAuY2FzZXMgPC0gYWdncmVnYXRlKGRhdGVSZXB+Y291bnRyaWVzQW5kVGVycml0b3JpZXMsIGRhdGE9ZGZbd2hpY2goZGYkY3Vtc3VtLmNhc2VzPj0xMDApLF0sbWluKQ0KZmlyc3QuZGF5LjEwLmRlYXRocyA8LSBhZ2dyZWdhdGUoZGF0ZVJlcH5jb3VudHJpZXNBbmRUZXJyaXRvcmllcywgZGF0YT1kZlt3aGljaChkZiRjdW1zdW0uZGVhdGhzPj0xMCksXSxtaW4pDQpkZjIgPC0gbWVyZ2UobWVyZ2UoZGYsIGZpcnN0LmRheS4xMDAuY2FzZXMsIGJ5PSJjb3VudHJpZXNBbmRUZXJyaXRvcmllcyIpLCBmaXJzdC5kYXkuMTAuZGVhdGhzLCBieT0iY291bnRyaWVzQW5kVGVycml0b3JpZXMiKQ0KbmFtZXMoZGYyKVtjKDIsMTcsMTgpXSA8LSBjKCJkYXRlUmVwIiwiZGF0ZS5maXJzdC4xMDAuY2FzZXMiLCJkYXRlLmZpcnN0LjEwLmRlYXRocyIpDQpkZjIkZGF5cy5zaW5jZS4xMDAuY2FzZXMgPC0gZGYyJGRhdGVSZXAgLSBkZjIkZGF0ZS5maXJzdC4xMDAuY2FzZXMNCmRmMiRkYXlzLnNpbmNlLjEwLmRlYXRocyA8LSBkZjIkZGF0ZVJlcCAtIGRmMiRkYXRlLmZpcnN0LjEwLmRlYXRocw0KDQoNCm4gPC0gZGYyICU+JSBmaWx0ZXIoZGF0ZVJlcCA9PSBmb3JtYXQoU3lzLnRpbWUoKSwiJVktJW0tJWQiKSkgJT4lDQogdG9wX24oMjAsIGN1bXN1bS5jYXNlcykgJT4lDQogYXJyYW5nZShkZXNjKGN1bXN1bS5jYXNlcykpDQoNCmc8LQ0KZGYyICU+JQ0KICBmaWx0ZXIoY291bnRyaWVzQW5kVGVycml0b3JpZXMgJWluJSBuJGNvdW50cmllc0FuZFRlcnJpdG9yaWVzLCBhcy5udW1lcmljKGRmMiRkYXlzLnNpbmNlLjEwMC5jYXNlcyk+MCkgJT4lDQogIGdncGxvdChhZXMoYXMubnVtZXJpYyhkYXlzLnNpbmNlLjEwMC5jYXNlcyksIGN1bXN1bS5jYXNlcywgZ3JvdXA9Y291bnRyaWVzQW5kVGVycml0b3JpZXMsIGNvbG9yPWNvdW50cmllc0FuZFRlcnJpdG9yaWVzKSkgKw0KIGdlb21fbGluZSgpICsNCiB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZT0xNCkgKw0KICB5bGFiKCJDdW11bGF0aXZlIGNvbmZpcm1lZCBudW1iZXIgb2YgY2FzZXMiKSArDQogIGdndGl0bGUoIlRvcCAyMCBjb3VudHJpZXMgLSBjdW11bGF0aXZlIikgKw0KIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWw9Y291bnRyaWVzQW5kVGVycml0b3JpZXMpLA0KIGZ1bmN0aW9uKGQpIGRbZCRkYXRlUmVwID09IGZvcm1hdChTeXMudGltZSgpLCIlWS0lbS0lZCIpLF0pICsNCiB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZT0xNCkgKw0KIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KDQojZw0KIyBhbmQgaW4gbG9nIHNwYWNlDQpnICsgc2NhbGVfeV9sb2cxMCgpIA0KDQpgYGANCg0KQW5kIGRvIHRoZSBzYW1lIGZvciB0aGUgbnVtYmVyIG9mIGN1bXVsYXRpdmUgY2FzZXMgcGVyIG9uZSBtaWxsaW9uIHBlb3BsZS4NCg0KYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTgsIGVjaG89RkFMU0V9DQpnPC0NCmRmMiAlPiUNCiAgZmlsdGVyKGNvdW50cmllc0FuZFRlcnJpdG9yaWVzICVpbiUgbiRjb3VudHJpZXNBbmRUZXJyaXRvcmllcywgYXMubnVtZXJpYyhkZjIkZGF5cy5zaW5jZS4xMDAuY2FzZXMpPjApICU+JQ0KICBnZ3Bsb3QoYWVzKGFzLm51bWVyaWMoZGF5cy5zaW5jZS4xMDAuY2FzZXMpLCBjYXNlcy5wZXIuZTA2LCBncm91cD1jb3VudHJpZXNBbmRUZXJyaXRvcmllcywgY29sb3I9Y291bnRyaWVzQW5kVGVycml0b3JpZXMpKSArDQogZ2VvbV9saW5lKCkgKw0KIHRoZW1lX21pbmltYWwoYmFzZV9zaXplPTE0KSArDQogIHlsYWIoIkN1bXVsYXRpdmUgY2FzZXMgcGVyIG1pbGxpb24gcGVvcGxlIikgKw0KICBnZ3RpdGxlKCJUb3AgMjAgY291bnRyaWVzIC0gY3VtdWxhdGl2ZSIpICsNCiBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsPWNvdW50cmllc0FuZFRlcnJpdG9yaWVzKSwNCiBmdW5jdGlvbihkKSBkW2QkZGF0ZVJlcCA9PSBmb3JtYXQoU3lzLnRpbWUoKSwiJVktJW0tJWQiKSxdKSArDQogdGhlbWVfbWluaW1hbChiYXNlX3NpemU9MTQpICsNCiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCg0KI2cNCiMgYW5kIGluIGxvZyBzcGFjZQ0KZyArIHNjYWxlX3lfbG9nMTAoKSANCg0KYGBgDQoNCiMjIENvdW50cnktbGV2ZWwgc3VtbWFyaWVzDQpIb3cgYXJlIGRpZmZlcmVudCBjb3VudHJpZXMgZG9pbmc/IEkgYW0gdGVzdGluZyBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBjb3VudHJ5IGFzIGFuIGFyZ3VtZW50IGFuZCBmaXRzIGJvdGggYW4gZXhwb25lbnRpYWwgZ3Jvd3RoIGFuZCBhIGxvZ2lzdGljIGdyb3d0aCBtb2RlbCB0byB0aGUgbnVtYmVyIG9mIGN1bXVsYXRpdmUgY2FzZXMuDQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04LCBlY2hvPUZBTFNFfQ0KbXkubG9naXN0aWMuZmN0IDwtIGZ1bmN0aW9uKGE9MTAwLCBiPTAuMSwgYz0xRTAzLCB0aSl7DQogIG91dCA8LSBjIC8gKDEgKyAoKChjLWEpL2EpKmV4cCgtYip0aSkpKQ0KICByZXR1cm4ob3V0KQ0KfQ0KDQoNCmNvdW50cnkuZGVhdGhzLmZjdCA8LSBmdW5jdGlvbihnLmlkKXsNCiAgdGhpcy5kZiA8LSBmaWx0ZXIoZGYyLCBnZW9JZD09Zy5pZCwgY3Vtc3VtLmRlYXRocz49MTApDQoNCiAgIyMgMTUgZGVhdGhzIHBlciBvbmUgbWlsbGlvbiBhcyBhIHN0YXJ0aW5nIHZhbHVlIGZvciB0aGUgYXN5bXB0b3RlIGMNCiAgYy5pbml0IDwtIDE1ICogKHVuaXF1ZSh0aGlzLmRmJHBvcERhdGEyMDE4KS8xRTA2KQ0KICAjYS5pbml0IDwtIGMuaW5pdC8xMDANCiAgICANCiAgbXkubG0gPC0gbG0obG9nKGN1bXN1bS5kZWF0aHMpfmRheXMuc2luY2UuMTAuZGVhdGhzLCBkYXRhPXRoaXMuZGYpDQogIHByZWQubG0gPC0gZGF0YS5mcmFtZShkYXRlUmVwPXRoaXMuZGYkZGF0ZVJlcCwgY3Vtc3VtLmRlYXRocz1leHAoZml0dGVkKG15LmxtKSkpDQoNCiAgaW5pdGlhbC5udW0uZGVhdGhzIDwtIHRoaXMuZGZbYXMubnVtZXJpYyh0aGlzLmRmJGRheXMuc2luY2UuMTAuZGVhdGhzKT09MCwiY3Vtc3VtLmRlYXRocyJdDQogIA0KICBteS5sb2dpc3RpYyA8LSBubHMoY3Vtc3VtLmRlYXRocyB+IG15LmxvZ2lzdGljLmZjdChhPWluaXRpYWwubnVtLmRlYXRocywgYiwgYywgYXMubnVtZXJpYyhkYXlzLnNpbmNlLjEwLmRlYXRocykpLCBkYXRhPXRoaXMuZGYsIHN0YXJ0PWxpc3QoYj0wLjM0LGM9Yy5pbml0KSkNCiAgbG9naXN0aWMucHJlZCA8LSBkYXRhLmZyYW1lKGRhdGVSZXA9dGhpcy5kZiRkYXRlUmVwLCBkYXlzLnNpbmNlLjEwLmRlYXRocz1hcy5udW1lcmljKHRoaXMuZGYkZGF5cy5zaW5jZS4xMC5kZWF0aHMpLCBjdW1zdW0uZGVhdGhzPWZpdHRlZChteS5sb2dpc3RpYykpDQogICMjIGluZmxlY3Rpb24gcG9pbnQNCiAgdDUwIDwtIChsb2coKGNvZWYobXkubG9naXN0aWMpWzJdLWluaXRpYWwubnVtLmRlYXRocykvaW5pdGlhbC5udW0uZGVhdGhzKSAtIGxvZygxKSkvY29lZihteS5sb2dpc3RpYylbMV0NCiAgbjUwIDwtIG15LmxvZ2lzdGljLmZjdChhPWluaXRpYWwubnVtLmRlYXRocywgY29lZihteS5sb2dpc3RpYylbMV0sIGNvZWYobXkubG9naXN0aWMpWzJdLCB0aT10NTApDQogIGxvZ2lzdGljLnRleHQgPC0gcGFzdGUwKCJJbmZsZWN0aW9uIHBvaW50OiAiLCByb3VuZCh0NTAsMCksICIgZGF5cyBhbmQgIiwgcm91bmQobjUwLDApLCAiIGRlYXRocyIpDQogIA0KICBjb3VudHJ5Lm5hbWUgPC0gcGFzdGUwKGFzLmNoYXJhY3Rlcih1bmlxdWUodGhpcy5kZiRjb3VudHJpZXNBbmRUZXJyaXRvcmllcykpLCAiIC0gIiwgZm9ybWF0KG1heCh0aGlzLmRmJGN1bXN1bS5kZWF0aHMpLGJpZy5tYXJrPSIsIiksICIgY3VtdWxhdGl2ZSBkZWF0aHMiKQ0KICAgIA0KICANCiAgZzwtZ2dwbG90KHRoaXMuZGYsIGFlcyhkYXRlUmVwLCBjdW1zdW0uZGVhdGhzKSkgKw0KICAgIGdlb21fbGluZShhZXMoY29sb3I9ImRhdGEiKSkgKw0KICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yPSJkYXRhIikpICsNCiAgICBnZW9tX2xpbmUoZGF0YT1wcmVkLmxtLCBhZXMoZGF0ZVJlcCwgY3Vtc3VtLmRlYXRocywgY29sb3I9ImV4cG9uZW50aWFsIG1vZGVsIiksIGxpbmV0eXBlPTIpICsNCiAgICBnZW9tX2xpbmUoZGF0YT1sb2dpc3RpYy5wcmVkLCBhZXMoZGF0ZVJlcCwgY3Vtc3VtLmRlYXRocywgY29sb3I9ImxvZ2lzdGljIG1vZGVsIiksIGxpbmV0eXBlPTEpICsNCiAgICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKCJNb2RlbCB0eXBlIikpICsNCiAgICBnZ3RpdGxlKGNvdW50cnkubmFtZSkgKw0KICAgIGdlb21fcG9pbnQoYWVzKHg9bWluKGRhdGVSZXApK3Q1MCwgeT1uNTApKSArDQogICAgYW5ub3RhdGUoInRleHQiLHg9bWluKHRoaXMuZGYkZGF0ZVJlcCkrKGFzLm51bWVyaWMoZGlmZihyYW5nZSh0aGlzLmRmJGRhdGVSZXApKSkqMC40KSwgeT1uNTAsIGxhYmVsPWxvZ2lzdGljLnRleHQpICsNCiAgICB5bGltKDAsbWF4KHRoaXMuZGYkY3Vtc3VtLmRlYXRocykqMS4yKQ0KDQogIGcNCiAgICANCn0NCg0KY291bnRyeS5kZWF0aHMuZmN0KCJJVCIpDQpjb3VudHJ5LmRlYXRocy5mY3QoIkVTIikNCmNvdW50cnkuZGVhdGhzLmZjdCgiVVMiKQ0KY291bnRyeS5kZWF0aHMuZmN0KCJGUiIpDQpjb3VudHJ5LmRlYXRocy5mY3QoIklSIikNCmNvdW50cnkuZGVhdGhzLmZjdCgiVUsiKQ0KY291bnRyeS5kZWF0aHMuZmN0KCJCRSIpDQpjb3VudHJ5LmRlYXRocy5mY3QoIkNIIikNCmNvdW50cnkuZGVhdGhzLmZjdCgiQ0EiKQ0KY291bnRyeS5kZWF0aHMuZmN0KCJDTCIpDQpgYGANCg0KYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTgsIGVjaG89RkFMU0V9DQoNCmNvdW50cnkuY2FzZXMuZmN0IDwtIGZ1bmN0aW9uKGcuaWQpew0KICB0aGlzLmRmIDwtIGZpbHRlcihkZjIsIGdlb0lkPT1nLmlkLCBjdW1zdW0uY2FzZXM+PTEwMCkNCg0KICAjIyAxNTAwIGNhc2VzIHBlciBvbmUgbWlsbGlvbiBhcyBhIHN0YXJ0aW5nIHZhbHVlIGZvciB0aGUgYXN5bXB0b3RlIGMNCiAgYy5pbml0IDwtIDE1MDAgKiAodW5pcXVlKHRoaXMuZGYkcG9wRGF0YTIwMTgpLzFFMDYpDQogICNhLmluaXQgPC0gYy5pbml0LzEwMA0KICAgIA0KICBteS5sbSA8LSBsbShsb2coY3Vtc3VtLmNhc2VzKX5kYXlzLnNpbmNlLjEwMC5jYXNlcywgZGF0YT10aGlzLmRmKQ0KICBwcmVkLmxtIDwtIGRhdGEuZnJhbWUoZGF0ZVJlcD10aGlzLmRmJGRhdGVSZXAsIGN1bXN1bS5jYXNlcz1leHAoZml0dGVkKG15LmxtKSkpDQogIA0KICBpbml0aWFsLm51bS5jYXNlcyA8LSB0aGlzLmRmW2FzLm51bWVyaWModGhpcy5kZiRkYXlzLnNpbmNlLjEwMC5jYXNlcyk9PTAsImN1bXN1bS5jYXNlcyJdDQogIG15LmxvZ2lzdGljIDwtIG5scyhjdW1zdW0uY2FzZXMgfiBteS5sb2dpc3RpYy5mY3QoYT1pbml0aWFsLm51bS5jYXNlcywgYixjLGFzLm51bWVyaWMoZGF5cy5zaW5jZS4xMDAuY2FzZXMpKSwgZGF0YT10aGlzLmRmLCBzdGFydD1saXN0KGI9MC40LGM9Yy5pbml0KSkNCiAgbG9naXN0aWMucHJlZCA8LSBkYXRhLmZyYW1lKGRhdGVSZXA9dGhpcy5kZiRkYXRlUmVwLCBkYXlzLnNpbmNlLjEwMC5jYXNlcz1hcy5udW1lcmljKHRoaXMuZGYkZGF5cy5zaW5jZS4xMDAuY2FzZXMpLCBjdW1zdW0uY2FzZXM9Zml0dGVkKG15LmxvZ2lzdGljKSkNCiAgIyMgaW5mbGVjdGlvbiBwb2ludA0KICB0NTAgPC0gKGxvZygoY29lZihteS5sb2dpc3RpYylbMl0taW5pdGlhbC5udW0uY2FzZXMpL2luaXRpYWwubnVtLmNhc2VzKSAtIGxvZygxKSkvY29lZihteS5sb2dpc3RpYylbMV0NCiAgbjUwIDwtIG15LmxvZ2lzdGljLmZjdChhPWluaXRpYWwubnVtLmNhc2VzLCBjb2VmKG15LmxvZ2lzdGljKVsxXSwgY29lZihteS5sb2dpc3RpYylbMl0sIHRpPXQ1MCkNCiAgbG9naXN0aWMudGV4dCA8LSBwYXN0ZTAoIkluZmxlY3Rpb24gcG9pbnQ6ICIsIHJvdW5kKHQ1MCwwKSwgIiBkYXlzIGFuZCAiLCByb3VuZChuNTAsMCksICIgY2FzZXMiKQ0KICANCiAgY291bnRyeS5uYW1lIDwtIHBhc3RlMChhcy5jaGFyYWN0ZXIodW5pcXVlKHRoaXMuZGYkY291bnRyaWVzQW5kVGVycml0b3JpZXMpKSwgIiAtICIsIGZvcm1hdChtYXgodGhpcy5kZiRjdW1zdW0uY2FzZXMpLGJpZy5tYXJrPSIsIiksICIgY3VtdWxhdGl2ZSBjYXNlcyIpDQogICAgDQogIA0KICBnPC1nZ3Bsb3QodGhpcy5kZiwgYWVzKGRhdGVSZXAsIGN1bXN1bS5jYXNlcykpICsNCiAgICBnZW9tX2xpbmUoYWVzKGNvbG9yPSJkYXRhIikpICsNCiAgICBnZW9tX3BvaW50KGFlcyhjb2xvcj0iZGF0YSIpKSArDQogICAgZ2VvbV9saW5lKGRhdGE9cHJlZC5sbSwgYWVzKGRhdGVSZXAsIGN1bXN1bS5jYXNlcywgY29sb3I9ImV4cG9uZW50aWFsIG1vZGVsIiksIGxpbmV0eXBlPTIpICsNCiAgICBnZW9tX2xpbmUoZGF0YT1sb2dpc3RpYy5wcmVkLCBhZXMoZGF0ZVJlcCwgY3Vtc3VtLmNhc2VzLCBjb2xvcj0ibG9naXN0aWMgbW9kZWwiKSwgbGluZXR5cGU9MSkgKw0KICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQoIk1vZGVsIHR5cGUiKSkgKw0KICAgIGdndGl0bGUoY291bnRyeS5uYW1lKSArDQogICAgZ2VvbV9wb2ludChhZXMoeD1taW4oZGF0ZVJlcCkrdDUwLCB5PW41MCkpICsNCiAgICBhbm5vdGF0ZSgidGV4dCIseD1taW4odGhpcy5kZiRkYXRlUmVwKSsoYXMubnVtZXJpYyhkaWZmKHJhbmdlKHRoaXMuZGYkZGF0ZVJlcCkpKSowLjQpLCB5PW41MCwgbGFiZWw9bG9naXN0aWMudGV4dCkgKw0KICAgIHlsaW0oMCxtYXgodGhpcy5kZiRjdW1zdW0uY2FzZXMpKjEuMikNCg0KICBnDQogICAgDQp9DQoNCg0KY291bnRyeS5jYXNlcy5mY3QoIlVTIikNCmNvdW50cnkuY2FzZXMuZmN0KCJJVCIpDQpjb3VudHJ5LmNhc2VzLmZjdCgiRVMiKQ0KY291bnRyeS5jYXNlcy5mY3QoIkNOIikNCmNvdW50cnkuY2FzZXMuZmN0KCJERSIpDQpjb3VudHJ5LmNhc2VzLmZjdCgiRlIiKQ0KY291bnRyeS5jYXNlcy5mY3QoIklSIikNCmNvdW50cnkuY2FzZXMuZmN0KCJVSyIpDQpjb3VudHJ5LmNhc2VzLmZjdCgiQ0giKQ0KY291bnRyeS5jYXNlcy5mY3QoIlRSIikNCmNvdW50cnkuY2FzZXMuZmN0KCJCRSIpDQpjb3VudHJ5LmNhc2VzLmZjdCgiTkwiKQ0KY291bnRyeS5jYXNlcy5mY3QoIkFUIikNCmNvdW50cnkuY2FzZXMuZmN0KCJLUiIpDQpjb3VudHJ5LmNhc2VzLmZjdCgiQ0EiKQ0KY291bnRyeS5jYXNlcy5mY3QoIlBUIikNCmNvdW50cnkuY2FzZXMuZmN0KCJCUiIpDQpjb3VudHJ5LmNhc2VzLmZjdCgiSUwiKQ0KY291bnRyeS5jYXNlcy5mY3QoIkFVIikNCmNvdW50cnkuY2FzZXMuZmN0KCJOTyIpDQpjb3VudHJ5LmNhc2VzLmZjdCgiQ0wiKQ0KDQojY291bnRyeS5jYXNlcy5mY3QoIkNaIikNCg0KDQoNCiN0ZXN0LmRmIDwtIGRhdGEuZnJhbWUoDQojICB0aT0wOjUwKQ0KI3Rlc3QuZGYkeSA8LSBteS5sb2dpc3RpYy5mY3QoYT0xMCwgYj0wLjIsIGM9MUUwMywgdGk9dGVzdC5kZiR0aSkNCg0KIyhsb2coMTAwKSAtIGxvZygxKSkvMC4yDQojdGVzdC5kZlt0ZXN0LmRmJHRpPT0yMyxdDQpgYGANCg0KDQoNCg==