├── preview.png ├── README.md ├── package.json ├── server.js ├── output └── result.txt ├── odometer-theme-default.css ├── index.html └── odometer.min.js /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ergors/coronavirus-live-map/HEAD/preview.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Coronavirus live map 2 | 3 | ![preview](https://raw.githubusercontent.com/ergoproxyDNS/coronavirus-live-map/master/preview.png) 4 | 5 | A simple map chart for coronavirus cases and deaths.
6 | For this applications I used geocharts from google and simple crawling with nodejs.
7 | I did this for studying web scraping in nodejs and Geocharts of google maps API. 8 | ## How run it? 9 | ### Dependencies 10 | ``` 11 | - nodejs 12 | - cheerio 13 | - request 14 | ``` 15 | ### Setup server 16 | After install dependencies you can simply run `node .` in project folder to download coronavirus data. Then you open the index.html in browser and edit `'mapsApiKey':` with your google API key. 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coronavirusmap.github.io", 3 | "version": "1.0.0", 4 | "description": "Live map of coronavirus confirmed cases", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/ergoproxyDNS/coronavirusmap.github.io.git" 12 | }, 13 | "keywords": [ 14 | "coronavirus", 15 | "live", 16 | "map" 17 | ], 18 | "author": "Ergo", 19 | "license": "ISC", 20 | "bugs": { 21 | "url": "https://github.com/ergoproxyDNS/coronavirusmap.github.io/issues" 22 | }, 23 | "homepage": "https://github.com/ergoproxyDNS/coronavirusmap.github.io#readme", 24 | "dependencies": { 25 | "cheerio": "^1.0.0-rc.3", 26 | "request": "^2.88.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | const cheerio = require('cheerio'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const target = "https://www.worldometers.info/coronavirus/#countries"; 6 | 7 | 8 | process.stdout.write("Downloading coronavirus status...\n"); 9 | fs.readdir("output", (err, files) => { 10 | if (err) throw err; 11 | //limpar arquivos do diretorio 12 | for (const file of files) { 13 | fs.unlink(path.join("output", file), err => { 14 | if (err) throw err; 15 | }); 16 | } 17 | }); 18 | request(target, function(err, res, body){ 19 | if (err) console.log("Ocorreu um erro " + err); 20 | var $ = cheerio.load(body); 21 | function GetResults(){ 22 | console.log("Writing counter..."); 23 | $(".maincounter-number span").each(function(i, elm) { 24 | let resultado = $(this).html().trim() + '\n'; 25 | // 3 numbers 26 | // 1 -> total cases 27 | // 2 -> total deaths 28 | fs.appendFileSync("output/result.txt", resultado); 29 | }); 30 | console.log("Writing country results...") 31 | $("tr td").each(function(i, elm) { 32 | let resultado = $(this).html().trim() + '\n'; 33 | // 7 columns each country 34 | // 1 -> country name 35 | // 2 -> total cases 36 | fs.appendFileSync("output/result.txt", resultado); 37 | }); 38 | } 39 | GetResults(); 40 | 41 | }); 42 | 43 | -------------------------------------------------------------------------------- /output/result.txt: -------------------------------------------------------------------------------- 1 | 65,247 2 | 1,491 3 | 7,099 4 | China 5 | 64,658 6 | +4,854 7 | 1,488 8 | +123 9 | 7,014 10 | 10,584 11 | Asia 12 | Japan 13 | 252 14 | +50 15 | 1 16 | +1 17 | 10 18 | 5 19 | Asia 20 | Singapore 21 | 58 22 | +8 23 | 24 | 25 | 15 26 | 8 27 | Asia 28 | Hong Kong 29 | 53 30 | +3 31 | 1 32 | 33 | 1 34 | 2 35 | Asia 36 | Thailand 37 | 33 38 | 39 | 40 | 41 | 12 42 | 1 43 | Asia 44 | S. Korea 45 | 28 46 | 47 | 48 | 49 | 7 50 | 51 | Asia 52 | Malaysia 53 | 19 54 | +1 55 | 56 | 57 | 3 58 | 59 | Asia 60 | Taiwan 61 | 18 62 | 63 | 64 | 65 | 1 66 | 67 | Asia 68 | Vietnam 69 | 16 70 | +1 71 | 72 | 73 | 7 74 | 75 | Asia 76 | Germany 77 | 16 78 | 79 | 80 | 81 | 1 82 | 83 | Europe 84 | Australia 85 | 15 86 | 87 | 88 | 89 | 8 90 | 91 | Oceania 92 | USA 93 | 15 94 | +2 95 | 96 | 97 | 3 98 | 99 | N.America 100 | France 101 | 11 102 | 103 | 104 | 105 | 2 106 | 1 107 | Europe 108 | Macao 109 | 10 110 | 111 | 112 | 113 | 3 114 | 115 | Asia 116 | U.K. 117 | 9 118 | 119 | 120 | 121 | 1 122 | 123 | Europe 124 | U.A.E. 125 | 8 126 | 127 | 128 | 129 | 1 130 | 1 131 | Asia 132 | Canada 133 | 7 134 | 135 | 136 | 137 | 1 138 | 139 | N.America 140 | India 141 | 5 142 | +2 143 | 144 | 145 | 1 146 | 147 | Asia 148 | Philippines 149 | 3 150 | 151 | 1 152 | 153 | 2 154 | 155 | Asia 156 | Italy 157 | 3 158 | 159 | 160 | 161 | 162 | 2 163 | Europe 164 | Russia 165 | 2 166 | 167 | 168 | 169 | 2 170 | 171 | Europe 172 | Spain 173 | 2 174 | 175 | 176 | 177 | 178 | 179 | Europe 180 | Sweden 181 | 1 182 | 183 | 184 | 185 | 186 | 187 | Europe 188 | Nepal 189 | 1 190 | 191 | 192 | 193 | 1 194 | 195 | Asia 196 | Sri Lanka 197 | 1 198 | 199 | 200 | 201 | 1 202 | 203 | Asia 204 | Finland 205 | 1 206 | 207 | 208 | 209 | 1 210 | 211 | Europe 212 | Cambodia 213 | 1 214 | 215 | 216 | 217 | 1 218 | 219 | Asia 220 | Belgium 221 | 1 222 | 223 | 224 | 225 | 226 | 227 | Europe 228 | -------------------------------------------------------------------------------- /odometer-theme-default.css: -------------------------------------------------------------------------------- 1 | .odometer.odometer-auto-theme, .odometer.odometer-theme-default { 2 | display: inline-block; 3 | vertical-align: middle; 4 | *vertical-align: auto; 5 | *zoom: 1; 6 | *display: inline; 7 | position: relative; 8 | } 9 | .odometer.odometer-auto-theme .odometer-digit, .odometer.odometer-theme-default .odometer-digit { 10 | display: inline-block; 11 | vertical-align: middle; 12 | *vertical-align: auto; 13 | *zoom: 1; 14 | *display: inline; 15 | position: relative; 16 | } 17 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer, .odometer.odometer-theme-default .odometer-digit .odometer-digit-spacer { 18 | display: inline-block; 19 | vertical-align: middle; 20 | *vertical-align: auto; 21 | *zoom: 1; 22 | *display: inline; 23 | visibility: hidden; 24 | } 25 | .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner, .odometer.odometer-theme-default .odometer-digit .odometer-digit-inner { 26 | text-align: left; 27 | display: block; 28 | position: absolute; 29 | top: 0; 30 | left: 0; 31 | right: 0; 32 | bottom: 0; 33 | overflow: hidden; 34 | } 35 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon, .odometer.odometer-theme-default .odometer-digit .odometer-ribbon { 36 | display: block; 37 | } 38 | .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner, .odometer.odometer-theme-default .odometer-digit .odometer-ribbon-inner { 39 | display: block; 40 | -webkit-backface-visibility: hidden; 41 | } 42 | .odometer.odometer-auto-theme .odometer-digit .odometer-value, .odometer.odometer-theme-default .odometer-digit .odometer-value { 43 | display: block; 44 | -webkit-transform: translateZ(0); 45 | } 46 | .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value, .odometer.odometer-theme-default .odometer-digit .odometer-value.odometer-last-value { 47 | position: absolute; 48 | } 49 | .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-up .odometer-ribbon-inner { 50 | -webkit-transition: -webkit-transform 2s; 51 | -moz-transition: -moz-transform 2s; 52 | -ms-transition: -ms-transform 2s; 53 | -o-transition: -o-transform 2s; 54 | transition: transform 2s; 55 | } 56 | .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-up.odometer-animating .odometer-ribbon-inner { 57 | -webkit-transform: translateY(-100%); 58 | -moz-transform: translateY(-100%); 59 | -ms-transform: translateY(-100%); 60 | -o-transform: translateY(-100%); 61 | transform: translateY(-100%); 62 | } 63 | .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-down .odometer-ribbon-inner { 64 | -webkit-transform: translateY(-100%); 65 | -moz-transform: translateY(-100%); 66 | -ms-transform: translateY(-100%); 67 | -o-transform: translateY(-100%); 68 | transform: translateY(-100%); 69 | } 70 | .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-down.odometer-animating .odometer-ribbon-inner { 71 | -webkit-transition: -webkit-transform 2s; 72 | -moz-transition: -moz-transform 2s; 73 | -ms-transition: -ms-transform 2s; 74 | -o-transition: -o-transform 2s; 75 | transition: transform 2s; 76 | -webkit-transform: translateY(0); 77 | -moz-transform: translateY(0); 78 | -ms-transform: translateY(0); 79 | -o-transform: translateY(0); 80 | transform: translateY(0); 81 | } 82 | 83 | .odometer.odometer-auto-theme, .odometer.odometer-theme-default { 84 | font-family: "Helvetica Neue", sans-serif; 85 | line-height: 1.1em; 86 | } 87 | .odometer.odometer-auto-theme .odometer-value, .odometer.odometer-theme-default .odometer-value { 88 | text-align: center; 89 | } 90 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Coronavirus live map 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 66 | 67 | 68 |

Coronavirus live map


69 |
70 |
71 |
72 |

Total Cases:

73 |

0

74 |

😷

75 |
76 |
77 | 78 |
79 |
80 |

Total Deaths:

81 |

0

82 |

💀

83 |
84 |
85 |
86 |
87 |

88 | What is coronavirus? 89 | 90 | 91 | 92 | 93 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /odometer.min.js: -------------------------------------------------------------------------------- 1 | /*! odometer 0.4.6 */ 2 | (function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G=[].slice;q='',n=''+q+"",d='8'+n+"",g='',c="(,ddd).dd",h=/^\(?([^)]*)\)?(?:(.)(d+))?$/,i=30,f=2e3,a=20,j=2,e=.5,k=1e3/i,b=1e3/a,o="transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd",y=document.createElement("div").style,p=null!=y.transition||null!=y.webkitTransition||null!=y.mozTransition||null!=y.oTransition,w=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,l=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,s=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.children[0]},v=function(a,b){return a.className=a.className.replace(new RegExp("(^| )"+b.split(" ").join("|")+"( |$)","gi")," ")},r=function(a,b){return v(a,b),a.className+=" "+b},z=function(a,b){var c;return null!=document.createEvent?(c=document.createEvent("HTMLEvents"),c.initEvent(b,!0,!0),a.dispatchEvent(c)):void 0},u=function(){var a,b;return null!=(a=null!=(b=window.performance)?"function"==typeof b.now?b.now():void 0:void 0)?a:+new Date},x=function(a,b){return null==b&&(b=0),b?(a*=Math.pow(10,b),a+=.5,a=Math.floor(a),a/=Math.pow(10,b)):Math.round(a)},A=function(a){return 0>a?Math.ceil(a):Math.floor(a)},t=function(a){return a-x(a)},C=!1,(B=function(){var a,b,c,d,e;if(!C&&null!=window.jQuery){for(C=!0,d=["html","text"],e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(function(a){var b;return b=window.jQuery.fn[a],window.jQuery.fn[a]=function(a){var c;return null==a||null==(null!=(c=this[0])?c.odometer:void 0)?b.apply(this,arguments):this[0].odometer.update(a)}}(a));return e}})(),setTimeout(B,0),m=function(){function a(b){var c,d,e,g,h,i,l,m,n,o,p=this;if(this.options=b,this.el=this.options.el,null!=this.el.odometer)return this.el.odometer;this.el.odometer=this,m=a.options;for(d in m)g=m[d],null==this.options[d]&&(this.options[d]=g);null==(h=this.options).duration&&(h.duration=f),this.MAX_VALUES=this.options.duration/k/j|0,this.resetFormat(),this.value=this.cleanValue(null!=(n=this.options.value)?n:""),this.renderInside(),this.render();try{for(o=["innerHTML","innerText","textContent"],i=0,l=o.length;l>i;i++)e=o[i],null!=this.el[e]&&!function(a){return Object.defineProperty(p.el,a,{get:function(){var b;return"innerHTML"===a?p.inside.outerHTML:null!=(b=p.inside.innerText)?b:p.inside.textContent},set:function(a){return p.update(a)}})}(e)}catch(q){c=q,this.watchForMutations()}}return a.prototype.renderInside=function(){return this.inside=document.createElement("div"),this.inside.className="odometer-inside",this.el.innerHTML="",this.el.appendChild(this.inside)},a.prototype.watchForMutations=function(){var a,b=this;if(null!=l)try{return null==this.observer&&(this.observer=new l(function(){var a;return a=b.el.innerText,b.renderInside(),b.render(b.value),b.update(a)})),this.watchMutations=!0,this.startWatchingMutations()}catch(c){a=c}},a.prototype.startWatchingMutations=function(){return this.watchMutations?this.observer.observe(this.el,{childList:!0}):void 0},a.prototype.stopWatchingMutations=function(){var a;return null!=(a=this.observer)?a.disconnect():void 0},a.prototype.cleanValue=function(a){var b;return"string"==typeof a&&(a=a.replace(null!=(b=this.format.radix)?b:".",""),a=a.replace(/[.,]/g,""),a=a.replace("","."),a=parseFloat(a,10)||0),x(a,this.format.precision)},a.prototype.bindTransitionEnd=function(){var a,b,c,d,e,f,g=this;if(!this.transitionEndBound){for(this.transitionEndBound=!0,b=!1,e=o.split(" "),f=[],c=0,d=e.length;d>c;c++)a=e[c],f.push(this.el.addEventListener(a,function(){return b?!0:(b=!0,setTimeout(function(){return g.render(),b=!1,z(g.el,"odometerdone")},0),!0)},!1));return f}},a.prototype.resetFormat=function(){var a,b,d,e,f,g,i,j;if(a=null!=(i=this.options.format)?i:c,a||(a="d"),d=h.exec(a),!d)throw new Error("Odometer: Unparsable digit format");return j=d.slice(1,4),g=j[0],f=j[1],b=j[2],e=(null!=b?b.length:void 0)||0,this.format={repeating:g,radix:f,precision:e}},a.prototype.render=function(a){var b,c,d,e,f,g,h,i,j,k,l,m;for(null==a&&(a=this.value),this.stopWatchingMutations(),this.resetFormat(),this.inside.innerHTML="",g=this.options.theme,b=this.el.className.split(" "),f=[],i=0,k=b.length;k>i;i++)c=b[i],c.length&&((e=/^odometer-theme-(.+)$/.exec(c))?g=e[1]:/^odometer(-|$)/.test(c)||f.push(c));for(f.push("odometer"),p||f.push("odometer-no-transitions"),f.push(g?"odometer-theme-"+g:"odometer-auto-theme"),this.el.className=f.join(" "),this.ribbons={},this.digits=[],h=!this.format.precision||!t(a)||!1,m=a.toString().split("").reverse(),j=0,l=m.length;l>j;j++)d=m[j],"."===d&&(h=!0),this.addDigit(d,h);return this.startWatchingMutations()},a.prototype.update=function(a){var b,c=this;return a=this.cleanValue(a),(b=a-this.value)?(v(this.el,"odometer-animating-up odometer-animating-down odometer-animating"),b>0?r(this.el,"odometer-animating-up"):r(this.el,"odometer-animating-down"),this.stopWatchingMutations(),this.animate(a),this.startWatchingMutations(),setTimeout(function(){return c.el.offsetHeight,r(c.el,"odometer-animating")},0),this.value=a):void 0},a.prototype.renderDigit=function(){return s(d)},a.prototype.insertDigit=function(a,b){return null!=b?this.inside.insertBefore(a,b):this.inside.children.length?this.inside.insertBefore(a,this.inside.children[0]):this.inside.appendChild(a)},a.prototype.addSpacer=function(a,b,c){var d;return d=s(g),d.innerHTML=a,c&&r(d,c),this.insertDigit(d,b)},a.prototype.addDigit=function(a,b){var c,d,e,f;if(null==b&&(b=!0),"-"===a)return this.addSpacer(a,null,"odometer-negation-mark");if("."===a)return this.addSpacer(null!=(f=this.format.radix)?f:".",null,"odometer-radix-mark");if(b)for(e=!1;;){if(!this.format.repeating.length){if(e)throw new Error("Bad odometer format without digits");this.resetFormat(),e=!0}if(c=this.format.repeating[this.format.repeating.length-1],this.format.repeating=this.format.repeating.substring(0,this.format.repeating.length-1),"d"===c)break;this.addSpacer(c)}return d=this.renderDigit(),d.querySelector(".odometer-value").innerHTML=a,this.digits.push(d),this.insertDigit(d)},a.prototype.animate=function(a){return p&&"count"!==this.options.animation?this.animateSlide(a):this.animateCount(a)},a.prototype.animateCount=function(a){var c,d,e,f,g,h=this;if(d=+a-this.value)return f=e=u(),c=this.value,(g=function(){var i,j,k;return u()-f>h.options.duration?(h.value=a,h.render(),void z(h.el,"odometerdone")):(i=u()-e,i>b&&(e=u(),k=i/h.options.duration,j=d*k,c+=j,h.render(Math.round(c))),null!=w?w(g):setTimeout(g,b))})()},a.prototype.getDigitCount=function(){var a,b,c,d,e,f;for(d=1<=arguments.length?G.call(arguments,0):[],a=e=0,f=d.length;f>e;a=++e)c=d[a],d[a]=Math.abs(c);return b=Math.max.apply(Math,d),Math.ceil(Math.log(b+1)/Math.log(10))},a.prototype.getFractionalDigitCount=function(){var a,b,c,d,e,f,g;for(e=1<=arguments.length?G.call(arguments,0):[],b=/^\-?\d*\.(\d*?)0*$/,a=f=0,g=e.length;g>f;a=++f)d=e[a],e[a]=d.toString(),c=b.exec(e[a]),e[a]=null==c?0:c[1].length;return Math.max.apply(Math,e)},a.prototype.resetDigits=function(){return this.digits=[],this.ribbons=[],this.inside.innerHTML="",this.resetFormat()},a.prototype.animateSlide=function(a){var b,c,d,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y,z,B,C,D,E;if(s=this.value,j=this.getFractionalDigitCount(s,a),j&&(a*=Math.pow(10,j),s*=Math.pow(10,j)),d=a-s){for(this.bindTransitionEnd(),f=this.getDigitCount(s,a),g=[],b=0,m=v=0;f>=0?f>v:v>f;m=f>=0?++v:--v){if(t=A(s/Math.pow(10,f-m-1)),i=A(a/Math.pow(10,f-m-1)),h=i-t,Math.abs(h)>this.MAX_VALUES){for(l=[],n=h/(this.MAX_VALUES+this.MAX_VALUES*b*e),c=t;h>0&&i>c||0>h&&c>i;)l.push(Math.round(c)),c+=n;l[l.length-1]!==i&&l.push(i),b++}else l=function(){E=[];for(var a=t;i>=t?i>=a:a>=i;i>=t?a++:a--)E.push(a);return E}.apply(this);for(m=w=0,y=l.length;y>w;m=++w)k=l[m],l[m]=Math.abs(k%10);g.push(l)}for(this.resetDigits(),D=g.reverse(),m=x=0,z=D.length;z>x;m=++x)for(l=D[m],this.digits[m]||this.addDigit(" ",m>=j),null==(u=this.ribbons)[m]&&(u[m]=this.digits[m].querySelector(".odometer-ribbon-inner")),this.ribbons[m].innerHTML="",0>d&&(l=l.reverse()),o=C=0,B=l.length;B>C;o=++C)k=l[o],q=document.createElement("div"),q.className="odometer-value",q.innerHTML=k,this.ribbons[m].appendChild(q),o===l.length-1&&r(q,"odometer-last-value"),0===o&&r(q,"odometer-first-value");return 0>t&&this.addDigit("-"),p=this.inside.querySelector(".odometer-radix-mark"),null!=p&&p.parent.removeChild(p),j?this.addSpacer(this.format.radix,this.digits[j-1],"odometer-radix-mark"):void 0}},a}(),m.options=null!=(E=window.odometerOptions)?E:{},setTimeout(function(){var a,b,c,d,e;if(window.odometerOptions){d=window.odometerOptions,e=[];for(a in d)b=d[a],e.push(null!=(c=m.options)[a]?(c=m.options)[a]:c[a]=b);return e}},0),m.init=function(){var a,b,c,d,e,f;if(null!=document.querySelectorAll){for(b=document.querySelectorAll(m.options.selector||".odometer"),f=[],c=0,d=b.length;d>c;c++)a=b[c],f.push(a.odometer=new m({el:a,value:null!=(e=a.innerText)?e:a.textContent}));return f}},null!=(null!=(F=document.documentElement)?F.doScroll:void 0)&&null!=document.createEventObject?(D=document.onreadystatechange,document.onreadystatechange=function(){return"complete"===document.readyState&&m.options.auto!==!1&&m.init(),null!=D?D.apply(this,arguments):void 0}):document.addEventListener("DOMContentLoaded",function(){return m.options.auto!==!1?m.init():void 0},!1),"function"==typeof define&&define.amd?define(["jquery"],function(){return m}):typeof exports===!1?module.exports=m:window.Odometer=m}).call(this); --------------------------------------------------------------------------------