training-academy/docs/training-game-redesign/PHASE-6.md

18 KiB

Phase 6: Stats/Achievements/Library Systems

Priority: MEDIUM - Cross-cutting systems for engagement
Estimated Effort: 14-18 hours
Status: Not Started
Dependencies: Phase 1 (for library foundation), can run parallel with Phase 2-5


🎯 Phase Goals

Implement comprehensive statistics tracking, achievement system, and advanced library management. These cross-cutting systems enhance engagement throughout the entire campaign and provide depth for post-graduation content.


📋 What This Phase Delivers

Core Systems:

  1. Statistics Dashboard - Track all Academy metrics
  2. Achievement System - 25+ achievements with unlock notifications
  3. Advanced Library Management - Quality scoring, diversity scoring, smart playlists
  4. Curator Rank Progression - Novice → Master with benefits
  5. Stats Visualization - Charts, graphs, progress bars
  6. Export/Import - Save/load library data, share achievements

End Result: Rich meta-game layer that rewards progress and curation.


🏗️ Implementation Tasks

Task 1: Achievement System (5-6 hours)

File to Create: src/features/academy/progressionManager.js

Responsibilities:

  • Define all achievements
  • Track achievement progress
  • Unlock achievements
  • Display achievement notifications
  • Achievement showcase

Achievement Definitions:

