playlist-data-engine 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +352 -0
  3. package/dist/__vite-browser-external-DYxpcVy9.js +4 -0
  4. package/dist/constants/DefaultClasses.d.ts +46 -0
  5. package/dist/constants/DefaultClasses.d.ts.map +1 -0
  6. package/dist/constants/DefaultEnchantments.d.ts +337 -0
  7. package/dist/constants/DefaultEnchantments.d.ts.map +1 -0
  8. package/dist/constants/DefaultEnemies.d.ts +83 -0
  9. package/dist/constants/DefaultEnemies.d.ts.map +1 -0
  10. package/dist/constants/DefaultEquipment.d.ts +23 -0
  11. package/dist/constants/DefaultEquipment.d.ts.map +1 -0
  12. package/dist/constants/DefaultFeatures.d.ts +22 -0
  13. package/dist/constants/DefaultFeatures.d.ts.map +1 -0
  14. package/dist/constants/DefaultRaces.d.ts +102 -0
  15. package/dist/constants/DefaultRaces.d.ts.map +1 -0
  16. package/dist/constants/DefaultSkills.d.ts +26 -0
  17. package/dist/constants/DefaultSkills.d.ts.map +1 -0
  18. package/dist/constants/DefaultSpells.d.ts +41 -0
  19. package/dist/constants/DefaultSpells.d.ts.map +1 -0
  20. package/dist/constants/EncounterBalance.d.ts +208 -0
  21. package/dist/constants/EncounterBalance.d.ts.map +1 -0
  22. package/dist/constants/EnemyEquipment.d.ts +71 -0
  23. package/dist/constants/EnemyEquipment.d.ts.map +1 -0
  24. package/dist/constants/EnemyRarity.d.ts +79 -0
  25. package/dist/constants/EnemyRarity.d.ts.map +1 -0
  26. package/dist/constants/EnemyTemplates/Construct.d.ts +63 -0
  27. package/dist/constants/EnemyTemplates/Construct.d.ts.map +1 -0
  28. package/dist/constants/EnemyTemplates/Dragon.d.ts +68 -0
  29. package/dist/constants/EnemyTemplates/Dragon.d.ts.map +1 -0
  30. package/dist/constants/EnemyTemplates/Elemental.d.ts +64 -0
  31. package/dist/constants/EnemyTemplates/Elemental.d.ts.map +1 -0
  32. package/dist/constants/EnemyTemplates/Fiend.d.ts +62 -0
  33. package/dist/constants/EnemyTemplates/Fiend.d.ts.map +1 -0
  34. package/dist/constants/EnemyTemplates/Monstrosity.d.ts +63 -0
  35. package/dist/constants/EnemyTemplates/Monstrosity.d.ts.map +1 -0
  36. package/dist/constants/EnemyTemplates/Undead.d.ts +61 -0
  37. package/dist/constants/EnemyTemplates/Undead.d.ts.map +1 -0
  38. package/dist/constants/ItemTemplates.d.ts +40 -0
  39. package/dist/constants/ItemTemplates.d.ts.map +1 -0
  40. package/dist/constants/MagicItems.d.ts +30 -0
  41. package/dist/constants/MagicItems.d.ts.map +1 -0
  42. package/dist/constants/SpellSlots.d.ts +30 -0
  43. package/dist/constants/SpellSlots.d.ts.map +1 -0
  44. package/dist/constants/StatScaling.d.ts +113 -0
  45. package/dist/constants/StatScaling.d.ts.map +1 -0
  46. package/dist/core/analysis/AudioAnalyzer.d.ts +599 -0
  47. package/dist/core/analysis/AudioAnalyzer.d.ts.map +1 -0
  48. package/dist/core/analysis/ColorExtractor.d.ts +64 -0
  49. package/dist/core/analysis/ColorExtractor.d.ts.map +1 -0
  50. package/dist/core/analysis/EssentiaPitchDetector.d.ts +282 -0
  51. package/dist/core/analysis/EssentiaPitchDetector.d.ts.map +1 -0
  52. package/dist/core/analysis/LevelSerializer.d.ts +265 -0
  53. package/dist/core/analysis/LevelSerializer.d.ts.map +1 -0
  54. package/dist/core/analysis/MelodyContourAnalyzer.d.ts +283 -0
  55. package/dist/core/analysis/MelodyContourAnalyzer.d.ts.map +1 -0
  56. package/dist/core/analysis/MultiBandAnalyzer.d.ts +214 -0
  57. package/dist/core/analysis/MultiBandAnalyzer.d.ts.map +1 -0
  58. package/dist/core/analysis/MusicClassifier.d.ts +524 -0
  59. package/dist/core/analysis/MusicClassifier.d.ts.map +1 -0
  60. package/dist/core/analysis/PitchAnalyzer.d.ts +266 -0
  61. package/dist/core/analysis/PitchAnalyzer.d.ts.map +1 -0
  62. package/dist/core/analysis/PitchDetector.d.ts +251 -0
  63. package/dist/core/analysis/PitchDetector.d.ts.map +1 -0
  64. package/dist/core/analysis/SpectrumScanner.d.ts +52 -0
  65. package/dist/core/analysis/SpectrumScanner.d.ts.map +1 -0
  66. package/dist/core/analysis/beat/BeatInterpolator.d.ts +477 -0
  67. package/dist/core/analysis/beat/BeatInterpolator.d.ts.map +1 -0
  68. package/dist/core/analysis/beat/BeatMapGenerator.d.ts +170 -0
  69. package/dist/core/analysis/beat/BeatMapGenerator.d.ts.map +1 -0
  70. package/dist/core/analysis/beat/BeatStream.d.ts +316 -0
  71. package/dist/core/analysis/beat/BeatStream.d.ts.map +1 -0
  72. package/dist/core/analysis/beat/BeatSubdivider.d.ts +205 -0
  73. package/dist/core/analysis/beat/BeatSubdivider.d.ts.map +1 -0
  74. package/dist/core/analysis/beat/BeatTracker.d.ts +137 -0
  75. package/dist/core/analysis/beat/BeatTracker.d.ts.map +1 -0
  76. package/dist/core/analysis/beat/CompositeStreamGenerator.d.ts +180 -0
  77. package/dist/core/analysis/beat/CompositeStreamGenerator.d.ts.map +1 -0
  78. package/dist/core/analysis/beat/DensityAnalyzer.d.ts +246 -0
  79. package/dist/core/analysis/beat/DensityAnalyzer.d.ts.map +1 -0
  80. package/dist/core/analysis/beat/DifficultyVariantGenerator.d.ts +1082 -0
  81. package/dist/core/analysis/beat/DifficultyVariantGenerator.d.ts.map +1 -0
  82. package/dist/core/analysis/beat/GrooveAnalyzer.d.ts +192 -0
  83. package/dist/core/analysis/beat/GrooveAnalyzer.d.ts.map +1 -0
  84. package/dist/core/analysis/beat/OnsetStrengthEnvelope.d.ts +133 -0
  85. package/dist/core/analysis/beat/OnsetStrengthEnvelope.d.ts.map +1 -0
  86. package/dist/core/analysis/beat/PhraseAnalyzer.d.ts +230 -0
  87. package/dist/core/analysis/beat/PhraseAnalyzer.d.ts.map +1 -0
  88. package/dist/core/analysis/beat/RhythmQuantizer.d.ts +399 -0
  89. package/dist/core/analysis/beat/RhythmQuantizer.d.ts.map +1 -0
  90. package/dist/core/analysis/beat/RhythmicBalancer.d.ts +262 -0
  91. package/dist/core/analysis/beat/RhythmicBalancer.d.ts.map +1 -0
  92. package/dist/core/analysis/beat/StreamScorer.d.ts +275 -0
  93. package/dist/core/analysis/beat/StreamScorer.d.ts.map +1 -0
  94. package/dist/core/analysis/beat/TempoAwareQuantizer.d.ts +256 -0
  95. package/dist/core/analysis/beat/TempoAwareQuantizer.d.ts.map +1 -0
  96. package/dist/core/analysis/beat/TempoDetector.d.ts +220 -0
  97. package/dist/core/analysis/beat/TempoDetector.d.ts.map +1 -0
  98. package/dist/core/analysis/beat/TransientDetector.d.ts +303 -0
  99. package/dist/core/analysis/beat/TransientDetector.d.ts.map +1 -0
  100. package/dist/core/analysis/beat/beatKeyHelpers.d.ts +180 -0
  101. package/dist/core/analysis/beat/beatKeyHelpers.d.ts.map +1 -0
  102. package/dist/core/analysis/beat/index.d.ts +41 -0
  103. package/dist/core/analysis/beat/index.d.ts.map +1 -0
  104. package/dist/core/analysis/beat/utils/audioUtils.d.ts +204 -0
  105. package/dist/core/analysis/beat/utils/audioUtils.d.ts.map +1 -0
  106. package/dist/core/analysis/beat/utils/beatInterpolationDebug.d.ts +404 -0
  107. package/dist/core/analysis/beat/utils/beatInterpolationDebug.d.ts.map +1 -0
  108. package/dist/core/analysis/beat/utils/subdivideBeatMap.d.ts +61 -0
  109. package/dist/core/analysis/beat/utils/subdivideBeatMap.d.ts.map +1 -0
  110. package/dist/core/analysis/beat/utils/unifyBeatMap.d.ts +33 -0
  111. package/dist/core/analysis/beat/utils/unifyBeatMap.d.ts.map +1 -0
  112. package/dist/core/analysis/index.d.ts +18 -0
  113. package/dist/core/analysis/index.d.ts.map +1 -0
  114. package/dist/core/combat/AI/AICombatRunner.d.ts +108 -0
  115. package/dist/core/combat/AI/AICombatRunner.d.ts.map +1 -0
  116. package/dist/core/combat/AI/CombatAI.d.ts +179 -0
  117. package/dist/core/combat/AI/CombatAI.d.ts.map +1 -0
  118. package/dist/core/combat/AI/CombatMetricsTracker.d.ts +30 -0
  119. package/dist/core/combat/AI/CombatMetricsTracker.d.ts.map +1 -0
  120. package/dist/core/combat/Analysis/BalanceValidator.d.ts +170 -0
  121. package/dist/core/combat/Analysis/BalanceValidator.d.ts.map +1 -0
  122. package/dist/core/combat/Analysis/ComparativeAnalyzer.d.ts +231 -0
  123. package/dist/core/combat/Analysis/ComparativeAnalyzer.d.ts.map +1 -0
  124. package/dist/core/combat/Analysis/DifficultyCalculator.d.ts +203 -0
  125. package/dist/core/combat/Analysis/DifficultyCalculator.d.ts.map +1 -0
  126. package/dist/core/combat/Analysis/ParameterSweep.d.ts +201 -0
  127. package/dist/core/combat/Analysis/ParameterSweep.d.ts.map +1 -0
  128. package/dist/core/combat/AttackResolver.d.ts +220 -0
  129. package/dist/core/combat/AttackResolver.d.ts.map +1 -0
  130. package/dist/core/combat/CombatEngine.d.ts +388 -0
  131. package/dist/core/combat/CombatEngine.d.ts.map +1 -0
  132. package/dist/core/combat/DiceRoller.d.ts +115 -0
  133. package/dist/core/combat/DiceRoller.d.ts.map +1 -0
  134. package/dist/core/combat/InitiativeRoller.d.ts +62 -0
  135. package/dist/core/combat/InitiativeRoller.d.ts.map +1 -0
  136. package/dist/core/combat/PartyAnalyzer.d.ts +215 -0
  137. package/dist/core/combat/PartyAnalyzer.d.ts.map +1 -0
  138. package/dist/core/combat/SeededDiceRoller.d.ts +120 -0
  139. package/dist/core/combat/SeededDiceRoller.d.ts.map +1 -0
  140. package/dist/core/combat/Simulation/CombatSimulator.d.ts +366 -0
  141. package/dist/core/combat/Simulation/CombatSimulator.d.ts.map +1 -0
  142. package/dist/core/combat/SpellCaster.d.ts +113 -0
  143. package/dist/core/combat/SpellCaster.d.ts.map +1 -0
  144. package/dist/core/config/index.d.ts +24 -0
  145. package/dist/core/config/index.d.ts.map +1 -0
  146. package/dist/core/config/progressionConfig.d.ts +73 -0
  147. package/dist/core/config/progressionConfig.d.ts.map +1 -0
  148. package/dist/core/config/sensorConfig.d.ts +134 -0
  149. package/dist/core/config/sensorConfig.d.ts.map +1 -0
  150. package/dist/core/equipment/BoxOpener.d.ts +175 -0
  151. package/dist/core/equipment/BoxOpener.d.ts.map +1 -0
  152. package/dist/core/equipment/EquipmentEffectApplier.d.ts +189 -0
  153. package/dist/core/equipment/EquipmentEffectApplier.d.ts.map +1 -0
  154. package/dist/core/equipment/EquipmentModifier.d.ts +327 -0
  155. package/dist/core/equipment/EquipmentModifier.d.ts.map +1 -0
  156. package/dist/core/equipment/EquipmentSpawnHelper.d.ts +246 -0
  157. package/dist/core/equipment/EquipmentSpawnHelper.d.ts.map +1 -0
  158. package/dist/core/equipment/EquipmentValidator.d.ts +173 -0
  159. package/dist/core/equipment/EquipmentValidator.d.ts.map +1 -0
  160. package/dist/core/extensions/ExtensionManager.d.ts +517 -0
  161. package/dist/core/extensions/ExtensionManager.d.ts.map +1 -0
  162. package/dist/core/extensions/WeightedSelector.d.ts +156 -0
  163. package/dist/core/extensions/WeightedSelector.d.ts.map +1 -0
  164. package/dist/core/extensions/index.d.ts +11 -0
  165. package/dist/core/extensions/index.d.ts.map +1 -0
  166. package/dist/core/extensions/initializeDefaults.d.ts +170 -0
  167. package/dist/core/extensions/initializeDefaults.d.ts.map +1 -0
  168. package/dist/core/features/FeatureEffectApplier.d.ts +102 -0
  169. package/dist/core/features/FeatureEffectApplier.d.ts.map +1 -0
  170. package/dist/core/features/FeatureQuery.d.ts +368 -0
  171. package/dist/core/features/FeatureQuery.d.ts.map +1 -0
  172. package/dist/core/features/FeatureTypes.d.ts +199 -0
  173. package/dist/core/features/FeatureTypes.d.ts.map +1 -0
  174. package/dist/core/features/FeatureValidator.d.ts +149 -0
  175. package/dist/core/features/FeatureValidator.d.ts.map +1 -0
  176. package/dist/core/features/index.d.ts +12 -0
  177. package/dist/core/features/index.d.ts.map +1 -0
  178. package/dist/core/generation/AbilityScoreCalculator.d.ts +83 -0
  179. package/dist/core/generation/AbilityScoreCalculator.d.ts.map +1 -0
  180. package/dist/core/generation/AppearanceGenerator.d.ts +32 -0
  181. package/dist/core/generation/AppearanceGenerator.d.ts.map +1 -0
  182. package/dist/core/generation/BeatConverter.d.ts +127 -0
  183. package/dist/core/generation/BeatConverter.d.ts.map +1 -0
  184. package/dist/core/generation/ButtonMapper.d.ts +346 -0
  185. package/dist/core/generation/ButtonMapper.d.ts.map +1 -0
  186. package/dist/core/generation/ButtonPatternLibrary.d.ts +92 -0
  187. package/dist/core/generation/ButtonPatternLibrary.d.ts.map +1 -0
  188. package/dist/core/generation/CRLevelConverter.d.ts +242 -0
  189. package/dist/core/generation/CRLevelConverter.d.ts.map +1 -0
  190. package/dist/core/generation/CharacterGenerator.d.ts +194 -0
  191. package/dist/core/generation/CharacterGenerator.d.ts.map +1 -0
  192. package/dist/core/generation/ClassSuggester.d.ts +184 -0
  193. package/dist/core/generation/ClassSuggester.d.ts.map +1 -0
  194. package/dist/core/generation/EnemyEquipmentGenerator.d.ts +151 -0
  195. package/dist/core/generation/EnemyEquipmentGenerator.d.ts.map +1 -0
  196. package/dist/core/generation/EnemyGenerator.d.ts +595 -0
  197. package/dist/core/generation/EnemyGenerator.d.ts.map +1 -0
  198. package/dist/core/generation/EquipmentGenerator.d.ts +204 -0
  199. package/dist/core/generation/EquipmentGenerator.d.ts.map +1 -0
  200. package/dist/core/generation/LegendaryGenerator.d.ts +213 -0
  201. package/dist/core/generation/LegendaryGenerator.d.ts.map +1 -0
  202. package/dist/core/generation/LevelGenerator.d.ts +390 -0
  203. package/dist/core/generation/LevelGenerator.d.ts.map +1 -0
  204. package/dist/core/generation/NamingEngine.d.ts +136 -0
  205. package/dist/core/generation/NamingEngine.d.ts.map +1 -0
  206. package/dist/core/generation/PitchBeatLinker.d.ts +150 -0
  207. package/dist/core/generation/PitchBeatLinker.d.ts.map +1 -0
  208. package/dist/core/generation/RaceSelector.d.ts +58 -0
  209. package/dist/core/generation/RaceSelector.d.ts.map +1 -0
  210. package/dist/core/generation/RhythmGenerator.d.ts +597 -0
  211. package/dist/core/generation/RhythmGenerator.d.ts.map +1 -0
  212. package/dist/core/generation/SkillAssigner.d.ts +78 -0
  213. package/dist/core/generation/SkillAssigner.d.ts.map +1 -0
  214. package/dist/core/generation/SpellManager.d.ts +132 -0
  215. package/dist/core/generation/SpellManager.d.ts.map +1 -0
  216. package/dist/core/generation/SpellcastingGenerator.d.ts +255 -0
  217. package/dist/core/generation/SpellcastingGenerator.d.ts.map +1 -0
  218. package/dist/core/generation/index.d.ts +41 -0
  219. package/dist/core/generation/index.d.ts.map +1 -0
  220. package/dist/core/parser/MetadataExtractor.d.ts +66 -0
  221. package/dist/core/parser/MetadataExtractor.d.ts.map +1 -0
  222. package/dist/core/parser/PlaylistParser.d.ts +45 -0
  223. package/dist/core/parser/PlaylistParser.d.ts.map +1 -0
  224. package/dist/core/playback/SubdivisionPlaybackController.d.ts +333 -0
  225. package/dist/core/playback/SubdivisionPlaybackController.d.ts.map +1 -0
  226. package/dist/core/playback/index.d.ts +5 -0
  227. package/dist/core/playback/index.d.ts.map +1 -0
  228. package/dist/core/progression/CharacterUpdater.d.ts +203 -0
  229. package/dist/core/progression/CharacterUpdater.d.ts.map +1 -0
  230. package/dist/core/progression/LevelUpProcessor.d.ts +234 -0
  231. package/dist/core/progression/LevelUpProcessor.d.ts.map +1 -0
  232. package/dist/core/progression/PrestigeSystem.d.ts +217 -0
  233. package/dist/core/progression/PrestigeSystem.d.ts.map +1 -0
  234. package/dist/core/progression/RhythmXPCalculator.d.ts +182 -0
  235. package/dist/core/progression/RhythmXPCalculator.d.ts.map +1 -0
  236. package/dist/core/progression/SessionTracker.d.ts +169 -0
  237. package/dist/core/progression/SessionTracker.d.ts.map +1 -0
  238. package/dist/core/progression/XPCalculator.d.ts +128 -0
  239. package/dist/core/progression/XPCalculator.d.ts.map +1 -0
  240. package/dist/core/progression/stat/StatIncreaseStrategy.d.ts +97 -0
  241. package/dist/core/progression/stat/StatIncreaseStrategy.d.ts.map +1 -0
  242. package/dist/core/progression/stat/StatManager.d.ts +179 -0
  243. package/dist/core/progression/stat/StatManager.d.ts.map +1 -0
  244. package/dist/core/sensors/EnvironmentalSensors.d.ts +301 -0
  245. package/dist/core/sensors/EnvironmentalSensors.d.ts.map +1 -0
  246. package/dist/core/sensors/GamingPlatformSensors.d.ts +162 -0
  247. package/dist/core/sensors/GamingPlatformSensors.d.ts.map +1 -0
  248. package/dist/core/sensors/GeolocationProvider.d.ts +156 -0
  249. package/dist/core/sensors/GeolocationProvider.d.ts.map +1 -0
  250. package/dist/core/sensors/MotionDetector.d.ts +58 -0
  251. package/dist/core/sensors/MotionDetector.d.ts.map +1 -0
  252. package/dist/core/sensors/SteamAPIClient.d.ts +108 -0
  253. package/dist/core/sensors/SteamAPIClient.d.ts.map +1 -0
  254. package/dist/core/sensors/WeatherAPIClient.d.ts +360 -0
  255. package/dist/core/sensors/WeatherAPIClient.d.ts.map +1 -0
  256. package/dist/core/sensors/schemas/weather.schema.d.ts +144 -0
  257. package/dist/core/sensors/schemas/weather.schema.d.ts.map +1 -0
  258. package/dist/core/skills/SkillQuery.d.ts +159 -0
  259. package/dist/core/skills/SkillQuery.d.ts.map +1 -0
  260. package/dist/core/skills/SkillTypes.d.ts +233 -0
  261. package/dist/core/skills/SkillTypes.d.ts.map +1 -0
  262. package/dist/core/skills/SkillValidator.d.ts +146 -0
  263. package/dist/core/skills/SkillValidator.d.ts.map +1 -0
  264. package/dist/core/skills/index.d.ts +11 -0
  265. package/dist/core/skills/index.d.ts.map +1 -0
  266. package/dist/core/spells/SpellQuery.d.ts +194 -0
  267. package/dist/core/spells/SpellQuery.d.ts.map +1 -0
  268. package/dist/core/spells/SpellTypes.d.ts +71 -0
  269. package/dist/core/spells/SpellTypes.d.ts.map +1 -0
  270. package/dist/core/spells/SpellValidator.d.ts +129 -0
  271. package/dist/core/spells/SpellValidator.d.ts.map +1 -0
  272. package/dist/core/spells/index.d.ts +11 -0
  273. package/dist/core/spells/index.d.ts.map +1 -0
  274. package/dist/core/types/AudioProfile.d.ts +143 -0
  275. package/dist/core/types/AudioProfile.d.ts.map +1 -0
  276. package/dist/core/types/BeatMap.d.ts +1825 -0
  277. package/dist/core/types/BeatMap.d.ts.map +1 -0
  278. package/dist/core/types/ButtonMapping.d.ts +345 -0
  279. package/dist/core/types/ButtonMapping.d.ts.map +1 -0
  280. package/dist/core/types/Character.d.ts +397 -0
  281. package/dist/core/types/Character.d.ts.map +1 -0
  282. package/dist/core/types/ChartedBeatMap.d.ts +169 -0
  283. package/dist/core/types/ChartedBeatMap.d.ts.map +1 -0
  284. package/dist/core/types/Combat.d.ts +268 -0
  285. package/dist/core/types/Combat.d.ts.map +1 -0
  286. package/dist/core/types/CombatAI.d.ts +143 -0
  287. package/dist/core/types/CombatAI.d.ts.map +1 -0
  288. package/dist/core/types/Enemy.d.ts +447 -0
  289. package/dist/core/types/Enemy.d.ts.map +1 -0
  290. package/dist/core/types/Environmental.d.ts +213 -0
  291. package/dist/core/types/Environmental.d.ts.map +1 -0
  292. package/dist/core/types/Equipment.d.ts +309 -0
  293. package/dist/core/types/Equipment.d.ts.map +1 -0
  294. package/dist/core/types/ISessionTracker.d.ts +48 -0
  295. package/dist/core/types/ISessionTracker.d.ts.map +1 -0
  296. package/dist/core/types/LevelExport.d.ts +366 -0
  297. package/dist/core/types/LevelExport.d.ts.map +1 -0
  298. package/dist/core/types/Playlist.d.ts +70 -0
  299. package/dist/core/types/Playlist.d.ts.map +1 -0
  300. package/dist/core/types/Prestige.d.ts +94 -0
  301. package/dist/core/types/Prestige.d.ts.map +1 -0
  302. package/dist/core/types/Progression.d.ts +214 -0
  303. package/dist/core/types/Progression.d.ts.map +1 -0
  304. package/dist/core/types/RhythmXP.d.ts +398 -0
  305. package/dist/core/types/RhythmXP.d.ts.map +1 -0
  306. package/dist/core/utils/AbilityConstants.d.ts +31 -0
  307. package/dist/core/utils/AbilityConstants.d.ts.map +1 -0
  308. package/dist/core/utils/EffectApplierUtils.d.ts +56 -0
  309. package/dist/core/utils/EffectApplierUtils.d.ts.map +1 -0
  310. package/dist/core/utils/ImageValidator.d.ts +66 -0
  311. package/dist/core/utils/ImageValidator.d.ts.map +1 -0
  312. package/dist/core/utils/PrerequisiteValidator.d.ts +88 -0
  313. package/dist/core/utils/PrerequisiteValidator.d.ts.map +1 -0
  314. package/dist/essentia-wasm.es-BUEnKUts.js +2990 -0
  315. package/dist/essentia.js-model.es-CGA0xotH.js +306 -0
  316. package/dist/index.d.ts +176 -0
  317. package/dist/index.d.ts.map +1 -0
  318. package/dist/playlist-data-engine.js +124 -0
  319. package/dist/playlist-data-engine.mjs +49251 -0
  320. package/dist/utils/EnchantmentLibrary.d.ts +378 -0
  321. package/dist/utils/EnchantmentLibrary.d.ts.map +1 -0
  322. package/dist/utils/arweaveGatewayManager.d.ts +485 -0
  323. package/dist/utils/arweaveGatewayManager.d.ts.map +1 -0
  324. package/dist/utils/arweaveUtils.d.ts +118 -0
  325. package/dist/utils/arweaveUtils.d.ts.map +1 -0
  326. package/dist/utils/constants.d.ts +439 -0
  327. package/dist/utils/constants.d.ts.map +1 -0
  328. package/dist/utils/equipmentConstants.d.ts +60 -0
  329. package/dist/utils/equipmentConstants.d.ts.map +1 -0
  330. package/dist/utils/hash.d.ts +33 -0
  331. package/dist/utils/hash.d.ts.map +1 -0
  332. package/dist/utils/logger.d.ts +192 -0
  333. package/dist/utils/logger.d.ts.map +1 -0
  334. package/dist/utils/magicItemExamples.d.ts +46 -0
  335. package/dist/utils/magicItemExamples.d.ts.map +1 -0
  336. package/dist/utils/playlistUtils.d.ts +149 -0
  337. package/dist/utils/playlistUtils.d.ts.map +1 -0
  338. package/dist/utils/random.d.ts +34 -0
  339. package/dist/utils/random.d.ts.map +1 -0
  340. package/dist/utils/sensorDashboard.d.ts +60 -0
  341. package/dist/utils/sensorDashboard.d.ts.map +1 -0
  342. package/dist/utils/validators.d.ts +189 -0
  343. package/dist/utils/validators.d.ts.map +1 -0
  344. package/dist/vite.svg +1 -0
  345. package/package.json +82 -0
