Files
gamercomp/frontend/public/assets/compatibility.js
T
2026-04-30 02:14:25 +00:00

1107 lines
40 KiB
JavaScript

/**
* Asset Compatibility System
* Defines compatibility rules between music, backgrounds, and avatar contexts
*/
(function() {
'use strict';
// ============================================================================
// MOOD → BACKGROUND THEME COMPATIBILITY
// ============================================================================
var MOOD_BACKGROUND_COMPAT = {
Epic: {
excellent: ['space', 'fantasy', 'sports', 'sky'],
good: ['urban', 'mechanical', 'nature'],
neutral: ['retro', 'colorful', 'indoor'],
poor: ['abstract']
},
Chill: {
excellent: ['nature', 'underwater', 'indoor', 'seasonal'],
good: ['sky', 'colorful', 'abstract'],
neutral: ['fantasy', 'retro'],
poor: ['urban', 'mechanical', 'spooky']
},
Intense: {
excellent: ['urban', 'mechanical', 'sports', 'weather'],
good: ['space', 'spooky', 'retro'],
neutral: ['nature', 'sky'],
poor: ['colorful', 'indoor', 'seasonal']
},
Playful: {
excellent: ['colorful', 'retro', 'nature', 'indoor'],
good: ['underwater', 'seasonal', 'abstract'],
neutral: ['fantasy', 'sky'],
poor: ['spooky', 'mechanical', 'urban']
},
Mysterious: {
excellent: ['spooky', 'fantasy', 'underwater', 'weather'],
good: ['nature', 'urban', 'abstract'],
neutral: ['space', 'indoor'],
poor: ['colorful', 'sports', 'retro']
},
Heroic: {
excellent: ['space', 'fantasy', 'urban', 'sky'],
good: ['nature', 'sports', 'mechanical'],
neutral: ['retro', 'weather'],
poor: ['indoor', 'colorful', 'abstract']
},
Quirky: {
excellent: ['retro', 'colorful', 'abstract', 'indoor'],
good: ['nature', 'mechanical', 'seasonal'],
neutral: ['urban', 'fantasy'],
poor: ['spooky', 'space', 'sports']
},
Ambient: {
excellent: ['nature', 'underwater', 'sky', 'seasonal'],
good: ['abstract', 'indoor', 'weather'],
neutral: ['space', 'fantasy'],
poor: ['urban', 'mechanical', 'sports', 'spooky']
}
};
// ============================================================================
// BACKGROUND THEME → AVATAR CONTEXT COMPATIBILITY
// ============================================================================
var THEME_CONTEXT_COMPAT = {
space: {
excellent: ['spaceship-cockpit', 'space-suit', 'mech-suit'],
good: ['jetpack', 'platformer-standard', 'adventure-hero'],
neutral: ['ninja-outfit', 'superhero-cape', 'wizard-robes'],
poor: ['chef-outfit', 'cowboy-gear', 'pirate-outfit', 'race-car', 'submarine', 'hot-air-balloon']
},
fantasy: {
excellent: ['knight-armor', 'wizard-robes', 'dragon-rider'],
good: ['adventure-hero', 'ninja-outfit', 'fairy-wings'],
neutral: ['platformer-standard', 'superhero-cape', 'pirate-outfit'],
poor: ['race-car', 'motorcycle', 'submarine', 'spaceship-cockpit', 'space-suit', 'mech-suit']
},
nature: {
excellent: ['adventure-hero', 'platformer-standard', 'fairy-wings'],
good: ['ninja-outfit', 'cowboy-gear', 'safari-outfit'],
neutral: ['wizard-robes', 'pirate-outfit', 'superhero-cape'],
poor: ['race-car', 'motorcycle', 'submarine', 'spaceship-cockpit', 'mech-suit', 'skateboard']
},
urban: {
excellent: ['skateboard', 'motorcycle', 'superhero-cape', 'parkour-outfit'],
good: ['platformer-standard', 'ninja-outfit', 'race-car'],
neutral: ['adventure-hero', 'chef-outfit', 'detective-outfit'],
poor: ['dragon-rider', 'fairy-wings', 'pirate-outfit', 'submarine', 'space-suit', 'cowboy-gear']
},
underwater: {
excellent: ['submarine', 'scuba-gear', 'mermaid-tail'],
good: ['pirate-outfit', 'adventure-hero', 'platformer-standard'],
neutral: ['ninja-outfit', 'wizard-robes', 'fairy-wings'],
poor: ['race-car', 'motorcycle', 'skateboard', 'cowboy-gear', 'knight-armor', 'hot-air-balloon']
},
retro: {
excellent: ['platformer-standard', 'arcade-classic', 'superhero-cape'],
good: ['adventure-hero', 'ninja-outfit', 'skateboard'],
neutral: ['wizard-robes', 'knight-armor', 'pirate-outfit'],
poor: ['mech-suit', 'spaceship-cockpit', 'submarine', 'dragon-rider', 'safari-outfit']
},
sports: {
excellent: ['race-car', 'motorcycle', 'skateboard', 'sports-uniform'],
good: ['platformer-standard', 'adventure-hero', 'superhero-cape'],
neutral: ['ninja-outfit', 'parkour-outfit', 'jetpack'],
poor: ['wizard-robes', 'knight-armor', 'pirate-outfit', 'submarine', 'fairy-wings', 'mermaid-tail']
},
spooky: {
excellent: ['wizard-robes', 'vampire-cloak', 'ghost-costume'],
good: ['ninja-outfit', 'adventure-hero', 'detective-outfit'],
neutral: ['platformer-standard', 'superhero-cape', 'pirate-outfit'],
poor: ['fairy-wings', 'chef-outfit', 'sports-uniform', 'safari-outfit', 'hot-air-balloon', 'race-car']
},
colorful: {
excellent: ['platformer-standard', 'superhero-cape', 'fairy-wings', 'arcade-classic'],
good: ['adventure-hero', 'skateboard', 'jetpack'],
neutral: ['ninja-outfit', 'wizard-robes', 'pirate-outfit'],
poor: ['vampire-cloak', 'ghost-costume', 'detective-outfit', 'mech-suit']
},
mechanical: {
excellent: ['mech-suit', 'race-car', 'motorcycle', 'jetpack'],
good: ['spaceship-cockpit', 'ninja-outfit', 'superhero-cape'],
neutral: ['platformer-standard', 'adventure-hero', 'skateboard'],
poor: ['fairy-wings', 'wizard-robes', 'pirate-outfit', 'cowboy-gear', 'mermaid-tail', 'safari-outfit']
},
indoor: {
excellent: ['platformer-standard', 'chef-outfit', 'detective-outfit', 'arcade-classic'],
good: ['adventure-hero', 'ninja-outfit', 'superhero-cape'],
neutral: ['wizard-robes', 'skateboard', 'parkour-outfit'],
poor: ['submarine', 'race-car', 'motorcycle', 'dragon-rider', 'hot-air-balloon', 'safari-outfit']
},
sky: {
excellent: ['jetpack', 'hot-air-balloon', 'dragon-rider', 'fairy-wings'],
good: ['superhero-cape', 'spaceship-cockpit', 'platformer-standard'],
neutral: ['adventure-hero', 'ninja-outfit', 'wizard-robes'],
poor: ['submarine', 'race-car', 'motorcycle', 'skateboard', 'chef-outfit', 'mermaid-tail']
},
seasonal: {
excellent: ['platformer-standard', 'adventure-hero', 'fairy-wings'],
good: ['superhero-cape', 'wizard-robes', 'chef-outfit'],
neutral: ['ninja-outfit', 'skateboard', 'detective-outfit'],
poor: ['submarine', 'mech-suit', 'spaceship-cockpit', 'vampire-cloak', 'race-car']
},
weather: {
excellent: ['adventure-hero', 'superhero-cape', 'wizard-robes'],
good: ['platformer-standard', 'ninja-outfit', 'jetpack'],
neutral: ['dragon-rider', 'hot-air-balloon', 'detective-outfit'],
poor: ['submarine', 'race-car', 'chef-outfit', 'mermaid-tail', 'arcade-classic']
},
abstract: {
excellent: ['platformer-standard', 'arcade-classic', 'superhero-cape'],
good: ['adventure-hero', 'ninja-outfit', 'wizard-robes'],
neutral: ['fairy-wings', 'jetpack', 'skateboard'],
poor: ['cowboy-gear', 'safari-outfit', 'chef-outfit', 'detective-outfit', 'pirate-outfit']
}
};
// ============================================================================
// CONTEXT → ANIMATION COMPATIBILITY
// ============================================================================
var CONTEXT_ANIMATIONS = {
'spaceship-cockpit': {
required: ['idle'],
recommended: ['bob', 'hurt', 'celebrate'],
incompatible: ['walk', 'run', 'jump', 'swim']
},
'space-suit': {
required: ['idle', 'walk'],
recommended: ['jump', 'float', 'hurt', 'celebrate'],
incompatible: ['swim']
},
'mech-suit': {
required: ['idle', 'walk'],
recommended: ['attack', 'hurt', 'celebrate', 'stomp'],
incompatible: ['swim', 'fly']
},
'race-car': {
required: ['idle'],
recommended: ['hurt', 'celebrate', 'boost'],
incompatible: ['walk', 'run', 'jump', 'fly', 'swim']
},
'motorcycle': {
required: ['idle'],
recommended: ['hurt', 'celebrate', 'wheelie'],
incompatible: ['walk', 'run', 'fly', 'swim']
},
'submarine': {
required: ['idle'],
recommended: ['hurt', 'celebrate', 'dive'],
incompatible: ['walk', 'run', 'jump', 'fly']
},
'platformer-standard': {
required: ['idle', 'walk', 'jump'],
recommended: ['run', 'fall', 'hurt', 'celebrate', 'crouch'],
incompatible: []
},
'adventure-hero': {
required: ['idle', 'walk', 'jump'],
recommended: ['run', 'attack', 'hurt', 'celebrate', 'climb'],
incompatible: []
},
'ninja-outfit': {
required: ['idle', 'walk', 'jump'],
recommended: ['run', 'attack', 'throw', 'hurt', 'celebrate', 'crouch', 'wallslide'],
incompatible: []
},
'knight-armor': {
required: ['idle', 'walk'],
recommended: ['attack', 'block', 'hurt', 'celebrate'],
incompatible: ['fly', 'swim']
},
'wizard-robes': {
required: ['idle', 'walk'],
recommended: ['cast', 'float', 'hurt', 'celebrate', 'teleport'],
incompatible: []
},
'dragon-rider': {
required: ['idle', 'fly'],
recommended: ['attack', 'hurt', 'celebrate', 'dive', 'breathe-fire'],
incompatible: ['walk', 'run', 'swim']
},
'fairy-wings': {
required: ['idle', 'fly'],
recommended: ['hover', 'hurt', 'celebrate', 'sparkle'],
incompatible: ['swim']
},
'jetpack': {
required: ['idle', 'fly'],
recommended: ['boost', 'hurt', 'celebrate', 'hover'],
incompatible: ['swim']
},
'hot-air-balloon': {
required: ['idle'],
recommended: ['float', 'hurt', 'celebrate'],
incompatible: ['walk', 'run', 'jump', 'swim', 'attack']
},
'pirate-outfit': {
required: ['idle', 'walk'],
recommended: ['attack', 'jump', 'hurt', 'celebrate', 'swim'],
incompatible: ['fly']
},
'cowboy-gear': {
required: ['idle', 'walk'],
recommended: ['shoot', 'jump', 'hurt', 'celebrate', 'lasso'],
incompatible: ['fly', 'swim']
},
'superhero-cape': {
required: ['idle', 'walk', 'fly'],
recommended: ['run', 'jump', 'attack', 'hurt', 'celebrate', 'land'],
incompatible: []
},
'skateboard': {
required: ['idle'],
recommended: ['trick', 'grind', 'hurt', 'celebrate', 'push'],
incompatible: ['walk', 'run', 'fly', 'swim']
},
'scuba-gear': {
required: ['idle', 'swim'],
recommended: ['dive', 'hurt', 'celebrate'],
incompatible: ['walk', 'run', 'jump', 'fly']
},
'mermaid-tail': {
required: ['idle', 'swim'],
recommended: ['dive', 'hurt', 'celebrate', 'splash'],
incompatible: ['walk', 'run', 'jump', 'fly']
},
'chef-outfit': {
required: ['idle', 'walk'],
recommended: ['chop', 'throw', 'hurt', 'celebrate'],
incompatible: ['fly', 'swim']
},
'safari-outfit': {
required: ['idle', 'walk'],
recommended: ['run', 'jump', 'hurt', 'celebrate', 'crouch'],
incompatible: ['fly']
},
'vampire-cloak': {
required: ['idle', 'walk'],
recommended: ['attack', 'fly', 'hurt', 'celebrate', 'transform'],
incompatible: ['swim']
},
'ghost-costume': {
required: ['idle', 'float'],
recommended: ['fly', 'phase', 'hurt', 'celebrate', 'fade'],
incompatible: ['walk', 'run', 'swim']
},
'detective-outfit': {
required: ['idle', 'walk'],
recommended: ['run', 'crouch', 'hurt', 'celebrate', 'inspect'],
incompatible: ['fly', 'swim']
},
'parkour-outfit': {
required: ['idle', 'walk', 'run', 'jump'],
recommended: ['wallrun', 'vault', 'roll', 'hurt', 'celebrate', 'climb'],
incompatible: ['fly', 'swim']
},
'arcade-classic': {
required: ['idle', 'walk'],
recommended: ['jump', 'hurt', 'celebrate'],
incompatible: []
},
'sports-uniform': {
required: ['idle', 'walk', 'run'],
recommended: ['jump', 'kick', 'throw', 'hurt', 'celebrate'],
incompatible: ['fly', 'swim']
}
};
// ============================================================================
// COLOR PALETTE HARMONY
// ============================================================================
var PALETTE_HARMONY = {
'space-blue': {
harmonious: ['fantasy-purple', 'ocean-teal', 'spooky-grey', 'cyber-neon'],
neutral: ['nature-green', 'retro-warm', 'neutral-earth'],
clash: ['sunset-orange', 'sports-red', 'candy-rainbow']
},
'fantasy-purple': {
harmonious: ['space-blue', 'spooky-grey', 'cyber-neon', 'sunset-orange'],
neutral: ['nature-green', 'ocean-teal', 'neutral-earth'],
clash: ['sports-red', 'candy-rainbow', 'retro-warm']
},
'nature-green': {
harmonious: ['ocean-teal', 'neutral-earth', 'sunset-orange', 'retro-warm'],
neutral: ['space-blue', 'fantasy-purple', 'candy-rainbow'],
clash: ['cyber-neon', 'spooky-grey', 'sports-red']
},
'ocean-teal': {
harmonious: ['space-blue', 'nature-green', 'fantasy-purple', 'neutral-earth'],
neutral: ['cyber-neon', 'spooky-grey', 'retro-warm'],
clash: ['sports-red', 'candy-rainbow', 'sunset-orange']
},
'sunset-orange': {
harmonious: ['fantasy-purple', 'nature-green', 'retro-warm', 'neutral-earth'],
neutral: ['spooky-grey', 'candy-rainbow', 'sports-red'],
clash: ['space-blue', 'ocean-teal', 'cyber-neon']
},
'sports-red': {
harmonious: ['neutral-earth', 'spooky-grey', 'retro-warm'],
neutral: ['sunset-orange', 'candy-rainbow', 'fantasy-purple'],
clash: ['space-blue', 'ocean-teal', 'nature-green', 'cyber-neon']
},
'retro-warm': {
harmonious: ['sunset-orange', 'nature-green', 'neutral-earth', 'sports-red'],
neutral: ['fantasy-purple', 'candy-rainbow', 'spooky-grey'],
clash: ['space-blue', 'ocean-teal', 'cyber-neon']
},
'spooky-grey': {
harmonious: ['space-blue', 'fantasy-purple', 'cyber-neon', 'sports-red'],
neutral: ['neutral-earth', 'ocean-teal', 'retro-warm'],
clash: ['candy-rainbow', 'nature-green', 'sunset-orange']
},
'candy-rainbow': {
harmonious: ['retro-warm', 'sunset-orange', 'fantasy-purple'],
neutral: ['nature-green', 'sports-red', 'neutral-earth'],
clash: ['space-blue', 'ocean-teal', 'spooky-grey', 'cyber-neon']
},
'cyber-neon': {
harmonious: ['space-blue', 'fantasy-purple', 'spooky-grey'],
neutral: ['ocean-teal', 'neutral-earth', 'candy-rainbow'],
clash: ['nature-green', 'sunset-orange', 'retro-warm', 'sports-red']
},
'neutral-earth': {
harmonious: ['nature-green', 'ocean-teal', 'retro-warm', 'sunset-orange'],
neutral: ['space-blue', 'fantasy-purple', 'sports-red', 'spooky-grey'],
clash: ['candy-rainbow', 'cyber-neon']
}
};
// ============================================================================
// ENERGY LEVEL MAPPINGS
// ============================================================================
var MOOD_ENERGY = {
Epic: 'high',
Chill: 'low',
Intense: 'high',
Playful: 'medium',
Mysterious: 'low',
Heroic: 'high',
Quirky: 'medium',
Ambient: 'low'
};
var CONTEXT_ENERGY = {
'spaceship-cockpit': 'medium',
'space-suit': 'medium',
'mech-suit': 'high',
'race-car': 'high',
'motorcycle': 'high',
'submarine': 'low',
'platformer-standard': 'medium',
'adventure-hero': 'medium',
'ninja-outfit': 'high',
'knight-armor': 'medium',
'wizard-robes': 'medium',
'dragon-rider': 'high',
'fairy-wings': 'low',
'jetpack': 'high',
'hot-air-balloon': 'low',
'pirate-outfit': 'medium',
'cowboy-gear': 'medium',
'superhero-cape': 'high',
'skateboard': 'high',
'scuba-gear': 'low',
'mermaid-tail': 'low',
'chef-outfit': 'low',
'safari-outfit': 'medium',
'vampire-cloak': 'medium',
'ghost-costume': 'low',
'detective-outfit': 'low',
'parkour-outfit': 'high',
'arcade-classic': 'medium',
'sports-uniform': 'high'
};
// ============================================================================
// THEME → DEFAULT PALETTE MAPPING
// ============================================================================
var THEME_DEFAULT_PALETTES = {
space: ['space-blue', 'cyber-neon', 'spooky-grey'],
fantasy: ['fantasy-purple', 'nature-green', 'sunset-orange'],
nature: ['nature-green', 'neutral-earth', 'ocean-teal'],
urban: ['neutral-earth', 'spooky-grey', 'cyber-neon'],
underwater: ['ocean-teal', 'space-blue', 'nature-green'],
retro: ['retro-warm', 'candy-rainbow', 'sunset-orange'],
sports: ['sports-red', 'neutral-earth', 'cyber-neon'],
spooky: ['spooky-grey', 'fantasy-purple', 'cyber-neon'],
colorful: ['candy-rainbow', 'sunset-orange', 'fantasy-purple'],
mechanical: ['spooky-grey', 'cyber-neon', 'sports-red'],
indoor: ['neutral-earth', 'retro-warm', 'sunset-orange'],
sky: ['space-blue', 'sunset-orange', 'ocean-teal'],
seasonal: ['nature-green', 'sunset-orange', 'neutral-earth'],
weather: ['spooky-grey', 'space-blue', 'nature-green'],
abstract: ['cyber-neon', 'candy-rainbow', 'fantasy-purple']
};
// ============================================================================
// MECHANICS → CONTEXT MAPPING
// ============================================================================
var MECHANICS_CONTEXTS = {
flying: ['dragon-rider', 'fairy-wings', 'jetpack', 'superhero-cape', 'hot-air-balloon'],
racing: ['race-car', 'motorcycle', 'skateboard'],
platforming: ['platformer-standard', 'adventure-hero', 'ninja-outfit', 'parkour-outfit', 'arcade-classic'],
swimming: ['submarine', 'scuba-gear', 'mermaid-tail'],
combat: ['knight-armor', 'ninja-outfit', 'superhero-cape', 'mech-suit', 'wizard-robes'],
exploration: ['adventure-hero', 'safari-outfit', 'detective-outfit', 'pirate-outfit'],
puzzle: ['platformer-standard', 'detective-outfit', 'wizard-robes', 'arcade-classic'],
stealth: ['ninja-outfit', 'ghost-costume', 'vampire-cloak', 'detective-outfit'],
cooking: ['chef-outfit'],
sports: ['sports-uniform', 'skateboard']
};
// ============================================================================
// VALIDATION FUNCTIONS
// ============================================================================
/**
* Get mood-background compatibility level
* @param {string} mood - Music mood
* @param {string} theme - Background theme
* @returns {string} - 'excellent', 'good', 'neutral', or 'poor'
*/
function getMoodBackgroundCompat(mood, theme) {
var compat = MOOD_BACKGROUND_COMPAT[mood];
if (!compat) return 'neutral';
if (compat.excellent && compat.excellent.indexOf(theme) !== -1) return 'excellent';
if (compat.good && compat.good.indexOf(theme) !== -1) return 'good';
if (compat.poor && compat.poor.indexOf(theme) !== -1) return 'poor';
return 'neutral';
}
/**
* Get theme-context compatibility level
* @param {string} theme - Background theme
* @param {string} context - Avatar context
* @returns {string} - 'excellent', 'good', 'neutral', or 'poor'
*/
function getThemeContextCompat(theme, context) {
var compat = THEME_CONTEXT_COMPAT[theme];
if (!compat) return 'neutral';
if (compat.excellent && compat.excellent.indexOf(context) !== -1) return 'excellent';
if (compat.good && compat.good.indexOf(context) !== -1) return 'good';
if (compat.poor && compat.poor.indexOf(context) !== -1) return 'poor';
return 'neutral';
}
/**
* Get context-animation compatibility
* @param {string} context - Avatar context
* @param {string} animation - Animation name
* @returns {string} - 'required', 'recommended', 'compatible', or 'incompatible'
*/
function getContextAnimationCompat(context, animation) {
var compat = CONTEXT_ANIMATIONS[context];
if (!compat) return 'compatible';
if (compat.required && compat.required.indexOf(animation) !== -1) return 'required';
if (compat.recommended && compat.recommended.indexOf(animation) !== -1) return 'recommended';
if (compat.incompatible && compat.incompatible.indexOf(animation) !== -1) return 'incompatible';
return 'compatible';
}
/**
* Get palette harmony level
* @param {string} palette1 - First palette
* @param {string} palette2 - Second palette
* @returns {string} - 'harmonious', 'neutral', or 'clash'
*/
function getPaletteHarmony(palette1, palette2) {
if (palette1 === palette2) return 'harmonious';
var compat = PALETTE_HARMONY[palette1];
if (!compat) return 'neutral';
if (compat.harmonious && compat.harmonious.indexOf(palette2) !== -1) return 'harmonious';
if (compat.clash && compat.clash.indexOf(palette2) !== -1) return 'clash';
return 'neutral';
}
/**
* Check energy level compatibility
* @param {string} moodEnergy - Music energy level
* @param {string} contextEnergy - Context energy level
* @returns {string} - 'match', 'close', or 'mismatch'
*/
function getEnergyCompat(moodEnergy, contextEnergy) {
if (moodEnergy === contextEnergy) return 'match';
var levels = ['low', 'medium', 'high'];
var diff = Math.abs(levels.indexOf(moodEnergy) - levels.indexOf(contextEnergy));
return diff === 1 ? 'close' : 'mismatch';
}
/**
* Validate a complete asset configuration
* @param {Object} config - Configuration object with music, background, avatarContext, palette
* @returns {Object} - { valid, score, issues }
*/
function validate(config) {
var issues = [];
var score = 100;
// Check music/background compatibility
if (config.music && config.background) {
var mood = config.music.mood || config.music;
var theme = config.background.theme || config.background;
var compat = getMoodBackgroundCompat(mood, theme);
if (compat === 'poor') {
issues.push({
type: 'warning',
category: 'mood-background',
message: 'Music mood "' + mood + '" doesn\'t match background theme "' + theme + '" well'
});
score -= 15;
} else if (compat === 'neutral') {
score -= 5;
} else if (compat === 'excellent') {
score += 10;
} else if (compat === 'good') {
score += 5;
}
}
// Check background/context compatibility
if (config.background && config.avatarContext) {
var theme = config.background.theme || config.background;
var context = config.avatarContext.context || config.avatarContext;
var compat = getThemeContextCompat(theme, context);
if (compat === 'poor') {
issues.push({
type: 'warning',
category: 'theme-context',
message: 'Avatar context "' + context + '" doesn\'t fit background theme "' + theme + '"'
});
score -= 20;
} else if (compat === 'excellent') {
score += 10;
} else if (compat === 'good') {
score += 5;
}
}
// Check energy level appropriateness
if (config.music && config.avatarContext) {
var mood = config.music.mood || config.music;
var context = config.avatarContext.context || config.avatarContext;
var moodEnergy = MOOD_ENERGY[mood];
var contextEnergy = CONTEXT_ENERGY[context];
if (moodEnergy && contextEnergy) {
var energyCompat = getEnergyCompat(moodEnergy, contextEnergy);
if (energyCompat === 'mismatch') {
issues.push({
type: 'info',
category: 'energy',
message: 'Music energy (' + moodEnergy + ') doesn\'t match avatar context energy (' + contextEnergy + ')'
});
score -= 10;
} else if (energyCompat === 'match') {
score += 5;
}
}
}
// Check palette harmony with theme
if (config.palette && config.background) {
var theme = config.background.theme || config.background;
var palette = config.palette.name || config.palette;
var themePalettes = THEME_DEFAULT_PALETTES[theme];
if (themePalettes) {
if (themePalettes.indexOf(palette) === -1) {
// Check if it's harmonious with any default palette
var hasHarmony = false;
for (var i = 0; i < themePalettes.length; i++) {
if (getPaletteHarmony(palette, themePalettes[i]) === 'harmonious') {
hasHarmony = true;
break;
}
}
if (!hasHarmony) {
var clashes = false;
for (var i = 0; i < themePalettes.length; i++) {
if (getPaletteHarmony(palette, themePalettes[i]) === 'clash') {
clashes = true;
break;
}
}
if (clashes) {
issues.push({
type: 'info',
category: 'palette',
message: 'Color palette "' + palette + '" may clash with theme "' + theme + '"'
});
score -= 5;
}
}
} else {
score += 5;
}
}
}
// Check animation compatibility with context
if (config.avatarContext && config.animations) {
var context = config.avatarContext.context || config.avatarContext;
var contextAnims = CONTEXT_ANIMATIONS[context];
if (contextAnims) {
// Check for missing required animations
var animations = Array.isArray(config.animations) ? config.animations : [config.animations];
if (contextAnims.required) {
for (var i = 0; i < contextAnims.required.length; i++) {
var required = contextAnims.required[i];
if (animations.indexOf(required) === -1) {
issues.push({
type: 'error',
category: 'animation',
message: 'Context "' + context + '" requires animation "' + required + '"'
});
score -= 25;
}
}
}
// Check for incompatible animations
if (contextAnims.incompatible) {
for (var i = 0; i < animations.length; i++) {
if (contextAnims.incompatible.indexOf(animations[i]) !== -1) {
issues.push({
type: 'warning',
category: 'animation',
message: 'Animation "' + animations[i] + '" is incompatible with context "' + context + '"'
});
score -= 10;
}
}
}
}
}
return {
valid: issues.filter(function(i) { return i.type === 'error'; }).length === 0,
score: Math.max(0, Math.min(100, score)),
issues: issues
};
}
// ============================================================================
// SUGGESTION FUNCTIONS
// ============================================================================
/**
* Get compatible music moods for a background theme
* @param {string} theme - Background theme
* @returns {Array} - Sorted array of { mood, compatibility }
*/
function getMusicForTheme(theme) {
var results = [];
var moods = Object.keys(MOOD_BACKGROUND_COMPAT);
for (var i = 0; i < moods.length; i++) {
var mood = moods[i];
var compat = getMoodBackgroundCompat(mood, theme);
results.push({ mood: mood, compatibility: compat });
}
// Sort by compatibility
var order = { excellent: 0, good: 1, neutral: 2, poor: 3 };
results.sort(function(a, b) {
return order[a.compatibility] - order[b.compatibility];
});
return results;
}
/**
* Get compatible background themes for a music mood
* @param {string} mood - Music mood
* @returns {Array} - Sorted array of { theme, compatibility }
*/
function getBackgroundsForMood(mood) {
var compat = MOOD_BACKGROUND_COMPAT[mood];
if (!compat) return [];
var results = [];
var allThemes = Object.keys(THEME_CONTEXT_COMPAT);
for (var i = 0; i < allThemes.length; i++) {
var theme = allThemes[i];
var level = getMoodBackgroundCompat(mood, theme);
results.push({ theme: theme, compatibility: level });
}
var order = { excellent: 0, good: 1, neutral: 2, poor: 3 };
results.sort(function(a, b) {
return order[a.compatibility] - order[b.compatibility];
});
return results;
}
/**
* Get compatible contexts for game mechanics
* @param {Array|string} mechanics - Game mechanics
* @returns {Array} - Array of context names with relevance scores
*/
function getContextsForMechanics(mechanics) {
var mechs = Array.isArray(mechanics) ? mechanics : [mechanics];
var contextScores = {};
for (var i = 0; i < mechs.length; i++) {
var mech = mechs[i];
var contexts = MECHANICS_CONTEXTS[mech];
if (contexts) {
for (var j = 0; j < contexts.length; j++) {
var ctx = contexts[j];
contextScores[ctx] = (contextScores[ctx] || 0) + 1;
}
}
}
var results = [];
var ctxNames = Object.keys(contextScores);
for (var i = 0; i < ctxNames.length; i++) {
results.push({
context: ctxNames[i],
relevance: contextScores[ctxNames[i]] / mechs.length
});
}
results.sort(function(a, b) {
return b.relevance - a.relevance;
});
return results;
}
/**
* Get compatible contexts for a background theme
* @param {string} theme - Background theme
* @returns {Array} - Sorted array of { context, compatibility }
*/
function getContextsForTheme(theme) {
var compat = THEME_CONTEXT_COMPAT[theme];
if (!compat) return [];
var results = [];
var allContexts = Object.keys(CONTEXT_ANIMATIONS);
for (var i = 0; i < allContexts.length; i++) {
var context = allContexts[i];
var level = getThemeContextCompat(theme, context);
results.push({ context: context, compatibility: level });
}
var order = { excellent: 0, good: 1, neutral: 2, poor: 3 };
results.sort(function(a, b) {
return order[a.compatibility] - order[b.compatibility];
});
return results;
}
/**
* Get compatible palettes for a background theme
* @param {string} theme - Background theme
* @returns {Array} - Array of palette names with compatibility
*/
function getPalettesForTheme(theme) {
var defaultPalettes = THEME_DEFAULT_PALETTES[theme] || [];
var results = [];
var allPalettes = Object.keys(PALETTE_HARMONY);
for (var i = 0; i < allPalettes.length; i++) {
var palette = allPalettes[i];
var isDefault = defaultPalettes.indexOf(palette) !== -1;
// Check harmony with default palettes
var harmony = 'neutral';
if (isDefault) {
harmony = 'excellent';
} else {
for (var j = 0; j < defaultPalettes.length; j++) {
var h = getPaletteHarmony(palette, defaultPalettes[j]);
if (h === 'harmonious') {
harmony = 'good';
break;
} else if (h === 'clash') {
harmony = 'poor';
}
}
}
results.push({ palette: palette, compatibility: harmony });
}
var order = { excellent: 0, good: 1, neutral: 2, poor: 3 };
results.sort(function(a, b) {
return order[a.compatibility] - order[b.compatibility];
});
return results;
}
/**
* Suggest improvements for a configuration
* @param {Object} config - Current configuration
* @returns {Array} - Array of suggestion objects
*/
function suggestImprovements(config) {
var suggestions = [];
var validation = validate(config);
if (validation.score >= 90) {
return suggestions;
}
// Analyze each issue and suggest fixes
for (var i = 0; i < validation.issues.length; i++) {
var issue = validation.issues[i];
if (issue.category === 'mood-background') {
var theme = config.background.theme || config.background;
var betterMoods = getMusicForTheme(theme)
.filter(function(m) { return m.compatibility === 'excellent' || m.compatibility === 'good'; })
.slice(0, 3);
if (betterMoods.length > 0) {
suggestions.push({
type: 'music',
message: 'Consider using music with mood: ' + betterMoods.map(function(m) { return m.mood; }).join(', '),
options: betterMoods
});
}
}
if (issue.category === 'theme-context') {
var context = config.avatarContext.context || config.avatarContext;
// Find better themes for this context
var betterThemes = [];
var themes = Object.keys(THEME_CONTEXT_COMPAT);
for (var j = 0; j < themes.length; j++) {
var compat = getThemeContextCompat(themes[j], context);
if (compat === 'excellent' || compat === 'good') {
betterThemes.push({ theme: themes[j], compatibility: compat });
}
}
if (betterThemes.length > 0) {
suggestions.push({
type: 'background',
message: 'Consider using background theme: ' + betterThemes.slice(0, 3).map(function(t) { return t.theme; }).join(', '),
options: betterThemes.slice(0, 5)
});
}
// Also suggest better contexts for current theme
var theme = config.background.theme || config.background;
var betterContexts = getContextsForTheme(theme)
.filter(function(c) { return c.compatibility === 'excellent' || c.compatibility === 'good'; })
.slice(0, 5);
if (betterContexts.length > 0) {
suggestions.push({
type: 'context',
message: 'Or consider avatar context: ' + betterContexts.slice(0, 3).map(function(c) { return c.context; }).join(', '),
options: betterContexts
});
}
}
if (issue.category === 'energy') {
var mood = config.music.mood || config.music;
var moodEnergy = MOOD_ENERGY[mood];
// Find contexts with matching energy
var matchingContexts = [];
var contexts = Object.keys(CONTEXT_ENERGY);
for (var j = 0; j < contexts.length; j++) {
if (CONTEXT_ENERGY[contexts[j]] === moodEnergy) {
matchingContexts.push(contexts[j]);
}
}
if (matchingContexts.length > 0) {
suggestions.push({
type: 'context',
message: 'For ' + moodEnergy + ' energy music, consider: ' + matchingContexts.slice(0, 4).join(', '),
options: matchingContexts.slice(0, 6).map(function(c) { return { context: c, energy: moodEnergy }; })
});
}
}
if (issue.category === 'animation' && issue.type === 'error') {
var context = config.avatarContext.context || config.avatarContext;
var contextAnims = CONTEXT_ANIMATIONS[context];
if (contextAnims && contextAnims.required) {
suggestions.push({
type: 'animation',
message: 'Required animations for "' + context + '": ' + contextAnims.required.join(', '),
options: contextAnims.required
});
}
}
if (issue.category === 'palette') {
var theme = config.background.theme || config.background;
var betterPalettes = getPalettesForTheme(theme)
.filter(function(p) { return p.compatibility === 'excellent' || p.compatibility === 'good'; })
.slice(0, 5);
if (betterPalettes.length > 0) {
suggestions.push({
type: 'palette',
message: 'Better palettes for "' + theme + '": ' + betterPalettes.map(function(p) { return p.palette; }).join(', '),
options: betterPalettes
});
}
}
}
return suggestions;
}
// ============================================================================
// CONVENIENCE FUNCTIONS
// ============================================================================
/**
* Get backgrounds compatible with a music mood
* @param {string} mood - Music mood
* @returns {Array} - Array of theme names (excellent and good only)
*/
function getCompatibleBackgrounds(mood) {
return getBackgroundsForMood(mood)
.filter(function(b) { return b.compatibility === 'excellent' || b.compatibility === 'good'; })
.map(function(b) { return b.theme; });
}
/**
* Get contexts compatible with a background theme
* @param {string} theme - Background theme
* @returns {Array} - Array of context names (excellent and good only)
*/
function getCompatibleContexts(theme) {
return getContextsForTheme(theme)
.filter(function(c) { return c.compatibility === 'excellent' || c.compatibility === 'good'; })
.map(function(c) { return c.context; });
}
/**
* Get palettes compatible with a background theme
* @param {string} theme - Background theme
* @returns {Array} - Array of palette names (excellent and good only)
*/
function getCompatiblePalettes(theme) {
return getPalettesForTheme(theme)
.filter(function(p) { return p.compatibility === 'excellent' || p.compatibility === 'good'; })
.map(function(p) { return p.palette; });
}
/**
* Get required animations for a context
* @param {string} context - Avatar context
* @returns {Array} - Array of required animation names
*/
function getRequiredAnimations(context) {
var anims = CONTEXT_ANIMATIONS[context];
return anims ? (anims.required || []) : [];
}
/**
* Get recommended animations for a context
* @param {string} context - Avatar context
* @returns {Array} - Array of recommended animation names
*/
function getRecommendedAnimations(context) {
var anims = CONTEXT_ANIMATIONS[context];
return anims ? (anims.recommended || []) : [];
}
/**
* Get all valid animations for a context
* @param {string} context - Avatar context
* @returns {Object} - { required, recommended, compatible }
*/
function getValidAnimations(context) {
var anims = CONTEXT_ANIMATIONS[context];
if (!anims) {
return { required: [], recommended: [], incompatible: [] };
}
return {
required: anims.required || [],
recommended: anims.recommended || [],
incompatible: anims.incompatible || []
};
}
/**
* Check if a complete asset set is compatible
* @param {string} mood - Music mood
* @param {string} theme - Background theme
* @param {string} context - Avatar context
* @returns {Object} - { compatible, score, issues }
*/
function checkFullCompatibility(mood, theme, context) {
return validate({
music: { mood: mood },
background: { theme: theme },
avatarContext: { context: context }
});
}
// ============================================================================
// PUBLIC API
// ============================================================================
window.AssetCompatibility = {
// Validation
validate: validate,
checkFullCompatibility: checkFullCompatibility,
// Compatibility checks
getMoodBackgroundCompat: getMoodBackgroundCompat,
getThemeContextCompat: getThemeContextCompat,
getContextAnimationCompat: getContextAnimationCompat,
getPaletteHarmony: getPaletteHarmony,
// Suggestions
getMusicForTheme: getMusicForTheme,
getBackgroundsForMood: getBackgroundsForMood,
getContextsForTheme: getContextsForTheme,
getContextsForMechanics: getContextsForMechanics,
getPalettesForTheme: getPalettesForTheme,
suggestImprovements: suggestImprovements,
// Get compatible options (convenience methods)
getCompatibleBackgrounds: getCompatibleBackgrounds,
getCompatibleContexts: getCompatibleContexts,
getCompatiblePalettes: getCompatiblePalettes,
// Animation helpers
getRequiredAnimations: getRequiredAnimations,
getRecommendedAnimations: getRecommendedAnimations,
getValidAnimations: getValidAnimations,
// Raw data
MOOD_BACKGROUND_COMPAT: MOOD_BACKGROUND_COMPAT,
THEME_CONTEXT_COMPAT: THEME_CONTEXT_COMPAT,
CONTEXT_ANIMATIONS: CONTEXT_ANIMATIONS,
PALETTE_HARMONY: PALETTE_HARMONY,
MOOD_ENERGY: MOOD_ENERGY,
CONTEXT_ENERGY: CONTEXT_ENERGY,
THEME_DEFAULT_PALETTES: THEME_DEFAULT_PALETTES,
MECHANICS_CONTEXTS: MECHANICS_CONTEXTS
};
})();