Skip to content

Commit 61d482f

Browse files
author
scinorandex
committed
refactor existing code
1 parent ff721cb commit 61d482f

File tree

9 files changed

+392
-196
lines changed

9 files changed

+392
-196
lines changed

src/utils/getInformation.ts

Lines changed: 107 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,38 @@
11
import axios from "axios";
2+
import { convertCountryCode } from "../utils/libs/convertCountry";
3+
import { capitalizeFirstLetter } from "../utils/libs/capitalizeFirstLetter";
24
axios.defaults.baseURL = "https://disease.sh/v3/covid-19";
35

4-
let countryCodes: { [key: string]: string } = {};
5-
(async () => {
6-
countryCodes = (await axios.get("http://country.io/names.json")).data;
7-
})();
8-
9-
export interface PlainData {
10-
data: {
11-
[key: string]: string;
12-
};
13-
metainfo: {
14-
[key: string]: number | string;
15-
};
16-
}
17-
186
/**
197
* @param isPlain Set to true to recieve an object containing the responses instead of the rows
208
* @returns an object containing the data and metainfo **if isPlain is set to true**
219
* @returns an array in the format of [timestamp, rows] **if isPlain is set to false**
2210
*/
23-
export const getAllInfo: (
24-
isPlain?: boolean
25-
) => Promise<[number, (string[] | string)[]] | PlainData> = async (
26-
isPlain = false
27-
) => {
11+
export const getAllInfo: () => Promise<{
12+
updated: number;
13+
data: {
14+
cases: number;
15+
deaths: number;
16+
recovered: number;
17+
deathRate: number;
18+
recoveryRate: number;
19+
};
20+
}> = async () => {
2821
let { data: globalData } = await axios.get("/all");
2922
let { cases, deaths, recovered, updated } = globalData;
23+
let deathRate = (deaths / cases) * 100;
24+
let recoveryRate = (recovered / cases) * 100;
3025

31-
let mortalityPercentage = ((deaths / cases) * 100).toFixed(2) + "%";
32-
let recoveredPercentage = ((recovered / cases) * 100).toFixed(2) + "%";
33-
34-
[cases, deaths, recovered] = [cases, deaths, recovered].map((num: number) =>
35-
num.toLocaleString("en-US", { maximumFractionDigits: 0 })
36-
);
37-
38-
// Return object containing information if isPlain is set to true
39-
if (isPlain) {
40-
return {
41-
data: {
42-
Cases: cases,
43-
Deaths: deaths,
44-
"Mortality %": mortalityPercentage,
45-
Recovered: recovered,
46-
"Recovered %": recoveredPercentage,
47-
},
48-
metainfo: {
49-
updated,
50-
},
51-
};
52-
}
53-
54-
// Return rows if isPlain is set to false
55-
// prettier-ignore
56-
return [updated, [
57-
["Cases".magenta, "Deaths".red,"Recovered".green, "Mortality %".red,"Recovered %".green],
58-
[cases, deaths, recovered, mortalityPercentage, recoveredPercentage]]]
26+
return {
27+
updated,
28+
data: {
29+
cases,
30+
deaths,
31+
recovered,
32+
deathRate,
33+
recoveryRate,
34+
},
35+
};
5936
};
6037

6138
/**
@@ -65,107 +42,108 @@ export const getAllInfo: (
6542
* @returns an array in the format of [timestamp, API countryname, formal countryname, rows[]] **if isPlain is false**
6643
*/
6744
export const getCountryInfo: (
68-
country: string,
69-
isPlain?: boolean
70-
) => Promise<
71-
[number, string, string, (string[] | string)[]] | PlainData
72-
> = async (country, isPlain) => {
73-
// Wait 1 second for countryCodes to initialize, needed for CLI
74-
if (Object.keys(countryCodes).length === 0) {
75-
await new Promise((resolve) => {
76-
setTimeout(resolve, 1000);
77-
});
78-
}
79-
80-
country =
81-
country.length < 3 ? countryCodes[country.toUpperCase()] : country; // Convert country code to country name
82-
83-
if (country === undefined || typeof country === "undefined")
84-
throw new Error(`Cannot find provided country`);
45+
country: string
46+
) => Promise<{
47+
updated: number;
48+
formalCountryName: string;
49+
apiCountryName: string;
50+
data: {
51+
cases: number;
52+
todayCases: number;
53+
active: number;
54+
recovered: number;
55+
deaths: number;
56+
todayDeaths: number;
57+
critical: number;
58+
deathRate: number;
59+
recoveryRate: number;
60+
casesPerOneMillion: number;
61+
};
62+
}> = async (country) => {
63+
// Convert country to country code
64+
country = await convertCountryCode(country);
65+
let formalCountryName = capitalizeFirstLetter(country);
8566

8667
try {
8768
let { data: countryData } = await axios.get(`/countries/${country}`);
8869
// prettier-ignore
89-
let { country: countryName, updated, cases, deaths, recovered, active, casesPerOneMillion, todayCases, todayDeaths, critical} = countryData;
90-
91-
let mortalityPercentage = ((deaths / cases) * 100).toFixed(2) + "%";
92-
let recoveredPercentage = ((recovered / cases) * 100).toFixed(2) + "%";
93-
94-
// prettier-ignore
95-
[ cases, deaths, recovered, active, casesPerOneMillion, todayCases, todayDeaths, critical ] =
96-
[ cases, deaths, recovered, active, casesPerOneMillion, todayCases, todayDeaths, critical,
97-
].map((num: number) =>
98-
num.toLocaleString("en-US", { maximumFractionDigits: 0 })
99-
);
100-
101-
// Return object containing information if isPlain is set to true
102-
if (isPlain) {
103-
return {
104-
data: {
105-
Cases: cases,
106-
"Today Cases": todayCases,
107-
Active: active,
108-
Recovered: recovered,
109-
Deaths: deaths,
110-
"Today Deaths": todayDeaths,
111-
Critical: critical,
112-
"Mortality %": mortalityPercentage,
113-
"Recovery %": recoveredPercentage,
114-
"Cases/Million": casesPerOneMillion,
115-
},
116-
metainfo: {
117-
updated,
118-
countryName,
119-
},
120-
};
121-
}
70+
let { country: apiCountryName, updated, cases, deaths, recovered, active, casesPerOneMillion, todayCases, todayDeaths, critical} = countryData;
71+
let deathRate = (deaths / cases) * 100;
72+
let recoveryRate = (recovered / cases) * 100;
12273

123-
//prettier-ignore
124-
return [updated, country, countryName, [
125-
[ "Cases".magenta, "Deaths".red, "Recovered".green, "Active".blue, "Cases/Million".blue,],
126-
[ cases, deaths, recovered, active, casesPerOneMillion,],
127-
[ "Today Cases".magenta, "Today Deaths".red, "Critical".red, "Mortaility %".red, "Recovery %".green],
128-
[ todayCases, todayDeaths, critical, mortalityPercentage, recoveredPercentage]]
129-
]
74+
return {
75+
updated,
76+
formalCountryName,
77+
apiCountryName,
78+
// prettier-ignore
79+
data: {
80+
cases, todayCases, active, recovered, deaths, todayDeaths, critical, deathRate, recoveryRate, casesPerOneMillion
81+
},
82+
};
13083
} catch {
13184
throw new Error(`Cannot find the provided country`);
13285
}
13386
};
13487

135-
/**
136-
* Get historical info about a country / the world
137-
* @param mode - mode that the user requested
138-
* @param country - countryname that the user requested, leave blank to get world data
139-
* @returns an object containing date and chartData properties
140-
*/
141-
export const getHistorical: (
142-
mode: "cases" | "deaths" | "recovered",
88+
type getHistoricalMode = "cases" | "deaths" | "recovered" | "all";
89+
90+
// prettier-ignore
91+
export async function getHistorical<T extends getHistoricalMode>(
92+
mode: T,
14393
country?: string
144-
) => Promise<{
94+
): Promise<
95+
T extends "all" ? {
96+
date: string;
97+
chartData: {
98+
[key: string]: {
99+
[key: string]: number;
100+
};
101+
};
102+
} : {
103+
date: string;
104+
chartData: number[];
105+
}
106+
>;
107+
108+
export async function getHistorical(
109+
mode: getHistoricalMode,
110+
country = "all"
111+
): Promise<{
145112
date: string;
146-
chart: number[];
147-
}> = async (mode, country = "all") => {
113+
chartData:
114+
| number[]
115+
| {
116+
[key: string]: {
117+
[key: string]: number;
118+
};
119+
};
120+
}> {
148121
const { data: historicalData } = await axios.get(`/historical/${country}`);
149122

150-
const data: {
151-
[key: string]: number;
152-
} =
153-
country === "all"
154-
? historicalData[mode]
155-
: historicalData["timeline"][mode];
123+
// Get all the modes
124+
let chartData =
125+
country === "all" ? historicalData : historicalData["timeline"];
126+
127+
// If the user did not select all, then get the mode they wanted
128+
if (mode !== "all") chartData = chartData[mode];
156129

157130
// Get first and last date
158-
const dates = Object.keys(data);
131+
const dates = Object.keys(mode === "all" ? chartData["cases"] : chartData);
159132

160133
// Label for chart
161134
const date = `${
162135
mode.charAt(0).toUpperCase() + mode.slice(1)
163136
} from ${dates.shift()} to ${dates.pop()}`;
164137

165-
const chartData = Object.values(data);
166-
167-
return {
168-
date,
169-
chart: chartData,
170-
};
171-
};
138+
if (mode === "all") {
139+
return {
140+
date,
141+
chartData,
142+
};
143+
} else {
144+
return {
145+
date,
146+
chartData: Object.values(chartData) as number[],
147+
};
148+
}
149+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
*
3+
* @param str String that you want to capitalize
4+
* @returns String with first letter capitalized
5+
*/
6+
export const capitalizeFirstLetter: (str: string) => string = (str) => {
7+
return str.charAt(0).toUpperCase() + str.slice(1);
8+
};

src/utils/libs/convertCountry.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import axios from "axios";
2+
let countryCodes: { [key: string]: string } = {};
3+
(async () => {
4+
countryCodes = (await axios.get("http://country.io/names.json")).data;
5+
})();
6+
7+
export const convertCountryCode: (country: string) => Promise<string> = async (
8+
country
9+
) => {
10+
// Wait 1 second for countryCodes to initialize, needed for CLI
11+
if (Object.keys(countryCodes).length === 0) {
12+
await new Promise((resolve) => {
13+
setTimeout(resolve, 1000);
14+
});
15+
}
16+
17+
if (country.length < 3) country = countryCodes[country.toUpperCase()];
18+
19+
if (country === undefined || typeof country === "undefined")
20+
throw new Error(`Cannot find provided country`);
21+
else return country;
22+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Takes a number, fixes it to 2 decimal places, and converts it into a string with a %
3+
* @param number Number that you want to convert to percentage
4+
* @returns String containing percentaged number
5+
*/
6+
export const convertToPercentage: (...args: number[]) => string[] = (
7+
...args
8+
) => {
9+
return args.map((number) => number.toFixed(2) + "%");
10+
};
11+
12+
/**
13+
* Takes numbers and adds commas every 3 digits starting from the right
14+
* @param args Numbers that you want to normalize
15+
* @returns Array of strings containing the normalized numbers
16+
*/
17+
export const normalizeNumbers: (...args: number[]) => string[] = (...args) => {
18+
return args.map((number) =>
19+
number.toLocaleString("en-US", { maximumFractionDigits: 0 })
20+
);
21+
};

src/utils/routes/plain/generatePlainOutput.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { PlainData } from "../../getInformation";
21
import { lines } from "../../libs/getResponses";
32
import { getSaying } from "../../libs/getSaying";
43
import { getTimestamp } from "../../libs/getTimestamp";
@@ -11,17 +10,22 @@ import { getTimestamp } from "../../libs/getTimestamp";
1110
* @returns A string showing the provided data and configuration
1211
*/
1312
export const generatePlainOutput: (
14-
info: PlainData,
13+
info: {
14+
data: {
15+
[key: string]: string;
16+
};
17+
timeUpdated: number;
18+
},
1519
chartType: string,
1620
quiet: boolean,
1721
extraRows?: string[]
18-
) => string = ({ data, metainfo }, chartType, quiet, extraRows) => {
22+
) => string = ({ data, timeUpdated }, chartType, quiet, extraRows) => {
1923
// Set line depending if it contains a chart or not
2024
let line = extraRows === undefined ? "-".repeat(60) : "-".repeat(68);
2125
line += "\n";
2226

2327
let header = `${lines.defaultHeader} - ${chartType}`;
24-
let timestamp = getTimestamp(metainfo.updated as number);
28+
let timestamp = getTimestamp(timeUpdated);
2529
let saying = getSaying();
2630

2731
// Generate table

0 commit comments

Comments
 (0)