@@ -0,0 +1,1082 @@
1
+ /**
2
+ * Difficulty Variant Generator for Procedural Rhythm Generation
3
+ *
4
+ * Generates difficulty variants (easy/medium/hard) from the composite stream
5
+ * by simplifying or enhancing density based on natural difficulty.
6
+ *
7
+ * Part of the Procedural Rhythm Generation pipeline - Phase 3.3
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // Basic usage - generate all 3 difficulty variants
12
+ * const generator = new DifficultyVariantGenerator();
13
+ * const variants = generator.generateAll(compositeStream, phraseAnalysis, gridDecisions);
14
+ *
15
+ * // Access each difficulty variant
16
+ * const easyVariant = variants.easy;
17
+ * const mediumVariant = variants.medium;
18
+ * const hardVariant = variants.hard;
19
+ *
20
+ * // Check which variant is unedited (natural difficulty)
21
+ * console.log(`Easy is unedited: ${easyVariant.isUnedited}`);
22
+ * console.log(`Medium is unedited: ${mediumVariant.isUnedited}`);
23
+ * console.log(`Hard is unedited: ${hardVariant.isUnedited}`);
24
+ *
25
+ * // Check edit details
26
+ * console.log(`Medium edit type: ${mediumVariant.editType}`);
27
+ * console.log(`Medium edit amount: ${mediumVariant.editAmount.toFixed(2)}`);
28
+ *
29
+ * // Custom configuration for phrase boundary preservation
30
+ * const customGenerator = new DifficultyVariantGenerator({
31
+ * preservePhraseBoundaries: true,
32
+ * logConversions: true,
33
+ * });
34
+ * ```
35
+ */
36
+ import type { CompositeBeat, CompositeStream } from './CompositeStreamGenerator.js';
37
+ import type { NaturalDifficulty } from './DensityAnalyzer.js';
38
+ import type { GridType, GridDecision } from './RhythmQuantizer.js';
39
+ import type { PhraseAnalysisResult } from './PhraseAnalyzer.js';
40
+ import type { UnifiedBeatMap } from '../../types/BeatMap.js';
41
+ import type { RhythmicBalanceConfig } from './RhythmicBalancer.js';
42
+ /**
43
+ * Extended grid type including simplified subdivisions for Easy difficulty
44
+ *
45
+ * - `straight_16th`: Standard 16th note grid (4 positions per beat: 0, 1, 2, 3)
46
+ * - `triplet_8th`: 8th note triplet grid (3 positions per beat: 0, 1, 2)
47
+ * - `straight_8th`: Standard 8th note grid (2 positions per beat: 0, 2)
48
+ * - `quarter_triplet`: Quarter note triplet (1 position per beat, triplet feel)
49
+ * - `straight_4th`: Quarter note grid (1 position per beat: 0) — Easy at BPM > 120
50
+ */
51
+ export type ExtendedGridType = GridType | 'straight_8th' | 'quarter_triplet' | 'straight_4th';
52
+ /**
53
+ * All possible grid types for reference
54
+ */
55
+ export declare const ALL_GRID_TYPES: ExtendedGridType[];
56
+ /**
57
+ * Subdivision limits for each difficulty level
58
+ *
59
+ * This constant defines which grid types are allowed for each difficulty
60
+ * at slow tempos (BPM < 70). For tempo-aware limits, use
61
+ * `getTempoAwareAllowedGridTypes()`.
62
+ *
63
+ * Easy and Medium have no tempo-dependent variation — their grid restrictions
64
+ * apply at all BPMs. Hard allows all types only at BPM < 70.
65
+ *
66
+ * | Difficulty | BPM < 70 | 70 ≤ BPM ≤ 120 | BPM > 120 |
67
+ * |------------|----------|----------------|-----------|
68
+ * | Easy | `straight_4th`, `quarter_triplet` | same | same |
69
+ * | Medium | `straight_8th`, `quarter_triplet` | same | same |
70
+ * | Hard | All types | `straight_8th`, `quarter_triplet` | same |
71
+ * | Natural | All types | All types | All types |
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * // Check if a grid type is allowed for a difficulty at a given BPM
76
+ * const allowed = getTempoAwareAllowedGridTypes('medium', 120);
77
+ * // ['straight_8th', 'quarter_triplet'] — 16th notes restricted at ≥70 BPM
78
+ * ```
79
+ */
80
+ export declare const SUBDIVISION_LIMITS: Record<DifficultyLevel, SubdivisionLimitConfig>;
81
+ /** BPM threshold: medium restricts 16th/triplet_8th at or above this value */
82
+ export declare const MEDIUM_RESTRICT_BPM = 70;
83
+ /** BPM threshold: hard restricts 16th/triplet_8th at or above this value */
84
+ export declare const HARD_RESTRICT_BPM = 70;
85
+ /** BPM threshold: easy restricts to quarter notes above this value */
86
+ export declare const EASY_QUARTER_NOTE_BPM = 120;
87
+ /**
88
+ * Get the allowed grid types for a difficulty at a given BPM.
89
+ *
90
+ * This function returns the effective subdivision limits after applying
91
+ * tempo-based restrictions:
92
+ *
93
+ * - **Easy**: Always `straight_4th` (quarter notes) and `quarter_triplet`.
94
+ * 8th notes are too rapid for beginners at any tempo.
95
+ * - **Medium**: Always `straight_8th` and `quarter_triplet`.
96
+ * 16th notes and 8th note triplets are reserved for hard/natural.
97
+ * - **Hard at BPM ≥ 70**: Only `straight_8th` and `quarter_triplet`.
98
+ * 16th notes and 8th note triplets are reserved for natural/custom at higher tempos.
99
+ * - **Natural**: Always all types (no restrictions).
100
+ *
101
+ * @param difficulty - The difficulty level
102
+ * @param bpm - The tempo in beats per minute
103
+ * @returns Array of allowed grid types
104
+ */
105
+ export declare function getTempoAwareAllowedGridTypes(difficulty: DifficultyLevel, bpm: number): ExtendedGridType[];
106
+ /**
107
+ * Derive allowed grid types from a DensityGenerationConfig and BPM.
108
+ *
109
+ * This is the core helper for density-based generation. It:
110
+ * 1. Looks up the base set of allowed grid types from the hierarchy based on `maxGridType`
111
+ * 2. Optionally applies BPM-based restrictions if `bpmBasedQuantization` is true
112
+ *
113
+ * @param config - The density generation configuration
114
+ * @param bpm - Current BPM for tempo-aware restrictions
115
+ * @returns Array of allowed ExtendedGridType values
116
+ */
117
+ export declare function deriveAllowedGridTypes(config: DensityGenerationConfig, bpm: number): ExtendedGridType[];
118
+ /**
119
+ * Calculate the maximum achievable density (notes/second) for a given set of
120
+ * allowed grid types at a specific BPM.
121
+ *
122
+ * This is used to detect impossible configurations (e.g., requesting 4.0 nps
123
+ * with only 8th notes at 60 BPM, where max achievable is ~2.0 nps).
124
+ *
125
+ * @param allowedGridTypes - The grid types that are allowed
126
+ * @param bpm - Current BPM
127
+ * @returns Maximum achievable density in notes/second
128
+ */
129
+ export declare function calculateMaxAchievableDensity(allowedGridTypes: ExtendedGridType[], bpm: number): number;
130
+ /**
131
+ * Difficulty level for rhythm variants
132
+ *
133
+ * - 'easy': Simplified rhythm with 8th notes max
134
+ * - 'medium': Moderate difficulty with density reduction
135
+ * - 'hard': Full density with all subdivisions
136
+ * - 'natural': Unedited composite stream (what was actually detected)
137
+ * - 'custom': Custom density-based variant — parameters provided at generation time
138
+ */
139
+ export type DifficultyLevel = 'easy' | 'medium' | 'hard' | 'natural' | 'custom';
140
+ /**
141
+ * Preset difficulty levels (excludes 'custom')
142
+ *
143
+ * Used for GeneratedRhythm.difficultyVariants which only contains preset variants.
144
+ * Custom variants are generated standalone via generateAtDensity().
145
+ */
146
+ export type PresetDifficultyLevel = 'easy' | 'medium' | 'hard' | 'natural';
147
+ /**
148
+ * Configuration for density-based level generation
149
+ *
150
+ * Provides independent control over target density (notes/second) and maximum
151
+ * quantization grid, enabling a continuous spectrum of difficulty alongside
152
+ * the existing easy/medium/hard/natural presets.
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * // Dense chart with only 8th note quantization
157
+ * const config: DensityGenerationConfig = {
158
+ * targetDensity: 3.0,
159
+ * maxGridType: 'straight_8th'
160
+ * };
161
+ *
162
+ * // Sparse chart with 16th note quantization allowed
163
+ * const config: DensityGenerationConfig = {
164
+ * targetDensity: 0.5,
165
+ * maxGridType: 'straight_16th'
166
+ * };
167
+ *
168
+ * // With BPM-based quantization restrictions
169
+ * const config: DensityGenerationConfig = {
170
+ * targetDensity: 2.0,
171
+ * maxGridType: 'straight_16th',
172
+ * bpmBasedQuantization: true, // At 80 BPM, this restricts to 8ths
173
+ * restrictBpm: 70 // Custom threshold (default: 70)
174
+ * };
175
+ * ```
176
+ */
177
+ export interface DensityGenerationConfig {
178
+ /** Target density in notes per second */
179
+ targetDensity: number;
180
+ /** Maximum quantization grid allowed (independent of density) */
181
+ maxGridType: ExtendedGridType;
182
+ /**
183
+ * When true, apply BPM-based restrictions on top of maxGridType.
184
+ * Uses medium's thresholds (default: 70 BPM):
185
+ * - At BPM >= restrictBpm: straight_16th and triplet_8th restricted to straight_8th
186
+ * When false, only maxGridType is enforced regardless of BPM.
187
+ * Default: false
188
+ */
189
+ bpmBasedQuantization?: boolean;
190
+ /** BPM threshold for restricting 16th/triplet_8th to 8ths. Default: 70 (MEDIUM_RESTRICT_BPM) */
191
+ restrictBpm?: number;
192
+ /** BPM threshold for restricting 8ths to quarter notes. Default: 120 (EASY_QUARTER_NOTE_BPM) */
193
+ quarterNoteBpm?: number;
194
+ }
195
+ /**
196
+ * Maximum subdivision type
197
+ */
198
+ export type MaxSubdivision = 'eighth' | 'sixteenth';
199
+ /**
200
+ * Configuration for subdivision limits at a difficulty level
201
+ */
202
+ export interface SubdivisionLimitConfig {
203
+ /** Maximum subdivision allowed at this difficulty */
204
+ maxSubdivision: MaxSubdivision;
205
+ /** Grid types allowed at this difficulty */
206
+ allowedGridTypes: ExtendedGridType[];
207
+ /** Human-readable description of the limits */
208
+ description: string;
209
+ /** Target density range for this difficulty (notes per second, BPM-adjusted) */
210
+ targetDensityRange: {
211
+ min: number;
212
+ max: number;
213
+ };
214
+ }
215
+ /**
216
+ * Type of edit applied to create a difficulty variant
217
+ */
218
+ export type EditType = 'none' | 'simplified' | 'interpolated' | 'pattern_inserted';
219
+ /**
220
+ * A beat in a difficulty variant that may have been converted to an extended grid type
221
+ *
222
+ * This extends CompositeBeat to support Easy difficulty grid types (straight_8th, quarter_triplet)
223
+ * that aren't in the original GridType.
224
+ */
225
+ export interface VariantBeat extends Omit<CompositeBeat, 'gridType'> {
226
+ /** Grid type - extended to support simplified subdivisions */
227
+ gridType: ExtendedGridType;
228
+ }
229
+ /**
230
+ * A difficulty variant of the composite stream
231
+ */
232
+ export interface DifficultyVariant {
233
+ /** The difficulty level of this variant */
234
+ difficulty: DifficultyLevel;
235
+ /** The beats in this variant (may include converted grid types) */
236
+ beats: VariantBeat[];
237
+ /** Whether this variant is unedited from the composite */
238
+ isUnedited: boolean;
239
+ /** Type of edit applied (if any) */
240
+ editType: EditType;
241
+ /** How much was changed (0 = no changes, 1 = heavily modified) */
242
+ editAmount: number;
243
+ /** IDs of patterns inserted (if editType is 'pattern_inserted') */
244
+ patternsInserted?: string[];
245
+ /** Metadata about subdivision conversions */
246
+ conversionMetadata?: SubdivisionConversionMetadata;
247
+ /** Metadata about density enhancement */
248
+ enhancementMetadata?: EnhancementMetadata;
249
+ /** Task 4.2.3: Density validation result for downstream consumers */
250
+ densityValidation?: VariantDensityValidationResult;
251
+ /** Whether density was clamped due to grid constraints (density-based generation only) */
252
+ densityClamped?: boolean;
253
+ }
254
+ /**
255
+ * Metadata about subdivision conversions during simplification
256
+ */
257
+ export interface SubdivisionConversionMetadata {
258
+ /** Number of beats converted from 16th to 8th */
259
+ sixteenthToEighth: number;
260
+ /** Number of beats converted from 8th triplet to quarter triplet */
261
+ tripletToQuarterTriplet: number;
262
+ /** Number of beats converted from 8th to quarter note (straight_8th → straight_4th) */
263
+ eighthToQuarter: number;
264
+ /** Number of beats that were removed entirely */
265
+ beatsRemoved: number;
266
+ /** Total beats before conversion */
267
+ totalBeatsBefore: number;
268
+ /** Total beats after conversion */
269
+ totalBeatsAfter: number;
270
+ /** Number of reduction passes used to reach target density */
271
+ reductionPasses?: number;
272
+ }
273
+ /**
274
+ * Metadata about density enhancement during variant generation
275
+ */
276
+ export interface EnhancementMetadata {
277
+ /** Total beats before enhancement */
278
+ totalBeatsBefore: number;
279
+ /** Total beats after enhancement */
280
+ totalBeatsAfter: number;
281
+ /** Number of beats added via pattern insertion */
282
+ patternsInserted: number;
283
+ /** Number of beats added via grid interpolation */
284
+ interpolatedBeats: number;
285
+ /** IDs of patterns that were inserted */
286
+ insertedPatternIds: string[];
287
+ }
288
+ /**
289
+ * Result of validating a variant against subdivision limits
290
+ */
291
+ export interface SubdivisionValidationResult {
292
+ /** Whether the variant passes validation */
293
+ isValid: boolean;
294
+ /** Beats that violate the subdivision limits */
295
+ violations: SubdivisionViolation[];
296
+ /** Total number of beats checked */
297
+ totalBeats: number;
298
+ /** Number of violating beats */
299
+ violationCount: number;
300
+ }
301
+ /**
302
+ * A single subdivision violation
303
+ */
304
+ export interface SubdivisionViolation {
305
+ /** The beat that violates the limits */
306
+ beat: VariantBeat;
307
+ /** The grid type that is not allowed */
308
+ gridType: ExtendedGridType;
309
+ /** Suggested conversion target */
310
+ suggestedConversion: ExtendedGridType;
311
+ }
312
+ /**
313
+ * Result of locking grid types per beat index
314
+ *
315
+ * This is the foundational structure for the density balancing refactor.
316
+ * Before any density work, the grid type for each beat index is locked
317
+ * so all subsequent operations know which grid to use.
318
+ */
319
+ export interface GridLockResult {
320
+ /** Beats after resolving mixed grids (single grid per beat index) */
321
+ beats: CompositeBeat[];
322
+ /** Map from beat index to locked grid type */
323
+ gridLock: Map<number, ExtendedGridType>;
324
+ }
325
+ /**
326
+ * Strategy for where to target within the density range
327
+ *
328
+ * - 'midpoint': Aim for the middle of the range (default)
329
+ * - 'lower': Aim closer to the minimum (more conservative)
330
+ * - 'upper': Aim closer to the maximum (more aggressive)
331
+ */
332
+ export type DensityTargetStrategy = 'midpoint' | 'lower' | 'upper';
333
+ /**
334
+ * Result of calculating beat count targets for a difficulty
335
+ */
336
+ export interface BeatCountTarget {
337
+ /** Target beat count to aim for (based on strategy) */
338
+ targetCount: number;
339
+ /** Maximum beat count allowed (upper bound of density range) */
340
+ maxCount: number;
341
+ /** Minimum beat count allowed (lower bound of density range) */
342
+ minCount: number;
343
+ /** The target density value (notes per second) used for calculation */
344
+ targetDensity: number;
345
+ }
346
+ /**
347
+ * Result of calculating how many beats to add for enhancement
348
+ */
349
+ export interface BeatsToAddResult {
350
+ /** Number of beats to add to reach target */
351
+ beatsToAdd: number;
352
+ /** Target beat count to aim for */
353
+ targetCount: number;
354
+ /** Maximum beats per index based on allowed grid types */
355
+ maxBeatsPerIndex: number;
356
+ }
357
+ /**
358
+ * Result of validating variant density against target range
359
+ *
360
+ * Task 4.1: Created for convergence validation
361
+ */
362
+ export interface VariantDensityValidationResult {
363
+ /** Whether the variant's density is within the target range */
364
+ inRange: boolean;
365
+ /** The calculated density (notes per second) */
366
+ density: number;
367
+ /** The target density range for this difficulty */
368
+ targetRange: {
369
+ min: number;
370
+ max: number;
371
+ };
372
+ /** The difficulty level that was validated */
373
+ difficulty: DifficultyLevel;
374
+ }
375
+ /**
376
+ * Configuration for difficulty variant generation
377
+ */
378
+ export interface DifficultyVariantConfig {
379
+ /** Whether to log subdivision conversions for debugging. Default: false */
380
+ logConversions: boolean;
381
+ /** Whether to preserve phrase boundaries when simplifying. Default: true */
382
+ preservePhraseBoundaries: boolean;
383
+ /** Minimum intensity threshold for keeping beats during simplification. Default: 0.3 */
384
+ simplificationIntensityThreshold: number;
385
+ /** Intensity threshold for keeping beats during HEAVY simplification. Default: 0.5 */
386
+ heavySimplificationIntensityThreshold: number;
387
+ /** Intensity threshold for removing offbeat 16ths during moderate simplification (hard→medium). Default: 0.4 */
388
+ moderateSimplificationIntensityThreshold: number;
389
+ /** Minimum intensity threshold for removing beats during density reduction. Default: 0.25 */
390
+ densityReductionMinIntensity: number;
391
+ /** Intensity for interpolated beats (0.0 - 1.0). Default: 0.5 */
392
+ interpolatedBeatIntensity: number;
393
+ /** Whether to prefer pattern insertion over simple interpolation. Default: true */
394
+ preferPatternInsertion: boolean;
395
+ /** Maximum phrase size to consider for pattern insertion (in beats). Default: 4 */
396
+ maxPatternInsertionSize: number;
397
+ /** Strategy for where to target within the density range. Default: 'midpoint' */
398
+ densityTargetStrategy: DensityTargetStrategy;
399
+ /** Maximum number of passes for density reduction with progressively relaxed protections. Default: 3 */
400
+ maxReductionPasses: number;
401
+ /** Seed for deterministic probability rolls in beat enhancement. If not provided, falls back to a hash of beat data. */
402
+ seed?: string;
403
+ /**
404
+ * Rhythmic balance configuration for density reduction awareness.
405
+ * When provided, the density reduction will use the strongBeatEmphasis setting
406
+ * to determine which beats are structurally important.
407
+ *
408
+ * This config is passed from RhythmGenerator to ensure density reduction
409
+ * respects the same rhythmic taste rules as the RhythmicBalancer.
410
+ */
411
+ rhythmicBalanceConfig?: RhythmicBalanceConfig;
412
+ }
413
+ /**
414
+ * Check if a grid type is allowed for a given difficulty at a given BPM.
415
+ *
416
+ * @param gridType - The grid type to check
417
+ * @param difficulty - The difficulty level
418
+ * @param bpm - Optional BPM. When omitted, uses static SUBDIVISION_LIMITS (no tempo restrictions).
419
+ * @returns True if the grid type is allowed
420
+ */
421
+ export declare function isGridTypeAllowed(gridType: GridType, difficulty: DifficultyLevel, bpm?: number): boolean;
422
+ /**
423
+ * Get the allowed grid types for a difficulty level at a given BPM.
424
+ *
425
+ * @param difficulty - The difficulty level
426
+ * @param bpm - Optional BPM. When omitted, uses static SUBDIVISION_LIMITS (no tempo restrictions).
427
+ * @returns Array of allowed grid types
428
+ */
429
+ export declare function getAllowedGridTypes(difficulty: DifficultyLevel, bpm?: number): ExtendedGridType[];
430
+ /**
431
+ * Convert a grid type to the closest allowed type for a difficulty at a given BPM.
432
+ *
433
+ * Conversion rules (when grid type is not already allowed):
434
+ *
435
+ * - `straight_16th` → `straight_8th` (or `straight_4th` for Easy at BPM > 120)
436
+ * - `triplet_8th` → `quarter_triplet`
437
+ * - `straight_8th` → `straight_4th` (Easy at BPM > 120 only)
438
+ *
439
+ * @param gridType - The original grid type (can be extended type)
440
+ * @param difficulty - The target difficulty
441
+ * @param bpm - Optional BPM. When omitted, uses static SUBDIVISION_LIMITS.
442
+ * @param allowedGridTypesOverride - Optional override for allowed grid types (for density-based generation)
443
+ * @returns The converted grid type (or original if already allowed)
444
+ */
445
+ export declare function convertToAllowedGridType(gridType: ExtendedGridType, difficulty: DifficultyLevel, bpm?: number, allowedGridTypesOverride?: ExtendedGridType[]): ExtendedGridType;
446
+ /**
447
+ * Map natural difficulty to difficulty level
448
+ *
449
+ * @param naturalDifficulty - The natural difficulty from density analysis
450
+ * @returns The corresponding difficulty level
451
+ */
452
+ export declare function naturalDifficultyToLevel(naturalDifficulty: NaturalDifficulty): DifficultyLevel;
453
+ /**
454
+ * Validate a list of beats against subdivision limits for a difficulty at a given BPM.
455
+ *
456
+ * @param beats - The beats to validate (may include extended grid types)
457
+ * @param difficulty - The difficulty level to validate against
458
+ * @param bpm - Optional BPM. When omitted, uses static SUBDIVISION_LIMITS.
459
+ * @returns Validation result with any violations
460
+ */
461
+ export declare function validateSubdivisionLimits(beats: VariantBeat[], difficulty: DifficultyLevel, bpm?: number): SubdivisionValidationResult;
462
+ /**
463
+ * Generates difficulty variants from a composite stream
464
+ *
465
+ * ## Algorithm Overview
466
+ *
467
+ * 1. **Determine Variants to Generate**: Based on the composite's natural difficulty,
468
+ * determine which variants need editing vs. remain unedited.
469
+ *
470
+ * 2. **Simplification** (for dense composites needing easier difficulties):
471
+ * - Enforce subdivision limits (primary constraint for Easy)
472
+ * - Prioritize keeping transients on strong beats (1, 3)
473
+ * - Remove offbeat subdivisions first
474
+ * - Snap removed subdivisions to nearest allowed grid
475
+ *
476
+ * 3. **Density Enhancement** (for sparse composites needing harder difficulties):
477
+ * - First priority: Insert detected patterns from phrase library
478
+ * - Fallback: Simple grid interpolation
479
+ *
480
+ * ## Usage
481
+ *
482
+ * ```typescript
483
+ * const generator = new DifficultyVariantGenerator();
484
+ * const variants = generator.generate(composite, phraseAnalysis);
485
+ *
486
+ * // Access each variant
487
+ * const easyVariant = variants.easy;
488
+ * const mediumVariant = variants.medium;
489
+ * const hardVariant = variants.hard;
490
+ *
491
+ * // Check if a variant was edited
492
+ * console.log('Easy was simplified:', easyVariant.editType === 'simplified');
493
+ * console.log('Medium is unedited:', mediumVariant.isUnedited);
494
+ * ```
495
+ */
496
+ export declare class DifficultyVariantGenerator {
497
+ private config;
498
+ /**
499
+ * Current unifiedBeatMap for time-signature-aware strong beat detection.
500
+ * Set during generate() and used by isStrongBeat().
501
+ */
502
+ private currentUnifiedBeatMap;
503
+ constructor(config?: Partial<DifficultyVariantConfig>);
504
+ /**
505
+ * Lock grid type per beat index before density work
506
+ *
507
+ * This is the foundational method for the density balancing refactor.
508
+ * Before any density work (simplification or enhancement), lock the grid
509
+ * type for each beat index so all subsequent operations know which grid to use.
510
+ *
511
+ * The method:
512
+ * 1. Runs `enforceSingleGridPerBeat()` to resolve any mixed grids
513
+ * 2. Builds a map of beatIndex → dominantGridType from resolved beats
514
+ * 3. For empty beat indices, resolves grid type from:
515
+ * - gridDecisions map (if available)
516
+ * - Nearest-neighbor fallback (offsets 1, -1, 2, -2, 3, -3)
517
+ * - Default to allowed grid type for target difficulty
518
+ *
519
+ * @param beats - Input beats (may have mixed grids)
520
+ * @param targetDifficulty - Target difficulty level for default grid type
521
+ * @param bpm - BPM for tempo-aware grid type defaults
522
+ * @param gridDecisions - Optional grid decisions from quantized streams
523
+ * @param allowedGridTypes - Optional override for allowed grid types (bypasses getTempoAwareAllowedGridTypes)
524
+ * @returns Grid lock result with cleaned beats and locked grid map
525
+ */
526
+ lockGridPerBeatIndex(beats: CompositeBeat[], targetDifficulty: DifficultyLevel, bpm: number, gridDecisions?: Map<number, GridDecision>, allowedGridTypes?: ExtendedGridType[]): GridLockResult;
527
+ /**
528
+ * Generate all three difficulty variants from a composite stream
529
+ *
530
+ * After generation, each variant is validated against its subdivision limits
531
+ * to ensure compliance.
532
+ *
533
+ * @param composite - The composite stream from CompositeStreamGenerator
534
+ * @param phraseAnalysis - Optional phrase analysis for pattern library access
535
+ * @param gridDecisions - Optional grid decisions from quantized streams
536
+ * @returns Object containing easy, medium, and hard variants
537
+ */
538
+ generate(composite: CompositeStream, unifiedBeatMap: UnifiedBeatMap, phraseAnalysis?: PhraseAnalysisResult, gridDecisions?: Map<number, GridDecision>): {
539
+ easy: DifficultyVariant;
540
+ medium: DifficultyVariant;
541
+ hard: DifficultyVariant;
542
+ natural: DifficultyVariant;
543
+ };
544
+ /**
545
+ * Generate a custom difficulty variant at a specific target density.
546
+ *
547
+ * This method provides granular control over difficulty generation by decoupling
548
+ * target density (notes/second) from maximum quantization grid. Unlike the preset
549
+ * difficulties (easy/medium/hard/natural), this allows any combination such as:
550
+ * - Dense chart (3.0 nps) with only 8th note quantization
551
+ * - Sparse chart (0.5 nps) with 16th note quantization allowed
552
+ *
553
+ * The method handles three scenarios:
554
+ * 1. **Current density > target**: Simplify beats (remove/convert notes)
555
+ * 2. **Current density < target**: Enhance beats (add notes via interpolation/patterns)
556
+ * 3. **Current density ≈ target**: Apply grid restrictions only if needed
557
+ *
558
+ * Best-effort: If the target density is impossible given the grid constraints
559
+ * (e.g., 4.0 nps with only 8th notes at 60 BPM), the density is clamped to the
560
+ * maximum achievable and a warning is logged.
561
+ *
562
+ * @param composite - The composite stream from CompositeStreamGenerator
563
+ * @param config - Density generation configuration (target density + max grid type)
564
+ * @param unifiedBeatMap - The unified beat map for timing information
565
+ * @param phraseAnalysis - Optional phrase analysis for pattern library access during enhancement
566
+ * @param gridDecisions - Optional grid decisions from quantized streams
567
+ * @returns A DifficultyVariant with `difficulty: 'custom'`
568
+ *
569
+ * @example
570
+ * ```typescript
571
+ * const generator = new DifficultyVariantGenerator();
572
+ *
573
+ * // Dense chart with 8th note max grid
574
+ * const denseVariant = generator.generateAtDensity(
575
+ * composite,
576
+ * { targetDensity: 3.0, maxGridType: 'straight_8th' },
577
+ * unifiedBeatMap
578
+ * );
579
+ *
580
+ * // Sparse chart with 16th note grid allowed, BPM-based restrictions
581
+ * const sparseVariant = generator.generateAtDensity(
582
+ * composite,
583
+ * { targetDensity: 0.5, maxGridType: 'straight_16th', bpmBasedQuantization: true },
584
+ * unifiedBeatMap
585
+ * );
586
+ * ```
587
+ */
588
+ generateAtDensity(composite: CompositeStream, config: DensityGenerationConfig, unifiedBeatMap: UnifiedBeatMap, phraseAnalysis?: PhraseAnalysisResult, gridDecisions?: Map<number, GridDecision>): DifficultyVariant;
589
+ /**
590
+ * Generate multiple custom difficulty variants at specific densities in one call
591
+ *
592
+ * This is a convenience method for generating multiple density-based variants
593
+ * efficiently. Each variant is generated independently with its own deep copy
594
+ * of the composite beats, ensuring no shared state or mutations between variants.
595
+ *
596
+ * @param composite - The composite stream from CompositeStreamGenerator
597
+ * @param configs - Array of labeled density configurations
598
+ * @param unifiedBeatMap - The unified beat map for timing information
599
+ * @param phraseAnalysis - Optional phrase analysis for pattern library access during enhancement
600
+ * @param gridDecisions - Optional grid decisions from quantized streams
601
+ * @returns A Map of labels to DifficultyVariants
602
+ *
603
+ * @example
604
+ * ```typescript
605
+ * const generator = new DifficultyVariantGenerator();
606
+ *
607
+ * const variants = generator.generateAtDensities(
608
+ * composite,
609
+ * [
610
+ * { label: 'beginner', config: { targetDensity: 0.5, maxGridType: 'straight_4th' } },
611
+ * { label: 'intermediate', config: { targetDensity: 1.5, maxGridType: 'straight_8th' } },
612
+ * { label: 'expert', config: { targetDensity: 3.0, maxGridType: 'straight_16th' } },
613
+ * ],
614
+ * unifiedBeatMap
615
+ * );
616
+ *
617
+ * const beginnerVariant = variants.get('beginner');
618
+ * const expertVariant = variants.get('expert');
619
+ * ```
620
+ */
621
+ generateAtDensities(composite: CompositeStream, configs: {
622
+ label: string;
623
+ config: DensityGenerationConfig;
624
+ }[], unifiedBeatMap: UnifiedBeatMap, phraseAnalysis?: PhraseAnalysisResult, gridDecisions?: Map<number, GridDecision>): Map<string, DifficultyVariant>;
625
+ /**
626
+ * Validate a generated variant against its subdivision limits
627
+ *
628
+ * This ensures that all generated variants comply with their respective
629
+ * difficulty's subdivision constraints. Logs warnings if violations are found.
630
+ *
631
+ * @param variant - The variant to validate
632
+ * @param difficulty - The difficulty level
633
+ */
634
+ private validateVariant;
635
+ /**
636
+ * Validate that a variant's beats have no mixed grid types per beat index
637
+ *
638
+ * Task 1.4.3: Validation-only check for grid lock compliance.
639
+ * When grid lock is used in generateVariant(), this method confirms
640
+ * that no grid violations exist (assert, don't fix).
641
+ *
642
+ * @param beats - The beats to validate
643
+ * @param difficulty - The difficulty level for logging
644
+ */
645
+ private validateGridLockResult;
646
+ /**
647
+ * Validate that a variant's density falls within the target range for its difficulty
648
+ *
649
+ * Task 4.1: Convergence validation - check final density against target range
650
+ *
651
+ * This method calculates the final density of a variant and compares it against
652
+ * the target density range defined in SUBDIVISION_LIMITS. It logs warnings for
653
+ * out-of-range variants but does NOT throw, since edge cases (very short songs,
654
+ * extreme tempos) may not be able to hit exact targets.
655
+ *
656
+ * @param variant - The variant to validate
657
+ * @param bpm - The tempo in beats per minute
658
+ * @returns DensityValidationResult with inRange status, density, and target range
659
+ */
660
+ private validateDensityInRange;
661
+ /**
662
+ * Generate a single difficulty variant
663
+ *
664
+ * @param targetDifficulty - The target difficulty level
665
+ * @param composite - The composite stream
666
+ * @param naturalDifficulty - The natural difficulty of the composite
667
+ * @param phraseAnalysis - Optional phrase analysis for pattern library access
668
+ * @param gridDecisions - Optional grid decisions from quantized streams
669
+ * @returns The difficulty variant
670
+ */
671
+ private generateVariant;
672
+ /**
673
+ * Simplify beats to meet subdivision limits for a target difficulty
674
+ *
675
+ * This method converts beats that violate subdivision limits to allowed grid types:
676
+ * - `straight_16th` → `straight_8th` (snap 16th notes to nearest 8th note)
677
+ * - `triplet_8th` → `quarter_triplet` (snap 8th triplets to quarter note triplet)
678
+ *
679
+ * For heavy simplification (hard -> easy), additional beat prioritization is applied:
680
+ * - Prioritize keeping transients on strong beats (beats 1 and 3 of each measure)
681
+ * - Remove offbeat subdivisions first (gridPosition 1 and 3)
682
+ * - Keep only core beats (high intensity or on strong beats)
683
+ *
684
+ * After conversion, duplicate beats at the same grid position are deduplicated
685
+ * (keeping the highest intensity).
686
+ *
687
+ * @param beats - The beats to simplify
688
+ * @param targetDifficulty - The target difficulty level
689
+ * @param quarterNoteInterval - Duration of a quarter note in seconds for timestamp calculation
690
+ * @param isHeavySimplification - Whether this is heavy simplification (hard -> easy)
691
+ * @param phraseAnalysis - Optional phrase analysis for preserving phrase boundaries
692
+ * @returns Simplified beats with conversion metadata
693
+ */
694
+ private simplifyBeats;
695
+ /**
696
+ * Filter beats for heavy simplification (hard -> easy)
697
+ *
698
+ * Implements beat prioritization:
699
+ * 1. Strong beats (beats 1 and 3 of each measure) are always kept
700
+ * 2. Downbeats (gridPosition 0) on weak beats are kept if high intensity
701
+ * 3. Offbeats (gridPosition 1, 2, 3) are only kept if very high intensity
702
+ * 4. Beats part of significant phrases get additional consideration
703
+ *
704
+ * In 4/4 time with 0-indexed beats:
705
+ * - Beat 0, 4, 8... = Beat 1 of measure (strong)
706
+ * - Beat 2, 6, 10... = Beat 3 of measure (strong)
707
+ * - Beat 1, 5, 9... = Beat 2 of measure (weak)
708
+ * - Beat 3, 7, 11... = Beat 4 of measure (weak)
709
+ *
710
+ * @param beats - The beats to filter
711
+ * @param metadata - Metadata object to track removals
712
+ * @param phraseMembership - Map of beat indices to phrase membership
713
+ * @returns Filtered beats
714
+ */
715
+ private filterBeatsForHeavySimplification;
716
+ /**
717
+ * Determine if a beat index is on a strong beat, based on time signature and emphasis mode
718
+ *
719
+ * This method uses the rhythmicBalanceConfig.strongBeatEmphasis to determine
720
+ * which beats are "strong" for density reduction priority. It is
721
+ * time-signature-aware: derives beatsPerMeasure from the active downbeat segment.
722
+ *
723
+ * @param beatIndex - The beat index (0-indexed)
724
+ * @returns True if this is a strong beat
725
+ */
726
+ private isStrongBeat;
727
+ /**
728
+ * Calculate the density (notes per second) of a beat collection
729
+ *
730
+ * Uses `maxBeatIndex + 1` as the denominator to match DensityAnalyzer's method,
731
+ * Uses the actual track duration in seconds to compute true notes-per-second.
732
+ *
733
+ * @param beats - The beats to analyze
734
+ * @param durationSeconds - Actual track duration in seconds (from unifiedBeatMap.duration)
735
+ * @returns Notes per second (0 if no beats or no duration)
736
+ */
737
+ private calculateDensity;
738
+ /**
739
+ * Calculate target beat count for a difficulty level based on density ranges
740
+ *
741
+ * This is the foundational helper for global target-based density control.
742
+ * It calculates exactly how many beats should be in the output based on:
743
+ * - The target density range for the difficulty
744
+ * - The total quarter-note span of the song
745
+ * - The BPM
746
+ * - The configured strategy (midpoint/lower/upper)
747
+ *
748
+ * Target densities by difficulty:
749
+ * - Easy: 0.9 nps (biased high within [0, 1.0] to preserve musical interest)
750
+ * - Medium: 1.25 nps (true center of [1.0, 1.5])
751
+ * - Hard: 1.75 nps (target above the 1.5 floor)
752
+ * - Natural: Uses the current density (no target)
753
+ *
754
+ * The formula derives from: density = (beatCount / totalQuarterNotes) * (bpm / 60)
755
+ * Solving for beatCount: beatCount = density * totalQuarterNotes * 60 / bpm
756
+ *
757
+ * @param currentBeatCount - The current number of beats
758
+ * @param totalQuarterNotes - The total quarter-note span (maxBeatIndex + 1)
759
+ * @param bpm - Tempo in beats per minute
760
+ * @param targetDifficulty - The target difficulty level
761
+ * @returns Beat count target with min/max bounds
762
+ */
763
+ private calculateBeatCountTarget;
764
+ /**
765
+ * Calculate how many beats to add for density enhancement
766
+ *
767
+ * This method calculates the exact number of beats to add to reach the target
768
+ * density for a given difficulty level. It uses the same target density midpoints
769
+ * as calculateBeatCountTarget() for consistency.
770
+ *
771
+ * Task 3.1: Global target-based density enhancement helper
772
+ *
773
+ * @param currentBeatCount - Current number of beats
774
+ * @param durationSeconds - Actual track duration in seconds
775
+ * @param bpm - Beats per minute
776
+ * @param targetDifficulty - Target difficulty level
777
+ * @returns BeatsToAddResult with beatsToAdd, targetCount, and maxBeatsPerIndex
778
+ */
779
+ private calculateBeatsToAdd;
780
+ /**
781
+ * Get max beats per index from a set of allowed grid types
782
+ *
783
+ * Returns the maximum number of beats that can fit at a single beat index
784
+ * based on the most complex grid type in the allowed set.
785
+ *
786
+ * @param allowedTypes - Array of allowed grid types
787
+ * @returns Maximum beats per index
788
+ */
789
+ private getMaxBeatsPerIndexFromGridTypes;
790
+ /**
791
+ * Get max beats for a single grid type
792
+ *
793
+ * @param gridType - The grid type
794
+ * @returns Maximum beats per index for this grid type
795
+ */
796
+ private getMaxBeatsForGridType;
797
+ /**
798
+ * Distribute beats across indices to reach a global target count
799
+ *
800
+ * Uses deterministic global target-based distribution.
801
+ *
802
+ * Strategy:
803
+ * - Phase A: Fill empty indices first (prioritize gaps in rhythm)
804
+ * - Phase B: Fill partially occupied indices (add to existing beats)
805
+ *
806
+ * The distribution is deterministic and greedy. Empty indices are always prioritized.
807
+ * Seed is only used for tiebreaking when multiple indices are equally good candidates.
808
+ *
809
+ * @param beatsToAdd - Global count of beats to add
810
+ * @param beatsByIndex - Current beat occupancy per index
811
+ * @param gridLock - Per-index grid types (from lockGridPerBeatIndex)
812
+ * @param maxBeatIndex - The highest beat index in the song
813
+ * @param seed - Seed for deterministic tiebreaking
814
+ * @returns Map of beatIndex → targetCount (how many beats should be at each index after distribution)
815
+ */
816
+ private distributeBeatsAcrossIndices;
817
+ /**
818
+ * Group consecutive empty indices into gaps
819
+ *
820
+ * @param emptyIndices - Array of empty beat indices (sorted)
821
+ * @returns Array of gap arrays, each containing consecutive empty indices
822
+ */
823
+ private groupConsecutiveEmptyIndices;
824
+ /**
825
+ * Reduce density by removing low-priority beats until target is reached
826
+ *
827
+ * This method implements a priority-based beat removal strategy:
828
+ * 1. Calculate current density
829
+ * 2. If above target, sort beats by removal priority (lowest priority first)
830
+ * 3. Remove beats one at a time until density is within target range
831
+ *
832
+ * Removal priority (lowest to highest - low priority = removed first):
833
+ * - Offbeats (gridPosition 1, 3) with low intensity - removed first
834
+ * - Mid-beat positions (gridPosition 2) with low intensity
835
+ * - Downbeats (gridPosition 0) on weak beats (2, 4 of measure)
836
+ * - Strong beats (beats 1, 3 of measure) - kept as long as possible
837
+ *
838
+ * Protected beats (not removed):
839
+ * - Pass 1: Beats with priority >= (1 - densityReductionMinIntensity) or intensity >= moderateSimplificationIntensityThreshold
840
+ * - Pass 2: Relaxed thresholds (priority threshold lowered by 0.15, intensity threshold lowered by 0.1)
841
+ * - Pass 3+: Only strong beats (beatIndex % 4 === 0 or 2) are protected
842
+ *
843
+ * @param beats - The beats to potentially reduce
844
+ * @param targetDifficulty - The target difficulty level
845
+ * @param metadata - Metadata to track removals
846
+ * @param phraseMembership - Map of beat indices to phrase membership
847
+ * @returns Beats with density reduced to target range
848
+ */
849
+ private reduceDensityToTarget;
850
+ /**
851
+ * Build a map of measureNumber → count of downbeats (gridPosition === 0) in that measure.
852
+ *
853
+ * Uses unifiedBeatMap to resolve measureNumber from beatIndex, supporting any time signature.
854
+ *
855
+ * @param beats - The beats to scan
856
+ * @returns Map from measureNumber to downbeat count
857
+ */
858
+ private buildDownbeatCountMap;
859
+ /**
860
+ * Calculate removal priority for a beat (higher = more important to keep)
861
+ *
862
+ * Priority factors:
863
+ * - Strong beat bonus: +0.3 (zeroed in 'neutral' mode)
864
+ * - Downbeat bonus: +0.2 (gridPosition 0)
865
+ * - Only-downbeat-in-measure bonus: +0.2 (stacks on downbeat bonus)
866
+ * - Intensity contribution: +intensity * 0.3
867
+ * - Phrase membership bonus: +0.15 (max)
868
+ * - Offbeat penalty: -0.1 (gridPosition 1 or 3)
869
+ *
870
+ * @param beat - The beat to evaluate
871
+ * @param phraseMembership - Map of beat indices to phrase membership
872
+ * @param downbeatCountByMeasure - Map of measureNumber → downbeat count for structural importance
873
+ * @returns Priority score (0-1 range, higher = keep)
874
+ */
875
+ private calculateRemovalPriority;
876
+ /**
877
+ * Convert a single beat to an allowed grid type
878
+ *
879
+ * Conversion rules for Easy difficulty:
880
+ * - `straight_16th` (4 positions: 0, 1, 2, 3) → `straight_8th` (2 positions: 0, 2)
881
+ * - Position 0 → 0 (quarter note)
882
+ * - Position 1 → 0 (snaps back to quarter)
883
+ * - Position 2 → 2 (8th note)
884
+ * - Position 3 → 2 (snaps to 8th)
885
+ *
886
+ * - `triplet_8th` (3 positions: 0, 1, 2) → `quarter_triplet` (1 position: 0)
887
+ * - All positions snap to 0 (quarter triplet)
888
+ *
889
+ * - `straight_8th` (2 positions: 0, 1) → `straight_4th` (1 position: 0)
890
+ * - All positions snap to 0 (quarter note) — Easy at BPM > 120
891
+ *
892
+ * - `straight_16th` → `straight_4th` (Easy at BPM > 120)
893
+ * - All positions snap to 0 (quarter note)
894
+ *
895
+ * @param beat - The beat to convert
896
+ * @param targetDifficulty - The target difficulty
897
+ * @param quarterNoteInterval - Duration of a quarter note in seconds
898
+ * @param bpm - The tempo in BPM (for tempo-aware grid type selection)
899
+ * @returns The converted beat as VariantBeat, or null if the beat should be removed
900
+ */
901
+ private convertBeatGridType;
902
+ /**
903
+ * Deduplicate converted beats that may have snapped to the same grid position
904
+ *
905
+ * After conversion, multiple beats may end up at the same (beatIndex, gridPosition, gridType).
906
+ * This method keeps only the highest-intensity beat at each position.
907
+ *
908
+ * @param beats - Converted beats (may have duplicates)
909
+ * @returns Deduplicated beats
910
+ */
911
+ private deduplicateConvertedBeats;
912
+ /**
913
+ * Determine if simplification is needed
914
+ *
915
+ * @param targetDifficulty - The target difficulty
916
+ * @param naturalDifficulty - The natural difficulty of the composite
917
+ * @returns True if simplification is needed
918
+ */
919
+ private needsSimplification;
920
+ /**
921
+ * Determine if enhancement is needed
922
+ *
923
+ * @param targetDifficulty - The target difficulty
924
+ * @param naturalDifficulty - The natural difficulty of the composite
925
+ * @returns True if enhancement is needed
926
+ */
927
+ private needsEnhancement;
928
+ /**
929
+ * Determine if this is heavy simplification (2 levels down)
930
+ *
931
+ * Heavy simplification occurs when going from hard -> easy (skipping medium).
932
+ * This requires more aggressive beat removal - keeping only core beats.
933
+ *
934
+ * @param targetDifficulty - The target difficulty
935
+ * @param naturalDifficulty - The natural difficulty of the composite
936
+ * @returns True if this is heavy simplification
937
+ */
938
+ private isHeavySimplification;
939
+ /**
940
+ * Enhance beats by adding density through pattern insertion and interpolation
941
+ *
942
+ * ## Algorithm Overview
943
+ *
944
+ * 1. **Pattern Insertion** (first priority):
945
+ * - Look for suitable patterns from the phrase library
946
+ * - Insert patterns at beats that have low density
947
+ * - Patterns are song-specific and more interesting than simple interpolation
948
+ *
949
+ * 2. **Grid Interpolation** (fallback):
950
+ * - For beats where no pattern matches, interpolate additional subdivisions
951
+ * - Respect per-beat grid decisions (16th vs triplet) from Phase 1
952
+ * - Add beats at intermediate grid positions
953
+ *
954
+ * @param beats - The beats to enhance
955
+ * @param targetDifficulty - The target difficulty level
956
+ * @param bpm - BPM for calculating global target beat count
957
+ * @param unifiedBeatMap - The unified beat map for timestamp derivation
958
+ * @param phraseAnalysis - Optional phrase analysis for pattern library
959
+ * @param gridDecisions - Optional grid decisions from quantized streams
960
+ * @param quarterNoteInterval - Duration of a quarter note in seconds for timestamp calculation
961
+ * @param gridLock - Optional grid lock map (from lockGridPerBeatIndex) - if provided, skips initial enforceSingleGridPerBeat
962
+ * @returns Enhanced beats with metadata
963
+ */
964
+ private enhanceBeats;
965
+ /**
966
+ * Group beats by their beat index
967
+ */
968
+ private groupBeatsByIndex;
969
+ /**
970
+ * Calculate target beats per beat index based on density multiplier
971
+ *
972
+ * Includes empty beat indices (those with no existing beats) so that
973
+ * enhancement can fill gaps in the rhythm. Empty beats get a target
974
+ * proportional to the multiplier, treating them as having 1 virtual beat.
975
+ */
976
+ private calculateTargetBeatsPerBeat;
977
+ /**
978
+ * Try to insert a pattern from the phrase library
979
+ *
980
+ * Looks for patterns that:
981
+ * - Have available slots in the current beat
982
+ * - Match the grid type of existing beats
983
+ * - Are within the max pattern size limit
984
+ */
985
+ private tryInsertPattern;
986
+ /**
987
+ * Create beats for an empty beat index (one with no existing beats)
988
+ *
989
+ * When enhancement needs to fill gaps in the rhythm, this method creates
990
+ * beats from scratch using grid decisions or neighbor context to determine
991
+ * the appropriate grid type and timing.
992
+ *
993
+ * @param beatIndex - The beat index to create beats for
994
+ * @param beatsToAdd - Number of beats to create
995
+ * @param unifiedBeatMap - Optional unified beat map for timestamp derivation
996
+ * @param gridDecisions - Optional grid decisions from quantized streams
997
+ * @param quarterNoteInterval - Duration of a quarter note in seconds
998
+ * @param beatsByIndex - All beats grouped by index (for neighbor lookup)
999
+ * @param occupiedSlots - Global occupied slot tracker
1000
+ * @param lockedGridType - Optional locked grid type from gridLock (takes priority over other sources)
1001
+ * @returns Array of newly created beats
1002
+ */
1003
+ private createBeatsForEmptyIndex;
1004
+ /**
1005
+ * Interpolate beats to add density
1006
+ *
1007
+ * Adds beats at intermediate grid positions that don't already have beats.
1008
+ * Always uses the existing beats' grid type to avoid mixed grids.
1009
+ *
1010
+ * @param existingBeats - Existing beats at this beat index
1011
+ * @param beatIndex - The beat index to interpolate for
1012
+ * @param beatsToAdd - Number of beats to add
1013
+ * @param quarterNoteInterval - Duration of a quarter note in seconds for timestamp calculation
1014
+ * @param occupiedSlots - Global occupied slot tracker
1015
+ * @param lockedGridType - Grid type locked for this beat index (ExtendedGridType for full support)
1016
+ * @param unifiedBeatMap - The unified beat map for authoritative timestamp derivation
1017
+ * @returns Array of interpolated beats
1018
+ */
1019
+ private interpolateBeats;
1020
+ /**
1021
+ * Determine the grid type for a beat index.
1022
+ * Used when creating beats for an empty index that has no existing beats.
1023
+ */
1024
+ private getGridForBeatIndex;
1025
+ /**
1026
+ * Deduplicate enhanced beats — each beat index has exactly one grid type.
1027
+ * Beats at the same beatIndex:gridPosition are the same musical event regardless
1028
+ * of grid type. If two grid types somehow landed at the same position, keep the
1029
+ * one matching the dominant grid type for that beat index.
1030
+ */
1031
+ private deduplicateEnhancedBeats;
1032
+ /**
1033
+ * Enforce single grid type per beat index.
1034
+ *
1035
+ * When a beat index has notes from both triplet and straight grids,
1036
+ * keep only the grid type with higher total intensity. This prevents
1037
+ * unmusical combinations like a 16th note and a triplet in the same beat.
1038
+ *
1039
+ * @param beats - The beats to enforce single-grid on
1040
+ * @returns Beats with at most one grid type per beat index
1041
+ */
1042
+ private enforceSingleGridPerBeat;
1043
+ /**
1044
+ * Validate that beats have no mixed grid types per beat index
1045
+ *
1046
+ * Task 1.3.4: Validation-only check for grid lock compliance.
1047
+ * When grid lock is provided to enhanceBeats(), this method confirms
1048
+ * that no grid violations exist (assert, don't fix).
1049
+ *
1050
+ * @param beats - The beats to validate
1051
+ * @returns Validation result with any violations found
1052
+ */
1053
+ private validateSingleGridPerBeat;
1054
+ /**
1055
+ * Get the current configuration
1056
+ */
1057
+ getConfig(): DifficultyVariantConfig;
1058
+ /**
1059
+ * Build a map of beat indices to their phrase membership
1060
+ *
1061
+ * This creates a lookup structure to quickly check if a beat is part of
1062
+ * a detected rhythmic phrase, and how significant that phrase is.
1063
+ *
1064
+ * @param phraseAnalysis - The phrase analysis result
1065
+ * @returns Map from beat index to array of phrases that include that beat
1066
+ */
1067
+ private buildPhraseMembershipMap;
1068
+ /**
1069
+ * Check if a beat should be preserved due to phrase membership
1070
+ *
1071
+ * When preservePhraseBoundaries is enabled, this method determines if
1072
+ * a beat that would normally be removed should be kept because it's
1073
+ * part of a significant detected phrase.
1074
+ *
1075
+ * @param beat - The beat to check
1076
+ * @param phraseMembership - Map of beat indices to phrase membership
1077
+ * @param intensityThreshold - The intensity threshold being used
1078
+ * @returns True if the beat should be preserved due to phrase membership
1079
+ */
1080
+ private shouldPreserveForPhrase;
1081
+ }
1082
+ //# sourceMappingURL=DifficultyVariantGenerator.d.ts.map