const achievements = [
  // Progression Achievements
  {
    id: 'first_level',
    name: 'First Steps',
    description: 'Complete Level 1',
    icon: '🎓',
    category: 'progression',
    condition: (stats) => stats.completedLevels.includes(1),
    reward: null
  },
  {
    id: 'foundation_complete',
    name: 'Foundation Graduate',
    description: 'Complete the Foundation Arc (L1-5)',
    icon: '🏛️',
    category: 'progression',
    condition: (stats) => stats.completedLevels.length >= 5,
    reward: null
  },
  {
    id: 'halfway',
    name: 'Halfway There',
    description: 'Complete 15 levels',
    icon: '🔥',
    category: 'progression',
    condition: (stats) => stats.completedLevels.length >= 15,
    reward: null
  },
  {
    id: 'all_30',
    name: 'Academy Graduate',
    description: 'Complete all 30 levels',
    icon: '🎓',
    category: 'progression',
    condition: (stats) => stats.graduationCompleted,
    reward: 'Certificate of Completion'
  },
  
  // Edging Achievements
  {
    id: 'edge_100',
    name: 'Century Club',
    description: 'Edge 100 times total',
    icon: '💯',
    category: 'edging',
    condition: (stats) => stats.totalEdges >= 100,
    reward: null
  },
  {
    id: 'edge_500',
    name: 'Edge Master',
    description: 'Edge 500 times total',
    icon: '🔥',
    category: 'edging',
    condition: (stats) => stats.totalEdges >= 500,
    reward: null
  },
  {
    id: 'edge_1000',
    name: 'Edge Legend',
    description: 'Edge 1000 times total',
    icon: '⭐',
    category: 'edging',
    condition: (stats) => stats.totalEdges >= 1000,
    reward: null
  },
  
  // Time Achievements
  {
    id: 'time_10h',
    name: '10 Hours Strong',
    description: 'Goon for 10 hours total',
    icon: '⏰',
    category: 'time',
    condition: (stats) => stats.totalSessionTime >= 36000, // 10 hours in seconds
    reward: null
  },
  {
    id: 'time_50h',
    name: 'Dedicated Gooner',
    description: 'Goon for 50 hours total',
    icon: '⏱️',
    category: 'time',
    condition: (stats) => stats.totalSessionTime >= 180000, // 50 hours
    reward: null
  },
  {
    id: 'time_100h',
    name: 'Gooner for Life',
    description: 'Goon for 100 hours total',
    icon: '🏆',
    category: 'time',
    condition: (stats) => stats.totalSessionTime >= 360000, // 100 hours
    reward: 'Honorary Title: Eternal Gooner'
  },
  
  // Feature Achievements
  {
    id: 'webcam_unlock',
    name: 'The Observer',
    description: 'Unlock webcam feature',
    icon: '📹',
    category: 'features',
    condition: (stats) => stats.featuresUnlocked.includes('webcam'),
    reward: null
  },
  {
    id: 'all_features',
    name: 'Feature Complete',
    description: 'Unlock all features',
    icon: '🎯',
    category: 'features',
    condition: (stats) => stats.featuresUnlocked.length >= 10,
    reward: null
  },
  
  // Library Achievements
  {
    id: 'first_directory',
    name: 'Curator Initiate',
    description: 'Add your first directory to the library',
    icon: '📁',
    category: 'library',
    condition: (stats) => stats.library.directories.length >= 1,
    reward: null
  },
  {
    id: 'tag_100',
    name: 'Tagger',
    description: 'Tag 100 files',
    icon: '🏷️',
    category: 'library',
    condition: (stats) => stats.library.taggedFiles >= 100,
    reward: null
  },
  {
    id: 'tag_500',
    name: 'Master Tagger',
    description: 'Tag 500 files',
    icon: '🏷️',
    category: 'library',
    condition: (stats) => stats.library.taggedFiles >= 500,
    reward: null
  },
  {
    id: 'coverage_90',
    name: 'Meticulous Curator',
    description: 'Reach 90% tag coverage',
    icon: '✨',
    category: 'library',
    condition: (stats) => stats.library.tagCoverage >= 90,
    reward: null
  },
  {
    id: 'curator_master',
    name: 'Master Curator',
    description: 'Achieve Master curator rank',
    icon: '👑',
    category: 'library',
    condition: (stats) => stats.library.curatorRank === 'Master',
    reward: 'Access to advanced library features'
  },
  
  // Challenge Achievements
  {
    id: 'marathon_first',
    name: 'Marathon Runner',
    description: 'Complete your first marathon session (15x)',
    icon: '🏃',
    category: 'challenge',
    condition: (stats) => stats.marathonSessionsCompleted >= 1,
    reward: null
  },
  {
    id: 'no_failures',
    name: 'Flawless',
    description: 'Complete 10 levels without any failures',
    icon: '💎',
    category: 'challenge',
    condition: (stats) => stats.consecutiveLevelsWithoutFailure >= 10,
    reward: null
  },
  {
    id: 'path_master',
    name: 'Path Master',
    description: 'Complete your chosen path (L22-25)',
    icon: '🛤️',
    category: 'challenge',
    condition: (stats) => stats.pathLevelsCompleted >= 4,
    reward: null
  },
  
  // Hidden Achievements
  {
    id: 'secret_ascended',
    name: 'Ascended',
    description: 'Complete 5 Ascended Mode levels',
    icon: '🌟',
    category: 'hidden',
    hidden: true,
    condition: (stats) => stats.ascendedLevelsCompleted >= 5,
    reward: 'Secret reward'
  },
  {
    id: 'secret_perfectionist',
    name: 'Perfectionist',
    description: 'Complete all 30 levels without any failures',
    icon: '🏆',
    category: 'hidden',
    hidden: true,
    condition: (stats) => stats.completedLevels.length === 30 && stats.totalFailedAttempts === 0,
    reward: 'Ultimate gooner title'
  }
  
  // Total: 25+ achievements
];

Methods:

class ProgressionManager {
  checkAchievements(stats) {
    // Loop through all achievements
    // Check conditions
    // Unlock new achievements
    // Return newly unlocked achievements
  }
  
  unlockAchievement(achievementId) {
    // Set achievement as unlocked
    // Show notification
    // Save to gameData
  }
  
  getUnlockedAchievements() {
    // Return list of unlocked achievements
  }
  
  getAchievementProgress(achievementId) {
    // For progressive achievements, return % progress
  }
  
