Create your own new coronavirus outbreak tracker

There are now hundreds of new crown epidemic trackers on the Internet. First I want to know where they put the data. After research, two main sources were quickly identified. I initially used one of them. That is Johns Hopkins University. They posted some useful csv files on GitHub. However, the data there is only updated once a day, so I started looking for some real-time services. I found TheVirusTracker. I ended up using their API. They have a summary of each country, but they also have a schedule. This is more interesting to me. I didn't find any information about the request limits, and there seems to be no limit information.
Structure
TheVirusTracker supports CORS requests, so the application can be built as a static page that works entirely in the browser. However, I went the other way. As mentioned above, I originally used data from Hopkins University, which is located on GitHub. So I need to pull it from there. The most reliable method is to use GitHub's content endpoint. The rate of all their endpoints is limited to 60 requests per hour, in order to increase the number of requests, you need to use personal access token. Such tokens should not be shared publicly. So I had to write some back-end code.

My client code is making a request to the Node.js process. The process will get the data, then normalize it and return. Later, I changed the data source, but decided to keep this process for three reasons:

I have a pretty good layer for standardizing and caching data. There is almost always a need to convert data. In any case, I will have this code, so why not put it on the back end and let the client use it. The remote API is public and free, so I should not re-request the request. In order to provide high traffic, I need a cache layer. The most basic way to solve this requirement is to implement a simple memory cache. Without a server, this is impossible.
I have spent time writing a server and don't want to give up this job.
So far, my code exposes three endpoints. I want to share this content with other developers and let others use normalization and caching.

After a few hours, my project structure became

Frontend
One reason for doing this project is to improve my React and TypeScript skills. I have created some projects with these two excellent techniques, and an installation mode has emerged. At some point, I grouped the necessary configuration into a package called starting (you can read more about "Webpack / TypeScript / React starter kit as of 2020" here). Therefore, I created an empty folder and ran:
npx beginning && yarn.
Copy the code. This creates a simple React application with TypeScript support.
The React
application in the React ecosystem itself is nothing special. Because this is a small project, I don't need any state management. Everything is just a component with several hooks.
I use charts built by recharts. Used its components:




Most outbreak trackers cannot filter data by country. Usually, such applications render a large amount of data, which is obviously difficult to filter information. I want my tracker to have this filtering function. I used react-tag-autocomplete, another popular software package. It provides input fields for managing tags. The label here is the country name.
export default function Builder ({countries, data}: BuilderProps) {
const [tags, setTags] = useState <Tag []> (getTags (countries, data));
const [suggestions, setSuggestions] = useState (getSuggestions (countries)) ;

function handleDelete(i: number) {
const t = tags.slice(0);
t.splice(i, 1);
setTags(t);
}
function handleAddition(tag: Tag) {
setTags([…tags, tag]);
}

return (
<>

{tags.length> 0 && (
<Link href = { https://c19stats.now.sh?countries=${tags.map(t => t.name).join(',')}}>
Click here to see stats for {tags.map (t => t.name)}

)}
</>
);
}
Copy the code for simplicity For the sake of clarity, I decided to generate a link instead of immediately making a new request to the API. In this way, the user will have a shareable URL.

The rest of the application is a few style-enabled components, some input content and a small data layer for requesting the backend. All code is posted on github.com/krasimir/co ...
Backend
First, I want to say that Zeit is so enjoyable as a platform. Everything went so smoothly. After a few minutes, the work of my web page on the web is driven by the Node.js backend.
I start with the following now.json file:
{
“version”: 2,
“builds”: [
{“src”: “public / . ”, “Use”: “@ now / static”},
{“src”: “ api / .js ",“ use ”:“ @ now / node ”}
],
“ routes ”: [
{“ src ”:“ / api / countries ”,“ dest ”:“ /api/countries.js ”},
{ "the src": "/ API", "dest": "/api/index.js"},
{ "the src": "(. /
)", "dest": "/ public / $. 1"}
]
}
copy The code public folder contains some static files, such as my index.html and the generated JavaScript bundle. Everything in the api directory is a lambda function. For example, after c19stats.now.sh/api/countri ..., I have
const countries = require(’./countries.json’);

function JSONResponse(res, data, status = 200) {
res.setHeader(‘Content-Type’, ‘application/json’);
res.setHeader(‘Access-Control-Allow-Origin’, ‘*’);
res.statusCode = status;
res.end(JSON.stringify(data));
}

module.exports = async function (req, res) {
JSONResponse (res, countries);
};
Copy the code In order to access the remote server of TheVirusTracker, I used superagent. This is nothing unusual, but it allows me to easily paste my "amazing" cache logic:
const memCache = {
lastUpdate: null,
data: null,
};

const CACHE_TTL = 20;

function getData (noCache) {
if (memCache.data && memCache.lastUpdate && typeof noCache === 'undefined') {
const now = new Date ();
const diff = (now.getTime ()-memCache.lastUpdate) / 1000 / 60;
if (diff <CACHE_TTL) {
return Promise.resolve (memCache.data);
}
}
// normalization of the data
}
Copy code We first check whether there is a cache. The data field of the memCache object holds the normalized version of the data, so it can be returned directly (note the Promise.resolve call). Second, if there is cached data, we will check the number of minutes since the last update. Here, we must clarify that all content retained in the global scope of the file will be retained. Of course, if I deploy a new version of lambda or restart the process for some reason, the cache will be cleared. But I am completely satisfied with this. The purpose of this is to avoid continuously sending requests to the far end. To be honest, it works well. c19stats.now.sh/ sometimes takes more time to load the data, but the result page refreshes quickly.
Create your own new crown outbreak tracker
You can always use certain endpoints on c19stats.now.sh/.

Get data for specific countries / regions-/ api? Countries = US, Italy, Norway
Get data
for all countries / regions-/ api? Countries = allGet list of all countries / regions

Or, you can directly use the API of thevirustracker.com/api. But if you need to cache data, you must implement it yourself. The rest is up to you. All code of c19stats.now.sh/ is open source and available at github.com/krasimir/co ... .

Published 28 original articles · Likes0 · Visits 907

Guess you like

Origin blog.csdn.net/srhgsr/article/details/105520168