All files / systems/animation AnimationCategory.ts

96.07% Statements 49/51
96.55% Branches 56/58
66.66% Functions 2/3
94.73% Lines 36/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136                                              1x     1x     1x       1x     1x       1x     1x       1x     1x     1x     1x     1x       1x     1x       1x       1x               51x     51x 9x 7x       42x 3x       39x 12x       27x 24x     24x 20x 13x 11x 10x     10x 8x     5x     4x     3x                          
/**
 * Animation Type Categories
 * 애니메이션 타입 분류
 *
 * Represents CATEGORIES of animations, not unique instances.
 * Multiple techniques can share the same AnimationType.
 * Each technique has a unique AnimationId for 1-1 mapping.
 *
 * PROPER ARCHITECTURE:
 * - AnimationType: Category (shared) - "What kind of animation?"
 * - AnimationId: Unique ID (1-1 with TechniqueId) - "Which specific animation?"
 *
 * @module systems/animation/AnimationCategory
 * @korean 애니메이션분류
 */
 
/**
 * Animation Type Categories
 * 
 * These represent broad categories of animations that can be
 * shared across multiple techniques. The animation system uses
 * these for categorization, fallbacks, and animation blending.
 */
export enum AnimationCategory {
  // ═══ STRIKING (타격) ═══
  /** Straight punches - jabs, crosses, straights */
  PUNCH = "punch",
  
  /** General strikes - palm, nerve, pressure point strikes */
  STRIKE = "strike",
 
  // ═══ KICKING (발차기) ═══
  /** General kicks - consolidated category for all kick types */
  KICK = "kick",
  
  /** Jumping/flying kicks - aerial kicks */
  JUMPING_KICK = "jumping_kick",
 
  // ═══ ELBOW/KNEE (팔꿈치/무릎) ═══
  /** Elbow strikes */
  ELBOW_STRIKE = "elbow_strike",
  
  /** Knee strikes */
  KNEE_STRIKE = "knee_strike",
 
  // ═══ GRAPPLING (잡기) ═══
  /** Throwing techniques - hip throws, shoulder throws */
  THROW = "throw",
  
  /** Joint locks - arm bars, wrist locks, shoulder locks */
  JOINT_LOCK = "joint_lock",
  
  /** Takedowns - single/double leg, body locks */
  TAKEDOWN = "takedown",
  
  /** Sweeps - leg sweeps, ankle picks */
  SWEEP = "sweep",
  
  /** General grappling control */
  GRAPPLE = "grapple",
 
  // ═══ DEFENSIVE (방어) ═══
  /** Defensive techniques - blocks, parries, guards */
  DEFENSIVE = "defensive",
  
  /** Counter techniques - defensive counters */
  COUNTER = "counter",
 
  // ═══ MOVEMENT (이동) ═══
  /** Footwork and repositioning */
  FOOTWORK = "footwork",
 
  // ═══ STANCE (자세) ═══
  /** Idle/ready stance */
  STANCE = "stance",
}
 
/**
 * Helper to get category from detailed animation name
 * Returns consolidated categories matching the 15-category system
 */
export function getAnimationCategoryFromId(animationId: string): AnimationCategory {
  const id = animationId.toLowerCase();
  
  // Kicks - all consolidated to KICK except jumping
  if (id.includes('kick')) {
    if (id.includes('jump') || id.includes('fly')) return AnimationCategory.JUMPING_KICK;
    return AnimationCategory.KICK;
  }
  
  // Punches
  if (id.includes('punch') || id.includes('jab') || id.includes('cross') || id.includes('fist') || id.includes('barrage') || id.includes('flash')) {
    return AnimationCategory.PUNCH;
  }
  
  // Strikes - palm, nerve, pressure point, spear, temple
  if (id.includes('palm') || id.includes('spear') || id.includes('nerve') || id.includes('pressure') || id.includes('plexus') || id.includes('temple') || id.includes('strike') || id.includes('flame') || id.includes('push')) {
    return AnimationCategory.STRIKE;
  }
  
  // Elbow/knee
  if (id.includes('elbow')) return AnimationCategory.ELBOW_STRIKE;
  Iif (id.includes('knee')) return AnimationCategory.KNEE_STRIKE;
  
  // Grappling
  if (id.includes('throw')) return AnimationCategory.THROW;
  if (id.includes('lock')) return AnimationCategory.JOINT_LOCK;
  if (id.includes('sweep') || id.includes('pick')) return AnimationCategory.SWEEP;
  if (id.includes('grapple') || id.includes('embrace')) return AnimationCategory.GRAPPLE;
  Iif (id.includes('takedown')) return AnimationCategory.TAKEDOWN;
  
  // Defense - block, parry, defense
  if (id.includes('block') || id.includes('parry') || id.includes('defense')) return AnimationCategory.DEFENSIVE;
  if (id.includes('counter') || id.includes('reversal')) return AnimationCategory.COUNTER;
  
  // Movement
  if (id.includes('footwork')) return AnimationCategory.FOOTWORK;
  
  // Stance
  if (id.includes('stance')) return AnimationCategory.STANCE;
  
  // Default fallback
  return AnimationCategory.STANCE;
}
 
/**
 * Validate that an animation ID matches its declared category
 */
export function validateAnimationCategory(
  animationId: string,
  declaredCategory: AnimationCategory
): boolean {
  const inferredCategory = getAnimationCategoryFromId(animationId);
  return inferredCategory === declaredCategory;
}