bulltrackers-module 1.0.673 → 1.0.674
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2049,27 +2049,49 @@ const fetchUserRecommendations = async (db, userId) => {
|
|
|
2049
2049
|
|
|
2050
2050
|
const fetchTrendingPopularInvestors = async (db) => {
|
|
2051
2051
|
// Path: /unified_insights/{DATE}/results/popular-investor/computations/TrendingPopularInvestors
|
|
2052
|
-
//
|
|
2052
|
+
// Data exists in pointer document (small size, not compressed/sharded)
|
|
2053
|
+
// Look back up to 7 days if today's data doesn't exist
|
|
2053
2054
|
const today = new Date().toISOString().split('T')[0];
|
|
2054
|
-
|
|
2055
|
-
const
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2055
|
+
for (let i = 0; i < 7; i++) {
|
|
2056
|
+
const checkDate = new Date(today);
|
|
2057
|
+
checkDate.setDate(checkDate.getDate() - i);
|
|
2058
|
+
const dateKey = checkDate.toISOString().split('T')[0];
|
|
2059
|
+
try {
|
|
2060
|
+
const result = await getComputationResults(db, 'TrendingPopularInvestors', dateKey);
|
|
2061
|
+
if (result && result.trending && Array.isArray(result.trending) && result.trending.length > 0) {
|
|
2062
|
+
return result.trending;
|
|
2063
|
+
}
|
|
2064
|
+
} catch (e) {
|
|
2065
|
+
// Continue to next date
|
|
2066
|
+
if (i === 6) {
|
|
2067
|
+
console.warn(`[Trending] Failed to fetch after 7 day lookback: ${e.message}`);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2060
2070
|
}
|
|
2071
|
+
return [];
|
|
2061
2072
|
};
|
|
2062
2073
|
|
|
2063
2074
|
const fetchPopularInvestorCategories = async (db) => {
|
|
2064
2075
|
// Data exists compressed in pointer document at /unified_insights/{DATE}/results/popular-investor/computations/PopularInvestorCategories
|
|
2076
|
+
// Look back up to 7 days if today's data doesn't exist
|
|
2065
2077
|
const today = new Date().toISOString().split('T')[0];
|
|
2066
|
-
|
|
2067
|
-
const
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2078
|
+
for (let i = 0; i < 7; i++) {
|
|
2079
|
+
const checkDate = new Date(today);
|
|
2080
|
+
checkDate.setDate(checkDate.getDate() - i);
|
|
2081
|
+
const dateKey = checkDate.toISOString().split('T')[0];
|
|
2082
|
+
try {
|
|
2083
|
+
const result = await getComputationResults(db, 'PopularInvestorCategories', dateKey);
|
|
2084
|
+
if (result && result.categories && typeof result.categories === 'object' && Object.keys(result.categories).length > 0) {
|
|
2085
|
+
return result.categories;
|
|
2086
|
+
}
|
|
2087
|
+
} catch (e) {
|
|
2088
|
+
// Continue to next date
|
|
2089
|
+
if (i === 6) {
|
|
2090
|
+
console.warn(`[Categories] Failed to fetch after 7 day lookback: ${e.message}`);
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2072
2093
|
}
|
|
2094
|
+
return {};
|
|
2073
2095
|
};
|
|
2074
2096
|
|
|
2075
2097
|
|
|
@@ -208,89 +208,56 @@ router.get('/computations', async (req, res) => {
|
|
|
208
208
|
// Fetch results for each computation
|
|
209
209
|
const results = {};
|
|
210
210
|
for (const compName of computationNames) {
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
let data = null;
|
|
212
|
+
let foundData = false;
|
|
213
|
+
|
|
214
|
+
// For RecommendedPopularInvestors in latest mode: Look back up to 7 days to find user's data
|
|
215
|
+
if (compName === 'RecommendedPopularInvestors' && mode === 'latest') {
|
|
216
|
+
const userCidStr = String(userId);
|
|
213
217
|
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
|
|
218
|
+
// Look back up to 7 days to find computation that contains this user's data
|
|
219
|
+
// Data structure: { [userId]: recommendations[] }
|
|
220
|
+
for (let i = 0; i < 7; i++) {
|
|
221
|
+
const checkDate = new Date(targetDate);
|
|
222
|
+
checkDate.setDate(checkDate.getDate() - i);
|
|
223
|
+
const dateKey = checkDate.toISOString().split('T')[0];
|
|
219
224
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
// For page mode: data is array of { date, data: {...} }
|
|
227
|
-
else if (Array.isArray(data) && data.length > 0) {
|
|
228
|
-
// Check if any entry has this user's data
|
|
229
|
-
for (const entry of data) {
|
|
230
|
-
if (entry.data && entry.data[userCidStr]) {
|
|
231
|
-
foundUserData = true;
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
225
|
+
try {
|
|
226
|
+
const checkData = await getComputationResults(db, compName, dateKey, userId);
|
|
227
|
+
if (checkData && typeof checkData === 'object' && checkData[userCidStr] && Array.isArray(checkData[userCidStr])) {
|
|
228
|
+
data = checkData;
|
|
229
|
+
foundData = true;
|
|
230
|
+
break;
|
|
235
231
|
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
for (let i = 1; i <= 7; i++) {
|
|
241
|
-
const checkDate = new Date(targetDate);
|
|
242
|
-
checkDate.setDate(checkDate.getDate() - i);
|
|
243
|
-
const dateKey = checkDate.toISOString().split('T')[0];
|
|
244
|
-
|
|
245
|
-
try {
|
|
246
|
-
const backData = await getComputationResults(db, compName, dateKey, userId);
|
|
247
|
-
if (backData && typeof backData === 'object') {
|
|
248
|
-
// Check if this date has the user's data
|
|
249
|
-
if (backData[userCidStr] && Array.isArray(backData[userCidStr])) {
|
|
250
|
-
data = backData;
|
|
251
|
-
foundUserData = true;
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
// For page mode
|
|
255
|
-
else if (Array.isArray(backData) && backData.length > 0) {
|
|
256
|
-
for (const entry of backData) {
|
|
257
|
-
if (entry.data && entry.data[userCidStr]) {
|
|
258
|
-
data = backData;
|
|
259
|
-
foundUserData = true;
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
if (foundUserData) break;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
} catch (e) {
|
|
267
|
-
// Continue to next date
|
|
268
|
-
}
|
|
232
|
+
} catch (e) {
|
|
233
|
+
// Continue to next date
|
|
234
|
+
if (i === 6) {
|
|
235
|
+
console.warn(`[Recommended] Failed to fetch after 7 day lookback: ${e.message}`);
|
|
269
236
|
}
|
|
270
237
|
}
|
|
271
|
-
|
|
272
|
-
// Only return data if it contains this user's recommendations
|
|
273
|
-
if (!foundUserData) {
|
|
274
|
-
results[compName] = null;
|
|
275
|
-
continue;
|
|
276
|
-
}
|
|
277
238
|
}
|
|
278
239
|
|
|
279
|
-
results[compName] = data;
|
|
280
|
-
}
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
240
|
+
results[compName] = foundData ? data : null;
|
|
241
|
+
} else {
|
|
242
|
+
// For other computations: Try today, then look back if latest mode
|
|
243
|
+
try {
|
|
244
|
+
data = await getComputationResults(db, compName, targetDate, userId);
|
|
245
|
+
results[compName] = data;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
// If latest mode and today fails, try yesterday
|
|
248
|
+
if (mode === 'latest') {
|
|
249
|
+
try {
|
|
250
|
+
const yesterday = new Date();
|
|
251
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
252
|
+
const yesterdayStr = yesterday.toISOString().split('T')[0];
|
|
253
|
+
data = await getComputationResults(db, compName, yesterdayStr, userId);
|
|
254
|
+
results[compName] = data;
|
|
255
|
+
} catch (e) {
|
|
256
|
+
results[compName] = null;
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
290
259
|
results[compName] = null;
|
|
291
260
|
}
|
|
292
|
-
} else {
|
|
293
|
-
results[compName] = null;
|
|
294
261
|
}
|
|
295
262
|
}
|
|
296
263
|
}
|