@rel-packages/osu-beatmap-preview 0.1.1

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 (58) hide show
  1. package/README.md +12 -0
  2. package/dist/index.d.ts +20 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +4 -0
  5. package/dist/index.js.map +32 -0
  6. package/dist/math/curves.d.ts +6 -0
  7. package/dist/math/curves.d.ts.map +1 -0
  8. package/dist/math/difficulty.d.ts +14 -0
  9. package/dist/math/difficulty.d.ts.map +1 -0
  10. package/dist/math/vector2.d.ts +14 -0
  11. package/dist/math/vector2.d.ts.map +1 -0
  12. package/dist/mods/index.d.ts +12 -0
  13. package/dist/mods/index.d.ts.map +1 -0
  14. package/dist/mods/mod_double_time.d.ts +4 -0
  15. package/dist/mods/mod_double_time.d.ts.map +1 -0
  16. package/dist/mods/mod_easy.d.ts +3 -0
  17. package/dist/mods/mod_easy.d.ts.map +1 -0
  18. package/dist/mods/mod_half_time.d.ts +3 -0
  19. package/dist/mods/mod_half_time.d.ts.map +1 -0
  20. package/dist/mods/mod_hard_rock.d.ts +3 -0
  21. package/dist/mods/mod_hard_rock.d.ts.map +1 -0
  22. package/dist/mods/mod_hidden.d.ts +5 -0
  23. package/dist/mods/mod_hidden.d.ts.map +1 -0
  24. package/dist/mods/types.d.ts +17 -0
  25. package/dist/mods/types.d.ts.map +1 -0
  26. package/dist/parser/beatmap_parser.d.ts +25 -0
  27. package/dist/parser/beatmap_parser.d.ts.map +1 -0
  28. package/dist/parser/osz_loader.d.ts +13 -0
  29. package/dist/parser/osz_loader.d.ts.map +1 -0
  30. package/dist/player/audio_controller.d.ts +28 -0
  31. package/dist/player/audio_controller.d.ts.map +1 -0
  32. package/dist/player/hitsound_controller.d.ts +16 -0
  33. package/dist/player/hitsound_controller.d.ts.map +1 -0
  34. package/dist/player/player.d.ts +96 -0
  35. package/dist/player/player.d.ts.map +1 -0
  36. package/dist/player/video_controller.d.ts +16 -0
  37. package/dist/player/video_controller.d.ts.map +1 -0
  38. package/dist/renderer/backend/canvas_backend.d.ts +38 -0
  39. package/dist/renderer/backend/canvas_backend.d.ts.map +1 -0
  40. package/dist/renderer/backend/render_backend.d.ts +33 -0
  41. package/dist/renderer/backend/render_backend.d.ts.map +1 -0
  42. package/dist/renderer/base_renderer.d.ts +46 -0
  43. package/dist/renderer/base_renderer.d.ts.map +1 -0
  44. package/dist/renderer/mania/mania_renderer.d.ts +20 -0
  45. package/dist/renderer/mania/mania_renderer.d.ts.map +1 -0
  46. package/dist/renderer/standard/standard_renderer.d.ts +39 -0
  47. package/dist/renderer/standard/standard_renderer.d.ts.map +1 -0
  48. package/dist/skin/skin_config.d.ts +29 -0
  49. package/dist/skin/skin_config.d.ts.map +1 -0
  50. package/dist/types/beatmap.d.ts +105 -0
  51. package/dist/types/beatmap.d.ts.map +1 -0
  52. package/dist/types/mods.d.ts +26 -0
  53. package/dist/types/mods.d.ts.map +1 -0
  54. package/dist/types/resources.d.ts +13 -0
  55. package/dist/types/resources.d.ts.map +1 -0
  56. package/dist/types/result.d.ts +31 -0
  57. package/dist/types/result.d.ts.map +1 -0
  58. package/package.json +41 -0
