Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dreancaste/TriviaPP/llms.txt

Use this file to discover all available pages before exploring further.

StorageService is the sole abstraction over browser localStorage in TriviaPP. It serialises and deserialises four independent data domains — player profile, game history, a local leaderboard, and cumulative statistics — each under its own namespaced key. All reads return sensible defaults when data is absent, so callers never need to guard against null. The local ranking additionally features an automatic 24-hour reset: a timestamp stored in sw_ranking_reset_time is checked on every ranking read or write, and if 24 hours have elapsed, the ranking is wiped so the daily leaderboard stays fresh.

Constructor / Dependencies

StorageService is provided in the root injector and has no constructor dependencies.
@Injectable({ providedIn: 'root' })
export class StorageService {}

Storage Keys

KeyData typeDescription
sw_profileProfilePlayer display name, avatar, and haptic preference
sw_historyHistoryItem[]Ordered list of past game sessions (most recent first)
sw_rankingRankingItem[]Local leaderboard, capped at 20 entries, sorted by score descending
sw_stats{ gamesPlayed, correctAnswers, maxScore }Cumulative lifetime statistics
sw_ranking_reset_timenumber (epoch ms)Unix timestamp of the last ranking reset; used to gate 24-hour resets

Models

// profile.model.ts
export interface Profile {
  displayName: string;
  avatar: string;
  vibrateOnError: boolean;
}

// history-item.model.ts
export interface HistoryItem {
  date: string;           // ISO date string
  score: number;
  correctAnswers: number;
  totalQuestions: number;
}

// ranking-item.model.ts
export interface RankingItem {
  name: string;
  score: number;
  date?: string;          // Optional ISO date string
}

Methods — Profile

saveProfile()

Serialises the given Profile object to localStorage under the sw_profile key.
saveProfile(profile: Profile): void
profile
Profile
required
The full profile object to persist. All three fields (displayName, avatar, vibrateOnError) should be present.

getProfile()

Reads and deserialises the stored profile. Returns a default profile object when no data is found.
getProfile(): Profile
Default value when key is absent:
{ displayName: '', avatar: '', vibrateOnError: true }

Methods — History

addHistory()

Prepends a new HistoryItem to the stored history array, keeping the most recent session at index 0.
addHistory(item: HistoryItem): void
item
HistoryItem
required
The completed game session record to add.

getHistory()

Returns the full history array. Returns an empty array [] if no history has been recorded yet.
getHistory(): HistoryItem[]

saveHistory()

Persists a complete, pre-built history array to localStorage, overwriting any existing data. Prefer addHistory() for appending individual records.
saveHistory(history: HistoryItem[]): void
history
HistoryItem[]
required
The full history array to store.

Methods — Local Ranking

addRankingItem()

Adds or updates an entry in the local leaderboard, applying merge-by-name, sorting, and a 20-entry cap.
addRankingItem(item: RankingItem): void
item
RankingItem
required
The ranking entry to add. name is used as the identity key (case-insensitive, trimmed).
Merge logic (in order):
  1. Calls checkAndResetRanking() — wipes the board if 24 hours have passed.
  2. Searches the existing ranking for an entry whose name matches item.name (case-insensitive).
  3. If a match is found, replaces it only if the new score is higher than the stored score.
  4. If no match is found, appends the new item.
  5. Sorts the resulting array by score descending.
  6. Caps the board at the top 20 entries.

getRanking()

Returns the current local leaderboard, checking for a 24-hour reset before reading.
getRanking(): RankingItem[]
Returns [] if the ranking is empty or has just been reset. The array is pre-sorted by score descending.

saveRanking()

Overwrites the stored ranking array. Prefer addRankingItem() for individual updates.
saveRanking(ranking: RankingItem[]): void
ranking
RankingItem[]
required
The full ranking array to store.

clearRanking()

Removes the sw_ranking key from localStorage, effectively resetting the local leaderboard to empty.
clearRanking(): void
clearRanking() does not update sw_ranking_reset_time. Use it for explicit manual resets (e.g., a “Clear leaderboard” button). The automatic 24-hour reset is handled internally by checkAndResetRanking().

Methods — Stats

updateStats()

Increments gamesPlayed and correctAnswers, and updates maxScore if the new score is a personal best. All updates are applied atomically to the stored stats object.
updateStats(score: number, correctCount: number): void
score
number
required
The total score achieved in the completed session.
correctCount
number
required
The number of questions answered correctly in the completed session.

getStats()

Returns the cumulative stats object. Returns zeroed defaults when no data is stored.
getStats(): { gamesPlayed: number; correctAnswers: number; maxScore: number }
Default value when key is absent:
{ gamesPlayed: 0, correctAnswers: 0, maxScore: 0 }

saveStats()

Persists a complete stats object to localStorage, overwriting any existing data. Prefer updateStats() for post-game recording.
saveStats(stats: any): void
stats
any
required
The stats object to store. Should include gamesPlayed, correctAnswers, and maxScore.

Usage Example

import { StorageService } from './services/storage.service';
import { HistoryItem } from './models/history-item.model';
import { RankingItem } from './models/ranking-item.model';

@Injectable({ providedIn: 'root' })
export class GameEndService {
  constructor(private storage: StorageService) {}

  saveGameResult(score: number, correct: number, total: number) {
    const profile = this.storage.getProfile();

    // 1. Record the completed session in history
    const historyEntry: HistoryItem = {
      date: new Date().toISOString(),
      score,
      correctAnswers: correct,
      totalQuestions: total,
    };
    this.storage.addHistory(historyEntry);

    // 2. Update the local leaderboard
    const rankingEntry: RankingItem = {
      name: profile.displayName || 'Anónimo',
      score,
    };
    this.storage.addRankingItem(rankingEntry);

    // 3. Accumulate lifetime stats
    this.storage.updateStats(score, correct);

    // 4. Read back stats for the results screen
    const stats = this.storage.getStats();
    console.log('Personal best:', stats.maxScore);
    console.log('Games played:', stats.gamesPlayed);
  }
}

Build docs developers (and LLMs) love