  displayAchievementNotification(achievement) {
    // Show toast notification
    // "Achievement Unlocked: [NAME]"
  }
}

Achievement Notification UI:

<div id="achievement-toast" class="toast hidden">
  <div class="achievement-icon"></div>
  <div class="achievement-content">
    <h4>Achievement Unlocked!</h4>
    <p class="achievement-name"></p>
    <p class="achievement-description"></p>
  </div>
</div>

Testing Checklist:

  • All 25+ achievements defined
  • Achievement conditions check correctly
  • Achievements unlock at right moments
  • Notifications display
  • Achievements persist
  • Hidden achievements stay hidden until unlocked

Task 2: Statistics Dashboard (4-5 hours)

File to Update: src/features/academy/progressionManager.js
File to Create: src/features/academy/statsVisualizer.js

Stats to Track:

const academyStats = {
  // Progression
  currentLevel: 1,
  highestUnlockedLevel: 1,
  completedLevels: [],
  arcsCompleted: [],
  
  // Time
  totalSessionTime: 0, // seconds
  longestSession: 0, // seconds
  averageSessionLength: 0, // seconds
  lastPlayedDate: null,
  
  // Edging
  totalEdges: 0,
  edgesPerLevel: {}, // { level: count }
  averageEdgesPerSession: 0,
  
  // Features
  featuresUnlocked: [],
  webcamTimeUsed: 0,
  ttsCommandsHeard: 0,
  hypnoTimeWatched: 0,
  captionsDisplayed: 0,
  interruptionsCompleted: 0,
  popupsViewed: 0,
  
  // Library
  library: {
    totalFiles: 0,
    taggedFiles: 0,
    tagCoverage: 0,
    curatorRank: 'Novice',
    directoriesAdded: 0
  },
  
  // Path
  selectedPath: null,
  pathLevelsCompleted: 0,
  
  // Failures
  totalFailedAttempts: 0,
  failuresByReason: {
    cumming: 0,
    abandoned: 0,
    featureClosed: 0
  },
  consecutiveLevelsWithoutFailure: 0,
  
  // Achievements
  achievementsUnlocked: [],
  achievementProgress: {}
};

Stats Dashboard UI:

<div id="stats-dashboard">
  <h2>Academy Statistics</h2>
  
  <section id="progression-stats">
    <h3>Progression</h3>
    <p>Current Level: <strong id="current-level"></strong></p>
    <p>Completed Levels: <strong id="completed-levels"></strong> / 30</p>
    <div class="progress-bar">
      <div class="progress-fill" id="level-progress"></div>
    </div>
    <p>Arcs Completed: <strong id="arcs-completed"></strong></p>
  </section>
  
  <section id="time-stats">
    <h3>Time Investment</h3>
    <p>Total Time: <strong id="total-time"></strong></p>
    <p>Longest Session: <strong id="longest-session"></strong></p>
    <p>Average Session: <strong id="average-session"></strong></p>
  </section>
  
  <section id="edge-stats">
    <h3>Edging Statistics</h3>
    <p>Total Edges: <strong id="total-edges"></strong></p>
    <p>Average per Session: <strong id="avg-edges"></strong></p>
    <canvas id="edges-chart"></canvas>
  </section>
  
  <section id="feature-stats">
    <h3>Feature Usage</h3>
    <ul>
      <li>Webcam Time: <span id="webcam-time"></span></li>
      <li>TTS Commands: <span id="tts-commands"></span></li>
      <li>Hypno Time: <span id="hypno-time"></span></li>
      <li>Captions Shown: <span id="captions"></span></li>
      <li>Interruptions: <span id="interruptions"></span></li>
      <li>Popups Viewed: <span id="popups"></span></li>
    </ul>
  </section>
  
  <section id="library-stats">
    <h3>Library Curation</h3>
    <p>Total Files: <strong id="library-files"></strong></p>
    <p>Tagged Files: <strong id="tagged-files"></strong></p>
    <p>Tag Coverage: <strong id="tag-coverage"></strong>%</p>
    <div class="progress-bar">
      <div class="progress-fill" id="coverage-bar"></div>
    </div>
    <p>Curator Rank: <strong id="curator-rank"></strong></p>
  </section>
  
  <section id="achievement-showcase">
    <h3>Achievements</h3>
    <div id="achievement-grid">
      <!-- Achievement cards -->
    </div>
  </section>
