Serien, Abzeichen und Ranglisten für Ihre Fitness-App
Backend-Tutorial zur Gamification: Entwerfen Sie Datenbankschemas und bauen Sie robuste Node.js-APIs für Serien, Abzeichen und Ranglisten mit PostgreSQL.
Auf dieser Seite
In der wettbewerbsintensiven Welt der Fitness-Apps ist die Nutzerbindung das A und O. Wie halten Sie Nutzer motiviert und sorgen dafür, dass sie Tag für Tag zurückkehren? Gamification ist eine wirkungsvolle Antwort. Durch die Integration spielähnlicher Mechaniken wie täglicher Serien, Erfolgsabzeichen und wettbewerbsorientierter Bestenlisten können Sie einen routinemäßigen Fitness-Tracker in ein spannendes und fesselndes Erlebnis verwandeln.
Dieses Tutorial führt Sie durch die Backend-Implementierung dieser zentralen Gamification-Funktionen. Wir entwerfen ein robustes PostgreSQL-Datenbankschema und erstellen die erforderlichen Node.js-API-Endpunkte, um Ihre Fitness-App zum Leben zu erwecken.
Voraussetzungen:
- Grundlegendes Verständnis von Node.js und Express.
- Vertrautheit mit PostgreSQL und den Grundlagen von SQL.
- Node.js und PostgreSQL auf Ihrem System installiert.
Das Problem verstehen
Die Implementierung von Gamification-Funktionen bringt einige interessante Herausforderungen im Backend mit sich. Wir müssen die Nutzeraktivität über die Zeit effizient erfassen, aufeinanderfolgende Tages-Serien berechnen, Abzeichen für bestimmte Erfolge vergeben und Nutzer in einer Bestenliste einordnen. Entscheidend ist, dies skalierbar umzusetzen, ohne die Anwendung bei wachsender Nutzerbasis auszubremsen.
Dieses Tutorial begegnet diesen Herausforderungen, indem es die leistungsstarken Abfragefunktionen von PostgreSQL nutzt, insbesondere Fensterfunktionen, um diese Berechnungen direkt in der Datenbank auszuführen und die Verarbeitungslast unserer Node.js-Anwendung zu minimieren.
Voraussetzungen
Bevor wir beginnen, stellen Sie sicher, dass Node.js, npm und PostgreSQL installiert sind.
Erstellen Sie ein neues Projektverzeichnis und initialisieren Sie ein Node.js-Projekt:
mkdir fitness-gamification-backend
cd fitness-gamification-backend
npm init -y
npm install express pg
Dadurch werden eine package.json-Datei erstellt und die erforderlichen Abhängigkeiten installiert: express für unseren Webserver und pg als PostgreSQL-Client für Node.js.
Entwurf des Datenbankschemas
Entwerfen wir zunächst das Datenbankschema zur Unterstützung unserer Gamification-Funktionen. Wir benötigen Tabellen für Nutzer, ihre täglichen Trainingsaktivitäten, die erworbenen Abzeichen sowie die Definitionen der verfügbaren Abzeichen.
Hier ist das SQL zum Erstellen unserer Tabellen:
-- users table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- workout_activities table to track daily user activity
CREATE TABLE workout_activities (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
activity_date DATE NOT NULL,
calories_burned INTEGER,
UNIQUE(user_id, activity_date)
);
-- badges table to define available badges
CREATE TABLE badges (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
criteria_value INTEGER
);
-- user_badges table to track earned badges
CREATE TABLE user_badges (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
badge_id INTEGER REFERENCES badges(id),
earned_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, badge_id)
);
Schritt 1: Trainingsserien implementieren
Eine Trainingsserie ist die Anzahl aufeinanderfolgender Tage, an denen ein Nutzer ein Training absolviert hat. Wir erstellen einen API-Endpunkt, der die aktuelle Serie eines Nutzers berechnet.
Was wir tun
Wir schreiben eine PostgreSQL-Abfrage, die Fensterfunktionen verwendet, um aufeinanderfolgende Daten in der Tabelle workout_activities zu erkennen. Das ist effizienter, als alle Aktivitäten eines Nutzers abzurufen und in der Anwendung zu verarbeiten.
Implementierung
Erstellen Sie eine Datei db.js, um Datenbankverbindungen und Abfragen zu verwalten.
// db.js
const { Pool } = require('pg');
const pool = new Pool({
user: 'your_db_user',
host: 'localhost',
database: 'your_db_name',
password: 'your_db_password',
port: 5432,
});
module.exports = {
query: (text, params) => pool.query(text, params),
};
Erstellen Sie nun streaks.js, um den API-Endpunkt zu definieren.
// streaks.js
const db = require('./db');
async function getUserStreak(userId) {
const query = `
WITH date_diffs AS (
SELECT
activity_date,
activity_date - ROW_NUMBER() OVER (ORDER BY activity_date) * INTERVAL '1 day' as date_group
FROM workout_activities
WHERE user_id = $1
ORDER BY activity_date DESC
)
SELECT
COUNT(*) AS streak
FROM date_diffs
WHERE date_group = (SELECT date_group FROM date_diffs LIMIT 1);
`;
const { rows } = await db.query(query, [userId]);
return rows[0] ? parseInt(rows[0].streak, 10) : 0;
}
module.exports = { getUserStreak };
Erstellen Sie abschließend Ihre Hauptserverdatei index.js.
// index.js
const express = require('express');
const { getUserStreak } = require('./streaks');
const app = express();
const port = 3000;
app.get('/users/:userId/streak', async (req, res) => {
try {
const streak = await getUserStreak(req.params.userId);
res.json({ streak });
} catch (err) {
console.error(err);
res.status(500).send('Server Error');
}
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
So funktioniert es
Die Magie liegt in der PostgreSQL-Abfrage. Indem wir die Zeilennummer (als Anzahl von Tagen) vom activity_date subtrahieren, können wir eine date_group erzeugen. Aufeinanderfolgende Daten haben dieselbe date_group. Anschließend zählen wir die Anzahl der Zeilen in der jüngsten date_group, um die aktuelle Serie zu erhalten.
Schritt 2: Abzeichen vergeben
Abzeichen werden für das Erreichen bestimmter Meilensteine vergeben, zum Beispiel für das Verbrennen von insgesamt 10.000 Kalorien.
Was wir tun
Wir erstellen eine Funktion, die den Fortschritt eines Nutzers in Richtung eines Abzeichens prüft und es vergibt, wenn die Kriterien erfüllt sind.
Implementierung
Fügen wir zunächst einige Abzeichendefinitionen in unsere Tabelle badges ein.
INSERT INTO badges (name, description, criteria_value) VALUES
('Calorie Crusher 10k', 'Burn a total of 10,000 calories', 10000);
Erstellen wir nun badges.js.
// badges.js
const db = require('./db');
async function checkAndAwardBadges(userId) {
const { rows: badges } = await db.query('SELECT * FROM badges');
const { rows: userBadges } = await db.query('SELECT badge_id FROM user_badges WHERE user_id = $1', [userId]);
const earnedBadgeIds = userBadges.map(b => b.badge_id);
for (const badge of badges) {
if (earnedBadgeIds.includes(badge.id)) continue;
if (badge.name === 'Calorie Crusher 10k') {
const { rows } = await db.query(
'SELECT SUM(calories_burned) as total_calories FROM workout_activities WHERE user_id = $1',
[userId]
);
const totalCalories = parseInt(rows[0].total_calories, 10) || 0;
if (totalCalories >= badge.criteria_value) {
await db.query('INSERT INTO user_badges (user_id, badge_id) VALUES ($1, $2)', [userId, badge.id]);
console.log(`Awarded badge "${badge.name}" to user ${userId}`);
}
}
}
}
module.exports = { checkAndAwardBadges };
Wir können checkAndAwardBadges aufrufen, nachdem ein Nutzer ein neues Training protokolliert hat.
Schritt 3: Eine Bestenliste erstellen
Eine Bestenliste ordnet Nutzer anhand einer bestimmten Kennzahl, etwa der insgesamt verbrannten Kalorien.
Was wir tun
Wir verwenden die Fensterfunktion RANK() von PostgreSQL, um effizient eine Bestenliste zu erzeugen.
Implementierung
Erstellen wir leaderboard.js.
// leaderboard.js
const db = require('./db');
async function getLeaderboard() {
const query = `
SELECT
u.username,
SUM(wa.calories_burned) as total_calories,
RANK() OVER (ORDER BY SUM(wa.calories_burned) DESC) as rank
FROM users u
JOIN workout_activities wa ON u.id = wa.user_id
GROUP BY u.id
ORDER BY rank;
`;
const { rows } = await db.query(query);
return rows;
}
module.exports = { getLeaderboard };
Und fügen Sie den Endpunkt zu index.js hinzu.
// index.js (add this to your existing file)
const { getLeaderboard } = require('./leaderboard');
app.get('/leaderboard', async (req, res) => {
try {
const leaderboard = await getLeaderboard();
res.json(leaderboard);
} catch (err) {
console.error(err);
res.status(500).send('Server Error');
}
});
So funktioniert es
Die Funktion RANK() weist jedem Nutzer einen Rang auf Grundlage der Summe seiner calories_burned zu. Die Klausel OVER (ORDER BY ...) legt fest, wie die Zeilen vor der Rangvergabe sortiert werden.
Alles zusammenfügen
Sie verfügen nun über die zentrale Backend-Logik für Serien, Abzeichen und Bestenlisten. Sie können darauf aufbauen, indem Sie komplexere Abzeichenkriterien, verschiedene Arten von Bestenlisten (z. B. wöchentlich, monatlich) und mehr hinzufügen.
Überlegungen zur Leistung
- Indizierung: Stellen Sie bei größeren Tabellen sicher, dass Sie Indizes auf Fremdschlüsseln (
user_id,badge_id) und häufig abgefragten Spalten (activity_date) haben. - Abfrageoptimierung: Verwenden Sie
EXPLAIN ANALYZE, um die Leistung Ihrer Abfragen zu prüfen und Engpässe zu erkennen. - Materialisierte Sichten: Erwägen Sie bei sehr großen Bestenlisten, die nicht in Echtzeit vorliegen müssen, materialisierte Sichten, um Ranglisten vorab zu berechnen.
Fazit
Durch die Integration von Serien, Abzeichen und Bestenlisten können Sie Motivation und Bindung der Nutzer in Ihrer Fitness-App deutlich steigern. Mit Node.js und den leistungsstarken Funktionen von PostgreSQL können Sie ein skalierbares und effizientes Backend aufbauen, das diese ansprechenden Gamification-Elemente unterstützt.
Nun sind Sie an der Reihe, auf diesem Fundament aufzubauen. Welche weiteren Gamification-Funktionen können Sie sich ausdenken?
Ressourcen
Kurzreferenz
| Aspekt | Wesentliche Information |
|---|---|
| Thema | Entwicklung |
| Relevanz | Patientenaufklärung und Bewusstsein |
| Maßnahme | Besprechen Sie dies mit Ihrer Ärztin oder Ihrem Arzt |
| Häufigkeit | Wie von Ihrem Behandlungsteam empfohlen |
| Evidenz | Basierend auf aktuellen klinischen Leitlinien |
Häufig gestellte Fragen
F: Woran erkenne ich, ob dies auf mich zutrifft? A: Besprechen Sie Ihre persönliche und familiäre Krankengeschichte mit Ihrer Ärztin oder Ihrem Arzt, um Ihre individuellen Risikofaktoren einzuschätzen und die geeigneten nächsten Schritte festzulegen.
F: Was sollte ich meine Ärztin oder meinen Arzt fragen? A: Gute Fragen sind: „Was bedeuten meine Ergebnisse?“, „Welche Möglichkeiten habe ich?“, „Welche Änderungen des Lebensstils würden helfen?“ und „Wann sollte ich zur Nachsorge kommen?“
F: Gibt es Änderungen des Lebensstils, die helfen können? A: Die meisten Gesundheitszustände profitieren von grundlegenden Maßnahmen: ausgewogene Ernährung, regelmäßige körperliche Aktivität (150+ Minuten/Woche), guter Schlaf (7–9 Stunden), Stressbewältigung und der Verzicht auf Tabak.
Medizinischer Haftungsausschluss
Dieser Artikel dient ausschließlich Bildungszwecken und stellt keine medizinische Beratung dar. Konsultieren Sie stets eine qualifizierte medizinische Fachperson, bevor Sie Entscheidungen über Ihre Gesundheit, Behandlung oder Versorgung treffen. Die individuellen Umstände unterscheiden sich, und was für eine Person angemessen ist, muss für eine andere nicht angemessen sein.
Wenn Sie einen medizinischen Notfall erleben, rufen Sie sofort 911 (oder Ihre örtliche Notrufnummer) an.