package/README.md ADDED
@@ -0,0 +1,12 @@
1
+ ## osu-beatmap-preview
2
+
3
+ vibecoded osu! beatmap preview using lazer and [this](https://github.com/Lekuruu/osu-preview) as reference.<br>
4
+ created to be used on [osu-stuff](https://github.com/mezleca/osu-stuff)
5
+
6
+ ## features
7
+
8
+ - basic preview for standard and mania.
9
+ - basic skin configuration (mostly colors).
10
+ - basic mod support for standard and mania (pretty sure only dt works for now...).
11
+ - canvas backend (performance wise, is fine even on stupid complicated slider maps)
12
+ - beatmap parser (literally 100% vibecoded, didn't even checked the code xd)
@@ -0,0 +1,20 @@
1
+ export { BeatmapPlayer, type IPlayerOptions } from "./player/player";
2
+ export { AudioController } from "./player/audio_controller";
3
+ export { VideoController } from "./player/video_controller";
4
+ export { BeatmapParser, extract_preview_time, extract_audio_filename, extract_background_filename, extract_video_info } from "./parser/beatmap_parser";
5
+ export { OszLoader, type IOszLoaderOptions } from "./parser/osz_loader";
6
+ export * from "./types/beatmap";
7
+ export * from "./types/mods";
8
+ export * from "./types/resources";
9
+ export * from "./types/result";
10
+ export { type ISkinConfig, DEFAULT_SKIN, merge_skin, get_combo_color, get_mania_lane_color } from "./skin/skin_config";
11
+ export * from "./mods";
12
+ export { type IRenderBackend } from "./renderer/backend/render_backend";
13
+ export { CanvasBackend } from "./renderer/backend/canvas_backend";
14
+ export { BaseRenderer, type IRendererConfig, DEFAULT_RENDERER_CONFIG, GridLevel, PLAYFIELD_WIDTH, PLAYFIELD_HEIGHT } from "./renderer/base_renderer";
15
+ export { StandardRenderer } from "./renderer/standard/standard_renderer";
16
+ export { ManiaRenderer } from "./renderer/mania/mania_renderer";
17
+ export { calculate_preempt, calculate_fade_in, calculate_radius, difficulty_range, inverse_difficulty_range, type IDifficultyRange, PREEMPT_RANGE, PREEMPT_MIN } from "./math/difficulty";
18
+ export { flatten_bezier, flatten_linear, flatten_perfect, flatten_catmull } from "./math/curves";
19
+ export * from "./math/vector2";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EACH,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,2BAA2B,EAC3B,kBAAkB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxE,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAG/B,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAGvH,cAAc,QAAQ,CAAC;AAGvB,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,uBAAuB,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACrJ,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGhE,OAAO,EACH,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,aAAa,EACb,WAAW,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACjG,cAAc,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ var l;((S)=>{S[S.Standard=0]="Standard";S[S.Taiko=1]="Taiko";S[S.Catch=2]="Catch";S[S.Mania=3]="Mania"})(l||={});var T0;((S)=>{S[S.Auto=0]="Auto";S[S.Normal=1]="Normal";S[S.Soft=2]="Soft";S[S.Drum=3]="Drum"})(T0||={});var z={Circle:1,Slider:2,NewCombo:4,Spinner:8,ComboSkip:112,Hold:128},c={Normal:1,Whistle:2,Finish:4,Clap:8},Z0=(T)=>(T.type&z.Circle)!==0,_=(T)=>(T.type&z.Slider)!==0,j=(T)=>(T.type&z.Spinner)!==0,I0=(T)=>(T.type&z.Hold)!==0,L0=(T)=>(T.type&z.NewCombo)!==0;var X0;((V)=>{V.NoOsuFiles="NO_OSU_FILES";V.DifficultyNotFound="DIFFICULTY_NOT_FOUND";V.InvalidBeatmap="INVALID_BEATMAP";V.UnsupportedMode="UNSUPPORTED_MODE";V.AudioNotLoaded="AUDIO_NOT_LOADED";V.AudioDecodeError="AUDIO_DECODE_ERROR";V.NotLoaded="NOT_LOADED";V.Unknown="UNKNOWN"})(X0||={});var z0=(T)=>({success:!0,data:T}),w=(T,I)=>({success:!1,code:T,reason:I}),H1=(T)=>{if(T.success)return T.data;throw Error(`[${T.code}] ${T.reason}`)},S1=(T)=>{return T.success},A1=(T)=>{return!T.success};var $={None:0,NoFail:1,Easy:2,TouchDevice:4,Hidden:8,HardRock:16,SuddenDeath:32,DoubleTime:64,Relax:128,HalfTime:256,Nightcore:512,Flashlight:1024,Autoplay:2048,SpunOut:4096,Autopilot:8192,Perfect:16384},h0=$.DoubleTime|$.HalfTime|$.Nightcore,V1=$.HardRock|$.Easy|h0,U1=(T)=>{let I=0,D=T.toLowerCase(),H={nf:$.NoFail,ez:$.Easy,td:$.TouchDevice,hd:$.Hidden,hr:$.HardRock,sd:$.SuddenDeath,dt:$.DoubleTime,rx:$.Relax,ht:$.HalfTime,nc:$.Nightcore,fl:$.Flashlight,at:$.Autoplay,so:$.SpunOut,ap:$.Autopilot,pf:$.Perfect};for(let S=0;S<D.length-1;S+=2){let A=D.slice(S,S+2);if(H[A])I|=H[A]}return I},R1=(T)=>{let I=[];if(T&$.NoFail)I.push("NF");if(T&$.Easy)I.push("EZ");if(T&$.Hidden)I.push("HD");if(T&$.HardRock)I.push("HR");if(T&$.SuddenDeath)I.push("SD");if(T&$.DoubleTime)I.push("DT");if(T&$.HalfTime)I.push("HT");if(T&$.Nightcore)I.push("NC");if(T&$.Flashlight)I.push("FL");if(T&$.SpunOut)I.push("SO");let D=I.indexOf("DT"),H=I.indexOf("NC");if(D>=0&&H>=0)I.splice(D,1);return I.join("")},h=(T)=>{if(T&($.DoubleTime|$.Nightcore))return 1.5;if(T&$.HalfTime)return 0.75;return 1},r0=[$.HardRock|$.Easy,$.DoubleTime|$.HalfTime|$.Nightcore],N1=(T,I)=>{if(T&I)return T&~I;let D=T;for(let H of r0)if(I&H)D&=~H;return D|I},P1=(T,I)=>(T&I)!==0;import E0 from"jszip";class y{beatmap;section="";parse(T){this.beatmap=this.create_empty_beatmap(),this.section="";let I=T.split(`
2
+ `);for(let D of I)this.parse_line(D);if(this.beatmap.ar===-1)this.beatmap.ar=this.beatmap.od;return this.beatmap}create_empty_beatmap(){return{format_version:1,mode:0,title:"",title_unicode:"",artist:"",artist_unicode:"",creator:"",version:"",ar:-1,cs:5,od:5,hp:5,sv:1,tick_rate:1,timing_points:[],objects:[],circle_count:0,slider_count:0,spinner_count:0,hold_count:0}}parse_line(T){if(T.startsWith(" ")||T.startsWith("_"))return;let I=T.trim();if(I.length===0||I.startsWith("//"))return;if(I.startsWith("[")&&I.endsWith("]")){this.section=I.slice(1,-1);return}let D=I.match(/osu file format v(\d+)/);if(D){this.beatmap.format_version=parseInt(D[1]);return}switch(this.section){case"General":this.parse_general(I);break;case"Metadata":this.parse_metadata(I);break;case"Difficulty":this.parse_difficulty(I);break;case"TimingPoints":this.parse_timing_point(I);break;case"HitObjects":this.parse_hit_object(I);break}}parse_general(T){let[I,D]=this.split_property(T);if(I==="Mode")this.beatmap.mode=parseInt(D)}parse_metadata(T){let[I,D]=this.split_property(T);switch(I){case"Title":this.beatmap.title=D;break;case"TitleUnicode":this.beatmap.title_unicode=D;break;case"Artist":this.beatmap.artist=D;break;case"ArtistUnicode":this.beatmap.artist_unicode=D;break;case"Creator":this.beatmap.creator=D;break;case"Version":this.beatmap.version=D;break}}parse_difficulty(T){let[I,D]=this.split_property(T),H=parseFloat(D);switch(I){case"CircleSize":this.beatmap.cs=H;break;case"OverallDifficulty":this.beatmap.od=H;break;case"ApproachRate":this.beatmap.ar=H;break;case"HPDrainRate":this.beatmap.hp=H;break;case"SliderMultiplier":this.beatmap.sv=H;break;case"SliderTickRate":this.beatmap.tick_rate=H;break}}current_beat_length=500;parse_timing_point(T){let I=T.split(",");if(I.length<2)return;let D=parseFloat(I[0]),H=parseFloat(I[1]),S=parseInt(I[3]??"0"),A=parseInt(I[4]??"0"),O=parseInt(I[5]??"100"),U=I.length>=7?I[6].trim()!=="0":!0,V=I.length>=8?(parseInt(I[7])&1)!==0:!1,R=H<0,N=R?-100/H:1;if(!R&&H>0)this.current_beat_length=H;this.beatmap.timing_points.push({time:D,ms_per_beat:H,change:U,sample_set:S,sample_index:A,volume:O,kiai:V,velocity:N,beat_length:this.current_beat_length})}parse_hit_object(T){let I=T.split(",");if(I.length<4)return;let D=parseFloat(I[0]),H=parseFloat(I[1]),S=parseFloat(I[2]),A=parseInt(I[3]),O=parseInt(I[4]??"0"),U={time:S,type:A,hit_sound:O,end_time:S,end_pos:[D,H],combo_number:0,combo_count:0,data:{pos:[D,H]}};if(A&z.Circle)this.beatmap.circle_count++,U.data={pos:[D,H]},this.parse_extras(I,5,U);else if(A&z.Slider){if(I.length<8)return;this.beatmap.slider_count++;let V=this.parse_slider_data(I,D,H);if(U.data=V,I.length>8)U.edge_sounds=I[8].split("|").map((R)=>parseInt(R));if(I.length>9)U.edge_sets=I[9].split("|").map((R)=>{let N=R.split(":");return[parseInt(N[0]),parseInt(N[1])]});this.parse_extras(I,10,U)}else if(A&z.Spinner){this.beatmap.spinner_count++;let V=parseInt(I[5]);U.data={end_time:V},U.end_time=V,U.end_pos=[256,192],this.parse_extras(I,6,U)}else if(A&z.Hold){this.beatmap.hold_count++;let V=parseInt(I[5].split(":")[0]);U.data={pos:[D,H],end_time:V},U.end_time=V,this.parse_extras(I,6,U)}this.beatmap.objects.push(U)}parse_extras(T,I,D){if(I<T.length){let H=T[I];if(H&&H.includes(":")){let S=H.split(":");D.hit_sample={normal_set:parseInt(S[0]),addition_set:parseInt(S[1]),index:parseInt(S[2]),volume:parseInt(S[3]),filename:S[4]||void 0}}}}parse_slider_data(T,I,D){let H=T[5].split("|"),S=H[0],A=[];for(let V=1;V<H.length;V++){let R=H[V].split(":");A.push([parseInt(R[0]),parseInt(R[1])])}let O=parseInt(T[6]),U=parseFloat(T[7]);return{pos:[I,D],path_type:S,control_points:A,repetitions:O,distance:U}}split_property(T){let I=T.indexOf(":");if(I===-1)return[T,""];return[T.slice(0,I).trim(),T.slice(I+1).trim()]}}var n=4096,D0=(T)=>{let I=T.slice(0,n).match(/PreviewTime:\s*([+-]?\d+)/);return I?parseInt(I[1]):-1},H0=(T)=>{let I=T.slice(0,n).match(/AudioFilename:\s*(.+)/);return I?I[1].trim():null},S0=(T)=>{let I=T.slice(0,n).match(/0,0,"([^"]+)"/);return I?I[1]:null},A0=(T)=>{let I=T.slice(0,n).match(/(?:Video|1),(-?\d+),"([^"]+)"/);if(!I)return null;return{offset:parseInt(I[1]),filename:I[2]}};class r{async load_osz(T,I){let D=await E0.loadAsync(T),H=new Map;for(let[S,A]of Object.entries(D.files))if(!A.dir)H.set(S,await A.async("arraybuffer"));return this.load_from_files(H,I)}async load_from_files(T,I){let D=[...T.keys()].filter((B)=>B.toLowerCase().endsWith(".osu"));if(D.length===0)throw Error("No .osu files found in beatmap");let H=this.select_difficulty(D,T,I?.difficulty),S=this.to_string(T.get(H)),O=new y().parse(S),U=H0(S),V=S0(S),R=A0(S),N=new Map;for(let[B,W]of T)if(W instanceof ArrayBuffer)N.set(B,W);else N.set(B,new TextEncoder().encode(W).buffer);let P;if(U)P=this.find_file(N,U);let J;if(V){let B=this.find_file(N,V);if(B)J=new Blob([B])}let F,M;if(R){let B=this.find_file(N,R.filename);if(B)F=new Blob([B]),M=R.offset}return{beatmap:O,files:N,audio:P,background:J,video:F,audio_filename:U??void 0,background_filename:V??void 0,video_filename:R?.filename,video_offset:M}}async list_difficulties(T){let I=await E0.loadAsync(T),D=[];for(let S of Object.keys(I.files))if(S.toLowerCase().endsWith(".osu"))D.push(S);let H=[];for(let S of D){let O=(await I.files[S].async("string")).match(/Version:\s*(.+)/);H.push(O?O[1].trim():S)}return H}select_difficulty(T,I,D){if(D===void 0)return T[0];if(typeof D==="number"){if(D<0||D>=T.length)throw Error(`Difficulty index ${D} out of range (0-${T.length-1})`);return T[D]}for(let H of T){let A=this.to_string(I.get(H)).match(/Version:\s*(.+)/);if(A&&A[1].trim()===D)return H}for(let H of T)if(H.toLowerCase().includes(D.toLowerCase()))return H;throw Error(`Difficulty "${D}" not found`)}find_file(T,I){if(T.has(I))return T.get(I);let D=I.toLowerCase();for(let[H,S]of T)if(H.toLowerCase()===D)return S;return}to_string(T){if(typeof T==="string")return T;return new TextDecoder().decode(T)}}var O0=512,V0=384,G0;((A)=>{A[A.None=0]="None";A[A.Large=32]="Large";A[A.Medium=16]="Medium";A[A.Small=8]="Small";A[A.Tiny=4]="Tiny"})(G0||={});var E={offset_x:64,offset_y:48,scale:1,show_playfield:!0,playfield_color:"#ffffff",playfield_opacity:0.1,grid_level:0,grid_color:"#ffffff",grid_opacity:0.35,use_high_dpi:!0};class g{backend;skin;config;mods;beatmap;objects=[];background_image=null;constructor(T,I,D=0,H=E){this.backend=T,this.skin=I,this.mods=D,this.config={...E,...H}}set_background(T){this.background_image=T}update_config(T){this.config={...this.config,...T}}dispose(){this.objects=[]}render_playfield(T,I,D,H){if(!this.config.show_playfield)return;let{backend:S,config:A}=this,O=T??512,U=I??384,V=D??0,R=H??0;S.save(),S.set_alpha(A.playfield_opacity),S.begin_path(),S.move_to(V,R),S.line_to(V+O,R),S.line_to(V+O,R+U),S.line_to(V,R+U),S.line_to(V,R),S.stroke_path(A.playfield_color,2),S.restore()}render_grid(){if(this.config.grid_level===0)return;let{backend:T,config:I}=this,D=I.grid_level;T.save(),T.set_alpha(I.grid_opacity);for(let H=0;H<=512;H+=D)T.begin_path(),T.move_to(H,0),T.line_to(H,384),T.stroke_path(I.grid_color,H%(D*4)===0?1:0.5);for(let H=0;H<=384;H+=D)T.begin_path(),T.move_to(0,H),T.line_to(512,H),T.stroke_path(I.grid_color,H%(D*4)===0?1:0.5);T.restore()}render_background(){if(!this.background_image)return;let{backend:T}=this;T.save(),T.set_alpha(0.3);let{width:I,height:D}=T,H=this.background_image.width||0,S=this.background_image.height||0;if(H>0&&S>0){let A=Math.max(I/H,D/S),O=H*A,U=S*A,V=(I-O)/2,R=(D-U)/2;T.draw_image(this.background_image,V,R,O,U)}else T.draw_image(this.background_image,0,0,I,D);T.restore()}get_visible_objects(T,I,D){let H=[];for(let S of this.objects){let A=S.time-I,O=S.end_time+D;if(T>=A&&T<=O)H.push(S)}return H}}class p{ctx;_width=0;_height=0;_dpr=1;get width(){return this._width}get height(){return this._height}initialize(T,I=!0){this._dpr=I?window.devicePixelRatio||1:1;let D=T.clientWidth||T.width,H=T.clientHeight||T.height;T.width=D*this._dpr,T.height=H*this._dpr;let S=T.getContext("2d",{alpha:!0,desynchronized:!0});if(!S)throw Error("Failed to get 2D context");this.ctx=S,this._width=D,this._height=H,S.scale(this._dpr,this._dpr),S.imageSmoothingEnabled=!0,S.imageSmoothingQuality="high"}clear(){this.ctx.save(),this.ctx.setTransform(this._dpr,0,0,this._dpr,0,0),this.ctx.clearRect(0,0,this._width,this._height),this.ctx.restore()}dispose(){}resize(T,I){this._width=T,this._height=I,this._dpr=window.devicePixelRatio||1;let D=this.ctx.canvas;D.width=T*this._dpr,D.height=I*this._dpr,D.style.width=`${T}px`,D.style.height=`${I}px`,this.ctx.resetTransform(),this.ctx.scale(this._dpr,this._dpr),this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high"}draw_circle(T,I,D,H,S,A){let O=this.ctx;if(O.beginPath(),O.arc(T,I,D,0,Math.PI*2),H&&H!=="transparent")O.fillStyle=H,O.fill();if(S&&A&&A>0)O.strokeStyle=S,O.lineWidth=A,O.stroke()}draw_arc(T,I,D,H,S,A,O,U=!1){let V=this.ctx;V.beginPath(),V.arc(T,I,D,H,S,U),V.strokeStyle=A,V.lineWidth=O,V.stroke()}draw_rect(T,I,D,H,S){this.ctx.fillStyle=S,this.ctx.fillRect(T,I,D,H)}draw_text(T,I,D,H,S,A="left",O="alphabetic"){let U=this.ctx;U.font=H,U.fillStyle=S,U.textAlign=A,U.textBaseline=O,U.fillText(T,I,D)}begin_path(){this.ctx.beginPath()}move_to(T,I){this.ctx.moveTo(T,I)}line_to(T,I){this.ctx.lineTo(T,I)}bezier_curve_to(T,I,D,H,S,A){this.ctx.bezierCurveTo(T,I,D,H,S,A)}quadratic_curve_to(T,I,D,H){this.ctx.quadraticCurveTo(T,I,D,H)}arc_to(T,I,D,H,S,A){this.ctx.arc(T,I,D,H,S,A)}rect(T,I,D,H){this.ctx.rect(T,I,D,H)}clip(){this.ctx.clip()}stroke_path(T,I,D="butt",H="miter"){let S=this.ctx;S.strokeStyle=T,S.lineWidth=I,S.lineCap=D,S.lineJoin=H,S.stroke()}fill_path(T){this.ctx.fillStyle=T,this.ctx.fill()}save(){this.ctx.save()}restore(){this.ctx.restore()}translate(T,I){this.ctx.translate(T,I)}scale(T,I){this.ctx.scale(T,I)}rotate(T){this.ctx.rotate(T)}set_alpha(T){this.ctx.globalAlpha=T}set_shadow(T,I){this.ctx.shadowColor=T,this.ctx.shadowBlur=I}set_composite_operation(T){this.ctx.globalCompositeOperation=T}draw_image(T,I,D,H,S){if(H!==void 0&&S!==void 0)this.ctx.drawImage(T,I,D,H,S);else this.ctx.drawImage(T,I,D)}draw_image_part(T,I,D,H,S,A,O,U,V){this.ctx.drawImage(T,I,D,H,S,A,O,U,V)}}var d={min:1800,mid:1200,max:450},b0=450,f0=(T,I)=>{if(T>5)return I.mid+(I.max-I.mid)*(T-5)/5;if(T<5)return I.mid+(I.mid-I.min)*(T-5)/5;return I.mid},U0=(T,I)=>{if(Math.sign(T-I.mid)===Math.sign(I.max-I.mid))return(T-I.mid)/(I.max-I.mid)*5+5;return(T-I.mid)/(I.mid-I.min)*5+5},b=(T)=>f0(T,d),R0=(T)=>400*Math.min(1,T/450),m0=(T)=>{return(1-0.7*((T-5)/5))/2},N0=(T)=>m0(T)*64;var P0={name:"Hard Rock",acronym:"HR",apply_to_difficulty(T){T.cs=Math.min(T.cs*1.3,10),T.ar=Math.min(T.ar*1.4,10),T.od=Math.min(T.od*1.4,10),T.hp=Math.min(T.hp*1.4,10)}};var $0={name:"Easy",acronym:"EZ",apply_to_difficulty(T){T.cs*=0.5,T.ar*=0.5,T.od*=0.5,T.hp*=0.5}};var l0={name:"Double Time",acronym:"DT",get_rate_multiplier:()=>1.5},c0={name:"Nightcore",acronym:"NC",get_rate_multiplier:()=>1.5};var _0={name:"Half Time",acronym:"HT",get_rate_multiplier:()=>0.75};var n0=0.4,p0=0.3,d0={name:"Hidden",acronym:"HD"};var B0=(T)=>{if(T&($.DoubleTime|$.Nightcore))return 1.5;if(T&$.HalfTime)return 0.75;return 1},s0=(T,I)=>{if(I&$.Easy)$0.apply_to_difficulty(T);if(I&$.HardRock)P0.apply_to_difficulty(T)},o0=(T,I)=>{if(I===1)return T;let D=b(T)/I;return U0(D,d)},w0=(T,I,D,H,S)=>{let A={cs:T,ar:I,od:D,hp:H};s0(A,S);let O=B0(S);return A.ar=o0(A.ar,O),A};var u0=(T,I)=>[T[0]+I[0],T[1]+I[1]],Y=(T,I)=>[T[0]-I[0],T[1]-I[1]],x0=(T,I)=>[T[0]*I,T[1]*I],i0=(T,I)=>[T[0]/I,T[1]/I],k1=(T,I)=>T[0]*I[0]+T[1]*I[1],L=(T)=>Math.sqrt(T[0]*T[0]+T[1]*T[1]),j1=(T)=>T[0]*T[0]+T[1]*T[1],h1=(T,I)=>L(Y(T,I)),F0=(T)=>{let I=L(T);return I>0?i0(T,I):[0,0]},u=(T,I,D)=>T+(I-T)*D,k=(T,I,D)=>[u(T[0],I[0],D),u(T[1],I[1],D)],K=(T,I,D)=>Math.min(D,Math.max(I,T));var s=(T,I=0.25)=>{if(T.length<2)return[...T];let D=[];return M0(T,D,I),D},M0=(T,I,D)=>{if(a0(T,D)){if(I.length===0)I.push(T[0]);I.push(T[T.length-1]);return}let H=[],S=[];e0(T,H,S),M0(H,I,D),M0(S,I,D)},a0=(T,I)=>{if(T.length<=2)return!0;let D=T[0],H=T[T.length-1];for(let S=1;S<T.length-1;S++)if(t0(T[S],D,H)>I)return!1;return!0},t0=(T,I,D)=>{let H=Y(D,I),S=H[0]*H[0]+H[1]*H[1];if(S===0)return L(Y(T,I));let A=Math.max(0,Math.min(1,((T[0]-I[0])*H[0]+(T[1]-I[1])*H[1])/S)),O=[I[0]+A*H[0],I[1]+A*H[1]];return L(Y(T,O))},e0=(T,I,D)=>{let H=T.length,S=[T];for(let A=1;A<H;A++){S[A]=[];for(let O=0;O<H-A;O++)S[A][O]=k(S[A-1][O],S[A-1][O+1],0.5)}for(let A=0;A<H;A++)I.push(S[A][0]),D.push(S[H-1-A][A])},o=(T,I,D)=>{let H=Y(I,T),S=L(H);if(S===0)return[T];let A=[H[0]/S,H[1]/S],O=u0(T,x0(A,D));return[T,O]},J0=(T,I)=>{if(T.length!==3)return s(T);let[D,H,S]=T,A=T1(D,H,S);if(!A)return o(D,S,I);let O=L(Y(D,A)),U=Math.atan2(D[1]-A[1],D[0]-A[0]),V=Math.atan2(S[1]-A[1],S[0]-A[0]),N=(H[0]-D[0])*(S[1]-D[1])-(H[1]-D[1])*(S[0]-D[0])>0,P=V-U;if(N&&P<0)P+=2*Math.PI;if(!N&&P>0)P-=2*Math.PI;let J=Math.abs(P)*O,F=Math.max(2,Math.ceil(Math.abs(P)*O/4)),M=[];for(let B=0;B<=F;B++){let W=B/F,Q=U+P*W*Math.min(1,I/J);M.push([A[0]+O*Math.cos(Q),A[1]+O*Math.sin(Q)])}return M},T1=(T,I,D)=>{let H=2*(T[0]*(I[1]-D[1])+I[0]*(D[1]-T[1])+D[0]*(T[1]-I[1]));if(Math.abs(H)<0.001)return null;let S=((T[0]*T[0]+T[1]*T[1])*(I[1]-D[1])+(I[0]*I[0]+I[1]*I[1])*(D[1]-T[1])+(D[0]*D[0]+D[1]*D[1])*(T[1]-I[1]))/H,A=((T[0]*T[0]+T[1]*T[1])*(D[0]-I[0])+(I[0]*I[0]+I[1]*I[1])*(T[0]-D[0])+(D[0]*D[0]+D[1]*D[1])*(I[0]-T[0]))/H;return[S,A]},C0=(T)=>{if(T.length<2)return[...T];let I=[];for(let D=0;D<T.length-1;D++){let H=T[Math.max(0,D-1)],S=T[D],A=T[D+1],O=T[Math.min(T.length-1,D+2)],U=50;for(let V=0;V<=50;V++){let R=V/50;I.push(I1(H,S,A,O,R))}}return I},I1=(T,I,D,H,S)=>{let A=S*S,O=A*S;return[0.5*(2*I[0]+(-T[0]+D[0])*S+(2*T[0]-5*I[0]+4*D[0]-H[0])*A+(-T[0]+3*I[0]-3*D[0]+H[0])*O),0.5*(2*I[1]+(-T[1]+D[1])*S+(2*T[1]-5*I[1]+4*D[1]-H[1])*A+(-T[1]+3*I[1]-3*D[1]+H[1])*O)]};var W0={1:["#d5bc00"],2:["#ffffff","#ffffff"],3:["#ffffff","#d5bc00","#ffffff"],4:["#ffffff","#dc8dba","#dc8dba","#ffffff"],5:["#ffffff","#dc8dba","#d5bc00","#dc8dba","#ffffff"],6:["#ffffff","#dc8dba","#ffffff","#ffffff","#dc8dba","#ffffff"],7:["#ffffff","#dc8dba","#ffffff","#d5bc00","#ffffff","#dc8dba","#ffffff"],8:["#d5bc00","#ffffff","#dc8dba","#ffffff","#d5bc00","#ffffff","#dc8dba","#ffffff"],9:["#ffffff","#dc8dba","#ffffff","#dc8dba","#d5bc00","#dc8dba","#ffffff","#dc8dba","#ffffff"],10:["#ffffff","#dc8dba","#d5bc00","#dc8dba","#ffffff","#ffffff","#dc8dba","#d5bc00","#dc8dba","#ffffff"]},K0={combo_colors:["0,185,0","7, 105, 227","224, 4, 38","227, 171, 2"],circle_border_width:0.13,hit_circle_opacity:1,approach_circle_width:0.1,slider_body_opacity:0.85,slider_border_opacity:1,slider_tick_opacity:0.75,slider_tick_size:0.1,follow_circle_factor:2,follow_circle_width:3,follow_circle_opacity:0.7,follow_point_width:2,spinner_size:180,spinner_center_size:10,mania_lane_width:30,mania_note_height:15,mania_hit_position:364,mania_lane_spacing:1,mania_lane_colors:W0,font_family:'"Exo 2", sans-serif',hit_animation_duration:300,hit_animation_scale:1.3},q0=(T)=>{if(!T)return{...K0};return{...K0,...T,mania_lane_colors:T.mania_lane_colors?{...W0,...T.mania_lane_colors}:W0}},x=(T,I,D=1)=>{return`rgba(${T.combo_colors[I%T.combo_colors.length]},${D})`},m=(T,I,D)=>{let H=T.mania_lane_colors[I]??T.mania_lane_colors[4];return H[D%H.length]??"#ffffff"};var f=(T)=>1-Math.pow(1-T,3),Q0=(T)=>384-T;class i extends g{radius=32;preempt=1200;fade_in=600;timing_points=[];use_hidden=!1;use_hard_rock=!1;slider_cache=new Map;constructor(T,I,D=0,H=E){super(T,I,D,H);this.use_hidden=(D&$.Hidden)!==0,this.use_hard_rock=(D&$.HardRock)!==0}initialize(T){this.beatmap=T,this.objects=JSON.parse(JSON.stringify(T.objects)).sort((D,H)=>D.time-H.time),this.timing_points=this.process_timing_points([...T.timing_points]),this.slider_cache.clear();let I=w0(T.cs,T.ar,T.od,T.hp,this.mods);this.radius=N0(I.cs),this.preempt=b(I.ar),this.fade_in=R0(this.preempt),this.preprocess_objects()}set_mods(T){if(this.mods=T,this.use_hidden=(T&$.Hidden)!==0,this.use_hard_rock=(T&$.HardRock)!==0,this.beatmap)this.initialize(this.beatmap)}process_timing_points(T){if(T.length===0)return T;T[0].time=0;let I=T[0].ms_per_beat;for(let D of T)if(D.ms_per_beat<0)D.ms_per_beat=I*(-D.ms_per_beat/100);else I=D.ms_per_beat;return T.reverse()}preprocess_objects(){let T=0,I=1;for(let D of this.objects){if(L0(D))T=(T+1)%this.skin.combo_colors.length,I=1;else I++;if(D.combo_number=T,D.combo_count=I,_(D)){let H=D.data;if(this.use_hard_rock)H.pos=[H.pos[0],Q0(H.pos[1])],H.control_points=H.control_points.map((O)=>[O[0],Q0(O[1])]);H.computed_path=this.compute_slider_path(H);let S=this.get_timing_at(D.time),A=H.distance/(100*this.beatmap.sv)*S.ms_per_beat;H.duration=A,D.end_time=D.time+A*H.repetitions,D.end_pos=this.get_slider_position(H,D.end_time-D.time,A)}else if(j(D))D.end_pos=[256,192];else{let H=D.data;if(this.use_hard_rock)H.pos=[H.pos[0],Q0(H.pos[1])];D.end_pos=H.pos}}}compute_slider_path(T){let I=[T.pos,...T.control_points];switch(T.path_type){case"L":return o(T.pos,T.control_points[0],T.distance);case"P":return J0(I,T.distance);case"C":return C0(I);case"B":default:return this.flatten_multibezier(I,T.distance)}}flatten_multibezier(T,I){let D=[],H=[T[0]];for(let A=1;A<T.length;A++){let O=T[A-1],U=T[A];if(O[0]===U[0]&&O[1]===U[1]){if(H.length>1)D.push(H);H=[U]}else H.push(U)}if(H.length>1)D.push(H);let S=[];for(let A of D){let O=s(A);S.push(...O)}return this.clamp_path_to_distance(S,I)}clamp_path_to_distance(T,I){if(T.length<2)return T;let D=[T[0]],H=0;for(let S=1;S<T.length;S++){let A=L(Y(T[S],T[S-1]));if(H+A>=I){let U=(I-H)/A;D.push(k(T[S-1],T[S],U));break}H+=A,D.push(T[S])}return D}get_timing_at(T){for(let I of this.timing_points)if(I.time<=T)return I;return this.timing_points[this.timing_points.length-1]}render(T){let{backend:I,config:D}=this;this.render_background(),I.save(),I.translate(D.offset_x,D.offset_y),I.scale(D.scale,D.scale),this.render_playfield(),this.render_grid();let H=this.get_visible_objects(T,this.preempt,200);for(let S=0;S<H.length-1;S++){let A=H[S],O=H[S+1];if(!j(A)&&!j(O))this.draw_follow_point(A,O,T)}H.reverse();for(let S of H){if(_(S)){if(this.draw_slider(S,T),!this.use_hidden&&T<=S.time)this.draw_approach_circle(S,T)}else if(Z0(S)){if(this.draw_hit_circle(S,T),!this.use_hidden&&T<=S.time)this.draw_approach_circle(S,T)}else if(j(S))this.draw_spinner(S,T);if(_(S)&&T>S.time&&T<=S.end_time)this.draw_follow_circle(S,T)}I.restore()}get_circle_opacity(T,I){let D=T.time-this.preempt;if(this.use_hidden){let S=this.preempt*0.4,A=D+S,O=this.preempt*0.3;if(I<D)return 0;if(I<A)return K((I-D)/S,0,1);return 1-K((I-A)/O,0,1)}if(I<D)return 0;let H=K((I-D)/this.fade_in,0,1);if(I>T.end_time){let S=K((I-T.end_time)/150,0,1);H=1-f(S)}return K(H,0,1)}get_slider_body_opacity(T,I){let D=T.time-this.preempt;if(this.use_hidden){let S=this.preempt*0.4,A=D+S;if(I<D)return 0;if(I<A)return K((I-D)/S,0,1);let O=T.end_time-A;return 1-K((I-A)/O,0,1)}if(I<D)return 0;let H=K((I-D)/this.fade_in,0,1);if(I>T.end_time){let S=K((I-T.end_time)/200,0,1);H=1-f(S)}return K(H,0,1)}draw_approach_circle(T,I){if(this.use_hidden)return;let{backend:D,skin:H,radius:S,preempt:A,fade_in:O}=this,U=T.data.pos,V=T.time-A;if(I<V||I>T.time)return;let N=1+(T.time-I)/A*3,P=S*N,J=Math.min(O*2,A),F=K((I-V)/J,0,0.9);D.set_alpha(F),D.draw_circle(U[0],U[1],P,"transparent",x(H,T.combo_number,1),S*H.approach_circle_width),D.set_alpha(1)}draw_hit_circle(T,I){let{backend:D,skin:H,radius:S}=this,A=T.data.pos,O=T.time-this.preempt,U=240;if(I<O)return;if(I>T.end_time+240)return;let V=1,R=1;if(I<T.time)if(this.use_hidden){let F=this.preempt*0.4,M=O+F,B=this.preempt*0.3;if(I<M)V=K((I-O)/F,0,1);else V=1-K((I-M)/B,0,1)}else V=K((I-O)/this.fade_in,0,1);else{let F=K((I-T.end_time)/240,0,1);R=1+0.4*f(F),V=1-f(F)}if(V<=0)return;let N=S*R,P=N*(1-H.circle_border_width/2),J=N*H.circle_border_width;if(D.set_alpha(V*H.hit_circle_opacity),D.draw_circle(A[0],A[1],P,x(H,T.combo_number,1),"rgba(255,255,255,1)",J),I<T.time){let F=S*0.8;D.draw_text(String(T.combo_count),A[0],A[1],`600 ${F}px ${H.font_family}`,"rgba(255,255,255,1)","center","middle")}D.set_alpha(1)}draw_slider(T,I){let{backend:D,skin:H,radius:S}=this,A=T.data,O=A.computed_path;if(!O||O.length<2)return;let U=this.get_slider_body_opacity(T,I);if(U<=0.01)return;let R=S*0.872,N=x(H,T.combo_number,1);if(H.slider_body_opacity<1&&H.slider_border_opacity>0)this.draw_masked_slider(T,O,S,R,N,U);else{D.save(),D.set_alpha(U*H.slider_border_opacity),D.begin_path(),D.move_to(O[0][0],O[0][1]);for(let B=1;B<O.length;B++)D.line_to(O[B][0],O[B][1]);D.stroke_path("rgba(255,255,255,1)",S*2,"round","round"),D.set_alpha(U*H.slider_body_opacity),D.begin_path(),D.move_to(O[0][0],O[0][1]);for(let B=1;B<O.length;B++)D.line_to(O[B][0],O[B][1]);D.stroke_path(N,R*2,"round","round"),D.restore(),D.set_alpha(U)}if(this.draw_slider_ticks(T,A,O,I),A.repetitions>1)this.handle_reverse_arrows(T,A,O,I);let P=T.time-this.preempt,J=150,F=0,M=1;if(this.use_hidden){let B=this.preempt*0.4,W=P+B,Q=this.preempt*0.3;if(I<P)F=0;else if(I<T.time)if(I<W)F=K((I-P)/B,0,1);else F=1-K((I-W)/Q,0,1);else if(I<T.time+J){let C=0;if(T.time<W)C=K((T.time-P)/B,0,1);else C=1-K((T.time-W)/Q,0,1);let X=(I-T.time)/J;F=C*(1-f(X)),M=1+f(X)*0.4}}else if(I<P)F=0;else if(I<T.time)F=K((I-P)/this.fade_in,0,1);else if(I<T.time+J){let B=K((T.time-P)/this.fade_in,0,1),W=(I-T.time)/J;F=B*(1-f(W)),M=1+f(W)*0.4}if(F>0){let B=A.pos,W=S*(1-H.circle_border_width/2)*M,Q=S*H.circle_border_width*M;D.set_alpha(F*H.hit_circle_opacity),D.draw_circle(B[0],B[1],W,x(H,T.combo_number,1),"rgba(255,255,255,1)",Q);let C=S*0.8*M;D.draw_text(String(T.combo_count),B[0],B[1],`600 ${C}px ${H.font_family}`,"rgba(255,255,255,1)","center","middle")}D.set_alpha(1)}handle_reverse_arrows(T,I,D,H){let{radius:S}=this,A=Math.max(0,H-T.time),O=I.duration,U=Math.floor(A/O),V=I.repetitions-1-U;if(V>=1&&U%2===0)this.draw_reverse_arrow(D,S,!0);if(V>=1&&U%2===1)this.draw_reverse_arrow(D,S,!1);if(H<T.time){if(this.draw_reverse_arrow(D,S,!0),I.repetitions>2)this.draw_reverse_arrow(D,S,!1)}}draw_masked_slider(T,I,D,H,S,A){let{backend:O,skin:U,config:V}=this,R=this.slider_cache.get(T);if(R&&Math.abs(R.scale-V.scale)<0.001){if(O.save(),V.scale!==0)O.scale(1/V.scale,1/V.scale),O.translate(-V.offset_x,-V.offset_y);let q=Math.floor(R.min_x*V.scale+V.offset_x),G=Math.floor(R.min_y*V.scale+V.offset_y);O.set_alpha(A),O.draw_image(R.canvas,q,G),O.restore();return}let N=1/0,P=1/0,J=-1/0,F=-1/0;for(let q of I){if(q[0]<N)N=q[0];if(q[0]>J)J=q[0];if(q[1]<P)P=q[1];if(q[1]>F)F=q[1]}let M=D+2;N-=M,P-=M,J+=M,F+=M;let B=Math.ceil((J-N)*V.scale),W=Math.ceil((F-P)*V.scale);if(B<=0||W<=0)return;let Q=document.createElement("canvas");Q.width=B,Q.height=W;let C=Q.getContext("2d");if(!C)return;if(C.save(),C.scale(V.scale,V.scale),C.translate(-N,-P),C.beginPath(),I.length>0){C.moveTo(I[0][0],I[0][1]);for(let q=1;q<I.length;q++)C.lineTo(I[q][0],I[q][1])}if(C.globalAlpha=U.slider_border_opacity,C.lineCap="round",C.lineJoin="round",C.lineWidth=D*2,C.strokeStyle="white",C.stroke(),C.globalCompositeOperation="destination-out",C.lineWidth=H*2,C.strokeStyle="white",C.globalAlpha=1,C.stroke(),C.globalCompositeOperation="source-over",C.lineWidth=H*2,C.strokeStyle=S,C.globalAlpha=U.slider_body_opacity,C.stroke(),C.restore(),this.slider_cache.set(T,{canvas:Q,scale:V.scale,min_x:N,min_y:P}),O.save(),V.scale!==0)O.scale(1/V.scale,1/V.scale),O.translate(-V.offset_x,-V.offset_y);let X=Math.floor(N*V.scale+V.offset_x),Z=Math.floor(P*V.scale+V.offset_y);O.set_alpha(A),O.draw_image(Q,X,Z),O.restore()}draw_slider_ticks(T,I,D,H){let{backend:S,skin:A,radius:O,preempt:U,fade_in:V}=this;if(H>T.end_time)return;let R=this.get_timing_at(T.time),N=100*this.beatmap.sv*R.velocity,P=N/R.beat_length,J=N/this.beatmap.tick_rate,F=P*10,M=I.distance,B=this.get_path_length(D);for(let W=J;W<=M;W+=J){if(W>=M-F)break;let C=W/M*B,X=this.get_position_at_length(D,C),Z=1;if(this.use_hidden){let q=T.time+W/M*I.duration,G=q-Math.min(1000,U*0.7),v=q-U;if(H<v||H>G)Z=0;else if(H>G-200)Z=(G-H)/200;else Z=K((H-v)/V,0,1)}else{let q=T.time-U;if(H<q)Z=0;else{let v=K((H-q)/V,0,1),k0=W/M*(V*0.3),j0=K((H-q-k0)/(V*0.5),0,1);Z=Math.min(v,j0)}let G=T.time+W/M*I.duration;if(H>G){let v=(H-G)/150;Z=Math.max(0,Z*(1-v))}}if(Z>0)S.set_alpha(Z*A.slider_tick_opacity),S.draw_circle(X[0],X[1],O*A.slider_tick_size,"rgba(255,255,255,1)","rgba(255,255,255,0.1)",1)}}get_position_at_length(T,I){let D=0;for(let H=1;H<T.length;H++){let S=L(Y(T[H],T[H-1]));if(D+S>=I){let A=(I-D)/S;return k(T[H-1],T[H],A)}D+=S}return T[T.length-1]}draw_reverse_arrow(T,I,D){let{backend:H}=this,S,A;if(D){S=T[T.length-1];let M=T[Math.max(0,T.length-2)];A=F0(Y(M,S))}else{S=T[0];let M=T[Math.min(1,T.length-1)];A=F0(Y(M,S))}let O=I*0.5,U=Math.atan2(A[1],A[0]),V=Math.PI/4,R=O,N=S[0]+Math.cos(U-V)*R,P=S[1]+Math.sin(U-V)*R,J=S[0]+Math.cos(U+V)*R,F=S[1]+Math.sin(U+V)*R;H.begin_path(),H.move_to(N,P),H.line_to(S[0],S[1]),H.line_to(J,F),H.stroke_path("rgba(255,255,255,1)",4,"round","round")}draw_follow_circle(T,I){let{backend:D,skin:H,radius:S,fade_in:A}=this,O=T.data,U=this.get_slider_position(O,I-T.time,O.duration),V;if(this.use_hidden)if(I<T.time-A)V=0;else if(I<T.time)V=(I-(T.time-A))/A;else if(I<=T.end_time)V=1;else V=1-K((I-T.end_time)/100,0,1);else V=this.get_slider_body_opacity(T,I);if(V<=0)return;let R=S*(1-H.circle_border_width/2),N=S*H.circle_border_width;D.set_alpha(V),D.draw_circle(U[0],U[1],R,x(H,T.combo_number,0.5),"rgba(255,255,255,1)",N);let P=1+Math.sin(I*0.01)*0.05;D.begin_path(),D.arc_to(U[0],U[1],R*H.follow_circle_factor*P,0,Math.PI*2),D.stroke_path("rgba(255,255,255,0.7)",H.follow_circle_width),D.set_alpha(1)}get_slider_position(T,I,D){let H=T.computed_path;if(!H||H.length===0)return T.pos;let S=I%(D*2),A=S<D?S/D:2-S/D;A=K(A,0,1);let O=this.get_path_length(H),U=A*O,V=0;for(let R=1;R<H.length;R++){let N=L(Y(H[R],H[R-1]));if(V+N>=U){let P=(U-V)/N;return k(H[R-1],H[R],P)}V+=N}return H[H.length-1]}get_path_length(T){let I=0;for(let D=1;D<T.length;D++)I+=L(Y(T[D],T[D-1]));return I}draw_spinner(T,I){let{backend:D,skin:H}=this,S=this.get_circle_opacity(T,I);if(S<=0)return;let A=256,O=192,U=T.end_time-T.time,V=K((I-T.time)/U,0,1);D.set_alpha(S);let R=H.spinner_size*(1-V);if(R>5)D.begin_path(),D.arc_to(A,O,R,0,Math.PI*2),D.stroke_path("rgba(255,255,255,0.6)",4);D.draw_circle(A,O,H.spinner_size,"rgba(0,0,0,0.2)"),D.draw_circle(A,O,12,"white")}draw_follow_point(T,I,D){if(this.use_hidden)return;if(T.combo_number!==I.combo_number)return;let{backend:H,skin:S}=this;if(D<T.end_time||D>I.time)return;let A=T.end_pos,O=I.data.pos,U=O[0]-A[0],V=O[1]-A[1];if(Math.sqrt(U*U+V*V)<48)return;let N=I.time-T.end_time,P=(D-T.end_time)/N,J=1;if(P<0.2)J=P/0.2;if(P>0.8)J=(1-P)/0.2;if(J<=0)return;let F=K(P*1.5,0,1),M=u(A[0],O[0],Math.max(0,P-0.3)),B=u(A[1],O[1],Math.max(0,P-0.3)),W=u(A[0],O[0],F),Q=u(A[1],O[1],F);H.set_alpha(J*0.6),H.begin_path(),H.move_to(M,B),H.line_to(W,Q),H.stroke_path("rgba(255,255,255,1)",S.follow_point_width,"round","round"),H.set_alpha(1)}}var v0=11485,y0=20;class a extends g{key_count=4;scroll_time=v0/y0;constructor(T,I,D=0,H=E){super(T,I,D,H);this.update_scroll_time()}initialize(T){this.beatmap=T,this.objects=[...T.objects],this.key_count=Math.floor(T.cs);for(let I of this.objects)if(I0(I))I.end_time=I.data.end_time}set_mods(T){this.mods=T,this.update_scroll_time()}update_scroll_time(){let T=B0(this.mods);this.scroll_time=v0/(y0*T)}time_to_y(T){let I=this.skin.mania_hit_position,D=T/this.scroll_time;return I-D*I}render(T){let{backend:I,config:D,skin:H,key_count:S}=this;this.render_background();let A=S*H.mania_lane_width,O=Math.floor((O0-A)/2),U=H.mania_hit_position;I.save(),I.translate(D.offset_x,D.offset_y),I.scale(D.scale,D.scale),this.render_playfield(A,V0,O),this.draw_lane_keys(T,O),this.draw_judgment_line(O),I.save(),I.begin_path(),I.rect(O,0,A,U),I.clip(),I.set_alpha(0.7),I.draw_rect(O,0,A,U,"#000000"),I.set_alpha(1);for(let V of this.objects){if(V.end_time<T)continue;if(I0(V))this.draw_hold_note(V,T,O);else this.draw_note(V,T,O)}I.restore(),I.restore()}get_lane(T){let I=T.data.pos;return Math.floor(I[0]*this.key_count/512)}draw_note(T,I,D){let{backend:H,skin:S,key_count:A}=this,O=this.get_lane(T),U=S.mania_lane_width,V=S.mania_note_height,R=S.mania_lane_spacing,N=T.time-I,P=this.time_to_y(N);if(P<-V-64)return;let J=D+O*U,F=m(S,A,O);H.set_alpha(1),H.draw_rect(J+R,P-V,U-2*R,V,F)}draw_hold_note(T,I,D){let{backend:H,skin:S,key_count:A}=this,O=T.data,U=this.get_lane(T),V=S.mania_lane_width,R=S.mania_note_height,N=S.mania_lane_spacing,P=T.time-I,J=O.end_time-I,F=this.time_to_y(P),M=this.time_to_y(J),B=D+U*V,W=m(S,A,U);if(M<-64&&F<-64)return;let Q=M,X=(P<0?S.mania_hit_position:F)-Q;if(X>0)H.set_alpha(0.9),H.draw_rect(B+N,Q,V-2*N,X,W);if(P>=0)H.set_alpha(1),H.draw_rect(B+N,F-R,V-2*N,R,W)}draw_judgment_line(T){let{backend:I,skin:D,key_count:H}=this,S=D.mania_lane_width,A=D.mania_hit_position;I.draw_rect(T,A-1,S*H,2,"#ffffff")}draw_lane_keys(T,I){let{backend:D,skin:H,key_count:S}=this,A=H.mania_lane_width,O=H.mania_hit_position,U=H.mania_note_height+5,V=new Set,R=50;for(let N of this.objects)if(T>=N.time-50&&T<=N.end_time+50)V.add(this.get_lane(N));for(let N=0;N<S;N++){let P=V.has(N),J=I+N*A,F=m(H,S,N),M=O;if(D.set_alpha(0.3),D.draw_rect(J+H.mania_lane_spacing,M,A-2*H.mania_lane_spacing,U,F),P)D.set_alpha(1),D.draw_rect(J+H.mania_lane_spacing,M,A-2*H.mania_lane_spacing,U,"#ff6666")}D.set_alpha(1)}}class t{audio_context;audio_source=null;audio_buffer=null;gain_node;start_time=0;pause_time=0;speed=1;_is_playing=!1;_duration=0;_is_loaded=!1;constructor(T){this.audio_context=T,this.gain_node=this.audio_context.createGain(),this.gain_node.connect(this.audio_context.destination)}get is_playing(){return this._is_playing}get is_loaded(){return this._is_loaded}get duration(){return this._duration}get current_time(){if(!this._is_playing)return this.pause_time;return(this.audio_context.currentTime-this.start_time)*this.speed*1000}async load(T,I=0){this.stop();try{this.audio_buffer=await this.audio_context.decodeAudioData(T.slice(0)),this._duration=this.audio_buffer.duration*1000,this.speed=h(I),this._is_loaded=!0,this.pause_time=0}catch(D){throw console.error("Failed to decode audio data",D),D}}play(T){if(!this.audio_buffer){console.warn("[AudioController] Cannot play: not loaded");return}this.stop_source();let I=T!==void 0?T/1000:this.pause_time/1000,D=this.audio_buffer.duration,H=Math.max(0,Math.min(I,D));if(H>=D){this.pause_time=D*1000;return}this.audio_source=this.audio_context.createBufferSource(),this.audio_source.buffer=this.audio_buffer,this.audio_source.playbackRate.value=this.speed,this.audio_source.connect(this.gain_node),this.audio_source.onended=()=>{if(this._is_playing)this._is_playing=!1,this.pause_time=this._duration,this.audio_source=null},this.start_time=this.audio_context.currentTime-H/this.speed,this.audio_source.start(0,H),this._is_playing=!0}pause(){if(!this._is_playing)return;this.pause_time=this.current_time,this.stop_source(),this._is_playing=!1}seek(T){let I=Math.max(0,Math.min(T,this._duration));if(this._is_playing)this.stop_source(),this._is_playing=!1,this.pause_time=I,this.play();else this.pause_time=I}stop(){this.pause(),this.pause_time=0}get_host_time(T){return this.start_time+T/1000/this.speed}stop_source(){if(this.audio_source){try{this.audio_source.onended=null,this.audio_source.stop(),this.audio_source.disconnect()}catch{}this.audio_source=null}}set_volume(T){if(this.gain_node)this.gain_node.gain.value=Math.max(0,Math.min(1,T))}set_speed(T){if(this._is_playing){let I=this.current_time;this.speed=T,this.start_time=this.audio_context.currentTime-I/1000/T}else this.speed=T;if(this.audio_source)this.audio_source.playbackRate.value=T}dispose(){this.stop(),this.audio_buffer=null,this._is_loaded=!1,this.gain_node.disconnect()}}class e{video=null;object_url=null;_offset=0;speed=1;get element(){return this.video}get offset(){return this._offset}async load(T,I=0,D=1){this.dispose(),this._offset=I,this.speed=D,this.video=document.createElement("video"),this.video.muted=!0,this.video.loop=!1,this.video.playsInline=!0,this.object_url=URL.createObjectURL(T),this.video.src=this.object_url,await new Promise((H,S)=>{if(!this.video)return S(Error("No video element"));this.video.onloadeddata=()=>H(),this.video.onerror=()=>S(Error("Failed to load video"))}),this.video.playbackRate=D}sync(T){if(!this.video)return;let I=(T-this._offset)/1000;if(I<0){if(!this.video.paused)this.video.pause();return}if(Math.abs(this.video.currentTime-I)>0.1)this.video.currentTime=I}play(){if(this.video&&this.video.paused)this.video.play().catch(()=>{console.log("failed to play video")})}pause(){if(this.video&&!this.video.paused)this.video.pause()}seek(T){if(!this.video)return;let I=Math.max(0,(T-this._offset)/1000);this.video.currentTime=I}set_speed(T){if(this.speed=T,this.video)this.video.playbackRate=T}dispose(){if(this.video)this.video.pause(),this.video.src="",this.video=null;if(this.object_url)URL.revokeObjectURL(this.object_url),this.object_url=null}}class Y0{context;gain_node;samples=new Map;volume=1;constructor(T){this.context=T,this.gain_node=T.createGain(),this.gain_node.connect(T.destination)}set_volume(T){this.volume=Math.max(0,Math.min(1,T)),this.gain_node.gain.value=this.volume}async load_samples(T){this.samples.clear();let I=[];for(let[D,H]of T)if(D.endsWith(".wav")||D.endsWith(".mp3")||D.endsWith(".ogg"))I.push(this.context.decodeAudioData(H.slice(0)).then((S)=>{let A=D.toLowerCase().replace(/\.(wav|mp3|ogg)$/,"");this.samples.set(A,S)}).catch((S)=>{console.warn(`[HitsoundController] Failed to decode ${D}:`,S)}));await Promise.all(I)}play(T,I,D,H,S=100,A,O=0){let U=this.get_set_name(T),V=this.get_set_name(I);if(A){let R=A.toLowerCase().replace(/\.(wav|mp3|ogg)$/,"");if(this.play_buffer(R,S,O))return}if(this.play_sound(U,"hitnormal",H,S,O),D&c.Whistle)this.play_sound(V,"hitwhistle",H,S,O);if(D&c.Finish)this.play_sound(V,"hitfinish",H,S,O);if(D&c.Clap)this.play_sound(V,"hitclap",H,S,O)}play_sound(T,I,D,H,S){let A=!1;if(D>1)A=this.play_buffer(`${T}-${I}${D}`,H,S);if(!A)this.play_buffer(`${T}-${I}`,H,S)}play_buffer(T,I,D){let H=this.samples.get(T);if(!H)return!1;let S=this.context.createBufferSource();S.buffer=H;let A=this.context.createGain();return A.gain.value=I/100,S.connect(A),A.connect(this.gain_node),S.start(D),!0}get_set_name(T){switch(T){case 3:return"drum";case 2:return"soft";default:return"normal"}}dispose(){this.samples.clear(),this.gain_node.disconnect()}}class g0{backend;renderer=null;audio_context;audio;hitsounds;video=null;resources=null;animation_frame=null;skin;mods;renderer_config;start_offset;volume;listeners=new Map;_raw_osu_content="";_is_loaded=!1;next_hit_object_index=0;resize_observer=null;key_handler=null;options;constructor(T){this.options=T,this.backend=T.backend??new p,this.skin=q0(T.skin),this.mods=T.mods??0,this.renderer_config={...E,...T.renderer_config},this.calculate_layout(T.canvas.width,T.canvas.height,T.playfield_scale),this.start_offset=T.start_time??-1,this.volume=T.volume??0.5,this.backend.initialize(T.canvas,this.renderer_config.use_high_dpi);let I=window.AudioContext||window.webkitAudioContext;if(this.audio_context=new I,this.audio=new t(this.audio_context),this.hitsounds=new Y0(this.audio_context),this.audio.set_volume(this.volume),this.hitsounds.set_volume(this.volume),T.auto_resize)this.setup_auto_resize();if(T.key_bindings)this.setup_key_bindings(T.key_bindings)}async load_osz(T,I){try{let H=await new r().load_osz(T,{difficulty:I});return this.resources=H,this.setup()}catch(D){let H=D instanceof Error?D.message:String(D);return this.emit("error","INVALID_BEATMAP",H),w("INVALID_BEATMAP",H)}}async load_files(T,I){try{let D=new r;this.resources=await D.load_from_files(T,{difficulty:I});for(let[H,S]of T)if(H.endsWith(".osu")){this._raw_osu_content=typeof S==="string"?S:new TextDecoder().decode(S);break}return this.setup()}catch(D){let H=D instanceof Error?D.message:String(D);return this.emit("error","INVALID_BEATMAP",H),w("INVALID_BEATMAP",H)}}async load_hitsounds(T){try{await this.hitsounds.load_samples(T)}catch(I){console.error("[BeatmapPlayer] Failed to load hitsounds:",I)}}async load_beatmap(T,I,D,H,S){return this.resources={beatmap:T,files:new Map,audio:I,background:D,video:H,video_offset:S},this.setup()}async load_osu_content(T,I){try{let H=new y().parse(T);return this._raw_osu_content=T,this.load_beatmap(H,I)}catch(D){let H=D instanceof Error?D.message:String(D);return this.emit("error","INVALID_BEATMAP",H),w("INVALID_BEATMAP",H)}}async setup(){if(!this.resources)return w("NOT_LOADED","No resources loaded");let{beatmap:T,audio:I,video:D,video_offset:H}=this.resources,S=h(this.mods);if(I)try{await this.audio.load(I,this.mods)}catch(A){let O=A instanceof Error?A.message:String(A);return this.emit("error","AUDIO_DECODE_ERROR",O),w("AUDIO_DECODE_ERROR",O)}if(D)this.video=new e,await this.video.load(D,H??0,S);try{this.renderer=this.create_renderer(T),this.renderer.initialize(T)}catch(A){let O=A instanceof Error?A.message:String(A);return this.emit("error","UNSUPPORTED_MODE",O),w("UNSUPPORTED_MODE",O)}if(this.start_offset<0&&this._raw_osu_content){let A=D0(this._raw_osu_content);this.start_offset=A>0?A:this.get_last_object_time()*0.42}if(this.start_offset<0)this.start_offset=0;if(this.update_hit_index(this.start_offset),this.resources?.background)try{let A=new Image;A.src=URL.createObjectURL(this.resources.background),await A.decode(),this.renderer.set_background(A),this._is_loaded=!0,requestAnimationFrame(()=>this.render_frame(this.start_offset))}catch(A){console.warn("[BeatmapPlayer] Failed to load background",A)}return this._is_loaded=!0,this.emit("loaded",T,this.resources),requestAnimationFrame(()=>this.render_frame(this.start_offset)),z0(this.resources)}create_renderer(T){switch(T.mode){case 0:return new i(this.backend,this.skin,this.mods,this.renderer_config);case 3:return new a(this.backend,this.skin,this.mods,this.renderer_config);case 1:case 2:default:throw Error(`Unsupported game mode: ${l[T.mode]??T.mode}`)}}get_last_object_time(){if(!this.resources?.beatmap.objects.length)return 0;let T=this.resources.beatmap.objects;return T[T.length-1].end_time}async play(){if(!this.renderer||!this._is_loaded){console.warn("[BeatmapPlayer] Cannot play: not loaded");return}if(this.audio.is_playing)return;if(this.audio_context.state==="suspended")await this.audio_context.resume();this.audio.play(this.start_offset),this.video?.play(),this.start_render_loop(),this.emit("statechange",!0)}pause(){if(!this.audio.is_playing)return;this.start_offset=this.audio.current_time,this.audio.pause(),this.video?.pause(),this.stop_render_loop(),this.emit("statechange",!1)}set_mods(T){this.mods=T;let I=h(T);if(this.renderer?.set_mods(T),this.audio.set_speed(I),this.video?.set_speed(I),this._is_loaded)requestAnimationFrame(()=>this.render_frame(this.current_time))}seek(T){this.start_offset=Math.max(0,Math.min(T,this.duration)),this.update_hit_index(this.start_offset),this.audio.seek(this.start_offset),this.video?.seek(this.start_offset),this.render_frame(this.start_offset)}update_hit_index(T){if(!this.resources?.beatmap)return;let I=this.resources.beatmap.objects;if(this.next_hit_object_index>0&&I[this.next_hit_object_index-1].time>T)this.next_hit_object_index=0;while(this.next_hit_object_index<I.length&&I[this.next_hit_object_index].time<T)this.next_hit_object_index++}stop(){this.pause(),this.start_offset=0,this.audio.seek(0),this.update_hit_index(0),this.render_frame(0)}dispose(){if(this.stop(),this.backend.dispose(),this.audio.dispose(),this.hitsounds.dispose(),this.video?.dispose(),this.renderer?.dispose(),this.listeners.clear(),this.resize_observer)this.resize_observer.disconnect(),this.resize_observer=null;if(this.key_handler)window.removeEventListener("keydown",this.key_handler),this.key_handler=null;if(this.audio_context&&this.audio_context.state!=="closed")this.audio_context.close().catch(()=>{});this.renderer=null,this.resources=null,this._is_loaded=!1,this.listeners.clear()}get current_time(){return this.audio.current_time}get duration(){return this.audio.duration||this.get_last_object_time()}get is_playing(){return this.audio.is_playing}get is_loaded(){return this._is_loaded}get beatmap(){return this.resources?.beatmap??null}get background(){return this.resources?.background}get config(){return this.renderer_config}resize(T,I,D){if(this.backend.resize(T,I),this.calculate_layout(T,I,D),this._is_loaded)requestAnimationFrame(()=>this.render_frame(this.current_time))}setup_auto_resize(){this.resize_observer=new ResizeObserver(()=>{let I=this.options.canvas.parentElement;if(I){let D=I.getBoundingClientRect();this.resize(D.width,D.height,this.options.playfield_scale)}}),this.resize_observer.observe(this.options.canvas.parentElement||this.options.canvas)}setup_key_bindings(T){this.key_handler=(I)=>{let D={toggle_pause:T.toggle_pause??"Space",seek_forward:T.seek_forward??"ArrowRight",seek_backward:T.seek_backward??"ArrowLeft",toggle_grid:T.toggle_grid??"g"};if(I.code===D.toggle_pause)I.preventDefault(),this.toggle_pause();else if(I.code===D.seek_forward)I.preventDefault(),this.seek(this.current_time+5000);else if(I.code===D.seek_backward)I.preventDefault(),this.seek(this.current_time-5000);else if(I.code===D.toggle_grid)this.toggle_grid()},window.addEventListener("keydown",this.key_handler)}toggle_pause(){if(!this._is_loaded)return;this.is_playing?this.pause():this.play()}toggle_grid(){if(this.renderer_config.grid_level===0)this.renderer_config.grid_level=32;else this.renderer_config.grid_level=0;this.render_frame(this.current_time)}calculate_layout(T,I,D){let A=0.8;if(typeof D==="number")A=D;let O=T*A/512,U=I*A/384,V=Math.min(O,U);if(this.renderer_config.scale=V,this.renderer_config.offset_x=Math.floor((T-512*V)/2),this.renderer_config.offset_y=Math.floor((I-384*V)/2),this.renderer)this.renderer.update_config(this.renderer_config)}set_volume(T){this.volume=T,this.audio.set_volume(T),this.hitsounds.set_volume(T)}on(T,I){if(!this.listeners.has(T))this.listeners.set(T,new Set);this.listeners.get(T).add(I)}off(T,I){this.listeners.get(T)?.delete(I)}emit(T,...I){let D=this.listeners.get(T);if(D)for(let H of D)H(...I)}start_render_loop(){if(this.animation_frame!==null)return;let T=()=>{if(!this.audio.is_playing){this.animation_frame=null;return}let I=this.audio.current_time;if(this.schedule_hitsounds(),this.render_frame(I),this.video?.sync(I),this.emit("timeupdate",I,this.duration),I>=this.duration){this.emit("ended"),this.stop_render_loop(),this.emit("statechange",!1);return}this.animation_frame=requestAnimationFrame(T)};this.animation_frame=requestAnimationFrame(T)}schedule_hitsounds(){if(!this.resources?.beatmap||!this.audio.is_playing)return;let T=this.resources.beatmap.objects,I=this.audio.current_time,H=I+100;while(this.next_hit_object_index<T.length&&T[this.next_hit_object_index].time<=H){let S=T[this.next_hit_object_index];if(S.time>=I-20)this.play_hitsound(S);this.next_hit_object_index++}}play_hitsound(T){let I=this.get_timing_point(T.time),D=I.volume,H=I.sample_set,S=I.sample_set,A=I.sample_index,O=void 0;if(T.hit_sample){let V=T.hit_sample;if(V.normal_set!==0){if(H=V.normal_set,V.addition_set===0)S=H}if(V.addition_set!==0)S=V.addition_set;if(V.index!==0)A=V.index;if(V.volume!==0)D=V.volume;O=V.filename}if(H===0)H=1;if(S===0)S=H;let U=this.audio.get_host_time(T.time);this.hitsounds.play(H,S,T.hit_sound,A,D,O,U)}get_timing_point(T){let I=this.resources?.beatmap.timing_points??[];for(let D=I.length-1;D>=0;D--)if(I[D].time<=T)return I[D];return I[0]}stop_render_loop(){if(this.animation_frame!==null)cancelAnimationFrame(this.animation_frame),this.animation_frame=null}render_frame(T){this.backend.clear(),this.renderer?.render(T)}}export{Y as vec2_sub,F0 as vec2_normalize,x0 as vec2_mul,k as vec2_lerp,j1 as vec2_len_sq,L as vec2_len,k1 as vec2_dot,i0 as vec2_div,h1 as vec2_dist,u0 as vec2_add,H1 as unwrap,N1 as toggle_mod,z0 as ok,R1 as mods_to_string,U1 as mods_from_string,q0 as merge_skin,u as lerp,j as is_spinner,_ as is_slider,S1 as is_ok,L0 as is_new_combo,I0 as is_hold,A1 as is_err,Z0 as is_circle,U0 as inverse_difficulty_range,P1 as has_mod,h as get_speed_multiplier,B0 as get_rate_multiplier,m as get_mania_lane_color,x as get_combo_color,w0 as get_adjusted_difficulty,J0 as flatten_perfect,o as flatten_linear,C0 as flatten_catmull,s as flatten_bezier,A0 as extract_video_info,D0 as extract_preview_time,S0 as extract_background_filename,H0 as extract_audio_filename,w as err,f0 as difficulty_range,K as clamp,N0 as calculate_radius,b as calculate_preempt,R0 as calculate_fade_in,o0 as apply_rate_to_ar,s0 as apply_mods_to_difficulty,e as VideoController,i as StandardRenderer,h0 as SpeedChangingMods,T0 as SampleSet,d as PREEMPT_RANGE,b0 as PREEMPT_MIN,O0 as PLAYFIELD_WIDTH,V0 as PLAYFIELD_HEIGHT,r as OszLoader,$ as Mods,c0 as ModNightcore,d0 as ModHidden,P0 as ModHardRock,_0 as ModHalfTime,$0 as ModEasy,l0 as ModDoubleTime,a as ManiaRenderer,c as HitSoundType,z as HitObjectType,p0 as HD_FADE_OUT_MULTIPLIER,n0 as HD_FADE_IN_MULTIPLIER,G0 as GridLevel,l as GameMode,X0 as ErrorCode,V1 as DifficultyChangingMods,K0 as DEFAULT_SKIN,E as DEFAULT_RENDERER_CONFIG,p as CanvasBackend,g0 as BeatmapPlayer,y as BeatmapParser,g as BaseRenderer,t as AudioController};
3
+
4
+ //# debugId=2A6C0FCF39EEB23D64756E2164756E21