</div>

Visualization Methods:

class StatsVisualizer {
  renderProgressBar(percent, elementId) {
    // Update progress bar width
  }
  
  renderEdgeChart(edgesPerLevel) {
    // Use Chart.js or similar to render edge graph
  }
  
  formatTime(seconds) {
    // Convert seconds to "Xh Ym" format
  }
  
  renderAchievementGrid(achievements) {
    // Display unlocked + locked achievements
  }
}

Testing Checklist:

  • All stats track correctly
  • Dashboard displays all sections
  • Progress bars update
  • Charts render correctly
  • Time formats correctly
  • Achievement grid displays

Task 3: Advanced Library Management (3-4 hours)

File to Update: src/features/academy/libraryManager.js

New Features:

  1. Quality Scoring - Rate files 1-5 stars
  2. Diversity Scoring - Measure tag variety
  3. Smart Playlists - Auto-generate playlists from tags

Quality Scoring:

class LibraryManager {
  // ... existing methods ...
  
  rateFile(filePath, rating) {
    // rating: 1-5 stars
    // Save to individualFiles
  }
  
  getHighestRatedFiles(count = 10) {
    // Return top-rated files
  }
  
  calculateAverageQuality() {
    // Average rating across all rated files
  }
}

Diversity Scoring:

class LibraryManager {
  // ... existing ...
  
  calculateDiversityScore() {
    // Count unique tags
    // Compare to total tags in catalog
    // Return % (0-100)
  }
  
  getUnderrepresentedTags() {
    // Return tags with < 10 files
    // Suggest adding content with these tags
  }
}

Smart Playlists:

class LibraryManager {
  // ... existing ...
  
  createSmartPlaylist(name, tagCombination, matchMode = 'AND') {
    // tagCombination: ['amateur', 'pov']
    // matchMode: 'AND' or 'OR'
    // Return playlist of matching files
  }
  
  getSuggestedPlaylists(preferences) {
    // Based on user preferences, suggest playlists
    // e.g., "Sissy + Humiliation", "Denial + Edging"
  }
  
  savePlaylist(playlist) {
    // Save to gameData
  }
  
  loadPlaylists() {
    // Return all saved playlists
  }
}

Smart Playlist UI:

<div id="smart-playlists">
  <h3>Smart Playlists</h3>
  <button id="create-playlist">Create Playlist</button>
  
  <div id="playlist-creator" class="hidden">
    <input type="text" id="playlist-name" placeholder="Playlist Name">
    <div id="tag-selector">
      <!-- Multi-select tags -->
    </div>
    <select id="match-mode">
      <option value="AND">Match ALL tags</option>
      <option value="OR">Match ANY tag</option>
    </select>
    <button id="save-playlist">Save Playlist</button>
  </div>
  
  <div id="playlist-list">
    <!-- Saved playlists -->
  </div>
</div>

Testing Checklist:

  • Can rate files 1-5 stars
  • Quality score calculates
  • Diversity score calculates
  • Smart playlists create correctly
  • Playlists save and load
  • Suggested playlists generate

Task 4: Curator Rank Benefits (2-3 hours)

Curator Rank System:

