From cc95bb195b427e6ece0a6ffddde273d9acd4b262 Mon Sep 17 00:00:00 2001 From: wancat Date: Mon, 9 Oct 2023 10:47:44 +0800 Subject: [PATCH] feat: add usercount, session count and complete rate --- packages/analytics/README.md | 59 +++++++++++++++++++++ packages/analytics/src/controllers/index.js | 15 ++++++ packages/analytics/src/index.js | 5 +- packages/analytics/src/models/quests.js | 24 +++++++++ packages/analytics/src/models/users.js | 6 +++ packages/analytics/views/home.handlebars | 23 +++++++- server/src/containers/expiryChecker.js | 4 +- 7 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 packages/analytics/README.md create mode 100644 packages/analytics/src/controllers/index.js create mode 100644 packages/analytics/src/models/quests.js create mode 100644 packages/analytics/src/models/users.js diff --git a/packages/analytics/README.md b/packages/analytics/README.md new file mode 100644 index 0000000..01371e4 --- /dev/null +++ b/packages/analytics/README.md @@ -0,0 +1,59 @@ +# Analytics + +## Information provided + +### 1. **Dashboard Overview**: + +- **Total Users**: Display the total number of registered users. +- **Active Users**: Count of users who've been active in the past day, week, or month. +- **Completed Quests**: Total quests or challenges completed by all users. +- **Average Time Usage**: Average time a user spends on the platform or on challenges. + +### 2. **User Analytics**: + +- **User Growth**: A graph showing user registrations over time (daily, weekly, monthly). +- **Retention Rate**: Percentage of users who return after their first visit. +- **User Segmentation**: Group users based on criteria like their progress level, frequency of usage, or other custom metrics. + +### 3. **Quest/Challenge Analytics**: + +- **Quest Popularity**: Rank quests by the number of completions or engagements. +- **Average Completion Time**: The average time taken by users to complete each quest. +- **Drop-Off Points**: Identify quests where users abandon or fail frequently. + +### 4. **Error Analysis**: + +- **Common Errors**: List frequently mistyped or erroneous commands. +- **Quest-specific Errors**: Identify challenges where users make the most mistakes. + +### 5. **Feedback & Survey Results**: + +- **Feedback Overview**: Display recent feedback or suggestions. +- **Survey Analysis**: If you've integrated a survey, show aggregated results or key insights. + +### 6. **System Health & Usage**: + +- **Server Load**: Monitor server performance metrics like CPU usage, memory usage, etc. +- **Error Logs**: View any system errors, glitches, or issues. + +### 7. **User Details**: + +- **Search & View**: Ability to search for specific users and view their profile, progress, and activity logs. +- **User Behavior**: For selected users, see a detailed path of their activity, including the quests they've engaged with, time spent, errors made, etc. + +### 8. **Notifications & Alerts**: + +- **System Alerts**: Notifications about server downtimes, high error rates, or other critical issues. +- **User Activity Alerts**: Set alerts for specific user activities, e.g., when a user completes all challenges. + +### 9. **Engagement Metrics**: + +- **Daily Active Users**: Users who engage with the platform daily. +- **Top Users**: Identify power users or those with high engagement rates. + +### 10. **Export & Reports**: + +- **Data Export**: Option to export user data, analytics, or other metrics. +- **Generate Reports**: Create detailed reports based on selected metrics, useful for team meetings or strategy planning. + +When designing this admin dashboard, focus on clarity and ease of use. Utilize visual aids like graphs, charts, and heatmaps to make data interpretation straightforward. Since your backend is built with NodeJS and ExpressJS and you use MongoDB for data storage, you can utilize various NPM packages to aid in data visualization and dashboard creation. Ensure the dashboard is secure and accessible only to authorized personnel. diff --git a/packages/analytics/src/controllers/index.js b/packages/analytics/src/controllers/index.js new file mode 100644 index 0000000..283a03b --- /dev/null +++ b/packages/analytics/src/controllers/index.js @@ -0,0 +1,15 @@ +import { userCount } from '../models/users.js' +import { sessionCount, sessionCompleted } from '../models/quests.js' + +// eslint-disable-next-line import/prefer-default-export +export async function homeController(req, res) { + const payload = { + title: 'Linux Odyssey Admin', + userCount: await userCount(), + sessionCount: await sessionCount(), + sessionCompleted: await sessionCompleted(), + } + payload.completedRate = + Math.round((payload.sessionCompleted / payload.sessionCount) * 10000) / 100 + res.render('home', payload) +} diff --git a/packages/analytics/src/index.js b/packages/analytics/src/index.js index e2b9360..3e4a4cb 100644 --- a/packages/analytics/src/index.js +++ b/packages/analytics/src/index.js @@ -2,6 +2,7 @@ import connectDB from '@linux-odyssey/models' import express from 'express' import { engine } from 'express-handlebars' import config from './config.js' +import { homeController } from './controllers/index.js' async function main() { await connectDB(config.db) @@ -12,9 +13,7 @@ async function main() { app.set('view engine', 'handlebars') app.set('views', './views') - app.get('/', (req, res) => { - res.render('home', { title: 'Linux Odyssey Admin' }) - }) + app.get('/', homeController) app.listen(3001, () => { console.log('Server started on http://localhost:3001') diff --git a/packages/analytics/src/models/quests.js b/packages/analytics/src/models/quests.js new file mode 100644 index 0000000..7a0a3b3 --- /dev/null +++ b/packages/analytics/src/models/quests.js @@ -0,0 +1,24 @@ +import { Session } from '@linux-odyssey/models' + +export function sessionCount() { + return Session.find().count() +} + +export function sessionCompleted() { + return Session.find({ status: 'finished' }).count() +} + +export function averageTimeUsage() { + return Session.aggregate([ + { + $group: { + _id: '$quest', + average: { + $avg: { + $subtract: ['$finishedAt', '$createdAt'], + }, + }, + }, + }, + ]) +} diff --git a/packages/analytics/src/models/users.js b/packages/analytics/src/models/users.js new file mode 100644 index 0000000..4862af2 --- /dev/null +++ b/packages/analytics/src/models/users.js @@ -0,0 +1,6 @@ +import { User } from '@linux-odyssey/models' + +// eslint-disable-next-line import/prefer-default-export +export function userCount() { + return User.find().count() +} diff --git a/packages/analytics/views/home.handlebars b/packages/analytics/views/home.handlebars index 35a5107..5d8ce3e 100644 --- a/packages/analytics/views/home.handlebars +++ b/packages/analytics/views/home.handlebars @@ -1,2 +1,23 @@

Welcome to {{title}}

-

This is the content of the homepage.

\ No newline at end of file +

This is the content of the homepage.

+
+

Users

+ + + + + + + + + + + + + + + + + +
Registered Users{{userCount}}
Session Count{{sessionCount}}
Completed Session{{sessionCompleted}}
Completed Rate{{completedRate}}%
+
\ No newline at end of file diff --git a/server/src/containers/expiryChecker.js b/server/src/containers/expiryChecker.js index 41699cc..3ecc30c 100644 --- a/server/src/containers/expiryChecker.js +++ b/server/src/containers/expiryChecker.js @@ -16,7 +16,9 @@ export async function removeExpired() { sessions.map(async (session) => { console.log('Expiring session: ', session._id, session.containerId) await deleteContainer(session.containerId) - session.status = 'inactive' + if (session.status === 'active') { + session.status = 'inactive' + } session.containerId = null await session.save() })