-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add function to download and update data
- Loading branch information
1 parent
540839a
commit 9a9ea4a
Showing
6 changed files
with
116 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export const BASE_URL: string = `https://singapore-ev-trends.ruchern.xyz`; | ||
|
||
export enum FUEL_TYPE { | ||
DIESEL = "Diesel", | ||
ELECTRIC = "Electric", | ||
OTHERS = "Others", | ||
PETROL = "Petrol", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,81 @@ | ||
import { ApiHandler } from "sst/node/api"; | ||
import fs from "fs"; | ||
import fetch from "node-fetch"; | ||
import * as d3 from "d3"; | ||
import AdmZip from "adm-zip"; | ||
import { FUEL_TYPE } from "./config"; | ||
import { sortByMake } from "./lib/sortByMake"; | ||
import type { Car } from "./types"; | ||
|
||
export const handler = ApiHandler(async (_evt) => { | ||
return { | ||
statusCode: 200, | ||
body: `Hello world. The time is ${new Date().toISOString()}`, | ||
}; | ||
const tempDir: string = "/tmp"; | ||
const zipFileName: string = `Monthly New Registration of Cars by Make.zip`; | ||
const zipFilePath: string = `${tempDir}/${zipFileName}`; | ||
const csvFileName: string = `M03-Car_Regn_by_make.csv`; | ||
const csvFilePath: string = `${tempDir}/${csvFileName}`; | ||
const zipUrl: string = `https://datamall.lta.gov.sg/content/dam/datamall/datasets/Facts_Figures/Vehicle Registration/${zipFileName}`; | ||
|
||
try { | ||
const response = await fetch(zipUrl) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error( | ||
`Failed to download the ZIP file: ${response.statusText}`, | ||
); | ||
} | ||
return response.buffer(); | ||
}) | ||
.then((data) => { | ||
fs.writeFileSync(zipFilePath, data); | ||
}) | ||
.catch((error) => | ||
console.error("Error while downloading the ZIP file:", error), | ||
); | ||
|
||
const zip = new AdmZip(zipFilePath); | ||
zip.extractAllTo(`${tempDir}`, true); | ||
|
||
const csvData = fs.readFileSync(csvFilePath, "utf-8"); | ||
|
||
const parsedData = d3.csvParse(csvData); | ||
|
||
const electricCars: Car[] = parsedData | ||
.filter( | ||
({ fuel_type, number }) => | ||
fuel_type === FUEL_TYPE.ELECTRIC && +number !== 0, | ||
) | ||
.reduce((result: Car[], { month, make, fuel_type, number }) => { | ||
const existingCar = result.find( | ||
(car) => car.month === month && car.make === make, | ||
); | ||
|
||
if (existingCar) { | ||
existingCar.number += Number(number); | ||
} else { | ||
result.push({ | ||
month, | ||
make, | ||
fuel_type, | ||
number: Number(number), | ||
}); | ||
} | ||
|
||
return result; | ||
}, []) | ||
.map((car) => ({ ...car, number: +car.number })) | ||
.sort(sortByMake); | ||
|
||
console.table(electricCars); | ||
|
||
return { | ||
statusCode: 200, | ||
body: JSON.stringify(electricCars), | ||
}; | ||
} catch (error) { | ||
console.error(error); | ||
return { | ||
statusCode: 500, | ||
body: "Error occurred while processing the ZIP file.", | ||
}; | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import type { Car } from "../types"; | ||
|
||
export const sortByMake = (a: Pick<Car, "make">, b: Pick<Car, "make">) => | ||
a.make.localeCompare(b.make); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { FUEL_TYPE } from "../config"; | ||
|
||
export interface Car { | ||
month: string; | ||
make: string; | ||
fuel_type: FUEL_TYPE | string; | ||
number: number; | ||
selected?: boolean; | ||
} | ||
|
||
export type Dataset = { | ||
label: string; | ||
data: number[]; | ||
}; | ||
|
||
export interface ChartDataset extends Dataset { | ||
borderColor: string; | ||
checked: boolean; | ||
} |