mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-08 10:16:56 +02:00
Add data aggregation command
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -23,4 +23,5 @@ pnpm-debug.log*
|
|||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
tests-examples
|
tests-examples
|
||||||
|
*.csv
|
129
bin/page-data-agg.cjs
Normal file
129
bin/page-data-agg.cjs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
const csv = require('csv-parser');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const csvFilePath = path.join(__dirname, '../data.csv');
|
||||||
|
|
||||||
|
const results = {};
|
||||||
|
const pageSummary = {};
|
||||||
|
|
||||||
|
fs.createReadStream(csvFilePath)
|
||||||
|
.pipe(
|
||||||
|
csv({
|
||||||
|
separator: ',',
|
||||||
|
mapHeaders: ({ header, index }) =>
|
||||||
|
header.toLowerCase().replace(/ /g, '_'),
|
||||||
|
mapValues: ({ header, index, value }) => {
|
||||||
|
if (header === 'page') {
|
||||||
|
return (
|
||||||
|
value
|
||||||
|
.replace(/"/g, '')
|
||||||
|
.replace(/'/g, '')
|
||||||
|
.replace(/`/g, '')
|
||||||
|
.replace(/\?r=/g, '#r#')
|
||||||
|
.replace(/\?.+?$/g, '')
|
||||||
|
.replace(/#r#/g, '?r=')
|
||||||
|
.replace(/\/$/g, '') || '/'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header !== 'month_of_year') {
|
||||||
|
return parseInt(value, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.on('data', (data) => {
|
||||||
|
const { page, month_of_year, unique_pageviews, users } = data;
|
||||||
|
const pageData = results[page] || {};
|
||||||
|
const existingPageMonthData = pageData[month_of_year] || {};
|
||||||
|
|
||||||
|
const existingViews = existingPageMonthData.views || 0;
|
||||||
|
const existingUsers = existingPageMonthData.users || 0;
|
||||||
|
|
||||||
|
const newViews = existingViews + unique_pageviews;
|
||||||
|
const newUsers = existingUsers + users;
|
||||||
|
|
||||||
|
pageData[month_of_year] = {
|
||||||
|
views: newViews,
|
||||||
|
users: newUsers,
|
||||||
|
};
|
||||||
|
|
||||||
|
results[page] = pageData;
|
||||||
|
|
||||||
|
pageSummary[page] = pageSummary[page] || { views: 0, users: 0 };
|
||||||
|
pageSummary[page].views += unique_pageviews;
|
||||||
|
pageSummary[page].users += users;
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
const csvHeader = [
|
||||||
|
'Page',
|
||||||
|
'Jan 2022',
|
||||||
|
'Feb 2022',
|
||||||
|
'Mar 2022',
|
||||||
|
'Apr 2022',
|
||||||
|
'May 2022',
|
||||||
|
'Jun 2022',
|
||||||
|
'Jul 2022',
|
||||||
|
'Aug 2022',
|
||||||
|
'Sep 2022',
|
||||||
|
'Oct 2022',
|
||||||
|
'Nov 2022',
|
||||||
|
'Dec 2022',
|
||||||
|
'Jan 2023',
|
||||||
|
'Feb 2023',
|
||||||
|
'Mar 2023',
|
||||||
|
'Apr 2023',
|
||||||
|
'May 2023',
|
||||||
|
'Jun 2023',
|
||||||
|
'Jul 2023',
|
||||||
|
'Aug 2023',
|
||||||
|
'Sep 2023',
|
||||||
|
'Oct 2023',
|
||||||
|
'Nov 2023',
|
||||||
|
'Dec 2023',
|
||||||
|
];
|
||||||
|
|
||||||
|
const csvRows = Object.keys(pageSummary)
|
||||||
|
.filter(pageUrl => pageSummary[pageUrl].views > 10)
|
||||||
|
.filter(pageUrl => !['/upcoming', '/pdfs', '/signup', '/login', '/@'].includes(pageUrl))
|
||||||
|
.sort((pageA, pageB) => {
|
||||||
|
const aViews = pageSummary[pageA].views;
|
||||||
|
const bViews = pageSummary[pageB].views;
|
||||||
|
|
||||||
|
return bViews - aViews;
|
||||||
|
})
|
||||||
|
.map((pageUrl) => {
|
||||||
|
const rawPageResult = results[pageUrl];
|
||||||
|
const pageResultCsvRow = [];
|
||||||
|
|
||||||
|
csvHeader.forEach((csvHeaderItem) => {
|
||||||
|
if (csvHeaderItem === 'Page') {
|
||||||
|
pageResultCsvRow.push(pageUrl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const csvHeaderItemAlt = csvHeaderItem
|
||||||
|
.replace(/ /g, '_')
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
const result = rawPageResult[csvHeaderItem || csvHeaderItemAlt] || {};
|
||||||
|
const views = result.views || 0;
|
||||||
|
const users = result.users || 0;
|
||||||
|
|
||||||
|
pageResultCsvRow.push(users);
|
||||||
|
});
|
||||||
|
|
||||||
|
return pageResultCsvRow;
|
||||||
|
});
|
||||||
|
|
||||||
|
const finalCsvRows = [csvHeader, ...csvRows];
|
||||||
|
const csvRowStrings = finalCsvRows.map((row) => {
|
||||||
|
return row.join(',');
|
||||||
|
});
|
||||||
|
|
||||||
|
const csvString = csvRowStrings.join('\n');
|
||||||
|
fs.writeFileSync(path.join(__dirname, '../data-agg.csv'), csvString);
|
||||||
|
});
|
@@ -41,6 +41,7 @@
|
|||||||
"@playwright/test": "^1.32.3",
|
"@playwright/test": "^1.32.3",
|
||||||
"@tailwindcss/typography": "^0.5.9",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"@types/js-cookie": "^3.0.3",
|
"@types/js-cookie": "^3.0.3",
|
||||||
|
"csv-parser": "^3.0.0",
|
||||||
"gh-pages": "^5.0.0",
|
"gh-pages": "^5.0.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
|
11
pnpm-lock.yaml
generated
11
pnpm-lock.yaml
generated
@@ -11,6 +11,7 @@ specifiers:
|
|||||||
'@types/js-cookie': ^3.0.3
|
'@types/js-cookie': ^3.0.3
|
||||||
astro: ^2.2.3
|
astro: ^2.2.3
|
||||||
astro-compress: ^1.1.35
|
astro-compress: ^1.1.35
|
||||||
|
csv-parser: ^3.0.0
|
||||||
gh-pages: ^5.0.0
|
gh-pages: ^5.0.0
|
||||||
jose: ^4.13.2
|
jose: ^4.13.2
|
||||||
js-cookie: ^3.0.1
|
js-cookie: ^3.0.1
|
||||||
@@ -50,6 +51,7 @@ devDependencies:
|
|||||||
'@playwright/test': 1.32.3
|
'@playwright/test': 1.32.3
|
||||||
'@tailwindcss/typography': 0.5.9_tailwindcss@3.3.1
|
'@tailwindcss/typography': 0.5.9_tailwindcss@3.3.1
|
||||||
'@types/js-cookie': 3.0.3
|
'@types/js-cookie': 3.0.3
|
||||||
|
csv-parser: 3.0.0
|
||||||
gh-pages: 5.0.0
|
gh-pages: 5.0.0
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
markdown-it: 13.0.1
|
markdown-it: 13.0.1
|
||||||
@@ -1787,6 +1789,14 @@ packages:
|
|||||||
css-tree: 2.2.1
|
css-tree: 2.2.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/csv-parser/3.0.0:
|
||||||
|
resolution: {integrity: sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
minimist: 1.2.8
|
||||||
|
dev: true
|
||||||
|
|
||||||
/debug/4.3.4:
|
/debug/4.3.4:
|
||||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
@@ -3605,7 +3615,6 @@ packages:
|
|||||||
|
|
||||||
/minimist/1.2.8:
|
/minimist/1.2.8:
|
||||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/minipass-collect/1.0.2:
|
/minipass-collect/1.0.2:
|
||||||
resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
|
resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==}
|
||||||
|
Reference in New Issue
Block a user