const curatorRanks = {
  Novice: {
    minCoverage: 0,
    benefits: ['Basic tagging']
  },
  Apprentice: {
    minCoverage: 50,
    benefits: ['Bulk tagging', 'Tag suggestions']
  },
  Journeyman: {
    minCoverage: 75,
    benefits: ['Smart playlists', 'Quality rating']
  },
  Expert: {
    minCoverage: 90,
    benefits: ['Advanced filters', 'Diversity insights']
  },
  Master: {
    minCoverage: 98,
    benefits: ['Full library analytics', 'Export/import', 'Custom tags']
  }
};

Rank-Gated Features:

  • Bulk Tagging: Apprentice+ can tag multiple files at once
  • Smart Playlists: Journeyman+ can create smart playlists
  • Advanced Filters: Expert+ can filter by multiple criteria
  • Export/Import: Master can export library data

Testing Checklist:

  • Rank calculates based on coverage
  • Benefits unlock at correct ranks
  • Features gate correctly

Task 5: Export/Import System (2-3 hours)

File to Create: src/features/academy/dataExporter.js

Responsibilities:

  • Export library data as JSON
  • Export achievements as JSON
  • Import library data
  • Share library configurations

Methods:

class DataExporter {
  exportLibrary() {
    // Return JSON of libraryData
  }
  
  exportAchievements() {
    // Return JSON of unlocked achievements
  }
  
  importLibrary(jsonData) {
    // Merge imported data with existing library
    // Avoid duplicates
  }
  
  downloadAsFile(data, filename) {
    // Trigger browser download
  }
}

UI:

<div id="export-import">
  <h3>Data Management</h3>
  <button id="export-library">Export Library</button>
  <button id="export-achievements">Export Achievements</button>
  <input type="file" id="import-file" accept=".json">
  <button id="import-library">Import Library</button>
</div>

Testing Checklist:

  • Library exports as JSON
  • Achievements export as JSON
  • Import merges correctly
  • No duplicate entries after import

📏 Measurable Test Criteria

After Phase 6, ALL of these must pass:

Achievement System:

  • All 25+ achievements defined
  • "First Steps" unlocks after L1
  • "Foundation Graduate" unlocks after L5
  • "Century Club" unlocks at 100 edges
  • "10 Hours Strong" unlocks at 10 hours
  • "Curator Initiate" unlocks after adding first directory
  • Achievement notifications display
  • Achievements persist across refresh
  • Hidden achievements stay hidden

Statistics Dashboard:

  • Dashboard displays all sections
  • Current level displays correctly
  • Completed levels count correct
  • Progress bar updates
  • Total time calculates correctly
  • Total edges track correctly
  • Feature usage stats accurate
  • Library stats display
  • Achievement grid shows unlocked + locked

Library Management:

  • Can rate files 1-5 stars
  • Average quality calculates
  • Diversity score calculates
  • Smart playlists create
  • Playlists save and load
  • Tag suggestions work

Curator Ranks:

  • Novice at 0% coverage
  • Apprentice at 50% coverage
  • Journeyman at 75% coverage
  • Expert at 90% coverage
  • Master at 98% coverage
  • Benefits unlock correctly

Export/Import:

  • Library exports as valid JSON
  • Achievements export as valid JSON
  • Import merges without duplicates
  • Download triggers correctly

Overall:

  • No console errors
  • All systems persist data
  • Performance acceptable with large library

🎯 Success Criteria

Phase 6 Complete When:

  1. Achievement system fully functional (25+ achievements)
  2. Stats dashboard displays all metrics
  3. Advanced library features work (quality, diversity, playlists)
  4. Curator rank progression works
  5. Export/import functional
  6. All measurable tests pass
  7. Meta-game layer enhances engagement

📂 Files Created/Modified

New Files:

  • src/features/academy/progressionManager.js
  • src/features/academy/statsVisualizer.js
  • src/features/academy/dataExporter.js
  • src/data/academy/achievements.js

Modified Files:

  • src/features/academy/libraryManager.js
  • src/core/gameDataManager.js
  • training-academy.html

🚀 Next Phase

After Phase 6: Phase 7: Polish/UI/UX/Testing (Final refinements and QA)