-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
131 lines (122 loc) · 3.79 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import fs from 'fs';
import path from 'path';
import { number } from '@inquirer/prompts'; // https://nodejs.org/en/learn/command-line/accept-input-from-the-command-line-in-nodejs
const file = path.join(__dirname, 'helpful-reviews.jsonl');
export interface Review {
asin: string;
sentence: string;
helpful: number;
main_image_url: string;
product_title: string;
}
export interface Product {
asin: string;
helpful: number;
title: string;
review: Review[];
}
export interface ProductCatalog {
[key: string]: Product;
}
let productCatalog: ProductCatalog = {};
const parseJSONLFile = async (): Promise<ProductCatalog> => {
return new Promise((resolve, reject) => {
const data = fs.readFileSync(file, { encoding: 'utf8' });
const dataStringToArray = data.split('\n');
const jsonDataArray = dataStringToArray.map((dataString) => {
try {
const review = JSON.parse(dataString);
if (productCatalog[review.asin]) {
productCatalog[review.asin].review.push(review);
} else {
const newProduct: Product = {
asin: review.asin,
helpful: 0,
title: review.product_title,
review: [review],
};
productCatalog[review.asin] = newProduct;
}
} catch (error) {
console.log(`Error Parsing JSON: "${dataString}" \n ERROR: ${error}`);
reject(error);
}
});
for (const productKey in productCatalog) {
const product = productCatalog[productKey];
const reviewCount = product.review.length;
const helpful =
product.review.reduce((acc, review) => {
return acc + review.helpful;
}, 0) / reviewCount;
productCatalog[productKey].helpful = Math.round(helpful * 100) / 100;
}
console.log('Reviews Loaded');
return resolve(productCatalog);
});
};
const searchForReviewsByCount = async (): Promise<void> => {
if (!Object.values(productCatalog).length) {
console.log('Loading Reviews');
productCatalog = await parseJSONLFile();
}
const numberArg: undefined | number = process.argv[2]
? parseInt(process.argv[2])
: undefined;
const answer = Number.isFinite(numberArg)
? numberArg
: await number({
message:
'The Product you are searching for has how many reviews? (type 0 to exit)',
});
try {
console.log(
`answer: ${answer} numberArg: ${numberArg} && ${typeof answer} && length: ${
Object.values(productCatalog).length
}`
);
if (answer === 0) {
console.log('Exiting');
process.exit(0);
} else if (answer === 1) {
await sortByScoreAndReviewCount();
}
if (!Number.isFinite(answer)) {
console.log('Please enter a valid number');
await searchForReviewsByCount();
return;
}
const products = Object.values(productCatalog).filter(
(product) => product.review.length === answer
);
products.forEach((product) => {
console.log(product);
});
if (numberArg) {
process.exit(0);
}
await searchForReviewsByCount();
} catch (error) {
console.log(`Error While searching for ${answer} review count:`, error);
}
};
const sortByScoreAndReviewCount = async (): Promise<void> => {
productCatalog = await parseJSONLFile();
const productCatalogArray = Object.values(productCatalog);
const sortedProductCatalogArray = productCatalogArray.sort((a, b) => {
if (a.helpful === b.helpful) {
return b.review.length - a.review.length;
}
return b.helpful - a.helpful;
});
const productTable = sortedProductCatalogArray.map((product) => {
return {
asin: product.asin,
title: product.title.slice(0, 50),
helpful: product.helpful,
reviewCount: product.review.length,
};
});
console.table(productTable);
};
searchForReviewsByCount();