263 lines
7.5 KiB
JavaScript
263 lines
7.5 KiB
JavaScript
(function() {
|
|
'use strict';
|
|
|
|
// =========================================================================
|
|
// AGGREGATE ALL CONTEXTS
|
|
// =========================================================================
|
|
|
|
var ALL_CONTEXTS = [];
|
|
|
|
// Add vehicle contexts
|
|
if (window.VehicleContexts) {
|
|
VehicleContexts.getAll().forEach(function(ctx) {
|
|
ALL_CONTEXTS.push(ctx);
|
|
});
|
|
}
|
|
|
|
// Add costume contexts
|
|
if (window.CostumeContexts) {
|
|
CostumeContexts.getAll().forEach(function(ctx) {
|
|
ALL_CONTEXTS.push(ctx);
|
|
});
|
|
}
|
|
|
|
// Add pure contexts
|
|
if (window.PureContexts) {
|
|
PureContexts.getAll().forEach(function(ctx) {
|
|
ALL_CONTEXTS.push(ctx);
|
|
});
|
|
}
|
|
|
|
// Create lookup map
|
|
var CONTEXT_MAP = {};
|
|
ALL_CONTEXTS.forEach(function(ctx) {
|
|
CONTEXT_MAP[ctx.id] = ctx;
|
|
});
|
|
|
|
// =========================================================================
|
|
// CATEGORY METADATA
|
|
// =========================================================================
|
|
|
|
var CATEGORIES = {
|
|
vehicle: {
|
|
id: 'vehicle',
|
|
name: 'Vehicles',
|
|
description: 'Place your avatar in vehicles and cockpits',
|
|
icon: '🚗',
|
|
count: 0 // calculated
|
|
},
|
|
costume: {
|
|
id: 'costume',
|
|
name: 'Costumes',
|
|
description: 'Dress your avatar in themed outfits',
|
|
icon: '👔',
|
|
count: 0
|
|
},
|
|
pure: {
|
|
id: 'pure',
|
|
name: 'Standard',
|
|
description: 'Your avatar with minimal modifications',
|
|
icon: '🏃',
|
|
count: 0
|
|
}
|
|
};
|
|
|
|
// Count per category
|
|
ALL_CONTEXTS.forEach(function(ctx) {
|
|
if (CATEGORIES[ctx.category]) {
|
|
CATEGORIES[ctx.category].count++;
|
|
}
|
|
});
|
|
|
|
// =========================================================================
|
|
// GAME TYPE MAPPINGS
|
|
// =========================================================================
|
|
|
|
var GAME_TYPE_CONTEXTS = {
|
|
platformer: ['platformer-standard', 'adventure-hero', 'knight-armor', 'ninja-outfit', 'superhero-cape'],
|
|
racing: ['race-car', 'motorcycle', 'hoverboard', 'airplane'],
|
|
shooter: ['spaceship-cockpit', 'tank', 'mech-suit', 'space-suit'],
|
|
flying: ['flappy-style', 'airplane', 'jetpack', 'dragon-rider'],
|
|
arcade: ['pacman-style', 'flappy-style', 'spaceship-cockpit', 'runner'],
|
|
rpg: ['knight-armor', 'wizard-robes', 'ninja-outfit', 'pirate-outfit', 'adventure-hero'],
|
|
sports: ['sports-player', 'athlete-uniform', 'runner'],
|
|
puzzle: ['scientist-labcoat', 'wizard-robes', 'platformer-standard'],
|
|
adventure: ['adventure-hero', 'pirate-outfit', 'cowboy-gear', 'dragon-rider'],
|
|
action: ['superhero-cape', 'ninja-outfit', 'mech-suit', 'jetpack'],
|
|
underwater: ['submarine', 'space-suit'],
|
|
space: ['spaceship-cockpit', 'space-suit', 'mech-suit'],
|
|
cooking: ['chef-outfit'],
|
|
simulation: ['airplane', 'submarine', 'race-car', 'tank']
|
|
};
|
|
|
|
// =========================================================================
|
|
// MODE GROUPINGS
|
|
// =========================================================================
|
|
|
|
var MODE_CONTEXTS = {
|
|
HEAD_ONLY: [],
|
|
HEAD_AND_SHOULDERS: [],
|
|
UPPER_BODY: [],
|
|
FULL_BODY: []
|
|
};
|
|
|
|
ALL_CONTEXTS.forEach(function(ctx) {
|
|
if (MODE_CONTEXTS[ctx.avatarMode]) {
|
|
MODE_CONTEXTS[ctx.avatarMode].push(ctx.id);
|
|
}
|
|
});
|
|
|
|
// =========================================================================
|
|
// CATALOG STATISTICS
|
|
// =========================================================================
|
|
|
|
var STATS = {
|
|
totalContexts: ALL_CONTEXTS.length,
|
|
vehicleCount: CATEGORIES.vehicle.count,
|
|
costumeCount: CATEGORIES.costume.count,
|
|
pureCount: CATEGORIES.pure.count,
|
|
version: '1.0.0',
|
|
lastUpdated: '2026-02-05'
|
|
};
|
|
|
|
// =========================================================================
|
|
// PUBLIC API
|
|
// =========================================================================
|
|
|
|
window.ContextCatalog = {
|
|
// Core getters
|
|
getAll: function() {
|
|
return ALL_CONTEXTS.slice();
|
|
},
|
|
|
|
getById: function(id) {
|
|
return CONTEXT_MAP[id] || null;
|
|
},
|
|
|
|
// Category queries
|
|
getByCategory: function(category) {
|
|
return ALL_CONTEXTS.filter(function(ctx) {
|
|
return ctx.category === category;
|
|
});
|
|
},
|
|
|
|
getCategories: function() {
|
|
return Object.values(CATEGORIES);
|
|
},
|
|
|
|
getCategoryInfo: function(categoryId) {
|
|
return CATEGORIES[categoryId] || null;
|
|
},
|
|
|
|
// Mode queries
|
|
getByMode: function(mode) {
|
|
var ids = MODE_CONTEXTS[mode] || [];
|
|
return ids.map(function(id) {
|
|
return CONTEXT_MAP[id];
|
|
}).filter(Boolean);
|
|
},
|
|
|
|
getModes: function() {
|
|
return Object.keys(MODE_CONTEXTS);
|
|
},
|
|
|
|
// Game type recommendations
|
|
getRecommendedFor: function(gameType) {
|
|
var ids = GAME_TYPE_CONTEXTS[gameType] || [];
|
|
return ids.map(function(id) {
|
|
return CONTEXT_MAP[id];
|
|
}).filter(Boolean);
|
|
},
|
|
|
|
getGameTypes: function() {
|
|
return Object.keys(GAME_TYPE_CONTEXTS);
|
|
},
|
|
|
|
// Search/filter
|
|
search: function(query) {
|
|
query = query.toLowerCase();
|
|
return ALL_CONTEXTS.filter(function(ctx) {
|
|
return ctx.id.toLowerCase().includes(query) ||
|
|
ctx.name.toLowerCase().includes(query) ||
|
|
ctx.description.toLowerCase().includes(query);
|
|
});
|
|
},
|
|
|
|
filter: function(filters) {
|
|
return ALL_CONTEXTS.filter(function(ctx) {
|
|
if (filters.category && ctx.category !== filters.category) return false;
|
|
if (filters.mode && ctx.avatarMode !== filters.mode) return false;
|
|
if (filters.gameType) {
|
|
var recommended = GAME_TYPE_CONTEXTS[filters.gameType] || [];
|
|
if (recommended.indexOf(ctx.id) === -1) return false;
|
|
}
|
|
return true;
|
|
});
|
|
},
|
|
|
|
// For UI display
|
|
getCatalogForUI: function() {
|
|
return {
|
|
categories: Object.values(CATEGORIES).map(function(cat) {
|
|
return {
|
|
id: cat.id,
|
|
name: cat.name,
|
|
description: cat.description,
|
|
icon: cat.icon,
|
|
contexts: ALL_CONTEXTS.filter(function(ctx) {
|
|
return ctx.category === cat.id;
|
|
}).map(function(ctx) {
|
|
return {
|
|
id: ctx.id,
|
|
name: ctx.name,
|
|
description: ctx.description,
|
|
mode: ctx.avatarMode,
|
|
recommendedFor: ctx.recommendedFor
|
|
};
|
|
})
|
|
};
|
|
})
|
|
};
|
|
},
|
|
|
|
// Random selection
|
|
getRandom: function(filters) {
|
|
var pool = filters ? this.filter(filters) : ALL_CONTEXTS;
|
|
if (pool.length === 0) return null;
|
|
return pool[Math.floor(Math.random() * pool.length)];
|
|
},
|
|
|
|
getRandomForGameType: function(gameType) {
|
|
var recommended = this.getRecommendedFor(gameType);
|
|
if (recommended.length === 0) return null;
|
|
return recommended[Math.floor(Math.random() * recommended.length)];
|
|
},
|
|
|
|
// Statistics
|
|
getStats: function() {
|
|
return Object.assign({}, STATS);
|
|
},
|
|
|
|
// Validation
|
|
validate: function() {
|
|
var issues = [];
|
|
|
|
ALL_CONTEXTS.forEach(function(ctx) {
|
|
if (!ctx.id) issues.push('Context missing id');
|
|
if (!ctx.name) issues.push(ctx.id + ': missing name');
|
|
if (!ctx.avatarMode) issues.push(ctx.id + ': missing avatarMode');
|
|
if (!ctx.category) issues.push(ctx.id + ': missing category');
|
|
if (!ctx.animations || ctx.animations.length === 0) {
|
|
issues.push(ctx.id + ': missing animations');
|
|
}
|
|
});
|
|
|
|
return {
|
|
valid: issues.length === 0,
|
|
issues: issues
|
|
};
|
|
}
|
|
};
|
|
|
|
})();
|